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 $@ >>/tmp/chooser 264 set >>/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=> 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