From 8f13f87bf75c293237427b4e09c9648d52b2c398 Mon Sep 17 00:00:00 2001 From: Michael Phipps Date: Sat, 21 Sep 2002 18:57:19 +0000 Subject: [PATCH] For Michael Pfeiffer, ready for beta... git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1108 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/print/BeUtils.cpp | 2 + src/servers/print/BeUtils.h | 66 ++++ src/servers/print/Jamfile | 2 + src/servers/print/Jobs.cpp | 307 ++++++++++++++++++ src/servers/print/Jobs.h | 122 +++++++ src/servers/print/PrintServer.FileTypes.rsrc | Bin 4209 -> 4209 bytes src/servers/print/PrintServerApp.R5.cpp | 35 +- .../print/PrintServerApp.Scripting.cpp | 4 +- src/servers/print/PrintServerApp.cpp | 172 ++++++---- src/servers/print/PrintServerApp.h | 20 +- src/servers/print/Printer.Scripting.cpp | 36 ++ src/servers/print/Printer.cpp | 198 ++++++++--- src/servers/print/Printer.h | 47 ++- src/servers/print/ResourceManager.cpp | 104 ++++++ src/servers/print/ResourceManager.h | 78 +++++ 15 files changed, 1037 insertions(+), 156 deletions(-) create mode 100644 src/servers/print/Jobs.cpp create mode 100644 src/servers/print/Jobs.h create mode 100644 src/servers/print/ResourceManager.cpp create mode 100644 src/servers/print/ResourceManager.h diff --git a/src/servers/print/BeUtils.cpp b/src/servers/print/BeUtils.cpp index 6b91d080f4..ea27c2ab6b 100644 --- a/src/servers/print/BeUtils.cpp +++ b/src/servers/print/BeUtils.cpp @@ -7,6 +7,8 @@ // very specific functions, but generally useful (could be here because of a // lack in the APIs, or just sheer lazyness :)) // +// Author +// Ithamar R. Adema // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written diff --git a/src/servers/print/BeUtils.h b/src/servers/print/BeUtils.h index 785069192a..ef1e3dc344 100644 --- a/src/servers/print/BeUtils.h +++ b/src/servers/print/BeUtils.h @@ -1,10 +1,76 @@ +/*****************************************************************************/ +// BeUtils.cpp +// +// Version: 1.0.0d1 +// +// Several utilities for writing applications for the BeOS. It are small +// very specific functions, but generally useful (could be here because of a +// lack in the APIs, or just sheer lazyness :)) +// +// Authors +// Ithamar R. Adema +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2001 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + #ifndef BEUTILS_H #define BEUTILS_H #include #include +#include status_t TestForAddonExistence(const char* name, directory_which which, const char* section, BPath& outPath); +// Reference counted object +class Object { +private: + volatile int32 fRefCount; + +public: + // After construction reference count is 1 + Object() : fRefCount(1) { } + // dtor should be private, but ie. ObjectList requires a public dtor! + virtual ~Object() { }; + + // thread-safe as long as thread that calls acquire has already + // a reference to the object + void Acquire() { + atomic_add(&fRefCount, 1); + } + + bool Release() { + atomic_add(&fRefCount, -1); + if (fRefCount == 0) { + delete this; return true; + } else { + return false; + } + } +}; + #endif diff --git a/src/servers/print/Jamfile b/src/servers/print/Jamfile index 5445602a3f..f6105c2d65 100644 --- a/src/servers/print/Jamfile +++ b/src/servers/print/Jamfile @@ -17,6 +17,8 @@ Server PrintServerApp.Scripting.cpp Printer.Scripting.cpp Printer.cpp + ResourceManager.cpp + Jobs.cpp BeUtils.cpp ; diff --git a/src/servers/print/Jobs.cpp b/src/servers/print/Jobs.cpp new file mode 100644 index 0000000000..bbc8debb02 --- /dev/null +++ b/src/servers/print/Jobs.cpp @@ -0,0 +1,307 @@ +/*****************************************************************************/ +// Jobs +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + + +#include "pr_server.h" +#include "Jobs.h" +#include "PrintServerApp.h" + +// posix +#include +#include + +// BeOS +#include +#include +#include +#include +#include + + +Job::Job(const BEntry& job, BHandler* handler) + : fHandler(handler) + , fTime(-1) + , fStatus(kUnknown) + , fPrinter(NULL) +{ + // store light weight versions of BEntry and BNode + job.GetRef(&fEntry); + job.GetNodeRef(&fNode); + + BNode node(&job); + if (node.InitCheck() != B_OK) return; + + BNodeInfo info(&node); + char mimeType[256]; + BString status; + + // Is job a spool file? + if (info.InitCheck() == B_OK /*&& + info.GetType(mimeType) == B_OK && + strcmp(mimeType, PSRV_SPOOL_FILETYPE) == 0 && + node.ReadAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, status, sizeof(status))*/) { + if (node.ReadAttrString(PSRV_SPOOL_ATTR_STATUS, &status) != B_OK) { + status = ""; + } + // read status attribute + UpdateStatus(status.String()); + // Now get file name and creation time from file name + fTime = 0; + BEntry entry(job); + char name[B_FILE_NAME_LENGTH]; + if (entry.InitCheck() == B_OK && entry.GetName(name) == B_OK) { + fName = name; + // search for last '@' in file name + char* p = NULL, *c = name; + while ((c = strchr(c, '@')) != NULL) { + p = c; c ++; + } + // and get time from file name + fTime = atoi(p+1); + } + // start watching if everything is ok + StartNodeWatching(); + } +} + +// conversion from string representation of status to JobStatus constant +void Job::UpdateStatus(const char* status) { + if (strcmp(status, PSRV_JOB_STATUS_WAITING) == 0) fStatus = kWaiting; + else if (strcmp(status, PSRV_JOB_STATUS_PROCESSING) == 0) fStatus = kProcessing; + else if (strcmp(status, PSRV_JOB_STATUS_FAILED) == 0) fStatus = kFailed; + else fStatus = kUnknown; +} + +// Write to status attribute of node +void Job::UpdateStatusAttribute(const char* status) { + BNode node(&fEntry); + if (node.InitCheck() == B_OK) { + node.WriteAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, status, strlen(status)+1); + } +} + +// Set status of object and optionally write to attribute of node +void Job::SetStatus(JobStatus s, bool writeToNode) { + fStatus = s; + if (!writeToNode) return; + switch (s) { + case kWaiting: UpdateStatusAttribute(PSRV_JOB_STATUS_WAITING); break; + case kProcessing: UpdateStatusAttribute(PSRV_JOB_STATUS_PROCESSING); break; + case kFailed: UpdateStatusAttribute(PSRV_JOB_STATUS_FAILED); break; + default: break; + } +} + +// Synchronize file attribute with member variable +void Job::UpdateAttribute() { + BNode node(&fEntry); + BString status; + if (node.InitCheck() == B_OK && + node.ReadAttrString(PSRV_SPOOL_ATTR_STATUS, &status) == B_OK) { + UpdateStatus(status.String()); + } +} + +void Job::Remove() { + BEntry entry(&fEntry); + if (entry.InitCheck() == B_OK) entry.Remove(); +} + +void Job::StartNodeWatching() { + watch_node(&fNode, B_WATCH_ATTR, fHandler, be_app); +} + +void Job::StopNodeWatching() { + watch_node(&fNode, B_STOP_WATCHING, fHandler, be_app); +} + + +// Implementation of Folder + +// BObjectList CompareFunction +int Folder::AscendingByTime(const Job* a, const Job* b) { + return a->Time() - b->Time(); +} + +bool Folder::AddJob(BEntry& entry) { + Job* job = new Job(entry, this); + if (job->InitCheck() == B_OK) { + fJobs.AddItem(job); + if (job->IsWaiting()) NotifyPrinter(); + return true; + } else { + job->Release(); + return false; + } +} + +// simplified assumption that ino_t identifies job file +// will probabely not work in all cases with link to a file on another volume??? +Job* Folder::Find(ino_t node) { + for (int i = 0; i < fJobs.CountItems(); i ++) { + Job* job = fJobs.ItemAt(i); + if (job->NodeRef().node == node) return job; + } + return NULL; +} + +void Folder::EntryCreated(BMessage* msg) { + BString name; + BEntry entry; + if (msg->FindString("name", &name) == B_OK && + fSpoolDir.FindEntry(name.String(), &entry) == B_OK) { + BAutolock lock(gLock); + if (lock.IsLocked() && AddJob(entry)) { + fJobs.SortItems(AscendingByTime); + } + } +} + +void Folder::EntryRemoved(BMessage* msg) { + ino_t node; + if (msg->FindInt64("node", &node) == B_OK) { + Job* job = Find(node); + if (job) { + fJobs.RemoveItem(job); + job->StopNodeWatching(); + job->Release(); + } + } +} + +void Folder::AttributeChanged(BMessage* msg) { + ino_t node; + if (msg->FindInt64("node", &node) == B_OK) { + Job* job = Find(node); + if (job) { + job->UpdateAttribute(); + if (job->IsWaiting()) NotifyPrinter(); + } + } +} + +void Folder::HandleNodeMonitorMessage(BMessage* msg) { + BAutolock lock(gLock); + if (!lock.IsLocked()) return; + int32 opcode; + if (msg->FindInt32("opcode", &opcode) != B_OK) return; + switch (opcode) { + case B_ENTRY_CREATED: // add to fJobs + EntryCreated(msg); + break; + case B_ENTRY_REMOVED: // remove from fJobs + EntryRemoved(msg); + break; + case B_ATTR_CHANGED: // notify Printer if status has changed to Waiting + AttributeChanged(msg); + break; + default: // nothing to do + break; + } +} + +void Folder::NotifyPrinter() { + be_app_messenger.SendMessage(PSRV_PRINT_SPOOLED_JOB); +} + +// initial setup of job list +void Folder::SetupJobList() { + if (fSpoolDir.InitCheck() == B_OK) { + fSpoolDir.Rewind(); + + BEntry entry; + while (fSpoolDir.GetNextEntry(&entry) == B_OK) { + AddJob(entry); + } + fJobs.SortItems(AscendingByTime); + } +} + +Folder::Folder(const BDirectory& spoolDir) + : fSpoolDir(spoolDir) + , fJobs() +{ + BAutolock lock(gLock); + if (!lock.IsLocked()) return; + // add this handler to the application for node monitoring + be_app->AddHandler(this); + + SetupJobList(); + + // start watching the spooler directory + node_ref ref; + spoolDir.GetNodeRef(&ref); + watch_node(&ref, B_WATCH_DIRECTORY, this, be_app); +} + + +Folder::~Folder() { + if (!gLock->Lock()) return; + // stop node watching for jobs + for (int i = 0; i < fJobs.CountItems(); i ++) { + Job* job = fJobs.ItemAt(i); + job->StopNodeWatching(); + job->Release(); + } + // stop node watching for spooler directory + node_ref ref; + fSpoolDir.GetNodeRef(&ref); + watch_node(&ref, B_STOP_WATCHING, this, be_app); + // stop sending notifications to this handler + stop_watching(this, be_app); + gLock->Unlock(); + + if (be_app->Lock()) { + // and remove it from application + be_app->RemoveHandler(this); + be_app->Unlock(); + } +} + + +void Folder::MessageReceived(BMessage* msg) { + if (msg->what == B_NODE_MONITOR) { + HandleNodeMonitorMessage(msg); + } else { + inherited::MessageReceived(msg); + } +} + +Job* Folder::GetNextJob() { + for (int i = 0; i < fJobs.CountItems(); i ++) { + Job* job = fJobs.ItemAt(i); + if (job->IsWaiting()) { + job->Acquire(); return job; + } + } + return NULL; +} + diff --git a/src/servers/print/Jobs.h b/src/servers/print/Jobs.h new file mode 100644 index 0000000000..63bb2c43c3 --- /dev/null +++ b/src/servers/print/Jobs.h @@ -0,0 +1,122 @@ +/*****************************************************************************/ +// Jobs +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#ifndef _JOBS_H +#define _JOBS_H + +#include "BeUtils.h" +#include "ObjectList.h" +#include +#include +#include +#include +#include + +enum JobStatus { + kWaiting, + kProcessing, + kFailed, + kUnknown, +}; + +class Printer; + +class Job : public Object { +private: + BHandler* fHandler; + BString fName; + node_ref fNode; + entry_ref fEntry; + JobStatus fStatus; + long fTime; + Printer* fPrinter; + + void UpdateStatus(const char* status); + void UpdateStatusAttribute(const char* status); + +public: + Job(const BEntry& entry, BHandler* handler); + + status_t InitCheck() const { return fTime >= 0 ? B_OK : B_ERROR; } + + // accessors + const BString& Name() const { return fName; } + JobStatus Status() const { return fStatus; } + long Time() const { return fTime; } + const node_ref& NodeRef() const { return fNode; } + const entry_ref& EntryRef() const { return fEntry; } + bool IsWaiting() const { return fStatus == kWaiting; } + Printer* GetPrinter() const { return fPrinter; } + + // modification + void SetPrinter(Printer* p) { fPrinter = p; } + void SetStatus(JobStatus s, bool writeToNode = true); + void UpdateAttribute(); + void Remove(); + + void StartNodeWatching(); + void StopNodeWatching(); +}; + + +class Folder : public BHandler { + typedef BHandler inherited; + +private: + BDirectory fSpoolDir; + BObjectList fJobs; + + static int AscendingByTime(const Job* a, const Job* b); + + bool AddJob(BEntry& entry); + Job* Find(ino_t node); + + // node monitor handling + void EntryCreated(BMessage* msg); + void EntryRemoved(BMessage* msg); + void AttributeChanged(BMessage* msg); + void HandleNodeMonitorMessage(BMessage* msg); + + void NotifyPrinter(); + + void SetupJobList(); + +public: + Folder(const BDirectory& spoolDir); + ~Folder(); + + void MessageReceived(BMessage* msg); + + // Caller is responsible to set the status of the job appropriately + // and to release the object when done + Job* GetNextJob(); +}; +#endif diff --git a/src/servers/print/PrintServer.FileTypes.rsrc b/src/servers/print/PrintServer.FileTypes.rsrc index ac9c4b6473bd4fe44576c939689b1d417a1d2574..7749f73064af7cad169fa70953abe5e844ebd957 100644 GIT binary patch delta 185 zcmeyU@KIsH1zQ#d2-v{Rz_5Y|!j9kq(ol&AJ|LSBD$dWqAO&GE6am>nn|T=*v$29y zGEP?H6yE%SeG2>J4eUCcZUF&~AWe*ueFbDV!=OB-$+!5`7?~$C3aB!&OjZ|=g`HF2AZeE08b1 o;NFn>v@E;1?pgPzlPvn>3&}UMc0aVTa0Q9&dcK`qY diff --git a/src/servers/print/PrintServerApp.R5.cpp b/src/servers/print/PrintServerApp.R5.cpp index b8029a0e65..79674b20b7 100644 --- a/src/servers/print/PrintServerApp.R5.cpp +++ b/src/servers/print/PrintServerApp.R5.cpp @@ -6,12 +6,9 @@ // The print_server manages the communication between applications and the // printer and transport drivers. // -// -// -// TODO: -// Handle spooled jobs at startup -// Handle printer status (asked to print a spooled job but printer busy) -// +// Authors +// Ithamar R. Adema +// Michael Pfeiffer // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written @@ -53,12 +50,16 @@ struct AsyncThreadParams { Printer* printer; - BMessage message; + BMessage* message; AsyncThreadParams(Printer* p, BMessage* m) : printer(p) - , message(*m) + , message(m) { } + + ~AsyncThreadParams() { + delete message; + } }; status_t PrintServerApp::async_thread(void* data) @@ -66,7 +67,7 @@ status_t PrintServerApp::async_thread(void* data) AsyncThreadParams* p = (AsyncThreadParams*)data; Printer* printer = p->printer; - BMessage* msg = &p->message; + BMessage* msg = p->message; switch (msg->what) { // Handle showing the page config dialog @@ -131,10 +132,6 @@ void PrintServerApp::AsyncHandleMessage(BMessage* msg) void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg) { - printf("PrintServerApp::Handle_BeOSR5_Message\n"); - msg->PrintToStream(); - fflush(stdout); - switch(msg->what) { // Get currently selected printer case PSRV_GET_ACTIVE_PRINTER: { @@ -186,18 +183,12 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg) case PSRV_SHOW_PAGE_SETUP: case PSRV_SHOW_PRINT_SETUP: - AsyncHandleMessage(msg); + AsyncHandleMessage(DetachCurrentMessage()); break; // Tell printer addon to print a spooled job - case PSRV_PRINT_SPOOLED_JOB: { - BString name, jobpath; - if (msg->FindString("Spool File",&jobpath) == B_OK && - msg->FindString("JobName", &name) == B_OK) { - // Handle the spooled job - HandleSpooledJob(name.String(), jobpath.String()); - } - } + case PSRV_PRINT_SPOOLED_JOB: + HandleSpooledJobs(); break; } } diff --git a/src/servers/print/PrintServerApp.Scripting.cpp b/src/servers/print/PrintServerApp.Scripting.cpp index 33d9cb25d9..b5484c493f 100644 --- a/src/servers/print/PrintServerApp.Scripting.cpp +++ b/src/servers/print/PrintServerApp.Scripting.cpp @@ -6,6 +6,8 @@ // The print_server manages the communication between applications and the // printer and transport drivers. // +// Author +// Ithamar R. Adema // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written @@ -105,7 +107,7 @@ PrintServerApp::HandleScriptingCommand(BMessage* msg) case B_DELETE_PROPERTY: { Printer* printer = GetPrinterFromSpecifier(&spec); status_t rc = B_BAD_VALUE; - + if (printer != NULL && (rc=printer->Remove()) == B_OK) { printer->Release(); } diff --git a/src/servers/print/PrintServerApp.cpp b/src/servers/print/PrintServerApp.cpp index 09b8cdeba3..8b85587ffb 100644 --- a/src/servers/print/PrintServerApp.cpp +++ b/src/servers/print/PrintServerApp.cpp @@ -6,12 +6,9 @@ // The print_server manages the communication between applications and the // printer and transport drivers. // -// -// -// TODO: -// Handle spooled jobs at startup -// Handle printer status (asked to print a spooled job but printer busy) -// +// Authors +// Ithamar R. Adema +// Michael Pfeiffer // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written @@ -45,23 +42,26 @@ #include "pr_server.h" // BeOS API -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include #include +#include +#include #include +#include +#include +#include +#include +#include +#include // ANSI C #include //for printf #include //for unlink +BLocker *gLock = NULL; + // --------------------------------------------------------------- typedef struct _printer_data { char defaultPrinterName[256]; @@ -83,16 +83,17 @@ typedef char* (*add_printer_func_t)(const char* printer_name); int main() { + gLock = new BLocker(); // Create our application object status_t rc = B_OK; - new PrintServerApp(&rc); + PrintServerApp print_server(&rc); // If all went fine, let's start it if (rc == B_OK) { - be_app->Run(); + print_server.Run(); } - delete be_app; + delete gLock; return rc; } @@ -111,10 +112,14 @@ main() PrintServerApp::PrintServerApp(status_t* err) : Inherited(PSRV_SIGNATURE_TYPE, err), fSelectedIconMini(BRect(0,0,B_MINI_ICON-1,B_MINI_ICON-1), B_CMAP8), - fSelectedIconLarge(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8) + fSelectedIconLarge(BRect(0,0,B_LARGE_ICON-1,B_LARGE_ICON-1), B_CMAP8), + fNumberOfPrinters(0), + fNoPrinterAvailable(0) { // If our superclass initialized ok if (*err == B_OK) { + fNoPrinterAvailable = create_sem(1, ""); + // let us try as well SetupPrinterList(); RetrieveDefaultPrinter(); @@ -123,6 +128,9 @@ PrintServerApp::PrintServerApp(status_t* err) BMimeType type(PRNT_SIGNATURE_TYPE); type.GetIcon(&fSelectedIconMini, B_MINI_ICON); type.GetIcon(&fSelectedIconLarge, B_LARGE_ICON); + + // Start handling of spooled files + PostMessage(PSRV_PRINT_SPOOLED_JOB); } } @@ -141,11 +149,69 @@ bool PrintServerApp::QuitRequested() ::watch_node(&nref, B_STOP_WATCHING, be_app_messenger); } } + + // Release all printers + Printer* printer; + while ((printer = Printer::At(0)) != NULL) { + Printer::Remove(printer); + printer->AbortPrintThread(); + printer->Release(); + } + + // Wait for printers + if (fNoPrinterAvailable > 0) { + acquire_sem(fNoPrinterAvailable); + delete_sem(fNoPrinterAvailable); + fNoPrinterAvailable = 0; + } } return rc; } + +void PrintServerApp::RegisterPrinter(BDirectory* printer) { + BString transport, address, connection; + + printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport); + printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address); + printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection); + + BAutolock lock(gLock); + if (lock.IsLocked()) { + Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String()); + new Printer(printer, r); + if (fNumberOfPrinters == 0) acquire_sem(fNoPrinterAvailable); + fNumberOfPrinters ++; + } +} + + +void PrintServerApp::NotifyPrinterDeletion(Resource* res) { + BAutolock lock(gLock); + if (lock.IsLocked()) { + fNumberOfPrinters --; + fResourceManager.Free(res); + if (fNumberOfPrinters == 0) release_sem(fNoPrinterAvailable); + } +} + +void PrintServerApp::HandleRemovedPrinter(BMessage* msg) { + int32 opcode; + dev_t device; + ino_t node; + Printer* printer; + if (msg->FindInt32("opcode", &opcode) == B_OK && opcode == B_ENTRY_REMOVED && + msg->FindInt32("device", &device) == B_OK && + msg->FindInt64("node", &node) == B_OK && + (printer = Printer::Find(device, node)) != NULL) { + if (printer == fDefaultPrinter) fDefaultPrinter = NULL; + Printer::Remove(printer); + printer->Release(); + } +} + + // --------------------------------------------------------------- // SetupPrinterList // @@ -176,14 +242,14 @@ status_t PrintServerApp::SetupPrinterList() // If the entry is a directory if (entry.IsDirectory()) { // Check it's Mime type for a spool director - BNode node(&entry); + BDirectory node(&entry); BNodeInfo info(&node); char buffer[256]; if (info.GetType(buffer) == B_OK && strcmp(buffer, PSRV_PRINTER_FILETYPE) == 0) { // Yes, it is a printer definition node - new Printer(&node); + RegisterPrinter(&node); } } } @@ -234,10 +300,12 @@ PrintServerApp::MessageReceived(BMessage* msg) case B_EXECUTE_PROPERTY: HandleScriptingCommand(msg); break; + + case B_NODE_MONITOR: + HandleRemovedPrinter(msg); + break; default: - printf("PrintServerApp::MessageReceived(): "); - msg->PrintToStream(); Inherited::MessageReceived(msg); } } @@ -298,10 +366,12 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName, // call the function and check its result if ((*func)(printerName) == NULL) { BEntry entry; - if (printer.GetEntry(&entry) == B_OK && entry.GetPath(&path) == B_OK) { + if (printer.GetEntry(&entry) == B_OK) { // Delete the printer if function failed - ::rmdir(path.Path()); + entry.Remove(); } + } else { + RegisterPrinter(&printer); } } @@ -360,55 +430,19 @@ PrintServerApp::SelectPrinter(const char* printerName) } // --------------------------------------------------------------- -// HandleSpooledJob(const char* jobname, const char* filepath) +// HandleSpooledJobs() // -// Handles calling the printer driver for printing a spooled job. +// Handles calling the printer drivers for printing a spooled job. // -// Parameters: -// msg - A copy of the message received, will be accessible -// to the printer driver for reading job config -// details. -// Returns: -// BMessage containing new job data, or NULL pointer if not -// successfull. // --------------------------------------------------------------- -status_t -PrintServerApp::HandleSpooledJob(const char* jobname, const char* filepath) +void +PrintServerApp::HandleSpooledJobs() { - BFile spoolFile(filepath, B_READ_ONLY); - print_file_header header; - BString driverName; - BMessage settings; - Printer* printer; - status_t rc; - BPath path; - - // Open the spool file - if ((rc=spoolFile.InitCheck()) == B_OK) { - // Read header from filestream - spoolFile.Seek(0, SEEK_SET); - spoolFile.Read(&header, sizeof(header)); - - // Get the printer settings - settings.Unflatten(&spoolFile); - - // Get name of printer from settings - const char* printerName; - if ((rc=settings.FindString("current_printer", &printerName)) == B_OK) { - // Find printer definition for this printer - if ((printer=Printer::Find(printerName)) != NULL) { - // and tell the printer to print the spooled job - printer->PrintSpooledJob(&spoolFile, settings); - } - } - - // Remove spool file if printing was successfull. - if (rc == B_OK) { - ::unlink(filepath); - } + const int n = Printer::CountPrinters(); + for (int i = 0; i < n; i ++) { + Printer* printer = Printer::At(i); + printer->HandleSpooledJob(); } - - return rc; } // --------------------------------------------------------------- diff --git a/src/servers/print/PrintServerApp.h b/src/servers/print/PrintServerApp.h index f2b8e874a3..5f7623cbb3 100644 --- a/src/servers/print/PrintServerApp.h +++ b/src/servers/print/PrintServerApp.h @@ -6,6 +6,9 @@ // The print_server manages the communication between applications and the // printer and transport drivers. // +// Authors +// Ithamar R. Adema +// Michael Pfeiffer // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written @@ -35,12 +38,18 @@ #ifndef PRINTSERVERAPP_H #define PRINTSERVERAPP_H +#include "ResourceManager.h" + class PrintServerApp; #include #include +#include #include +// global BLocker for synchronisation +extern BLocker* gLock; + /*****************************************************************************/ // PrintServerApp // @@ -52,8 +61,10 @@ class PrintServerApp : public BApplication typedef BApplication Inherited; public: PrintServerApp(status_t* err); + bool QuitRequested(); void MessageReceived(BMessage* msg); + void NotifyPrinterDeletion(Resource* res); // Scripting support, see PrintServerApp.Scripting.cpp status_t GetSupportedSuites(BMessage* msg); @@ -64,12 +75,15 @@ public: private: status_t SetupPrinterList(); - status_t HandleSpooledJob(const char* jobname, const char* filepath); + void HandleSpooledJobs(); status_t SelectPrinter(const char* printerName); status_t CreatePrinter( const char* printerName, const char* driverName, const char* connection, const char* transportName, const char* transportPath); + + void RegisterPrinter(BDirectory* node); + void HandleRemovedPrinter(BMessage* msg); status_t StoreDefaultPrinter(); status_t RetrieveDefaultPrinter(); @@ -77,14 +91,18 @@ private: status_t FindPrinterNode(const char* name, BNode& node); status_t FindPrinterDriver(const char* name, BPath& outPath); + ResourceManager fResourceManager; Printer* fDefaultPrinter; BBitmap fSelectedIconMini; BBitmap fSelectedIconLarge; + int fNumberOfPrinters; + sem_id fNoPrinterAvailable; // "Classic" BeOS R5 support, see PrintServerApp.R5.cpp static status_t async_thread(void* data); void AsyncHandleMessage(BMessage* msg); void Handle_BeOSR5_Message(BMessage* msg); + }; #endif diff --git a/src/servers/print/Printer.Scripting.cpp b/src/servers/print/Printer.Scripting.cpp index fe77c088cc..1aab6fb2c0 100644 --- a/src/servers/print/Printer.Scripting.cpp +++ b/src/servers/print/Printer.Scripting.cpp @@ -1,3 +1,39 @@ +/*****************************************************************************/ +// print_server Background Application. +// +// Version: 1.0.0d1 +// +// The print_server manages the communication between applications and the +// printer and transport drivers. +// +// Author +// Ithamar R. Adema +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2001 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + #include "Printer.h" diff --git a/src/servers/print/Printer.cpp b/src/servers/print/Printer.cpp index 9598a444dd..da58df4368 100644 --- a/src/servers/print/Printer.cpp +++ b/src/servers/print/Printer.cpp @@ -6,18 +6,15 @@ // The print_server manages the communication between applications and the // printer and transport drivers. // -// -// -// TODO: -// Handle spooled jobs at startup -// Handle printer status (asked to print a spooled job but printer busy) -// +// Authors +// Ithamar R. Adema +// Michael Pfeiffer // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001,2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -42,13 +39,21 @@ #include "pr_server.h" #include "BeUtils.h" +#include "PrintServerApp.h" + + // posix +#include +#include +#include // BeOS API #include +#include #include +#include #include -#include -#include +#include +#include // --------------------------------------------------------------- typedef BMessage* (*config_func_t)(BNode*, const BMessage*); @@ -84,9 +89,18 @@ Printer* Printer::Find(const BString& name) return NULL; } -int32 Printer::CountPrinters() +Printer* Printer::Find(dev_t dev, ino_t node) { - return sPrinters.CountItems(); + // Look in list to find printer definition + for (int32 idx=0; idx < sPrinters.CountItems(); idx++) { + Printer* printer = sPrinters.ItemAt(idx); + node_ref ref; + printer->fNode.GetNodeRef(&ref); + if (ref.device == dev && ref.node == node) return printer; + } + + // None found, so return NULL + return NULL; } Printer* Printer::At(int32 idx) @@ -94,6 +108,15 @@ Printer* Printer::At(int32 idx) return sPrinters.ItemAt(idx); } +void Printer::Remove(Printer* printer) { + sPrinters.RemoveItem(printer); +} + +int32 Printer::CountPrinters() +{ + return sPrinters.CountItems(); +} + // --------------------------------------------------------------- // Printer [constructor] // @@ -106,15 +129,22 @@ Printer* Printer::At(int32 idx) // Returns: // none. // --------------------------------------------------------------- -Printer::Printer(const BNode* node) +Printer::Printer(const BDirectory* node, Resource* res) : Inherited(B_EMPTY_STRING), + fFolder(*node), + fResource(res), fNode(*node), - fRefCount(1) + fSinglePrintThread(true), + fJob(NULL), + fProcessing(0), + fAbort(false) { // Set our name to the name of the passed node BString name; fNode.ReadAttrString(PSRV_PRINTER_ATTR_PRT_NAME, &name); SetName(name.String()); + + if (name == "Preview") fSinglePrintThread = false; // Add us to the global list of known printer definitions sPrinters.AddItem(this); @@ -123,19 +153,7 @@ Printer::Printer(const BNode* node) Printer::~Printer() { - sPrinters.RemoveItem(this); - be_app->RemoveHandler(this); -} - -void Printer::Acquire() -{ - fRefCount ++; -} - -void Printer::Release() -{ - fRefCount --; - if (fRefCount == 0) delete this; + ((PrintServerApp*)be_app)->NotifyPrinterDeletion(fResource); } status_t Printer::Remove() @@ -144,6 +162,8 @@ status_t Printer::Remove() BPath path; if ((rc=::find_directory(B_USER_PRINTERS_DIRECTORY, &path)) == B_OK) { + sPrinters.RemoveItem(this); + be_app->RemoveHandler(this); path.Append(Name()); rc = rmdir(path.Path()); } @@ -242,29 +262,11 @@ status_t Printer::ConfigureJob(BMessage& settings) if ((rc=get_image_symbol(id, "config_job", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) { // call the function and check its result BMessage* new_settings = (*func)(&fNode, &settings); - if (new_settings != NULL && new_settings->what != 'baad') + if ((new_settings != NULL) && (new_settings->what != 'baad')) settings = *new_settings; - } - - ::unload_add_on(id); - } - - return rc; -} - -status_t Printer::PrintSpooledJob(BFile* spoolFile, const BMessage& settings) -{ - take_job_func_t func; - image_id id; - status_t rc; - - if ((rc=LoadPrinterAddon(id)) == B_OK) { - // Addon was loaded, so try and get the take_job symbol - if ((rc=get_image_symbol(id, "take_job", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) { - // call the function and check its result - BMessage* result = (*func)(spoolFile, &fNode, &settings); - if (result == NULL || result->what == 'baad') + else rc = B_ERROR; + delete new_settings; } ::unload_add_on(id); @@ -273,6 +275,23 @@ status_t Printer::PrintSpooledJob(BFile* spoolFile, const BMessage& settings) return rc; } + +// --------------------------------------------------------------- +// HandleSpooledJobs +// +// Print spooled jobs in a new thread. +// --------------------------------------------------------------- +void Printer::HandleSpooledJob() { + BAutolock lock(gLock); + if (lock.IsLocked() && (!fSinglePrintThread || fProcessing == 0) && FindSpooledJob()) { + StartPrintThread(); + } +} + +void Printer::AbortPrintThread() { + fAbort = true; +} + // --------------------------------------------------------------- // LoadPrinterAddon // @@ -310,6 +329,10 @@ status_t Printer::LoadPrinterAddon(image_id& id) void Printer::MessageReceived(BMessage* msg) { + printf("Printer::MessageReceived(): "); + msg->PrintToStream(); + + switch(msg->what) { case B_GET_PROPERTY: case B_SET_PROPERTY: @@ -324,3 +347,84 @@ void Printer::MessageReceived(BMessage* msg) Inherited::MessageReceived(msg); } } + +bool Printer::FindSpooledJob() { + fJob = fFolder.GetNextJob(); + if (fJob) fJob->SetPrinter(this); + return fJob; +} + +void Printer::CloseJob() { + fJob->Release(); +} + +status_t Printer::PrintSpooledJob(BFile* spoolFile, const BMessage& settings) +{ + take_job_func_t func; + image_id id; + status_t rc; + + if ((rc=LoadPrinterAddon(id)) == B_OK) { + // Addon was loaded, so try and get the take_job symbol + if ((rc=get_image_symbol(id, "take_job", B_SYMBOL_TYPE_TEXT, (void**)&func)) == B_OK) { + // call the function and check its result + BMessage* result = (*func)(spoolFile, &fNode, &settings); + if (result == NULL || result->what == 'baad') + rc = B_ERROR; + } + + ::unload_add_on(id); + } + + return rc; +} + +void Printer::PrintThread(Job* job) { + fResource->Lock(); + if (!fAbort) { + BFile jobFile(&job->EntryRef(), B_READ_ONLY); + print_file_header header; + BMessage settings; + + // Read header from filestream + jobFile.Seek(0, SEEK_SET); + jobFile.Read(&header, sizeof(header)); + + // Get the printer settings + settings.Unflatten(&jobFile); + + // and tell the printer to print the spooled job + if (PrintSpooledJob(&jobFile, settings) == B_OK) { + // Remove spool file if printing was successfull. + job->Remove(); + } else { + job->SetStatus(kFailed); + } + } else { + job->SetStatus(kFailed); + } + fResource->Unlock(); + job->Release(); + atomic_add(&fProcessing, -1); + Release(); + be_app_messenger.SendMessage(PSRV_PRINT_SPOOLED_JOB); +} + +status_t Printer::print_thread(void* data) { + Job* job = static_cast(data); + job->GetPrinter()->PrintThread(job); + return 0; +} + +status_t Printer::StartPrintThread() { + Acquire(); + thread_id tid = spawn_thread(print_thread, "print", B_NORMAL_PRIORITY, (void*)fJob); + if (tid > 0) { + fJob->SetStatus(kProcessing); + atomic_add(&fProcessing, 1); + resume_thread(tid); + } else { + CloseJob(); Release(); + } +} + diff --git a/src/servers/print/Printer.h b/src/servers/print/Printer.h index 18f5a33361..53e95fba1a 100644 --- a/src/servers/print/Printer.h +++ b/src/servers/print/Printer.h @@ -5,13 +5,10 @@ // // The print_server manages the communication between applications and the // printer and transport drivers. -// -// -// -// TODO: -// Handle spooled jobs at startup -// Handle printer status (asked to print a spooled job but printer busy) // +// Authors +// Ithamar R. Adema +// Michael Pfeiffer // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written @@ -43,11 +40,17 @@ class Printer; +#include "BeUtils.h" +#include "ResourceManager.h" +#include "Jobs.h" + // BeOS API +#include #include -#include #include -#include +#include +#include +#include // OpenTracker shared sources #include "ObjectList.h" @@ -58,27 +61,27 @@ class Printer; // This class represents one printer definition. It is manages all actions & // data related to that printer. /*****************************************************************************/ -class Printer : public BHandler +class Printer : public BHandler, public Object { typedef BHandler Inherited; public: - Printer(const BNode* node); + Printer(const BDirectory* node, Resource* res); ~Printer(); - void Acquire(); - void Release(); - // Static helper functions static Printer* Find(const BString& name); + static Printer* Find(dev_t device, ino_t node); static Printer* At(int32 idx); + static void Remove(Printer* printer); static int32 CountPrinters(); status_t Remove(); status_t ConfigurePrinter(); status_t ConfigureJob(BMessage& ioSettings); status_t ConfigurePage(BMessage& ioSettings); - status_t PrintSpooledJob(BFile* spoolFile, const BMessage& settings); + void HandleSpooledJob(); + void AbortPrintThread(); void MessageReceived(BMessage* msg); @@ -90,10 +93,22 @@ public: private: status_t LoadPrinterAddon(image_id& id); - BNode fNode; - int32 fRefCount; + Folder fFolder; + Resource* fResource; + BDirectory fNode; + bool fSinglePrintThread; + Job* fJob; + volatile vint32 fProcessing; + bool fAbort; static BObjectList sPrinters; + + bool FindSpooledJob(); + void CloseJob(); + status_t PrintSpooledJob(BFile* spoolFile, const BMessage& settings); + void PrintThread(Job* job); + static status_t print_thread(void* data); + status_t StartPrintThread(); }; #endif diff --git a/src/servers/print/ResourceManager.cpp b/src/servers/print/ResourceManager.cpp new file mode 100644 index 0000000000..ee9ae48161 --- /dev/null +++ b/src/servers/print/ResourceManager.cpp @@ -0,0 +1,104 @@ +/*****************************************************************************/ +// ResourceManager +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + +#include "ResourceManager.h" + +#include +#include + +Resource::Resource(const char* transport, const char* address, const char* connection) + : fTransport(transport) + , fTransportAddress(address) + , fConnection(connection) + , fResourceAvailable(0) + +{ + if (NeedsLocking()) { + fResourceAvailable = create_sem(1, "resource"); + } +} + +Resource::~Resource() { + if (fResourceAvailable > 0) delete_sem(fResourceAvailable); +} + +bool Resource::NeedsLocking() { + return !(fTransport == "Print to File" || fTransport == "NONE"); +} + +bool Resource::Equals(const char* transport, const char* address, const char* connection) { + return fTransport == transport && + fTransportAddress == address && + fConnection == connection; +} + +bool Resource::Lock() { + if (fResourceAvailable > 0) { + return acquire_sem(fResourceAvailable) == B_NO_ERROR; + } + return true; +} + +void Resource::Unlock() { + if (fResourceAvailable > 0) { + release_sem(fResourceAvailable); + } +} + +ResourceManager::~ResourceManager() { + ASSERT(fResources.CountItems() == 0); +} + +Resource* ResourceManager::Find(const char* transport, const char* address, const char* connection) { + for (int i = 0; i < fResources.CountItems(); i ++) { + Resource* r = fResources.ItemAt(i); + if (r->Equals(transport, address, connection)) return r; + } + return NULL; +} + +Resource* ResourceManager::Allocate(const char* transport, const char* address, const char* connection) { + Resource* r = Find(transport, address, connection); + if (r == NULL) { + r = new Resource(transport, address, connection); + fResources.AddItem(r); + } else { + r->Acquire(); + } + return r; +} + + +void ResourceManager::Free(Resource* r) { + if (r->Release()) { + fResources.RemoveItem(r); + } +} diff --git a/src/servers/print/ResourceManager.h b/src/servers/print/ResourceManager.h new file mode 100644 index 0000000000..6f0992d773 --- /dev/null +++ b/src/servers/print/ResourceManager.h @@ -0,0 +1,78 @@ +/*****************************************************************************/ +// ResourceManager +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + + +#ifndef RESOURCE_MANAGER_H +#define RESOURCE_MANAGER_H + +#include "ObjectList.h" + +#include +#include + +#include "BeUtils.h" + +class Resource : public Object { +private: + BString fTransport; + BString fTransportAddress; + BString fConnection; + sem_id fResourceAvailable; + + bool NeedsLocking(); + + +public: + Resource(const char* transport, const char* address, const char* connection); + ~Resource(); + + bool Equals(const char* transport, const char* address, const char* connection); + + const BString& Transport() const { return fTransport; } + + bool Lock(); + void Unlock(); +}; + +class ResourceManager { +private: + BObjectList fResources; + + Resource* Find(const char* transport, const char* address, const char* connection); + +public: + ~ResourceManager(); + + Resource* Allocate(const char* transport, const char* address, const char* connection); + void Free(Resource* r); +}; + +#endif