summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2010-08-27 14:44:16 +0200
committerVolker Lendecke <vl@samba.org>2010-08-27 16:47:07 +0200
commite8cfc2f1de4b60f192a391dd02e405a152a7d5a6 (patch)
tree7c3e382043fb33f144a89bd0fb0df95eb1cc5919
parent44b2a7941c1da4c565cb14bae7acc355787ecc6e (diff)
downloadsamba-e8cfc2f1de4b60f192a391dd02e405a152a7d5a6.tar.gz
samba-e8cfc2f1de4b60f192a391dd02e405a152a7d5a6.tar.bz2
samba-e8cfc2f1de4b60f192a391dd02e405a152a7d5a6.zip
s3: Cache results of finding printer names
With hundreds of printers or on a slow machine, this can become expensive. Problem reported and patch sponsored by DESY, Hamburg (www.desy.de)
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 5df20d4f08..4e97122736 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -470,6 +470,14 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
struct spoolss_PrinterInfo2 *info2 = NULL;
WERROR result;
+ /*
+ * Hopefully nobody names his printers like this. Maybe \ or ,
+ * are illegal in printer names even?
+ */
+ const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
+ char *cache_key;
+ char *tmp;
+
DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
(unsigned long)strlen(handlename)));
@@ -509,6 +517,27 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
found = true;
}
+ /*
+ * With hundreds of printers, the "for" loop iterating all
+ * shares can be quite expensive, as it is done on every
+ * OpenPrinter. The loop maps "aprinter" to "sname", the
+ * result of which we cache in gencache.
+ */
+
+ cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
+ aprinter);
+ if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
+
+ found = (strcmp(tmp, printer_not_found) != 0);
+ if (!found) {
+ DEBUG(4, ("Printer %s not found\n", aprinter));
+ SAFE_FREE(tmp);
+ return false;
+ }
+ fstrcpy(sname, tmp);
+ SAFE_FREE(tmp);
+ }
+
/* Search all sharenames first as this is easier than pulling
the printer_info_2 off of disk. Don't use find_service() since
that calls out to map_username() */
@@ -569,10 +598,20 @@ static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
}
if ( !found ) {
+ if (cache_key != NULL) {
+ gencache_set(cache_key, printer_not_found,
+ time(NULL)+300);
+ TALLOC_FREE(cache_key);
+ }
DEBUGADD(4,("Printer not found\n"));
return false;
}
+ if (cache_key != NULL) {
+ gencache_set(cache_key, sname, time(NULL)+300);
+ TALLOC_FREE(cache_key);
+ }
+
DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
fstrcpy(Printer->sharename, sname);