cupsdLogClient(con, CUPSD_LOG_DEBUG2, "copy_subscription_attrs: sub=%p, ra=%p, exclude=%p", (void *)sub, (void *)ra, (void *)exclude);
+ cupsRWLockRead(&sub->lock);
+
/*
* Copy the subscription attributes to the response using the
* requested-attributes attribute that may be provided by the client.
if (!ra || cupsArrayFind(ra, "notify-subscription-id"))
ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
"notify-subscription-id", sub->id);
+
+ cupsRWUnlock(&sub->lock);
}
goto finish_response;
}
- // TODO: Grab printer icon file...
httpClose(http);
/*
ipp_attribute_t *uri) /* I - Printer/job URI */
{
http_status_t status; /* Policy status */
- int count; /* Number of subscriptions */
+ int i, /* Looping var */
+ scount; /* Total number of subscriptions */
+ int count; /* Number of subscriptions returned */
int limit; /* Limit */
cupsd_subscription_t *sub; /* Subscription */
cups_array_t *ra; /* Requested attributes array */
else
username[0] = '\0';
- for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions), count = 0;
- sub;
- sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ cupsRWLockRead(&SubscriptionsLock);
+
+ for (i = 0, count = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
+ {
+ sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
+
if ((!printer || sub->dest == printer) && (!job || sub->job == job) &&
(!username[0] || !_cups_strcasecmp(username, sub->owner)))
{
if (limit && count >= limit)
break;
}
+ }
+
+ cupsRWUnlock(&SubscriptionsLock);
cupsArrayDelete(ra);
* Renew the subscription...
*/
+ cupsRWLockWrite(&sub->lock);
+
lease = ippFindAttribute(con->request, "notify-lease-duration",
IPP_TAG_INTEGER);
sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
+ cupsRWUnlock(&sub->lock);
+
cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
con->response->request.status.status_code = IPP_STATUS_OK;
static int cupsd_compare_subscriptions(cupsd_subscription_t *first,
cupsd_subscription_t *second,
void *unused);
-static void cupsd_delete_event(cupsd_event_t *event, void *data);
+static void cupsd_delete_event(cupsd_event_t *event, void *data);
#ifdef HAVE_DBUS
static void cupsd_send_dbus(cupsd_eventmask_t event, cupsd_printer_t *dest,
cupsd_job_t *job);
const char *text, /* I - Notification text */
...) /* I - Additional arguments as needed */
{
+ int i, /* Looping var */
+ scount; /* Number of subscriptions */
va_list ap; /* Pointer to additional arguments */
char ftext[1024]; /* Formatted text buffer */
ipp_attribute_t *attr; /* Printer/job attribute */
- cupsd_event_t *temp; /* New event pointer */
+ cupsd_event_t *temp = NULL; /* New event pointer */
cupsd_subscription_t *sub; /* Current subscription */
if (job && !dest)
dest = cupsdFindPrinter(job->dest);
- for (temp = NULL, sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
- sub;
- sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ cupsRWLockRead(&SubscriptionsLock);
+
+ for (i = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
{
/*
* Check if this subscription requires this event...
*/
+ sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
+
if ((sub->mask & event) != 0 && (sub->dest == dest || !sub->dest || sub->job == job))
{
/*
cupsdLogMessage(CUPSD_LOG_CRIT,
"Unable to allocate memory for event - %s",
strerror(errno));
+ cupsRWUnlock(&SubscriptionsLock);
return;
}
}
}
+ cupsRWUnlock(&SubscriptionsLock);
+
if (temp)
cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
else
mask, (void *)dest, dest ? dest->name : "", (void *)job, job ? job->id : 0,
uri ? uri : "(null)");
+ cupsRWLockWrite(&SubscriptionsLock);
+
if (!Subscriptions)
Subscriptions = cupsArrayNew((cups_array_func_t)cupsd_compare_subscriptions,
NULL);
cupsdLogMessage(CUPSD_LOG_CRIT,
"Unable to allocate memory for subscriptions - %s",
strerror(errno));
+ cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
"cupsdAddSubscription: Reached MaxSubscriptions %d "
"(count=%d)", MaxSubscriptions,
cupsArrayCount(Subscriptions));
+ cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
"cupsdAddSubscription: Reached MaxSubscriptionsPerJob %d "
"for job #%d (count=%d)", MaxSubscriptionsPerJob,
job->id, count);
+ cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
}
"cupsdAddSubscription: Reached "
"MaxSubscriptionsPerPrinter %d for %s (count=%d)",
MaxSubscriptionsPerPrinter, dest->name, count);
+ cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
}
cupsdLogMessage(CUPSD_LOG_CRIT,
"Unable to allocate memory for subscription object - %s",
strerror(errno));
+ cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
+ cupsRWInit(&temp->lock);
+
/*
* Fill in common data...
*/
cupsArrayAdd(Subscriptions, temp);
+ cupsRWUnlock(&SubscriptionsLock);
+
/*
* For RSS subscriptions, run the notifier immediately...
*/
if (!Subscriptions)
return;
+ cupsRWLockWrite(&SubscriptionsLock);
+
for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
sub;
sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
cupsArrayDelete(Subscriptions);
Subscriptions = NULL;
+
+ cupsRWUnlock(&SubscriptionsLock);
}
* Remove subscription from array...
*/
+ cupsRWLockWrite(&SubscriptionsLock);
+
cupsArrayRemove(Subscriptions, sub);
+ cupsRWUnlock(&SubscriptionsLock);
+
/*
* Free memory...
*/
+ cupsRWDestroy(&sub->lock);
+
cupsdClearString(&(sub->owner));
cupsdClearString(&(sub->recipient));
cupsd_subscription_t * /* O - Subscription object */
cupsdFindSubscription(int id) /* I - Subscription ID */
{
- cupsd_subscription_t sub; /* Subscription template */
+ cupsd_subscription_t key, /* Subscription key */
+ *sub; /* Matching subscription */
+
+ key.id = id;
+
+ cupsRWLockRead(&SubscriptionsLock);
+ sub = (cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub);
- sub.id = id;
+ cupsRWUnlock(&SubscriptionsLock);
- return ((cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub));
+ return (sub);
}
void
cupsdSaveAllSubscriptions(void)
{
- int i; /* Looping var */
+ int i, j, /* Looping vars */
+ scount; /* Number of subscriptions */
cups_file_t *fp; /* subscriptions.conf file */
char filename[1024]; /* subscriptions.conf filename */
cupsd_subscription_t *sub; /* Current subscription */
* Write every subscription known to the system...
*/
- for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
- sub;
- sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ cupsRWLockRead(&SubscriptionsLock);
+
+ for (i = 0, scount = cupsArrayGetCount(Subscriptions); i < scount; i ++)
{
+ sub = (cupsd_subscription_t *)cupsArrayGetElement(Subscriptions, i);
+
cupsFilePrintf(fp, "<Subscription %d>\n", sub->id);
if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
{
cupsFilePuts(fp, "UserData ");
- for (i = 0, hex = 0; i < sub->user_data_len; i ++)
+ for (j = 0, hex = 0; j < sub->user_data_len; j ++)
{
- if (sub->user_data[i] < ' ' ||
- sub->user_data[i] > 0x7f ||
- sub->user_data[i] == '<')
+ if (sub->user_data[j] < ' ' ||
+ sub->user_data[j] > 0x7f ||
+ sub->user_data[j] == '<')
{
if (!hex)
{
- cupsFilePrintf(fp, "<%02X", sub->user_data[i]);
+ cupsFilePrintf(fp, "<%02X", sub->user_data[j]);
hex = 1;
}
else
- cupsFilePrintf(fp, "%02X", sub->user_data[i]);
+ cupsFilePrintf(fp, "%02X", sub->user_data[j]);
}
else
{
if (hex)
{
- cupsFilePrintf(fp, ">%c", sub->user_data[i]);
+ cupsFilePrintf(fp, ">%c", sub->user_data[j]);
hex = 0;
}
else
- cupsFilePutChar(fp, sub->user_data[i]);
+ cupsFilePutChar(fp, sub->user_data[j]);
}
}
cupsFilePuts(fp, "</Subscription>\n");
}
+ cupsRWUnlock(&SubscriptionsLock);
+
cupsdCloseCreatedConfFile(fp, filename);
}
* Allocate the events array as needed...
*/
+ cupsRWLockWrite(&sub->lock);
+
if (!sub->events)
{
sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
*/
sub->next_event_id ++;
+
+ cupsRWUnlock(&sub->lock);
}
typedef struct cupsd_subscription_s /**** Subscription structure ****/
{
+ cups_rwlock_t lock; /* Reader/writer lock */
int id; /* subscription-id */
unsigned mask; /* Event mask */
char *owner; /* notify-subscriber-user-name */
* Globals...
*/
-VAR int MaxSubscriptions VALUE(100),
+VAR int MaxSubscriptions VALUE(100),
/* Overall subscription limit */
- MaxSubscriptionsPerJob VALUE(0),
+ MaxSubscriptionsPerJob VALUE(0),
/* Per-job subscription limit */
MaxSubscriptionsPerPrinter VALUE(0),
/* Per-printer subscription limit */
- MaxSubscriptionsPerUser VALUE(0),
+ MaxSubscriptionsPerUser VALUE(0),
/* Per-user subscription limit */
- NextSubscriptionId VALUE(1),
+ NextSubscriptionId VALUE(1),
/* Next subscription ID */
- DefaultLeaseDuration VALUE(86400),
+ DefaultLeaseDuration VALUE(86400),
/* Default notify-lease-duration */
- MaxLeaseDuration VALUE(0);
+ MaxLeaseDuration VALUE(0);
/* Maximum notify-lease-duration */
-VAR cups_array_t *Subscriptions VALUE(NULL);
+VAR cups_array_t *Subscriptions VALUE(NULL);
/* Active subscriptions */
-
-VAR int MaxEvents VALUE(100); /* Maximum number of events */
-
-VAR unsigned LastEvent VALUE(0); /* Last event(s) processed */
-VAR int NotifierPipes[2] VALUE2(-1, -1);
+VAR cups_rwlock_t SubscriptionsLock VALUE(CUPS_RWLOCK_INITIALIZER);
+ /* Reader/writer lock for subscriptions */
+VAR int MaxEvents VALUE(100);
+ /* Maximum number of events */
+
+VAR unsigned LastEvent VALUE(0);
+ /* Last event(s) processed */
+VAR int NotifierPipes[2] VALUE2(-1, -1);
/* Pipes for notifier error/debug output */
VAR cupsd_statbuf_t *NotifierStatusBuffer VALUE(NULL);
/* Status buffer for pipes */