Harold's Blog -- 个人技术笔记

所有原创文章  |  个人分享(公开)  |  关于
02 Aug 2013

Squid定制开发(二)之怎样在不影响业务的情况下重新加载hosts文件(增量模式)

Squid定制开发(二)之怎样在不影响业务的情况下重新加载hosts文件(增量模式)

NOTE: 原创文章,转载请注明:转载自 blog.miaohong.org 本文链接地址: http://blog.miaohong.org/2013/08/02/squid_reconfig2.html

接上文,如果考虑到hosts文件很大的情况下,前面的替换方案效率可能会有影响。所以引入增量方式,具体来说:

假设 hosts文件内容如下
[root@miaohong squiddiff]# cat etc/hosts
192.168.3.9 s4
192.168.1.19 s1
192.168.2.12 s2

更新的文件为hosts_new
[root@miaohong squiddiff]# cat  etc/hosts_new
192.168.3.9 s8
192.168.2.12 s2
192.168.4.11 s19


首先将上面两个文件进行排序
[root@miaohong squiddiff]# sort etc/hosts
192.168.1.19 s1
192.168.2.12 s2
192.168.3.9 s4

[root@miaohong squiddiff]# sort etc/hosts_new
192.168.2.12 s2
192.168.3.9 s8
192.168.4.11 s19

上面排序后的两个文件 分别命名为 hosts_sort    hosts_new_sort

对hosts_sort    hosts_new_sort 做comm运算

对于增加
[root@miaohong squiddiff]# comm -13 etc/hosts_sort etc/hosts_new_sort
192.168.3.9 s8
192.168.4.11 s19

生成文件命名为hosts_add 即为要增加的文件内容


对于删除
[root@miaohong squiddiff]# comm -23 etc/hosts_sort etc/hosts_new_sort
192.168.1.19 s1
192.168.3.9 s4

生成文件命名为hosts_del 即为要删除的文件内容

贴一个diff吧

Index: src/fqdncache.c
===================================================================
--- src/fqdncache.c  (revision 101206)
+++ src/fqdncache.c  (working copy)
@@ -565,6 +565,42 @@
     purge_entries_fromhosts();
 }
 
+//add by miaohong
+
+void fqdncacheDel(const char *name)
+{
+    fqdncache_entry * fqdndelEntry;
+    if(fqdndelEntry=fqdncache_get(name)) {
+        fqdncacheRelease(fqdndelEntry);
+    }
+}
+
+
+void
+debug_walkfqdntables() 
+{   
+    int i;
+    hash_table *hfqdn = fqdn_table;
+    hash_link *walker = NULL;
+    debug(35, 1) ("-----fqdn_table->count = %d ------- \n",
+        hfqdn->count);
+    /*
+  debug(35, 1) ("---------hashkey_count = %d------\n",
+      hashkey_count); 
+  debug(35, 1) ("walking hash table...\n"); 
+  for (i = 0; i < hashkey_count; i++) {
+      walker = hfqdn->buckets[hashkey[i]];
+      debug(14, 1) ("item %5d: key: '%s' \n",
+      i, walker->key); 
+  }
+  debug(35, 1) ("done walking hash table...\n");
+  */
+}
+
+
+//add by miaohong end
+
+
 /*
  *  adds a "static" entry from /etc/hosts.  the worldist is to be
  *  managed by the caller, including pointed-to strings
Index: src/ipcache.c
===================================================================
--- src/ipcache.c  (revision 101211)
+++ src/ipcache.c  (working copy)
@@ -759,21 +759,29 @@
 }
 
 //add by miaohong
-int hashkey[];
-static int hashkey_count = 0;
+/*
+int hashkey[] ={0};
+int hashkey_count = 0;
+*/
 
-void initPara()
+void ipcacheDel(const char *addrname)
 {
-    hashkey_count = 0;
+    ipcache_entry * ipdelEntry;
+    int b;
+    if(ipdelEntry=ipcache_get(addrname)) {
+        ipcacheRelease(ipdelEntry);
+        //b = ip_table->hash(hostname, hid->size);
+        //hashkey_count--;
+    }
 }
 
-void
-releaseIptable()
+/*
+void initPara()
 {
-  hashFreeItems(ip_table, ipcacheFreeEntry);
+  hashkey_count = 0;
 }
+*/
 
-
 void
 debug_walkIptables() 
 {   
@@ -780,19 +788,21 @@
    int i;
    hash_table *hid = ip_table;
    hash_link *walker = NULL;
-    debug(14, 1) ("-----ip_table->count = %d ------- \n",
-        hid->count);
-    debug(14, 1) ("---------hashkey_count = %d------\n",
-        hashkey_count);   
+    debug(14, 1) ("-----ip_table->count = %d ------- \n",hid->count);
+    /*
+  debug(14, 1) ("---------hashkey_count = %d------\n",hashkey_count);   
   debug(14, 1) ("walking hash table...\n"); 
+  
   for (i = 0; i < hashkey_count; i++) {
       walker = hid->buckets[hashkey[i]];
-      debug(14, 1) ("item %5d: key: '%s' \n",
-      i, walker->key); 
+      debug(14, 1) ("item %5d: key: '%s' \n",i, walker->key);    
   }
+  
   debug(14, 1) ("done walking hash table...\n");
+  */
 }
 
+/*
 void
 genHashkey(hash_table *hid, const char *name)
 {
@@ -800,9 +810,11 @@
   b = hid->hash(name, hid->size);
   hashkey[hashkey_count] = b; 
   hashkey_count++;
-}
+} 
+*/
 
 //add by miaohong end
+
 /*
  *  adds a "static" entry from /etc/hosts.  
  *  returns 0 upon success, 1 if the ip address is invalid
@@ -844,10 +856,9 @@
     ipcacheAddEntry(i);
     ipcacheLockEntry(i);
   //add by miaohong
-  genHashkey(ip_table, name);
+  //genHashkey(ip_table, name);
   //debug_walkIptables();
   //add by miaohong end
-  printf("---------------end--------------\n");
     return 0;
 }
 
Index: src/stat.c
===================================================================
--- src/stat.c (revision 101206)
+++ src/stat.c (working copy)
@@ -1471,23 +1471,32 @@
 }
 
 //add by mh
+/*
 static void releaseSource()
 {
   ipcacheFreeMemory();
   fqdncacheFreeMemory();
 }
+*/
+static void debugReconfig()
+{
+    debug_walkIptables();
+    debug_walkfqdntables();
+}
+
 static void
 doReconfig(StoreEntry * s)
 {
-    initPara();
-    //prevent memory leaks
-    releaseSource();
-    ipcache_init(); 
-    fqdncache_init();
-    parseEtcHosts();
-    debug_walkIptables();
+    debugReconfig();
+    debug(18, 1) ("[ADD] hosts to be add...\n");
+    parseDiffHostsAdd();
+    debugReconfig();
+    debug(18, 1) ("[DEL] hosts to be del...\n");
+    parseDiffHostsDel();
+    debugReconfig();
 }
 //add by mh end 
+
 static void
 statClientRequests(StoreEntry * s)
 {
Index: src/tools.c
===================================================================
--- src/tools.c  (revision 101206)
+++ src/tools.c  (working copy)
@@ -1137,7 +1137,159 @@
     return 1;
 }
 
+//miaohong add
+
+#define DIFF_HOSTS_ADD "/opt/squiddiff/etc/hosts_add"
+#define DIFF_HOSTS_DEL "/opt/squiddiff/etc/hosts_del"
+
+
 void
+parseDiffHostsDel(void)
+{
+    FILE *fp;
+    char buf[1024];
+    char buf2[512];
+    char *nt = buf;
+    char *lt = buf;
+    /*
+    if (NULL == Config.etcHostsPath)
+  return;
+    if (0 == strcmp(Config.etcHostsPath, "none"))
+  return;
+  */
+    fp = fopen(DIFF_HOSTS_DEL, "r");
+    if (fp == NULL) {
+    debug(1, 1) ("parseDiffHostsDel: %s: %s\n",
+        DIFF_HOSTS_DEL, xstrerror());
+    return;
+    }
+#ifdef _SQUID_WIN32_
+    setmode(fileno(fp), O_TEXT);
+#endif
+    while (fgets(buf, 1024, fp)) {    /* for each line */
+    wordlist *hosts = NULL;
+    char *addr;
+    if (buf[0] == '#') /* MS-windows likes to add comments */
+        continue;
+    strtok(buf, "#");   /* chop everything following a comment marker */
+    lt = buf;
+    addr = buf;
+    debug(1, 5) ("etc_hosts: line is '%s'\n", buf);
+    nt = strpbrk(lt, w_space);
+    if (nt == NULL)       /* empty line */
+        continue;
+    *nt = '\0';     /* null-terminate the address */
+    debug(1, 5) ("etc_hosts: address is '%s'\n", addr);
+    lt = nt + 1;
+    while ((nt = strpbrk(lt, w_space))) {
+        char *host = NULL;
+        if (nt == lt) {    /* multiple spaces */
+        debug(1, 5) ("etc_hosts: multiple spaces, skipping\n");
+        lt = nt + 1;
+        continue;
+        }
+        *nt = '\0';
+        debug(1, 5) ("etc_hosts: got hostname '%s'\n", lt);
+        if (Config.appendDomain && !strchr(lt, '.')) {
+        /* I know it's ugly, but it's only at reconfig */
+        strncpy(buf2, lt, 512);
+        strncat(buf2, Config.appendDomain, 512 - strlen(lt) - 1);
+        host = buf2;
+        } else {
+        host = lt;
+        }
+        ipcacheDel(host);
+
+        //if (ipcacheAddEntryFromHosts(host, addr) != 0)
+        //goto skip;   /* invalid address, continuing is useless */
+        //wordlistAdd(&hosts, host);
+        lt = nt + 1;
+        
+    }
+    //ipcacheDel(addr);
+    fqdncacheDel(addr);
+    /*
+  fqdncacheAddEntryFromHosts(addr, hosts);
+      skip:
+  wordlistDestroy(&hosts);
+  */
+    }
+    fclose(fp);
+}
+
+
+
+void
+parseDiffHostsAdd(void)
+{
+    FILE *fp;
+    char buf[1024];
+    char buf2[512];
+    char *nt = buf;
+    char *lt = buf;
+    /*
+    if (NULL == Config.etcHostsPath)
+  return;
+    if (0 == strcmp(Config.etcHostsPath, "none"))
+  return;
+  */
+    fp = fopen(DIFF_HOSTS_ADD, "r");
+    if (fp == NULL) {
+    debug(1, 1) ("parseDiffHostsAdd: %s: %s\n",
+        DIFF_HOSTS_ADD, xstrerror());
+    return;
+    }
+#ifdef _SQUID_WIN32_
+    setmode(fileno(fp), O_TEXT);
+#endif
+    while (fgets(buf, 1024, fp)) {    /* for each line */
+    wordlist *hosts = NULL;
+    char *addr;
+    if (buf[0] == '#') /* MS-windows likes to add comments */
+        continue;
+    strtok(buf, "#");   /* chop everything following a comment marker */
+    lt = buf;
+    addr = buf;
+    debug(1, 5) ("etc_hosts: line is '%s'\n", buf);
+    nt = strpbrk(lt, w_space);
+    if (nt == NULL)       /* empty line */
+        continue;
+    *nt = '\0';     /* null-terminate the address */
+    debug(1, 5) ("etc_hosts: address is '%s'\n", addr);
+    lt = nt + 1;
+    while ((nt = strpbrk(lt, w_space))) {
+        char *host = NULL;
+        if (nt == lt) {    /* multiple spaces */
+        debug(1, 5) ("etc_hosts: multiple spaces, skipping\n");
+        lt = nt + 1;
+        continue;
+        }
+        *nt = '\0';
+        debug(1, 5) ("etc_hosts: got hostname '%s'\n", lt);
+        if (Config.appendDomain && !strchr(lt, '.')) {
+        /* I know it's ugly, but it's only at reconfig */
+        strncpy(buf2, lt, 512);
+        strncat(buf2, Config.appendDomain, 512 - strlen(lt) - 1);
+        host = buf2;
+        } else {
+        host = lt;
+        }
+        if (ipcacheAddEntryFromHosts(host, addr) != 0)
+        goto skip; /* invalid address, continuing is useless */
+        wordlistAdd(&hosts, host);
+        lt = nt + 1;
+    }
+    fqdncacheAddEntryFromHosts(addr, hosts);
+      skip:
+    wordlistDestroy(&hosts);
+    }
+    fclose(fp);
+}
+
+//miaohong add end