1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
3<html>
4  <head>
5    <meta name="generator" content="HTML Tidy, see www.w3.org">
6    <title>Load Balance Queues and Printer Pools</title>
7    <meta name="GENERATOR" content=
8    "Modular DocBook HTML Stylesheet Version 1.7">
9    <link rel="HOME" title=" LPRng Reference Manual" href=
10    "index.htm">
11    <link rel="UP" title="Print Spooling Tutorial " href=
12    "tutorial.htm">
13    <link rel="PREVIOUS" title="Holding and Releasing Jobs" href=
14    "x3515.htm">
15    <link rel="NEXT" title="Routing Jobs To Print Queues" href=
16    "x3694.htm">
17  </head>
18
19  <body class="SECT1" bgcolor="#FFFFFF" text="#000000" link=
20  "#0000FF" vlink="#840084" alink="#0000FF">
21    <div class="NAVHEADER">
22      <table summary="Header navigation table" width="100%" border=
23      "0" cellpadding="0" cellspacing="0">
24        <tr>
25          <th colspan="3" align="center">LPRng Reference Manual: 5
26          Sep 2003 (For LPRng-3.8.22)</th>
27        </tr>
28
29        <tr>
30          <td width="10%" align="left" valign="bottom"><a href=
31          "x3515.htm" accesskey="P">Prev</a></td>
32
33          <td width="80%" align="center" valign="bottom">Chapter 4.
34          Print Spooling Tutorial</td>
35
36          <td width="10%" align="right" valign="bottom"><a href=
37          "x3694.htm" accesskey="N">Next</a></td>
38        </tr>
39      </table>
40      <hr align="LEFT" width="100%">
41    </div>
42
43    <div class="SECT1">
44      <h1 class="SECT1"><a name="AEN3593">4.17. Load Balance Queues
45      and Printer Pools</a></h1>
46
47      <p>A Load Balance Queue provides a way to use multiple
48      printers for a single print queue. All jobs are normally sent
49      to the main or load balance queue which then dispatches the
50      jobs to <span class="emphasis"><i class=
51      "EMPHASIS">server</i></span> queues or printers that do the
52      actual printing as they become available. You can also send
53      jobs to the individual server printers if they have special
54      processing or setups required for a particular job. Because
55      all of the server printers are shared by the load balance
56      queue, they are said to be in a <span class="emphasis"><i
57      class="EMPHASIS">printer pool</i></span>.</p>
58
59      <p>Edit the printcap file so it have the contents indicated
60      below, create the <tt class="FILENAME">/tmp/lp2</tt> and <tt
61      class="FILENAME">/tmp/lp3</tt> files with <var class=
62      "LITERAL">0777</var> permissions, use <tt class=
63      "COMMAND">checkpc -f</tt> to check the printcap, and then use
64      <tt class="COMMAND">lpc reread</tt> to restart the <b class=
65      "APPLICATION">lpd</b> server.</p>
66
67      <div class="INFORMALEXAMPLE">
68        <a name="AEN3605"></a>
69<pre class="SCREEN">
70    # printcap
71    lp:force_localhost
72    lp:server
73      :sd=/var/spool/lpd/%P
74      :sv=lp2,lp3
75    lp2:force_localhost
76    lp2:server
77      :ss=lp
78      :sd=/var/spool/lpd/%P
79      :lp=/tmp/lp2
80    lp3:force_localhost
81    lp3:server
82      :ss=lp
83      :sd=/var/spool/lpd/%P
84      :lp=/tmp/lp2
85</pre>
86      </div>
87      <br>
88      <br>
89
90      <p>The <var class="LITERAL">:sv=...</var> option flags the
91      queue as a load balance queue and lists the queues that are
92      used for load balancing. The <var class=
93      "LITERAL">:ss=...</var> option flags the queue as a server
94      for a load balance queue and specifies the name of the load
95      balance queue. When a job is sent to the load balance queue
96      the <b class="APPLICATION">lpd</b> server checks to see which
97      server queues are available and then the first one to become
98      available.</p>
99
100      <p>Execute the following commands to print the <tt class=
101      "FILENAME">/tmp/hi</tt> file and observe the results:</p>
102
103      <div class="INFORMALEXAMPLE">
104        <a name="AEN3613"></a>
105<pre class="SCREEN">
106    <samp class="PROMPT">h4: {274} %</samp> <kbd class=
107"USERINPUT">lpq</kbd>
108    Printer: lp@h4  (subservers lp2, lp3)
109     Queue: no printable jobs in queue
110     Status: job 'papowell@h4+42' removed at 07:29:57.924
111    Server Printer: lp2@h4  (serving lp)
112     Queue: no printable jobs in queue
113    Server Printer: lp3@h4  (serving lp)
114     Queue: no printable jobs in queue
115    <samp class="PROMPT">h4: {275} %</samp> <kbd class=
116"USERINPUT">lpr /tmp/hi</kbd>
117    <samp class="PROMPT">h4: {276} %</samp> <kbd class=
118"USERINPUT">lpq</kbd>
119    Printer: lp@h4  (subservers lp2, lp3)
120     Queue: 1 printable job
121     Server: pid 4063 active
122     Status: waiting for subserver to finish at 07:31:08.074
123     Rank   Owner/ID           Class Job Files        Size Time
124    1      papowell@h4+62        A    62 /tmp/hi         3 07:31:07
125    Server Printer: lp2@h4  (serving lp)
126     Queue: no printable jobs in queue
127    Server Printer: lp3@h4  (serving lp)
128     Queue: no printable jobs in queue
129    <samp class="PROMPT">h4: {277} %</samp> <kbd class=
130"USERINPUT">lpq</kbd>
131    Printer: lp@h4  (subservers lp2, lp3)
132     Queue: no printable jobs in queue
133     Status: no more jobs to process in load balance queue at 07:31:12.317
134    Server Printer: lp2@h4  (serving lp)
135     Queue: no printable jobs in queue
136    Server Printer: lp3@h4  (serving lp)
137     Queue: no printable jobs in queue
138     Status: job 'papowell@h4+62' removed at 07:31:10.311
139</pre>
140      </div>
141      <br>
142      <br>
143
144      <p>The first <b class="APPLICATION">lpq</b> command shows how
145      the status is displayed for a load balance queue - the queue
146      and its server queues are shown as well. Next, we use <b
147      class="APPLICATION">lpr</b> to print a job (job id <var
148      class="LITERAL">papowell@h4+62</var>). We then use a couple
149      of <b class="APPLICATION">lpq</b> commands to see how the job
150      is first sent to the <var class="LITERAL">lp</var> queue,
151      which then forwards it to the <var class="LITERAL">lp3</var>
152      queue, which then processes it and removes it. (For purposes
153      of demonstration we have artificially slowed down the
154      operation of the load balance queue so that the jobs will
155      remain in the queue for sufficient time for us to display
156      their status.) We can send another job to the load balance
157      queue:</p>
158
159      <div class="INFORMALEXAMPLE">
160        <a name="AEN3630"></a>
161<pre class="SCREEN">
162    <samp class="PROMPT">h4: {278} %</samp> <kbd class=
163"USERINPUT">lpr /tmp/hi</kbd>
164    <samp class="PROMPT">h4: {279} %</samp> <kbd class=
165"USERINPUT">lpq</kbd>
166    Printer: lp@h4  (subservers lp2, lp3)
167     Queue: no printable jobs in queue
168     Status: no more jobs to process in load balance queue at 07:37:17.953
169    Server Printer: lp2@h4  (serving lp)
170     Queue: no printable jobs in queue
171     Status: job 'papowell@h4+89' removed at 07:37:15.936
172    Server Printer: lp3@h4  (serving lp)
173     Queue: no printable jobs in queue
174     Status: job 'papowell@h4+81' removed at 07:36:40.116
175</pre>
176      </div>
177      <br>
178      <br>
179
180      <p>This time we see that the job was put in <var class=
181      "LITERAL">lp2</var>. The normal load balance queue operation
182      is to use the server queues in round robin order.</p>
183
184      <p>While this simple configuration is suitable for a large
185      number of configurations, there are situations where server
186      queue must be chosen <span class="emphasis"><i class=
187      "EMPHASIS">dynamically</i></span>. For example, if the server
188      queues are actually transferring jobs to remote clients then
189      as soon as the job is sent to the remote client the queue
190      appears empty and available for use. To correctly check to
191      see if the queue is available, the status of the remote queue
192      or destination of the server queue must be checked.</p>
193
194      <p>To handle this situation, a <var class=
195      "LITERAL">:chooser</var> program or filter can be used. When
196      the load balance queue is trying to decide where to send a
197      job, it first checks the server queues to see if they are
198      enabled for printing. If a <var class=
199      "LITERAL">:chooser</var> program is specified in the load
200      balance queue printcap entry, then it is started with the
201      normal filter options and environment variables, supplemented
202      as discussed below. The <var class="LITERAL">:chooser</var>
203      program will read a list of candidate queues from its
204      <acronym class="ACRONYM">STDIN</acronym>, write the chosen
205      one to its <acronym class="ACRONYM">STDOUT</acronym>, and
206      then exit. The <b class="APPLICATION">lpd</b> server checks
207      the <var class="LITERAL">:chooser</var> exit code - if it is
208      zero (successful) then the chosen queue is used otherwise the
209      exit code is used for the result value of processing the job.
210      This allows the chooser process to not only control the
211      destination of the job but also to hold, remove, or abort the
212      job handling process. If the <var class=
213      "LITERAL">:chooser</var> does not specify a queue, then the
214      job is skipped and another job is chosen.</p>
215
216      <p>One side effect of the using a chooser program is that
217      while there are jobs that can be processed in the queue the
218      <b class="APPLICATION">lpd</b> server needs to periodically
219      check to see if a server queue has become available. If it
220      did this continually then a very high load would be put on
221      the system. Instead, the <var class=
222      "LITERAL">chooser_interval</var> option specifies a maximum
223      time in seconds (default 10 seconds) between the times that
224      the <b class="APPLICATION">lpd</b> server checks to see if
225      there is an available server.</p>
226
227      <p>Edit the printcap file so it have the contents indicated
228      below, create the <tt class="FILENAME">/tmp/lp2</tt> and <tt
229      class="FILENAME">/tmp/lp3</tt> files with <var class=
230      "LITERAL">0777</var> permissions. Then create the <tt class=
231      "FILENAME">/tmp/chooser.script</tt> with the contents
232      indicated below, and give it <var class="LITERAL">0755</var>
233      (executable) permissions. Make sure that the path to the <b
234      class="APPLICATION">head</b> program used in <tt class=
235      "FILENAME">chooser.script</tt> is correct. Use <tt class=
236      "COMMAND">checkpc -f</tt> to check the printcap, and then use
237      <tt class="COMMAND">lpc reread</tt> to restart the <b class=
238      "APPLICATION">lpd</b> server.</p>
239
240      <div class="INFORMALEXAMPLE">
241        <a name="AEN3664"></a>
242<pre class="SCREEN">
243    # printcap
244    lp:force_localhost
245    lp:server
246      :sd=/var/spool/lpd/%P
247      :sv=lp2,lp3
248      :chooser=/tmp/chooser.script
249    lp2:force_localhost
250    lp2:server
251      :ss=lp
252      :sd=/var/spool/lpd/%P
253      :lp=/tmp/lp2
254    lp3:force_localhost
255    lp3:server
256      :ss=lp
257      :sd=/var/spool/lpd/%P
258      :lp=/tmp/lp2
259    
260    # /tmp/chooser.script
261    
262    #!/bin/sh
263    echo CHOOSER $0 $@ &gt;&gt;/tmp/chooser
264    set &gt;&gt;/tmp/chooser
265    /usr/bin/head -1
266    exit 0
267</pre>
268      </div>
269      <br>
270      <br>
271
272      <p>Now run the following commands:</p>
273
274      <div class="INFORMALEXAMPLE">
275        <a name="AEN3667"></a>
276<pre class="SCREEN">
277    <samp class="PROMPT">h4: {280} %</samp> <kbd class=
278"USERINPUT">lpr /tmp/hi</kbd>
279    <samp class="PROMPT">h4: {281} %</samp> <kbd class=
280"USERINPUT">lpq -lll</kbd>
281    Printer: lp@h4  (subservers lp2, lp3)
282     Queue: no printable jobs in queue
283     Status: CHOOSER selected 'lp3' at 14:02:50.605
284     Status: transferring 'papowell@h4+178' 
285          to subserver 'lp3' at 14:02:50.614
286     Status: transfer 'papowell@h4+178' 
287          to subserver 'lp3' finished at 14:02:50.624
288     Status: job 'papowell@h4+178' removed at 14:02:50.632
289     Status: starting subserver 'lp3' at 14:02:50.632
290     Status: waiting for server queue process to exit at 14:02:50.651
291     Status: subserver pid 10182 exit status 'JSUCC' at 14:02:52.872
292     Status: no more jobs to process in load balance queue at 14:02:52.879
293    Server Printer: lp2@h4  (serving lp)
294     Queue: no printable jobs in queue
295    Server Printer: lp3@h4  (serving lp)
296     Queue: no printable jobs in queue
297     Status: waiting for subserver to exit at 14:02:50.748
298     Status: subserver pid 10183 starting at 14:02:50.820
299     Status: accounting at start at 14:02:50.821
300     Status: opening device '/tmp/lp3' at 14:02:50.833
301     Status: printing job 'papowell@h4+178' at 14:02:50.834
302     Status: processing 'dfA178h4.private', size 3, format 'f', \
303          IF filter 'none - passthrough' at 14:02:50.838
304     Status: printing finished at 14:02:50.839
305     Status: accounting at end at 14:02:50.839
306     Status: finished 'papowell@h4+178', status 'JSUCC' at 14:02:50.841
307     Status: subserver pid 10183 exit status 'JSUCC' at 14:02:50.843
308     Status: lp3@h4.private: job 'papowell@h4+178' printed at 14:02:50.856
309     Status: job 'papowell@h4+178' removed at 14:02:50.871
310</pre>
311      </div>
312      <br>
313      <br>
314
315      <p>As you see from the example above, the <acronym class=
316      "ACRONYM">CHOOSER</acronym> selected <var class=
317      "LITERAL">lp3</var> for use. Let us look at the <tt class=
318      "FILENAME">/tmp/chooser</tt> file and see how the <tt class=
319      "FILENAME">chooser.script</tt> program was run:</p>
320
321      <div class="INFORMALEXAMPLE">
322        <a name="AEN3678"></a>
323<pre class="SCREEN">
324    CHOOSER -Apapowell@h4+113 -CA -D2000-06-01-14:02:13.313 -Hh4.private \
325       -J/tmp/hi -Lpapowell -Plp -Qlp -aacct -b3 -d/var/tmp/LPD/lp \
326       -hh4.private -j113 -kcfA113h4.private -l66 -npapowell -sstatus \
327       -t2000-06-01-14:02:13.379 -w80 -x0 -y0 acct
328    USER=papowell
329    LD_LIBRARY_PATH=/lib:/usr/lib:/usr/5lib:/usr/ucblib
330    HOME=/home/papowell
331    PRINTCAP_ENTRY=lp
332     :chooser=/var/tmp/LPD/chooser
333     :lp=/tmp/lp
334     :sd=/var/tmp/LPD/lp
335     :server
336     :sv=lp2,lp3
337    
338    lp2=change=0x0
339     done_time=0x1
340     held=0x0
341     move=0x0
342     printable=0x0
343     printer=lp2
344     printing_aborted=0x0
345     printing_disabled=0x0
346     queue_control_file=control.lp2
347     server=0
348     spooldir=/var/tmp/LPD/lp2
349    lp3=change=0x0
350     done_time=0x2
351     held=0x0
352     move=0x0
353     printable=0x0
354     printer=lp3
355     printing_aborted=0x0
356     printing_disabled=0x0
357     queue_control_file=control.lp3
358     server=0
359     spooldir=/var/tmp/LPD/lp3
360    PS1=$
361    OPTIND=1
362    PS2=&gt;
363    SPOOL_DIR=/var/tmp/LPD/lp
364    LOGNAME=papowell
365    CONTROL=Hh4.private
366    Ppapowell
367    J/tmp/hi
368    CA
369    Lpapowell
370    Apapowell@h4+113
371    D2000-06-01-14:02:13.313
372    Qlp
373    N/tmp/hi
374    fdfA113h4.private
375    UdfA113h4.private
376</pre>
377      </div>
378      <br>
379      <br>
380
381      <p>As you can see, the program is invoked with the same
382      options as a normal filter. In addition, the printcap
383      information for each server queue is passed in an environment
384      variable with the name of the server queue. This means that
385      if there is information needed by the chooser program to test
386      for the availability of hardware, etc., this can be placed in
387      the printcap information.</p>
388
389      <p>One of the limitations of using the <var class=
390      "LITERAL">:chooser</var> program is that you may have a high
391      overhead associated with running the program. The <b class=
392      "APPLICATION">LPRng</b> software provides support for linking
393      in a user provided routine that does the same thing as the
394      <var class="LITERAL">:chooser</var> program. This routine has
395      the following API or interface:</p>
396
397      <div class="INFORMALEXAMPLE">
398        <a name="AEN3685"></a>
399<pre class="SCREEN">
400    Printcap Option: chooser_routine
401       chooser_routine@  - default - do not use chooser routine
402       chooser_routine   - use chooser routine
403    
404    Configuration:
405       configure --with-chooser_routine=name --with-user_objs=objectfile.o
406          defines the CHOOSER_ROUTINE compilation option to name
407          includes the objectfile.o in the library.
408    
409    extern int CHOOSER_ROUTINE( struct line_list *servers,
410        struct line_list *available, int *use_subserver );
411      servers:    all subserver queues for this load balance queue
412      available:  subserver queues to choose from
413      use_subserver: chosen subserver queue
414      RETURNS:
415         0 - use the 'use_subserver' value as index into servers
416             list for server to use
417         != 0 - set job status to value returned.
418</pre>
419      </div>
420      <br>
421      <br>
422
423      <p>See the <tt class=
424      "FILENAME">LPRng/src/common/lpd_jobs.c</tt> and <tt class=
425      "FILENAME">LPRng/src/common/user_objs.c</tt> files for
426      details of the servers, available, and user_subserver
427      parameters. The <tt class="FILENAME">user_objs.c</tt> file
428      provides a simple template that can be used as a starting
429      point for a more complex routine. You should modify the code
430      in the <tt class="FILENAME">user_objs.c</tt> file and then
431      use the configure options shown above to cause the <tt class=
432      "FILENAME">user_objs.c</tt> file to be compiled and linked
433      into the <b class="APPLICATION">LPRng</b> executables.</p>
434    </div>
435
436    <div class="NAVFOOTER">
437      <hr align="LEFT" width="100%">
438
439      <table summary="Footer navigation table" width="100%" border=
440      "0" cellpadding="0" cellspacing="0">
441        <tr>
442          <td width="33%" align="left" valign="top"><a href=
443          "x3515.htm" accesskey="P">Prev</a></td>
444
445          <td width="34%" align="center" valign="top"><a href=
446          "index.htm" accesskey="H">Home</a></td>
447
448          <td width="33%" align="right" valign="top"><a href=
449          "x3694.htm" accesskey="N">Next</a></td>
450        </tr>
451
452        <tr>
453          <td width="33%" align="left" valign="top">Holding and
454          Releasing Jobs</td>
455
456          <td width="34%" align="center" valign="top"><a href=
457          "tutorial.htm" accesskey="U">Up</a></td>
458
459          <td width="33%" align="right" valign="top">Routing Jobs
460          To Print Queues</td>
461        </tr>
462      </table>
463    </div>
464  </body>
465</html>
466
467