Hello all!
I've included a patch which reloads acl-files when they have changed.
It is against squid-1.1.16 and my squids are running with this patch
for several days now (before that, it ran on 1.1.8 for several weeks ...)
I am reloading a large acl file with ~3000 entires 2-3 times a day.
But: Why not give squid a configure-interface like innd. squid would
wait on one end of a named pipe and then a simple program, maybe called
"ctlsquid" (from ctlinnd) could write simple commands like "reload acls"
to this pipe.
That's all!
And here's the patch:
diff -c squid-1.1.16/src/acl.c squid-1.1.16.1/src/acl.c
*** squid-1.1.16/src/acl.c	Thu Apr 24 21:43:17 1997
--- squid-1.1.16.1/src/acl.c	Mon Sep  1 09:25:46 1997
***************
*** 56,61 ****
--- 56,65 ----
  static int aclFromFile = 0;
  static FILE *aclFile;
  
+ /* These two to transport info from strtokFile to aclParseAclLine */
+ time_t aclfile_last_read_st_mtime = 0;
+ char *aclfile_last_read_filename = NULL;
+ 
  static void aclDestroyAclList _PARAMS((struct _acl_list * list));
  static void aclDestroyTimeList _PARAMS((struct _acl_time_data * data));
  static int aclMatchAclList _PARAMS((const struct _acl_list *, aclCheck_t *));
***************
*** 104,109 ****
--- 108,114 ----
  strtokFile(void)
  {
      char *t, *fn;
+     struct stat filestat;
      LOCAL_ARRAY(char, buf, 256);
  
    strtok_again:
***************
*** 120,130 ****
--- 125,142 ----
                  return (NULL);
              }
              aclFromFile = 1;
+             if(stat(fn, &filestat)) {
+               debug(28,0, "strtokFile: %s: cannot stat\n", fn);
+             } else {
+               aclfile_last_read_st_mtime = filestat.st_mtime;
+               aclfile_last_read_filename = xstrdup(fn);
+             }
          } else {
              return (t);
          }
      }
      /* aclFromFile */
+     read_again:
      if (fgets(buf, 256, aclFile) == NULL) {
          /* stop reading from file */
          fclose(aclFile);
***************
*** 135,140 ****
--- 147,157 ----
          /* skip leading and trailing white space */
          t += strspn(buf, w_space);
          t[strcspn(t, w_space)] = '\0';
+         if(*t == '#') /* Allow comments */
+            goto read_again;
+         if(strlen(t) == 0) /* Allow blank lines */
+            goto read_again;
+ 
          return (t);
      }
  }
***************
*** 654,659 ****
--- 671,685 ----
          debug_trap("Bad ACL type");
          break;
      }
+ 
+     if(aclfile_last_read_st_mtime) {
+       A->aclfile_st_mtime = aclfile_last_read_st_mtime;
+       aclfile_last_read_st_mtime = 0;
+       A->aclfile_filename = xstrdup(aclfile_last_read_filename);
+       safe_free(aclfile_last_read_filename);
+       A->aclfile_last_checked = squid_curtime;
+     }
+ 
      if (!new_acl)
          return;
      if (A->data == NULL) {
***************
*** 1047,1055 ****
--- 1073,1170 ----
      const request_t *r = checklist->request;
      const ipcache_addrs *ia = NULL;
      const char *fqdn = NULL;
+     char *my_cfgline;
      int k;
+     struct stat filestat;
+ 
      if (!acl)
          return 0;
+ 
+     if(acl->aclfile_last_checked && (squid_curtime - acl->aclfile_last_checked) > Config.aclfile_CheckInterval) {
+       debug(28,2, "aclMatchAcl: checking if aclfile \"%s\" has changed\n", acl->aclfile_filename);
+       if(stat(acl->aclfile_filename, &filestat)) {
+         debug(28,0, "aclMatchAcl: cannot stat \"%s\"\n", acl->aclfile_filename);
+       } else {
+         if(filestat.st_mtime > acl->aclfile_st_mtime) {
+           debug(28,1, "aclMatchAcl: re-reading aclfile \"%s\"\n", acl->aclfile_filename);
+ 
+           /* Reinitialize strtok */
+           my_cfgline = xstrdup(acl->cfgline);
+           strtok(my_cfgline, w_space); /* acl */
+           strtok(NULL, w_space);         /* name */
+           strtok(NULL, w_space);         /* type */
+ 
+           /* Delete old acl->data  and re-read it */
+           switch (acl->type) {
+             case ACL_SRC_IP:
+             case ACL_DST_IP:
+ #if defined (USE_SPLAY_TREE)
+               splay_destroy(acl->data, xfree);
+ #elif defined(USE_BIN_TREE)
+               aclDestroyTree(acl->data);
+ #else /* LINKED LIST */
+               aclDestroyIpList(acl->data);
+ #endif
+               acl->data = NULL;
+               aclParseIpList(&acl->data);
+               break;
+             case ACL_DST_DOMAIN:
+             case ACL_SRC_DOMAIN:
+ #if defined(USE_SPLAY_TREE)
+               splay_destroy(acl->data, xfree);
+ #elif defined(USE_BIN_TREE)
+               aclDestroyTree(acl->data);
+ #else /* LINKED LIST */
+               wordlistDestroy((wordlist **) & acl->data);
+ #endif
+               acl->data = NULL;
+               aclParseDomainList(&acl->data);
+               break;
+             case ACL_USER:
+               wordlistDestroy((wordlist **) & acl->data);
+               Config.identLookup = 1;
+               acl->data = NULL;
+               aclParseWordList(&acl->data);
+               break;
+             case ACL_TIME:
+               aclDestroyTimeList(acl->data);
+               acl->data = NULL;
+               aclParseTimeSpec(&acl->data);
+               break;
+             case ACL_URL_REGEX:
+             case ACL_URLPATH_REGEX:
+             case ACL_BROWSER:
+               aclDestroyRegexList(acl->data);
+               acl->data = NULL;
+               aclParseRegexList(&acl->data, 0);
+               break;
+             case ACL_URL_PORT:
+               intlistDestroy((intlist **) & acl->data);
+               acl->data = NULL;
+               aclParseIntlist(&acl->data);
+               break;
+             case ACL_PROTO:
+               intlistDestroy((intlist **) & acl->data);
+               acl->data = NULL;
+               aclParseProtoList(&acl->data);
+             case ACL_METHOD:
+               intlistDestroy((intlist **) & acl->data);
+               acl->data = NULL;
+               aclParseMethodList(&acl->data);
+               break;
+             case ACL_NONE:
+               default:
+             fatal_dump("aclDestroyAcls: Found ACL_NONE?");
+               break;
+           }
+           xfree(my_cfgline);
+ 
+           acl->aclfile_st_mtime = filestat.st_mtime;
+         }
+         acl->aclfile_last_checked = squid_curtime;
+       }
+     }
+ 
      debug(28, 3, "aclMatchAcl: checking '%s'\n", acl->cfgline);
      switch (acl->type) {
      case ACL_SRC_IP:
diff -c squid-1.1.16/src/acl.h squid-1.1.16.1/src/acl.h
*** squid-1.1.16/src/acl.h	Thu Feb 20 22:03:10 1997
--- squid-1.1.16.1/src/acl.h	Mon Sep  1 10:02:07 1997
***************
*** 96,101 ****
--- 96,104 ----
      squid_acl type;
      void *data;
      char *cfgline;
+     char *aclfile_filename;
+     time_t aclfile_last_checked;
+     time_t aclfile_st_mtime;
      struct _acl *next;
  };
  
diff -c squid-1.1.16/src/cache_cf.c squid-1.1.16.1/src/cache_cf.c
*** squid-1.1.16/src/cache_cf.c	Thu Aug 21 21:17:04 1997
--- squid-1.1.16.1/src/cache_cf.c	Mon Sep  1 09:31:03 1997
***************
*** 209,215 ****
--- 209,217 ----
  #define DefaultOptionsClientDb	1	/* default on */
  #define DefaultOptionsQueryIcmp	0	/* default off */
  
+ #define DefaultAclFileCheckInterval 300
  
+ 
  int httpd_accel_mode = 0;	/* for fast access */
  const char *DefaultSwapDir = DEFAULT_SWAP_DIR;
  const char *DefaultConfigFile = DEFAULT_CONFIG_FILE;
***************
*** 1143,1148 ****
--- 1145,1153 ----
          else if (!strcmp(token, "acl"))
              aclParseAclLine();
  
+         else if (!strcmp(token, "aclfile_checkinterval"))
+            parseIntegerValue(&Config.aclfile_CheckInterval);
+ 
          else if (!strcmp(token, "deny_info"))
              aclParseDenyInfoLine(&DenyInfoList);
  
***************
*** 1611,1616 ****
--- 1620,1626 ----
      Config.Options.anonymizer = DefaultOptionsAnonymizer;
      Config.Options.icp_hit_stale = DefaultOptionsIcpHitStale;
      Config.Options.enable_purge = DefaultOptionsEnablePurge;
+     Config.aclfile_CheckInterval = DefaultAclFileCheckInterval;
      Config.Options.client_db = DefaultOptionsClientDb;
      Config.Options.query_icmp = DefaultOptionsQueryIcmp;
  #ifdef RELOAD_INTO_IMS
diff -c squid-1.1.16/src/cache_cf.h squid-1.1.16.1/src/cache_cf.h
*** squid-1.1.16/src/cache_cf.h	Thu Aug  7 22:49:23 1997
--- squid-1.1.16.1/src/cache_cf.h	Mon Sep  1 09:33:23 1997
***************
*** 282,287 ****
--- 283,289 ----
          int reload_into_ims;
  #endif				/* RELOAD_INTO_IMS */
      } Options;
+     int aclfile_CheckInterval;
      char *fake_ua;
  };
  
diff -c squid-1.1.16/src/squid.conf.pre.in squid-1.1.16.1/src/squid.conf.pre.in
*** squid-1.1.16/src/squid.conf.pre.in	Thu Aug  7 22:38:02 1997
--- squid-1.1.16.1/src/squid.conf.pre.in	Mon Sep  1 09:39:43 1997
***************
*** 1166,1171 ****
--- 1166,1180 ----
  #
  #http_anonymizer off
  
+ #  TAG: aclfile_checkinterval
+ #       If you are using config files for your acls, these files
+ #       are checked for changes after this interval.
+ #       If the modification time has changed, they are reloaded.
+ #
+ #       default are 300 seconds
+ #aclfile_checkinterval 300
+ 
+ 
  #  TAG: fake_user_agent
  #	If you use the paranoid http_anonymizer setting, Squid will strip
  #	your User-agent string from the request.  Some Web servers will
Received on Tue Jul 29 2003 - 13:15:43 MDT
This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:11:25 MST