The branch, master has been updated via 1ad71f7 printing: reload printer shares on OpenPrinter via 2706af4 smbd: split printer reload processing via 2685df1 server: remove duplicate snum_is_shared_printer() via a2182e0 smbd: only reprocess printer_list.tdb if it changed via 30ce835 printing: return last change time with pcap_cache_loaded() via 6d75e20 printing: remove pcap_cache_add() via e5e6e2c printing: reload printer_list.tdb from in memory list via 4f4501a printing: only reload printer shares on client enum via 1e83435 printing: traverse_read the printer list for share updates from 9c5470b lib/krb5_wrap: provide krb5_warnx() replacement.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 1ad71f79eb473822d36d9629cf52c2fca4c53752 Author: David Disseldorp <dd...@samba.org> Date: Tue Aug 5 17:33:33 2014 +0200 printing: reload printer shares on OpenPrinter The printer share inventory should be reloaded on open _and_ enumeration, as there are some clients, such as cupsaddsmb, that do not perform an enumeration prior to access. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> Autobuild-User(master): Andreas Schneider <a...@cryptomilk.org> Autobuild-Date(master): Fri Aug 8 16:33:50 CEST 2014 on sn-devel-104 commit 2706af4d78fc9a47a4ac45b373edf276e3a9b354 Author: David Disseldorp <dd...@samba.org> Date: Fri Aug 1 16:25:59 2014 +0200 smbd: split printer reload processing All printer inventory updates are currently done via delete_and_reload_printers(), which handles registry.tdb updates for added or removed printers, AD printer unpublishing on removal, as well as share service creation and deletion. This change splits this functionality into two functions such that per-client smbd processes do not perform registry.tdb updates or printer unpublishing. This is now only performed by the process that performs the printcap cache update. This change is similar to ac6604868d1325dd4c872dc0f6ab056d10ebaecf from the 3.6 branch. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 2685df1177ffd39b1af34eb116bd7b24d4b12974 Author: David Disseldorp <dd...@samba.org> Date: Tue Aug 5 18:45:24 2014 +0200 server: remove duplicate snum_is_shared_printer() Only keep a single definition in server_reload.c Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit a2182e03a061de6c1f111ce083cb5f668fe75e4e Author: David Disseldorp <dd...@samba.org> Date: Wed Jul 23 14:42:00 2014 +0200 smbd: only reprocess printer_list.tdb if it changed The per-client smbd printer share inventory is currently updated from printer_list.tdb when a client enumerates printers, via EnumPrinters or NetShareEnum. printer_list.tdb is populated by the background print process, based on the latest printcap values retrieved from the printing backend (e.g. CUPS) at regular intervals. This change ensures that per-client smbd processes don't reparse printer_list.tdb if it hasn't been updated since the last enumeration. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Suggested-by: Volker Lendecke <v...@samba.org> Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 30ce835670a6aeca6fb960ea7c4fe1b982bdd5b0 Author: David Disseldorp <dd...@samba.org> Date: Wed Jul 23 12:12:34 2014 +0200 printing: return last change time with pcap_cache_loaded() Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 6d75e20ca8acf1a55838694ac77940e21e9a1e6a Author: David Disseldorp <dd...@samba.org> Date: Fri Jul 25 12:18:54 2014 +0200 printing: remove pcap_cache_add() All print list updates are now done via pcap_cache_replace(), which can call into the print_list code directly. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit e5e6e2c796f026ee6b04f99b327941d57b9bd026 Author: David Disseldorp <dd...@samba.org> Date: Tue Jul 22 20:17:38 2014 +0200 printing: reload printer_list.tdb from in memory list This will allow in future for a single atomic printer_list.tdb update. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 4f4501ac1f35ab15f25d207c0d33e7c4d1abdf38 Author: David Disseldorp <dd...@samba.org> Date: Fri Jul 11 17:00:05 2014 +0200 printing: only reload printer shares on client enum Currently, automatic printer share updates are handled in the following way: - Background printer process (BPP) forked on startup - Parent smbd and per-client children await MSG_PRINTER_PCAP messages - BPP periodically polls the printing backend for printcap data - printcap data written to printer_list.tdb - MSG_PRINTER_PCAP sent to all smbd processes following update - smbd processes all read the latest printer_list.tdb data, and update their share listings This procedure is not scalable, as all smbd processes hit printer_list.tdb in parallel, resulting in a large spike in CPU usage. This change sees smbd processes only update their printer share lists only when a client asks for this information, e.g. via NetShareEnum or EnumPrinters. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Suggested-by: Volker Lendecke <v...@samba.org> Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> commit 1e83435eac2cef03fccb4cf69ef5e0bfbd710410 Author: David Disseldorp <dd...@samba.org> Date: Thu Jul 10 00:18:10 2014 +0200 printing: traverse_read the printer list for share updates The printcap update procedure involves the background printer process obtaining the printcap information from the printing backend, writing this to printer_list.tdb, and then notifying all smbd processes of the new list. The processes then all attempt to simultaneously traverse printer_list.tdb, in order to update their local share lists. With a large number of printers, and a large number of per-client smbd processes, this traversal results in significant lock contention, mostly due to the fact that the traversal is unnecessarily done with an exclusive (write) lock on the printer_list.tdb database. This commit changes the share update code path to perform a read-only traversal. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10652 Reported-by: Alex K <korobkin+sa...@gmail.com> Reported-by: Franz Pförtsch <franz.pfoert...@brose.com> Signed-off-by: David Disseldorp <dd...@samba.org> Reviewed-by: Andreas Schneider <a...@samba.org> ----------------------------------------------------------------------- Summary of changes: source3/printing/load.c | 4 +- source3/printing/pcap.c | 54 +++++++------- source3/printing/pcap.h | 13 ++-- source3/printing/print_aix.c | 17 ++++- source3/printing/print_iprint.c | 16 +++-- source3/printing/print_standard.c | 8 ++- source3/printing/print_svid.c | 11 ++- source3/printing/printer_list.c | 17 +++-- source3/printing/printer_list.h | 4 +- source3/printing/queue_process.c | 102 +++++++++++++++++++++++++- source3/printing/spoolssd.c | 38 ++-------- source3/rpc_server/spoolss/srv_spoolss_nt.c | 30 +++++--- source3/rpc_server/srvsvc/srv_srvsvc_nt.c | 1 + source3/smbd/lanman.c | 1 + source3/smbd/proto.h | 1 + source3/smbd/server.c | 20 ----- source3/smbd/server_reload.c | 74 ++++++++------------ 17 files changed, 241 insertions(+), 170 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/printing/load.c b/source3/printing/load.c index 136d055..238998d 100644 --- a/source3/printing/load.c +++ b/source3/printing/load.c @@ -65,11 +65,11 @@ load automatic printer services from pre-populated pcap cache void load_printers(struct tevent_context *ev, struct messaging_context *msg_ctx) { - SMB_ASSERT(pcap_cache_loaded()); + SMB_ASSERT(pcap_cache_loaded(NULL)); add_auto_printers(); /* load all printcap printers */ if (lp_load_printers() && lp_servicenumber(PRINTERS_NAME) >= 0) - pcap_printer_fn(lp_add_one_printer, NULL); + pcap_printer_read_fn(lp_add_one_printer, NULL); } diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c index dd7ba62..c5524ad 100644 --- a/source3/printing/pcap.c +++ b/source3/printing/pcap.c @@ -83,28 +83,26 @@ void pcap_cache_destroy_specific(struct pcap_cache **pp_cache) *pp_cache = NULL; } -bool pcap_cache_add(const char *name, const char *comment, const char *location) -{ - NTSTATUS status; - time_t t = time_mono(NULL); - - status = printer_list_set_printer(talloc_tos(), name, comment, location, t); - return NT_STATUS_IS_OK(status); -} - -bool pcap_cache_loaded(void) +bool pcap_cache_loaded(time_t *_last_change) { NTSTATUS status; time_t last; status = printer_list_get_last_refresh(&last); - return NT_STATUS_IS_OK(status); + if (!NT_STATUS_IS_OK(status)) { + return false; + } + if (_last_change != NULL) { + *_last_change = last; + } + return true; } bool pcap_cache_replace(const struct pcap_cache *pcache) { const struct pcap_cache *p; NTSTATUS status; + time_t t = time_mono(NULL); status = printer_list_mark_reload(); if (!NT_STATUS_IS_OK(status)) { @@ -113,7 +111,11 @@ bool pcap_cache_replace(const struct pcap_cache *pcache) } for (p = pcache; p; p = p->next) { - pcap_cache_add(p->name, p->comment, p->location); + status = printer_list_set_printer(talloc_tos(), p->name, + p->comment, p->location, t); + if (!NT_STATUS_IS_OK(status)) { + return false; + } } status = printer_list_clean_old(); @@ -132,8 +134,8 @@ void pcap_cache_reload(struct tevent_context *ev, { const char *pcap_name = lp_printcapname(); bool pcap_reloaded = False; - NTSTATUS status; bool post_cache_fill_fn_handled = false; + struct pcap_cache *pcache = NULL; DEBUG(3, ("reloading printcap cache\n")); @@ -143,12 +145,6 @@ void pcap_cache_reload(struct tevent_context *ev, return; } - status = printer_list_mark_reload(); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to mark printer list for reload!\n")); - return; - } - #ifdef HAVE_CUPS if (strequal(pcap_name, "cups")) { pcap_reloaded = cups_cache_reload(ev, msg_ctx, @@ -164,26 +160,26 @@ void pcap_cache_reload(struct tevent_context *ev, #ifdef HAVE_IPRINT if (strequal(pcap_name, "iprint")) { - pcap_reloaded = iprint_cache_reload(); + pcap_reloaded = iprint_cache_reload(&pcache); goto done; } #endif #if defined(SYSV) || defined(HPUX) if (strequal(pcap_name, "lpstat")) { - pcap_reloaded = sysv_cache_reload(); + pcap_reloaded = sysv_cache_reload(&pcache); goto done; } #endif #ifdef AIX if (strstr_m(pcap_name, "/qconfig") != NULL) { - pcap_reloaded = aix_cache_reload(); + pcap_reloaded = aix_cache_reload(&pcache); goto done; } #endif - pcap_reloaded = std_pcap_cache_reload(pcap_name); + pcap_reloaded = std_pcap_cache_reload(pcap_name, &pcache); done: DEBUG(3, ("reload status: %s\n", (pcap_reloaded) ? "ok" : "error")); @@ -192,14 +188,16 @@ done: /* cleanup old entries only if the operation was successful, * otherwise keep around the old entries until we can * successfully reload */ - status = printer_list_clean_old(); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0, ("Failed to cleanup printer list!\n")); + + if (!pcap_cache_replace(pcache)) { + DEBUG(0, ("Failed to replace printer list!\n")); } + if (post_cache_fill_fn != NULL) { post_cache_fill_fn(ev, msg_ctx); } } + pcap_cache_destroy_specific(&pcache); return; } @@ -229,11 +227,11 @@ void pcap_printer_fn_specific(const struct pcap_cache *pc, return; } -void pcap_printer_fn(void (*fn)(const char *, const char *, const char *, void *), void *pdata) +void pcap_printer_read_fn(void (*fn)(const char *, const char *, const char *, void *), void *pdata) { NTSTATUS status; - status = printer_list_run_fn(fn, pdata); + status = printer_list_read_run_fn(fn, pdata); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Failed to run fn for all printers!\n")); } diff --git a/source3/printing/pcap.h b/source3/printing/pcap.h index 7056213..8fc9e9d 100644 --- a/source3/printing/pcap.h +++ b/source3/printing/pcap.h @@ -35,11 +35,10 @@ struct pcap_cache; bool pcap_cache_add_specific(struct pcap_cache **ppcache, const char *name, const char *comment, const char *location); void pcap_cache_destroy_specific(struct pcap_cache **ppcache); -bool pcap_cache_add(const char *name, const char *comment, const char *location); -bool pcap_cache_loaded(void); +bool pcap_cache_loaded(time_t *_last_change); bool pcap_cache_replace(const struct pcap_cache *cache); void pcap_printer_fn_specific(const struct pcap_cache *, void (*fn)(const char *, const char *, const char *, void *), void *); -void pcap_printer_fn(void (*fn)(const char *, const char *, const char *, void *), void *); +void pcap_printer_read_fn(void (*fn)(const char *, const char *, const char *, void *), void *); void pcap_cache_reload(struct tevent_context *ev, struct messaging_context *msg_ctx, @@ -49,7 +48,7 @@ bool pcap_printername_ok(const char *printername); /* The following definitions come from printing/print_aix.c */ -bool aix_cache_reload(void); +bool aix_cache_reload(struct pcap_cache **_pcache); /* The following definitions come from printing/print_cups.c */ @@ -60,13 +59,13 @@ bool cups_cache_reload(struct tevent_context *ev, /* The following definitions come from printing/print_iprint.c */ -bool iprint_cache_reload(void); +bool iprint_cache_reload(struct pcap_cache **_pcache); /* The following definitions come from printing/print_svid.c */ -bool sysv_cache_reload(void); +bool sysv_cache_reload(struct pcap_cache **_pcache); /* The following definitions come from printing/print_standard.c */ -bool std_pcap_cache_reload(const char *pcap_name); +bool std_pcap_cache_reload(const char *pcap_name, struct pcap_cache **_pcache); #endif /* _PRINTING_PCAP_H_ */ diff --git a/source3/printing/print_aix.c b/source3/printing/print_aix.c index 23d9a86..927a71b 100644 --- a/source3/printing/print_aix.c +++ b/source3/printing/print_aix.c @@ -29,12 +29,13 @@ #include "printing/pcap.h" #ifdef AIX -bool aix_cache_reload(void) +bool aix_cache_reload(struct pcap_cache **_pcache) { int iEtat; XFILE *pfile; char *line = NULL, *p; char *name = NULL; + struct pcap_cache *pcache = NULL; TALLOC_CTX *ctx = talloc_init("aix_cache_reload"); if (!ctx) { @@ -52,6 +53,8 @@ bool aix_cache_reload(void) iEtat = 0; /* scan qconfig file for searching <printername>: */ for (;(line = fgets_slash(NULL, 1024, pfile)); free(line)) { + bool ok; + if (*line == '*' || *line == 0) continue; @@ -67,6 +70,7 @@ bool aix_cache_reload(void) if (strcmp(p, "bsh") != 0) { name = talloc_strdup(ctx, p); if (!name) { + pcap_cache_destroy_specific(&pcache); SAFE_FREE(line); x_fclose(pfile); TALLOC_FREE(ctx); @@ -86,7 +90,10 @@ bool aix_cache_reload(void) /* name is found without stanza device */ /* probably a good printer ??? */ iEtat = 0; - if (!pcap_cache_add(name, NULL, NULL)) { + ok = pcap_cache_add_specific(&pcache, + name, NULL, NULL); + if (!ok) { + pcap_cache_destroy_specific(&pcache); SAFE_FREE(line); x_fclose(pfile); TALLOC_FREE(ctx); @@ -101,7 +108,10 @@ bool aix_cache_reload(void) } else if (strstr_m(line, "device")) { /* it's a good virtual printer */ iEtat = 0; - if (!pcap_cache_add(name, NULL, NULL)) { + ok = pcap_cache_add_specific(&pcache, + name, NULL, NULL); + if (!ok) { + pcap_cache_destroy_specific(&pcache); SAFE_FREE(line); x_fclose(pfile); TALLOC_FREE(ctx); @@ -113,6 +123,7 @@ bool aix_cache_reload(void) } } + *_pcache = pcache; x_fclose(pfile); TALLOC_FREE(ctx); return true; diff --git a/source3/printing/print_iprint.c b/source3/printing/print_iprint.c index ad61a0a..eeb193c 100644 --- a/source3/printing/print_iprint.c +++ b/source3/printing/print_iprint.c @@ -206,7 +206,8 @@ static int iprint_get_server_version(http_t *http, char* serviceUri) static int iprint_cache_add_printer(http_t *http, int reqId, - char* url) + char *url, + struct pcap_cache **pcache) { ipp_t *request = NULL, /* IPP Request */ *response = NULL; /* IPP Response */ @@ -342,7 +343,7 @@ static int iprint_cache_add_printer(http_t *http, */ if (name != NULL && !secure && smb_enabled) - pcap_cache_add(name, info, NULL); + pcap_cache_add_specific(pcache, name, info, NULL); } out: @@ -351,7 +352,7 @@ static int iprint_cache_add_printer(http_t *http, return(0); } -bool iprint_cache_reload(void) +bool iprint_cache_reload(struct pcap_cache **_pcache) { http_t *http = NULL; /* HTTP connection to server */ ipp_t *request = NULL, /* IPP Request */ @@ -359,7 +360,8 @@ bool iprint_cache_reload(void) ipp_attribute_t *attr; /* Current attribute */ cups_lang_t *language = NULL; /* Default language */ int i; - bool ret = False; + bool ret = false; + struct pcap_cache *pcache = NULL; DEBUG(5, ("reloading iprint printcap cache\n")); @@ -441,14 +443,16 @@ bool iprint_cache_reload(void) char *url = ippGetString(attr, i, NULL); if (!url || !strlen(url)) continue; - iprint_cache_add_printer(http, i+2, url); + iprint_cache_add_printer(http, i+2, url, + &pcache); } } attr = ippNextAttribute(response); } } - ret = True; + ret = true; + *_pcache = pcache; out: if (response) diff --git a/source3/printing/print_standard.c b/source3/printing/print_standard.c index c4f9c5b..b5f1056 100644 --- a/source3/printing/print_standard.c +++ b/source3/printing/print_standard.c @@ -59,10 +59,11 @@ #include "printing/pcap.h" /* handle standard printcap - moved from pcap_printer_fn() */ -bool std_pcap_cache_reload(const char *pcap_name) +bool std_pcap_cache_reload(const char *pcap_name, struct pcap_cache **_pcache) { XFILE *pcap_file; char *pcap_line; + struct pcap_cache *pcache = NULL; if ((pcap_file = x_fopen(pcap_name, O_RDONLY, 0)) == NULL) { DEBUG(0, ("Unable to open printcap file %s for read!\n", pcap_name)); @@ -117,12 +118,15 @@ bool std_pcap_cache_reload(const char *pcap_name) } } - if (*name && !pcap_cache_add(name, comment, NULL)) { + if ((*name != '\0') + && !pcap_cache_add_specific(&pcache, name, comment, NULL)) { x_fclose(pcap_file); + pcap_cache_destroy_specific(&pcache); return false; } } x_fclose(pcap_file); + *_pcache = pcache; return true; } diff --git a/source3/printing/print_svid.c b/source3/printing/print_svid.c index 2226493..879661b 100644 --- a/source3/printing/print_svid.c +++ b/source3/printing/print_svid.c @@ -35,10 +35,11 @@ #include "printing/pcap.h" #if defined(SYSV) || defined(HPUX) -bool sysv_cache_reload(void) +bool sysv_cache_reload(struct pcap_cache **_pcache) { char **lines; int i; + struct pcap_cache *pcache = NULL; #if defined(HPUX) DEBUG(5, ("reloading hpux printcap cache\n")); @@ -111,14 +112,16 @@ bool sysv_cache_reload(void) *tmp = '\0'; /* add it to the cache */ - if (!pcap_cache_add(name, NULL, NULL)) { + if (!pcap_cache_add_specific(&pcache, name, NULL, NULL)) { TALLOC_FREE(lines); - return False; + pcap_cache_destroy_specific(&pcache); + return false; } } TALLOC_FREE(lines); - return True; + *_pcache = pcache; + return true; } #else diff --git a/source3/printing/printer_list.c b/source3/printing/printer_list.c index 4a66b96..9a9fa0b 100644 --- a/source3/printing/printer_list.c +++ b/source3/printing/printer_list.c @@ -284,7 +284,8 @@ done: typedef int (printer_list_trv_fn_t)(struct db_record *, void *); static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn, - void *private_data) + void *private_data, + bool read_only) { struct db_context *db; NTSTATUS status; @@ -294,7 +295,11 @@ static NTSTATUS printer_list_traverse(printer_list_trv_fn_t *fn, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = dbwrap_traverse(db, fn, private_data, NULL); + if (read_only) { + status = dbwrap_traverse_read(db, fn, private_data, NULL); + } else { + status = dbwrap_traverse(db, fn, private_data, NULL); + } return status; } @@ -364,7 +369,7 @@ NTSTATUS printer_list_clean_old(void) state.status = NT_STATUS_OK; - status = printer_list_traverse(printer_list_clean_fn, &state); + status = printer_list_traverse(printer_list_clean_fn, &state, false); if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) && !NT_STATUS_IS_OK(state.status)) { status = state.status; @@ -417,8 +422,8 @@ static int printer_list_exec_fn(struct db_record *rec, void *private_data) return 0; } -NTSTATUS printer_list_run_fn(void (*fn)(const char *, const char *, const char *, void *), - void *private_data) +NTSTATUS printer_list_read_run_fn(void (*fn)(const char *, const char *, const char *, void *), + void *private_data) { struct printer_list_exec_state state; NTSTATUS status; @@ -427,7 +432,7 @@ NTSTATUS printer_list_run_fn(void (*fn)(const char *, const char *, const char * state.private_data = private_data; state.status = NT_STATUS_OK; - status = printer_list_traverse(printer_list_exec_fn, &state); + status = printer_list_traverse(printer_list_exec_fn, &state, true); if (NT_STATUS_EQUAL(status, NT_STATUS_UNSUCCESSFUL) && !NT_STATUS_IS_OK(state.status)) { status = state.status; diff --git a/source3/printing/printer_list.h b/source3/printing/printer_list.h index fb2e007..b12c192 100644 --- a/source3/printing/printer_list.h +++ b/source3/printing/printer_list.h @@ -100,6 +100,6 @@ NTSTATUS printer_list_mark_reload(void); */ NTSTATUS printer_list_clean_old(void); -NTSTATUS printer_list_run_fn(void (*fn)(const char *, const char *, const char *, void *), - void *private_data); +NTSTATUS printer_list_read_run_fn(void (*fn)(const char *, const char *, const char *, void *), + void *private_data); #endif /* _PRINTER_LIST_H_ */ diff --git a/source3/printing/queue_process.c b/source3/printing/queue_process.c index aa0d0fb..88196b4 100644 --- a/source3/printing/queue_process.c +++ b/source3/printing/queue_process.c @@ -33,10 +33,102 @@ #include "rpc_server/rpc_config.h" #include "printing/load.h" #include "rpc_server/spoolss/srv_spoolss_nt.h" +#include "auth.h" +#include "nt_printing.h" extern pid_t start_spoolssd(struct tevent_context *ev_ctx, struct messaging_context *msg_ctx); +/** + * @brief Purge stale printers and reload from pre-populated pcap cache. + * + * This function should normally only be called as a callback on a successful + * pcap_cache_reload(). + * + * This function can cause DELETION of printers and drivers from our registry, + * so calling it on a failed pcap reload may REMOVE permanently all printers + * and drivers. + * + * @param[in] ev The event context. + * -- Samba Shared Repository