Index: doc/help/ref-cupsd-conf.html.in =================================================================== --- doc/help/ref-cupsd-conf.html.in (revision 7465) +++ doc/help/ref-cupsd-conf.html.in (working copy) @@ -1007,6 +1007,22 @@ HREF="#Limit">Limit section.

+

DirtyCleanInterval

+ +

Examples

+ +
+DirtyCleanInterval 60
+DirtyCleanInterval 0
+
+ +

Description

+ +

The DirtyCleanInterval directive specifies the number of +seconds to wait before updating configuration and state files for printers, +classes, subscriptions, and jobs. The default is 60 seconds.

+ +

DocumentRoot

Examples

Index: scheduler/subscriptions.c =================================================================== --- scheduler/subscriptions.c (revision 7465) +++ scheduler/subscriptions.c (working copy) @@ -297,7 +297,7 @@ } if (temp) - cupsdSaveAllSubscriptions(); + cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS); else cupsdLogMessage(CUPSD_LOG_DEBUG, "Discarding unused %s event...", cupsdEventName(event)); @@ -463,7 +463,7 @@ */ if (update) - cupsdSaveAllSubscriptions(); + cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS); } @@ -646,7 +646,7 @@ } if (update) - cupsdSaveAllSubscriptions(); + cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS); } Index: scheduler/sysman.c =================================================================== --- scheduler/sysman.c (revision 7465) +++ scheduler/sysman.c (working copy) @@ -3,7 +3,7 @@ * * System management definitions for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -14,6 +14,9 @@ * * Contents: * + * cupsdCleanDirty() - Write dirty config and state files. + * cupsdMarkDirty() - Mark config or state files as needing a + * write. * cupsdStartSystemMonitor() - Start monitoring for system change. * cupsdStopSystemMonitor() - Stop monitoring for system change. * cupsdUpdateSystemMonitor() - Update the current system state. @@ -34,15 +37,91 @@ /* - * Power management is a new addition to CUPS. Right now it is only - * implemented on MacOS X, but essentially we use these three functions - * to let the OS know when it is OK to put the system to sleep, typically - * when we are not in the middle of printing a job. + * The system management functions cover disk and power management which + * are primarily used on portable computers. * - * Once put to sleep, we invalidate all remote printers since it is - * common to wake up in a new location. + * Disk management involves delaying the write of certain configuration + * and state files to minimize the number of times the disk has to spin + * up. + * + * Power management support is currently only implemented on MacOS X, but + * essentially we use four functions to let the OS know when it is OK to + * put the system to idle sleep, typically when we are not in the middle of + * printing a job. + * + * Once put to sleep, we invalidate all remote printers since it is common + * to wake up in a new location/on a new wireless network. */ + +/* + * 'cupsdCleanDirty()' - Write dirty config and state files. + */ + +void +cupsdCleanDirty(void) +{ + if (DirtyFiles & CUPSD_DIRTY_PRINTERS) + cupsdSaveAllPrinters(); + + if (DirtyFiles & CUPSD_DIRTY_CLASSES) + cupsdSaveAllClasses(); + + if (DirtyFiles & CUPSD_DIRTY_REMOTE) + cupsdSaveRemoteCache(); + + if (DirtyFiles & CUPSD_DIRTY_PRINTCAP) + cupsdWritePrintcap(); + + if (DirtyFiles & CUPSD_DIRTY_JOBS) + { + cupsd_job_t *job; /* Current job */ + + cupsdSaveAllJobs(); + + for (job = (cupsd_job_t *)cupsArrayFirst(Jobs); + job; + job = (cupsd_job_t *)cupsArrayNext(Jobs)) + if (job->dirty) + cupsdSaveJob(job); + } + + if (DirtyFiles & CUPSD_DIRTY_SUBSCRIPTIONS) + cupsdSaveAllSubscriptions(); + + DirtyFiles = CUPSD_DIRTY_NONE; + DirtyCleanTime = 0; +} + + +/* + * 'cupsdMarkDirty()' - Mark config or state files as needing a write. + */ + +void +cupsdMarkDirty(int what) /* I - What file(s) are dirty? */ +{ + cupsdSetBusy(1); + + DirtyFiles |= what; + + if (!DirtyCleanTime) + DirtyCleanTime = time(NULL) + DirtyCleanInterval; +} + + +/* + * 'cupsdSetBusy()' - Let the system know when we are busy doing something. + */ + +void +cupsdSetBusy(int busy) /* I - 1 = busy, 0 = idle */ +{ + /* TODO */ + (void)busy; +} + + #ifdef __APPLE__ /* * This is the Apple-specific system event code. It works by creating Index: scheduler/sysman.h =================================================================== --- scheduler/sysman.h (revision 7465) +++ scheduler/sysman.h (working copy) @@ -3,7 +3,7 @@ * * System management definitions for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -14,9 +14,27 @@ */ /* + * Constants... + */ + +#define CUPSD_DIRTY_NONE 0 /* Nothing is dirty */ +#define CUPSD_DIRTY_PRINTERS 1 /* printers.conf is dirty */ +#define CUPSD_DIRTY_CLASSES 2 /* classes.conf is dirty */ +#define CUPSD_DIRTY_REMOTE 4 /* remote.cache is dirty */ +#define CUPSD_DIRTY_PRINTCAP 8 /* printcap is dirty */ +#define CUPSD_DIRTY_JOBS 16 /* jobs.cache or "c" file(s) are dirty */ +#define CUPSD_DIRTY_SUBSCRIPTIONS 32 /* subscriptions.conf is dirty */ + +/* * Globals... */ +VAR int DirtyFiles VALUE(CUPSD_DIRTY_NONE), + /* What files are dirty? */ + DirtyCleanInterval VALUE(60); + /* How often do we write dirty files? */ +VAR time_t DirtyCleanTime VALUE(0); + /* When to clean dirty files next */ VAR int Sleeping VALUE(0); /* Non-zero if machine is entering or * * in a sleep state... */ @@ -30,6 +48,9 @@ * Prototypes... */ +extern void cupsdCleanDirty(void); +extern void cupsdMarkDirty(int what); +extern void cupsdSetBusy(int busy); extern void cupsdStartSystemMonitor(void); extern void cupsdStopSystemMonitor(void); extern void cupsdUpdateSystemMonitor(void); Index: scheduler/conf.c =================================================================== --- scheduler/conf.c (revision 7465) +++ scheduler/conf.c (working copy) @@ -103,6 +103,7 @@ { "DefaultLeaseDuration", &DefaultLeaseDuration, CUPSD_VARTYPE_INTEGER }, { "DefaultPolicy", &DefaultPolicy, CUPSD_VARTYPE_STRING }, { "DefaultShared", &DefaultShared, CUPSD_VARTYPE_BOOLEAN }, + { "DirtyCleanInterval", &DirtyCleanInterval, CUPSD_VARTYPE_INTEGER }, { "DocumentRoot", &DocumentRoot, CUPSD_VARTYPE_STRING }, { "ErrorLog", &ErrorLog, CUPSD_VARTYPE_STRING }, { "ErrorPolicy", &ErrorPolicy, CUPSD_VARTYPE_STRING }, @@ -516,6 +517,7 @@ #ifdef HAVE_SSL DefaultEncryption = HTTP_ENCRYPT_REQUIRED; #endif /* HAVE_SSL */ + DirtyCleanInterval = 60; JobRetryLimit = 5; JobRetryInterval = 300; FileDevice = FALSE; @@ -1188,7 +1190,7 @@ cupsdLoadAllPrinters(); cupsdLoadAllClasses(); cupsdLoadRemoteCache(); - cupsdWritePrintcap(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); cupsdCreateCommonData(); @@ -1219,7 +1221,7 @@ */ cupsdUpdatePrinters(); - cupsdWritePrintcap(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); cupsdLogMessage(CUPSD_LOG_INFO, "Partial reload complete."); } Index: scheduler/ipp.c =================================================================== --- scheduler/ipp.c (revision 7465) +++ scheduler/ipp.c (working copy) @@ -858,14 +858,14 @@ if (dtype & CUPS_PRINTER_CLASS) { - cupsdSaveAllClasses(); + cupsdMarkDirty(CUPSD_DIRTY_CLASSES); cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" now accepting jobs (\"%s\").", printer->name, get_username(con)); } else { - cupsdSaveAllPrinters(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" now accepting jobs (\"%s\").", @@ -1162,7 +1162,7 @@ */ cupsdSetPrinterAttrs(pclass); - cupsdSaveAllClasses(); + cupsdMarkDirty(CUPSD_DIRTY_CLASSES); if (need_restart_job && pclass->job) { @@ -1183,7 +1183,7 @@ if (need_restart_job) cupsdCheckJobs(); - cupsdWritePrintcap(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); if (modify) { @@ -1265,6 +1265,9 @@ job->num_files ++; + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); + return (0); } @@ -1487,8 +1490,11 @@ job->dtype = printer->type & (CUPS_PRINTER_CLASS | CUPS_PRINTER_IMPLICIT | CUPS_PRINTER_REMOTE); job->attrs = con->request; + job->dirty = 1; con->request = ippNewRequest(job->attrs->request.op.operation_id); + cupsdMarkDirty(CUPSD_DIRTY_JOBS); + add_job_uuid(con, job); apply_printer_defaults(printer, job); @@ -2071,7 +2077,7 @@ attr = attr->next; } - cupsdSaveAllSubscriptions(); + cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS); /* * Remove all of the subscription attributes from the job request... @@ -2720,7 +2726,7 @@ */ cupsdSetPrinterAttrs(printer); - cupsdSaveAllPrinters(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); if (need_restart_job && printer->job) { @@ -2741,7 +2747,7 @@ if (need_restart_job) cupsdCheckJobs(); - cupsdWritePrintcap(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); if (modify) { @@ -5453,8 +5459,6 @@ * Save and log the job... */ - cupsdSaveJob(job); - cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Queued on \"%s\" by \"%s\".", job->id, job->dest, job->username); } @@ -6001,8 +6005,7 @@ attr = attr->next; } - cupsdSaveAllSubscriptions(); - + cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS); } @@ -6091,7 +6094,7 @@ printer->name, get_username(con)); cupsdDeletePrinter(printer, 0); - cupsdSaveAllClasses(); + cupsdMarkDirty(CUPSD_DIRTY_CLASSES); } else { @@ -6099,10 +6102,10 @@ printer->name, get_username(con)); cupsdDeletePrinter(printer, 0); - cupsdSaveAllPrinters(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); } - cupsdWritePrintcap(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); /* * Return with no errors... @@ -6597,6 +6600,11 @@ completed = 0; list = Jobs; } + else if (attr && !strcmp(attr->values[0].string.text, "printing")) + { + completed = 0; + list = PrintingJobs; + } else { completed = 0; @@ -6611,7 +6619,7 @@ IPP_TAG_INTEGER)) != NULL) limit = attr->values[0].integer; else - limit = 1000000; + limit = 0; if ((attr = ippFindAttribute(con->request, "first-job-id", IPP_TAG_INTEGER)) != NULL) @@ -6637,7 +6645,7 @@ */ for (count = 0, job = (cupsd_job_t *)cupsArrayFirst(list); - count < limit && job; + (limit <= 0 || count < limit) && job; job = (cupsd_job_t *)cupsArrayNext(list)) { /* @@ -8271,8 +8279,6 @@ cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] hold_until = %d", job->id, (int)job->hold_until); - cupsdSaveJob(job); - /* * Start the job if possible... */ @@ -8525,14 +8531,14 @@ if (dtype & CUPS_PRINTER_CLASS) { - cupsdSaveAllClasses(); + cupsdMarkDirty(CUPSD_DIRTY_CLASSES); cupsdLogMessage(CUPSD_LOG_INFO, "Class \"%s\" rejecting jobs (\"%s\").", printer->name, get_username(con)); } else { - cupsdSaveAllPrinters(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); cupsdLogMessage(CUPSD_LOG_INFO, "Printer \"%s\" rejecting jobs (\"%s\").", printer->name, get_username(con)); @@ -8761,7 +8767,7 @@ sub->expire = sub->lease ? time(NULL) + sub->lease : 0; - cupsdSaveAllSubscriptions(); + cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS); con->response->request.status.status_code = IPP_OK; @@ -9485,7 +9491,8 @@ } } - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); /* * Start the job if possible... Since cupsdCheckJobs() can cancel a @@ -9509,7 +9516,9 @@ job->state->values[0].integer = IPP_JOB_HELD; job->state_value = IPP_JOB_HELD; job->hold_until = time(NULL) + 60; - cupsdSaveJob(job); + job->dirty = 1; + + cupsdMarkDirty(CUPSD_DIRTY_JOBS); } } @@ -9676,11 +9685,9 @@ DefaultPrinter = printer; - cupsdSaveAllPrinters(); - cupsdSaveAllClasses(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES | + CUPSD_DIRTY_REMOTE | CUPSD_DIRTY_PRINTCAP); - cupsdWritePrintcap(); - cupsdLogMessage(CUPSD_LOG_INFO, "Default destination set to \"%s\" by \"%s\".", printer->name, get_username(con)); @@ -10025,7 +10032,8 @@ * Save the job... */ - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); /* * Send events as needed... Index: scheduler/dirsvc.c =================================================================== --- scheduler/dirsvc.c (revision 7465) +++ scheduler/dirsvc.c (working copy) @@ -98,7 +98,7 @@ ipp_pstate_t state, const char *location, const char *info, const char *make_model, int num_attrs, cups_option_t *attrs); -static void process_implicit_classes(int *write_printcap); +static void process_implicit_classes(void); static void send_cups_browse(cupsd_printer_t *p); #ifdef HAVE_LDAP static void send_ldap_browse(cupsd_printer_t *p); @@ -616,7 +616,7 @@ * Do auto-classing if needed... */ - process_implicit_classes(NULL); + process_implicit_classes(); } @@ -801,7 +801,6 @@ cupsd_printer_t *p; /* Current printer */ time_t ut, /* Minimum update time */ to; /* Timeout time */ - int write_printcap; /* Write the printcap file? */ if (!Browsing || !BrowseLocalProtocols || !Printers) @@ -899,7 +898,7 @@ * Loop through all of the printers and send local updates as needed... */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers), write_printcap = 0; + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) { @@ -924,13 +923,10 @@ cupsArraySave(Printers); cupsdDeletePrinter(p, 1); cupsArrayRestore(Printers); - write_printcap = 1; + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); } } } - - if (write_printcap) - cupsdWritePrintcap(); } @@ -1749,8 +1745,7 @@ cups_option_t *attrs) /* I - Attributes */ { int i; /* Looping var */ - int update, /* Update printer attributes? */ - write_printcap; /* Write the printcap file? */ + int update; /* Update printer attributes? */ char finaluri[HTTP_MAX_URI], /* Final URI for printer */ name[IPP_MAX_NAME], /* Name of printer */ newname[IPP_MAX_NAME], /* New name of printer */ @@ -1837,12 +1832,11 @@ * See if we already have it listed in the Printers list, and add it if not... */ - type |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED; - type &= ~CUPS_PRINTER_IMPLICIT; - update = 0; - write_printcap = 0; - hptr = strchr(host, '.'); - sptr = strchr(ServerName, '.'); + type |= CUPS_PRINTER_REMOTE | CUPS_PRINTER_DISCOVERED; + type &= ~CUPS_PRINTER_IMPLICIT; + update = 0; + hptr = strchr(host, '.'); + sptr = strchr(ServerName, '.'); if (!ServerNameIsIP && sptr != NULL && hptr != NULL) { @@ -1965,8 +1959,9 @@ cupsdSetString(&p->device_uri, uri); cupsdSetString(&p->hostname, host); - update = 1; - write_printcap = 1; + update = 1; + + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); } } else @@ -2072,8 +2067,9 @@ cupsdSetString(&p->uri, uri); cupsdSetString(&p->device_uri, uri); - write_printcap = 1; - update = 1; + update = 1; + + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); } } @@ -2132,8 +2128,9 @@ if (info && (!p->info || strcmp(p->info, info))) { cupsdSetString(&p->info, info); - update = 1; - write_printcap = 1; + update = 1; + + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); } if (!make_model || !make_model[0]) @@ -2198,7 +2195,7 @@ cupsdDeletePrinter(p, 1); cupsdUpdateImplicitClasses(); - write_printcap = 1; + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); } else if (update) { @@ -2223,7 +2220,7 @@ if (p->type & CUPS_PRINTER_DEFAULT) { DefaultPrinter = p; - write_printcap = 1; + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); break; } } @@ -2232,14 +2229,7 @@ * Do auto-classing if needed... */ - process_implicit_classes(&write_printcap); - - /* - * Update the printcap file... - */ - - if (write_printcap) - cupsdWritePrintcap(); + process_implicit_classes(); } @@ -2766,8 +2756,7 @@ */ static void -process_implicit_classes( - int *write_printcap) /* O - Write printcap file? */ +process_implicit_classes(void) { int i; /* Looping var */ int update; /* Update printer attributes? */ @@ -2848,8 +2837,7 @@ update = 1; - if (write_printcap) - *write_printcap = 1; + cupsdMarkDirty(CUPSD_DIRTY_PRINTCAP); cupsdLogMessage(CUPSD_LOG_DEBUG, "Added implicit class \"%s\"...", name); Index: scheduler/printers.c =================================================================== --- scheduler/printers.c (revision 7465) +++ scheduler/printers.c (working copy) @@ -2793,9 +2793,9 @@ update) { if (p->type & CUPS_PRINTER_CLASS) - cupsdSaveAllClasses(); + cupsdMarkDirty(CUPSD_DIRTY_CLASSES); else - cupsdSaveAllPrinters(); + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); } } @@ -2841,8 +2841,9 @@ job->state->values[0].integer = IPP_JOB_PENDING; job->state_value = IPP_JOB_PENDING; + job->dirty = 1; - cupsdSaveJob(job); + cupsdMarkDirty(CUPSD_DIRTY_JOBS); cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job, "Job stopped due to printer being paused"); Index: scheduler/server.c =================================================================== --- scheduler/server.c (revision 7465) +++ scheduler/server.c (working copy) @@ -3,7 +3,7 @@ * * Server start/stop routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -137,7 +137,6 @@ cupsdStopPolling(); cupsdStopBrowsing(); cupsdStopAllNotifiers(); - cupsdSaveRemoteCache(); cupsdDeleteAllCerts(); if (Clients) @@ -203,6 +202,13 @@ cupsdDestroyProfile(DefaultProfile); DefaultProfile = NULL; + /* + * Write out any dirty files... + */ + + if (DirtyFiles) + cupsdCleanDirty(); + started = 0; } Index: scheduler/job.c =================================================================== --- scheduler/job.c (revision 7466) +++ scheduler/job.c (working copy) @@ -211,10 +211,11 @@ cupsdExpireSubscriptions(NULL, job); /* - * Remove the job from the active list... + * Remove the job from the active and printing lists... */ cupsArrayRemove(ActiveJobs, job); + cupsArrayRemove(PrintingJobs, job); /* * Remove any authentication data... @@ -277,7 +278,8 @@ * Save job state info... */ - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); } else { @@ -301,6 +303,9 @@ free_job(job); } + + if (!cupsArrayCount(PrintingJobs) && !DirtyCleanTime) + cupsdSetBusy(0); } @@ -395,7 +400,8 @@ { attr->value_tag = IPP_TAG_KEYWORD; cupsdSetString(&(attr->values[0].string.text), "no-hold"); - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); } } @@ -462,6 +468,9 @@ else ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-actual-printer-uri", NULL, printer->uri); + + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); } if ((!(printer->type & CUPS_PRINTER_DISCOVERED) && /* Printer is local */ @@ -608,7 +617,8 @@ job->state_value = IPP_JOB_PENDING; } - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); /* * If the job was queued to a class, try requeuing it... For @@ -686,7 +696,8 @@ job->state->values[0].integer = IPP_JOB_HELD; job->state_value = IPP_JOB_HELD; - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job, "Job held due to backend errors; please consult " @@ -703,7 +714,9 @@ job->state->values[0].integer = IPP_JOB_PENDING; job->state_value = IPP_JOB_PENDING; - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); + cupsdSetPrinterState(printer, IPP_PRINTER_STOPPED, 1); cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job, @@ -730,7 +743,8 @@ job->state->values[0].integer = IPP_JOB_HELD; job->state_value = IPP_JOB_HELD; - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job, "Authentication is required for job %d.", job->id); @@ -752,7 +766,8 @@ cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Job stopped due to filter errors.", job->id); cupsdStopJob(job, 1); - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, printer, job, "Job stopped due to filter errors; please consult the " "error_log file for details."); @@ -812,6 +827,7 @@ { cupsArrayRemove(Jobs, job); cupsArrayRemove(ActiveJobs, job); + cupsArrayRemove(PrintingJobs, job); free_job(job); } @@ -902,7 +918,8 @@ job->state_value = IPP_JOB_HELD; job->current_file = 0; - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); cupsdCheckJobs(); } @@ -931,6 +948,9 @@ if (!ActiveJobs) ActiveJobs = cupsArrayNew(compare_active_jobs, NULL); + if (!PrintingJobs) + PrintingJobs = cupsArrayNew(compare_jobs, NULL); + /* * See whether the job.cache file is older than the RequestRoot directory... */ @@ -1317,7 +1337,8 @@ "Job #%d moved from %s to %s.", job->id, olddest, p->name); - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); } @@ -1336,7 +1357,8 @@ job->state->values[0].integer = IPP_JOB_PENDING; job->state_value = IPP_JOB_PENDING; - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); cupsdCheckJobs(); } } @@ -1364,7 +1386,8 @@ job->state->values[0].integer = IPP_JOB_PENDING; job->state_value = IPP_JOB_PENDING; - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); if (old_state > IPP_JOB_STOPPED) cupsArrayAdd(ActiveJobs, job); @@ -1479,6 +1502,8 @@ "[Job %d] Unable to write job control file!", job->id); cupsFileClose(fp); + + job->dirty = 0; } @@ -1654,7 +1679,8 @@ cupsArrayAdd(ActiveJobs, job); - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); } @@ -1780,7 +1806,12 @@ job = (cupsd_job_t *)cupsArrayNext(Jobs)) if (job->attrs && job->state_value >= IPP_JOB_STOPPED && job->access_time < expire) + { + if (job->dirty) + cupsdSaveJob(job); + unload_job(job); + } } @@ -2426,7 +2457,8 @@ else cupsdSetString(&attr->values[0].string.text, holdstr); - cupsdSaveJob(job); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); } @@ -2728,6 +2760,14 @@ if (job->current_file == 0) { /* + * Add to the printing list... + */ + + cupsArrayAdd(PrintingJobs, job); + + cupsdSetBusy(1); + + /* * Set the processing time... */ @@ -3692,7 +3732,11 @@ { cupsdSetAuthInfoRequired(job->printer, attr, NULL); cupsdSetPrinterAttrs(job->printer); - cupsdSaveAllPrinters(); + + if (job->printer->type & CUPS_PRINTER_DISCOVERED) + cupsdMarkDirty(CUPSD_DIRTY_REMOTE); + else + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); } if ((attr = cupsGetOption("printer-alert", num_attrs, attrs)) != NULL) Index: scheduler/job.h =================================================================== --- scheduler/job.h (revision 7465) +++ scheduler/job.h (working copy) @@ -20,7 +20,8 @@ typedef struct cupsd_job_s { int id, /* Job ID */ - priority; /* Job priority */ + priority, /* Job priority */ + dirty; /* Do we need to write the "c" file? */ ipp_jstate_t state_value; /* Cached job-state */ int pending_timeout;/* Non-zero if the job was created and waiting on files */ char *username; /* Printing user */ @@ -84,8 +85,10 @@ /* Automatically purge jobs */ VAR cups_array_t *Jobs VALUE(NULL), /* List of current jobs */ - *ActiveJobs VALUE(NULL); + *ActiveJobs VALUE(NULL), /* List of active jobs */ + *PrintingJobs VALUE(NULL); + /* List of jobs that are printing */ VAR int NextJobId VALUE(1); /* Next job ID to use */ VAR int JobRetryLimit VALUE(5), Index: scheduler/main.c =================================================================== --- scheduler/main.c (revision 7465) +++ scheduler/main.c (working copy) @@ -862,6 +862,18 @@ current_time = time(NULL); + /* + * Write dirty config/state files... + */ + + if (DirtyCleanTime && current_time >= DirtyCleanTime) + { + cupsdCleanDirty(); + + if (!cupsArrayCount(PrintingJobs)) + cupsdSetBusy(0); + } + #ifndef __APPLE__ /* * Update the network interfaces once a minute... @@ -1910,6 +1922,16 @@ * Check for any active jobs... */ + if (DirtyCleanTime && timeout > DirtyCleanTime) + { + timeout = DirtyCleanTime; + why = "write dirty config/state files"; + } + + /* + * Check for any active jobs... + */ + if (timeout > (now + 10) && ActiveJobs) { for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);