106 lines
4.5 KiB
Plaintext
106 lines
4.5 KiB
Plaintext
MACPRINT SPOOLER CDD
|
|
|
|
|
|
|
|
Design Goals:
|
|
|
|
MacPrint is ported from the OS/2 implementation. The primary design
|
|
goal is to simplify the porting process as much as possible. The
|
|
original structure of MacPrint was retained and modified only where
|
|
necessary. There are 3 main areas of modification:
|
|
|
|
* configuration
|
|
* synchronization
|
|
* removal of the despooler component
|
|
* support for cached dictionaries
|
|
|
|
configuration changes -
|
|
|
|
Where the OS/2 implementation depended on being able to determine
|
|
at service start time the configuration for all possible shared
|
|
print queues (this was read from lanman.ini), the NT implementation
|
|
allows for the dynamic addition and removal of printer objects
|
|
without specifying configuration information in a data file. This
|
|
forced the modification of the main queue list structure to be
|
|
a single linked list instead of an array. In the NT implementation,
|
|
there is now a single data structure for NT printer objects, and
|
|
being in this structure implies the existence of a validly configured
|
|
NT Printer Object.
|
|
|
|
All of the code to read and parse configuration information from
|
|
LANMAN.INI at service start time was removed and replaced by code
|
|
to get configuration information from the EnumPrinters() API as new
|
|
printers are discovered.
|
|
|
|
|
|
synchronization changes -
|
|
|
|
NT provides a more robust synchronization mechanism than OS/2.
|
|
WaitForMultipleObjects() actually works correctly under NT, and
|
|
it is possible to wait on objects besides semaphores. Mutual
|
|
exclusion to data is achieved through critical sections as opposed
|
|
to mutexes or semaphores. Critical sections require fewer resources
|
|
than either, but can only be shared between threads of the same
|
|
process. Events are used to process jobs asynchronously. Instead
|
|
of clearing a semaphore when a read or open occurs, an event is
|
|
signaled. Semaphores in NT are used as a gating mechanism,
|
|
and are not designed to be used as a signaling mechanism. Syncronization
|
|
with the termination of threads is achieved by waiting on the thread
|
|
object as opposed to waiting on an event that the thread signals
|
|
just before it terminates.
|
|
|
|
|
|
removal of the despooler -
|
|
|
|
The spooler and despooler were somewhat integrated in the OS/2
|
|
implementation - especially with regards to configuration information.
|
|
Data structures pertinent to the despooler only were removed, and
|
|
the configuration routines are no longer contained in a DLL shared
|
|
by the spooler and despooler. The only connection between the two
|
|
components is now through a PostScript comment that is included by
|
|
the spooler to indicate if ctrl-d's should be stripped by the
|
|
despooler.
|
|
|
|
|
|
support for cached dictionaries -
|
|
|
|
As the caching of PostScript dictionaries achieved only modest performance
|
|
improvements at best, and since it added significant complexity to the
|
|
code, support for cached dictionaries will most likely be removed in
|
|
the NT implementation. If at coding time it becomes clear that more
|
|
work is involved to remove the feature than to port it, it may stay
|
|
in.
|
|
|
|
|
|
|
|
|
|
Thread/Process Structure:
|
|
|
|
MacPrint is an NT Service, hence it follows the NT Service Model. main()
|
|
is the service control dispatcher for the MacPrint service. This thread
|
|
is used by the NT Service Controller to communicate with the MacPrint
|
|
Service.
|
|
|
|
MacPrintMain() is the main thread for MacPrint. It is responsible for
|
|
monitoring the NT Print Manager for configuration changes (creation
|
|
and removal of printer objects) and for starting and stopping threads
|
|
to manage each NT Printer Object. Essentially, MacPrintMain polls
|
|
until a service stop request is received. While polling, it enumerates
|
|
printers from the NT Print Manager and either creates a control thread
|
|
for a newly discovered printer or terminates the control thread for
|
|
each printer no longer configured.
|
|
|
|
QueueServiceThread() is the thread for each active NT Printer Object.
|
|
This thread listens for jobs directed to the NT printer and processes
|
|
the job. One thread supports multiple jobs for the printer. This is
|
|
done by using two events per queue - ReadEvent and OpenEvent. The
|
|
PAP API have the property that they take an address to store a completion
|
|
code when the event completes, and this address is specified to be in
|
|
a per job data structure. The event is common for all jobs in the
|
|
queue. When a particular event is signaled, the list of pending jobs
|
|
in that queue is walked to find one that is in the correct state
|
|
(read_pending or open_pending) and that has it's completion code set.
|
|
The event is processed for that job, and the job is moved to the end
|
|
of the list so that events for jobs are processed in round-robin
|
|
order.
|