]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1594. [bug] 'rndc dumpdb' could prevent named from answering
authorMark Andrews <marka@isc.org>
Thu, 8 Apr 2004 00:10:42 +0000 (00:10 +0000)
committerMark Andrews <marka@isc.org>
Thu, 8 Apr 2004 00:10:42 +0000 (00:10 +0000)
                        queries while the dump was in progress.  [RT #10565]

CHANGES
bin/named/server.c

diff --git a/CHANGES b/CHANGES
index e0be390874eb47abbbdc993c6ef6fedabe1ee5b9..33178b1432083b51aba3042c380968d3b6ce7339 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -25,7 +25,8 @@
 1595.  [func]          New notify type 'master-only'.  Enable notify for
                        master zones only.
 
-1594.  [placeholder]   rt10565
+1594.  [bug]           'rndc dumpdb' could prevent named from answering
+                       queries while the dump was in progress.  [RT #10565]
 
 1593.  [bug]           rndc should return "unknown command" to unknown
                        commands. [RT# 10642]
index 9b41de3cb44ef426ed098a8bf398893e1ddc9662..89a9b4b2a9092b814fb373c4d3f177be86225cf5 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.419 2004/03/14 23:00:47 marka Exp $ */
+/* $Id: server.c,v 1.420 2004/04/08 00:10:42 marka Exp $ */
 
 #include <config.h>
 
@@ -49,6 +49,7 @@
 #include <dns/journal.h>
 #include <dns/keytable.h>
 #include <dns/master.h>
+#include <dns/masterdump.h>
 #include <dns/order.h>
 #include <dns/peer.h>
 #include <dns/portlist.h>
@@ -129,6 +130,32 @@ struct ns_dispatch {
        ISC_LINK(struct ns_dispatch)    link;
 };
 
+struct dumpcontext {
+       isc_mem_t                       *mctx;
+       isc_boolean_t                   dumpcache;
+       isc_boolean_t                   dumpzones;
+       FILE                            *fp;
+       ISC_LIST(struct viewlistentry)  viewlist;
+       struct viewlistentry            *view;
+       struct zonelistentry            *zone;
+       dns_dumpctx_t                   *mdctx;
+       dns_db_t                        *db;
+       dns_db_t                        *cache;
+       isc_task_t                      *task;
+       dns_dbversion_t                 *version;
+};
+
+struct viewlistentry {
+       dns_view_t                      *view;
+       ISC_LINK(struct viewlistentry)  link;
+       ISC_LIST(struct zonelistentry)  zonelist;
+};
+
+struct zonelistentry {
+       dns_zone_t                      *zone;
+       ISC_LINK(struct zonelistentry)  link;
+};
+
 static void
 fatal(const char *msg, isc_result_t result);
 
@@ -3518,32 +3545,206 @@ ns_server_dumpstats(ns_server_t *server) {
 }
 
 static isc_result_t
-printzone(dns_zone_t *zone, void *uap) {
-       FILE *fp = uap;
-       char buf[1024+32];
-       isc_result_t result;
+add_zone_tolist(dns_zone_t *zone, void *uap) {
+       struct dumpcontext *dctx = uap;
+       struct zonelistentry *zle;
+
+       zle = isc_mem_get(dctx->mctx, sizeof *zle);
+       if (zle ==  NULL)
+               return (ISC_R_NOMEMORY);
+       zle->zone = NULL;
+       dns_zone_attach(zone, &zle->zone);
+       ISC_LINK_INIT(zle, link);
+       ISC_LIST_APPEND(ISC_LIST_TAIL(dctx->viewlist)->zonelist, zle, link);
+       return (ISC_R_SUCCESS);
+}
 
-       dns_zone_name(zone, buf, sizeof(buf));
-       fprintf(fp, ";\n; Zone dump of '%s'\n;\n", buf);
-       result = dns_zone_dumptostream(zone, fp);
-       if (result == ISC_R_NOTIMPLEMENTED) {
-               fprintf(fp, "; %s\n", dns_result_totext(result));
-               result = ISC_R_SUCCESS;
-       }
+static isc_result_t
+add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
+       struct viewlistentry *vle;
+       isc_result_t result = ISC_R_SUCCESS;
+       
+       vle = isc_mem_get(dctx->mctx, sizeof *vle);
+       if (vle == NULL)
+               return (ISC_R_NOMEMORY);
+       vle->view = NULL;
+       dns_view_attach(view, &vle->view);
+       ISC_LINK_INIT(vle, link);
+       ISC_LIST_INIT(vle->zonelist);
+       ISC_LIST_APPEND(dctx->viewlist, vle, link);
+       if (dctx->dumpzones)
+               result = dns_zt_apply(view->zonetable, ISC_TRUE,
+                                     add_zone_tolist, dctx);
        return (result);
 }
 
+static void
+dumpcontext_destroy(struct dumpcontext *dctx) {
+       struct viewlistentry *vle;
+       struct zonelistentry *zle;
+
+       vle = ISC_LIST_HEAD(dctx->viewlist);
+       while (vle != NULL) {
+               ISC_LIST_UNLINK(dctx->viewlist, vle, link);
+               zle = ISC_LIST_HEAD(vle->zonelist);
+               while (zle != NULL) {
+                       ISC_LIST_UNLINK(vle->zonelist, zle, link);
+                       dns_zone_detach(&zle->zone);
+                       isc_mem_put(dctx->mctx, zle, sizeof *zle);
+                       zle = ISC_LIST_HEAD(vle->zonelist);
+               }
+               dns_view_detach(&vle->view);
+               isc_mem_put(dctx->mctx, vle, sizeof *vle);
+               vle = ISC_LIST_HEAD(dctx->viewlist);
+       }
+       if (dctx->version != NULL)
+               dns_db_closeversion(dctx->db, &dctx->version, ISC_FALSE);
+       if (dctx->db != NULL)
+               dns_db_detach(&dctx->db);
+       if (dctx->cache != NULL)
+               dns_db_detach(&dctx->cache);
+       if (dctx->task != NULL)
+               isc_task_detach(&dctx->task);
+       if (dctx->fp != NULL)
+               (void)isc_stdio_close(dctx->fp);
+       if (dctx->mdctx != NULL)
+               dns_dumpctx_detach(&dctx->mdctx);
+       isc_mem_put(dctx->mctx, dctx, sizeof *dctx);
+}
+
+static void
+dumpdone(void *arg, isc_result_t result) {
+       struct dumpcontext *dctx = arg;
+       char buf[1024+32];
+       const dns_master_style_t *style;
+       
+       if (result != ISC_R_SUCCESS)
+               goto cleanup;
+       if (dctx->mdctx != NULL)
+               dns_dumpctx_detach(&dctx->mdctx);
+       if (dctx->view == NULL) {
+               dctx->view = ISC_LIST_HEAD(dctx->viewlist);
+               if (dctx->view == NULL)
+                       goto done;
+               INSIST(dctx->zone == NULL);
+       }
+ nextview:
+       fprintf(dctx->fp, ";\n; Start view %s\n;\n", dctx->view->view->name);
+       if (dctx->zone == NULL && dctx->cache == NULL && dctx->dumpcache) {
+               style = &dns_master_style_cache;
+               /* start cache dump */
+               if (dctx->view->view->cachedb != NULL)
+                       dns_db_attach(dctx->view->view->cachedb, &dctx->cache);
+               if (dctx->cache != NULL) {
+
+                       fprintf(dctx->fp, ";\n; Cache dump of view '%s'\n;\n",
+                               dctx->view->view->name);
+                       result = dns_master_dumptostreaminc(dctx->mctx,
+                                                           dctx->cache, NULL,
+                                                           style, dctx->fp,
+                                                           dctx->task,
+                                                           dumpdone, dctx,
+                                                           &dctx->mdctx);
+                       if (result == DNS_R_CONTINUE)
+                               return;
+                       if (result == ISC_R_NOTIMPLEMENTED)
+                               fprintf(dctx->fp, "; %s\n",
+                                       dns_result_totext(result));
+                       else if (result != ISC_R_SUCCESS)
+                               goto cleanup;
+               }
+       }
+       if (dctx->cache != NULL) {
+               dns_adb_dump(dctx->view->view->adb, dctx->fp);
+               dns_db_detach(&dctx->cache);
+       }
+       if (dctx->dumpzones) {
+               style = &dns_master_style_full;
+ nextzone:
+               if (dctx->version != NULL)
+                       dns_db_closeversion(dctx->db, &dctx->version,
+                                           ISC_FALSE);
+               if (dctx->db != NULL)
+                       dns_db_detach(&dctx->db);
+               if (dctx->zone == NULL)
+                       dctx->zone = ISC_LIST_HEAD(dctx->view->zonelist);
+               else
+                       dctx->zone = ISC_LIST_NEXT(dctx->zone, link);
+               if (dctx->zone != NULL) {
+                       /* start zone dump */
+                       dns_zone_name(dctx->zone->zone, buf, sizeof(buf));
+                       fprintf(dctx->fp, ";\n; Zone dump of '%s'\n;\n", buf);
+                       result = dns_zone_getdb(dctx->zone->zone, &dctx->db);
+                       if (result != ISC_R_SUCCESS) {
+                               fprintf(dctx->fp, "; %s\n",
+                                       dns_result_totext(result));
+                               goto nextzone;
+                       }
+                       dns_db_currentversion(dctx->db, &dctx->version);
+                       result = dns_master_dumptostreaminc(dctx->mctx,
+                                                           dctx->db,
+                                                           dctx->version,
+                                                           style, dctx->fp,
+                                                           dctx->task,
+                                                           dumpdone, dctx,
+                                                           &dctx->mdctx);
+                       if (result == DNS_R_CONTINUE)
+                               return;
+                       if (result == ISC_R_NOTIMPLEMENTED)
+                               fprintf(dctx->fp, "; %s\n",
+                                       dns_result_totext(result));
+                       if (result != ISC_R_SUCCESS)
+                               goto cleanup;
+               }
+       }
+       if (dctx->view != NULL)
+               dctx->view = ISC_LIST_NEXT(dctx->view, link);
+       if (dctx->view != NULL)
+               goto nextview;
+ done:
+       fprintf(dctx->fp, "; Dump complete\n");
+       result = isc_stdio_flush(dctx->fp);
+       if (result == ISC_R_SUCCESS)
+               isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+                             NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+                             "dumpdb complete");
+ cleanup:
+       if (result != ISC_R_SUCCESS)
+               isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+                             NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+                             "dumpdb failed: %s", dns_result_totext(result));
+       dumpcontext_destroy(dctx);
+}
+
+
 isc_result_t
 ns_server_dumpdb(ns_server_t *server, char *args) {
-       FILE *fp = NULL;
+       struct dumpcontext *dctx = NULL;
        dns_view_t *view;
        isc_result_t result;
-       isc_boolean_t zones = ISC_FALSE;
-       isc_boolean_t cache = ISC_TRUE;
        char *ptr;
        const char *sep;
 
-       CHECKMF(isc_stdio_open(server->dumpfile, "w", &fp),
+       dctx = isc_mem_get(server->mctx, sizeof(*dctx));
+       if (dctx == NULL)
+               return (ISC_R_NOMEMORY);
+
+       dctx->mctx = server->mctx;
+       dctx->dumpcache = ISC_TRUE;
+       dctx->dumpzones = ISC_FALSE;
+       dctx->fp = NULL;
+       ISC_LIST_INIT(dctx->viewlist);
+       dctx->view = NULL;
+       dctx->zone = NULL;
+       dctx->cache = NULL;
+       dctx->mdctx = NULL;
+       dctx->db = NULL;
+       dctx->cache = NULL;
+       dctx->task = NULL;
+       dctx->version = NULL;
+       isc_task_attach(server->task, &dctx->task);
+
+       CHECKMF(isc_stdio_open(server->dumpfile, "w", &dctx->fp),
                "could not open dump file", server->dumpfile);
 
        /* Skip the command name. */
@@ -3558,16 +3759,16 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
 
        ptr = next_token(&args, " \t");
        if (ptr != NULL && strcmp(ptr, "-all") == 0) {
-               zones = ISC_TRUE;
-               cache = ISC_TRUE;
+               dctx->dumpzones = ISC_TRUE;
+               dctx->dumpcache = ISC_TRUE;
                ptr = next_token(&args, " \t");
        } else if (ptr != NULL && strcmp(ptr, "-cache") == 0) {
-               zones = ISC_FALSE;
-               cache = ISC_TRUE;
+               dctx->dumpzones = ISC_FALSE;
+               dctx->dumpcache = ISC_TRUE;
                ptr = next_token(&args, " \t");
        } else if (ptr != NULL && strcmp(ptr, "-zones") == 0) {
-               zones = ISC_TRUE;
-               cache = ISC_FALSE;
+               dctx->dumpzones = ISC_TRUE;
+               dctx->dumpcache = ISC_FALSE;
                ptr = next_token(&args, " \t");
        } 
 
@@ -3577,23 +3778,14 @@ ns_server_dumpdb(ns_server_t *server, char *args) {
        {
                if (ptr != NULL && strcmp(view->name, ptr) != 0)
                        continue;
-               fprintf(fp, ";\n; Start view %s\n;\n", view->name);
-               if (cache && view->cachedb != NULL)
-                       CHECKM(dns_view_dumpdbtostream(view, fp),
-                              "could not dump cache");
-               if (zones && view->zonetable != NULL)
-                       CHECKM(dns_zt_apply(view->zonetable, ISC_TRUE,
-                                           printzone, fp),
-                              "could not dump zones");
+               CHECK(add_view_tolist(dctx, view));
        }
-       fprintf(fp, "; Dump complete\n");
-       result = isc_stdio_flush(fp);
-       isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
-                     NS_LOGMODULE_SERVER, ISC_LOG_INFO,
-                     "dumpdb complete");
+       dumpdone(dctx, ISC_R_SUCCESS);
+       return (ISC_R_SUCCESS);
+
  cleanup:
-       if (fp != NULL)
-               (void)isc_stdio_close(fp);
+       if (dctx != NULL)
+               dumpcontext_destroy(dctx);
        return (result);
 }