]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Add support for rrd restore to explicitly end xml files when using
authorPeter Stamfest <peter@stamfest.at>
Wed, 19 Feb 2014 08:56:16 +0000 (09:56 +0100)
committerPeter Stamfest <peter@stamfest.at>
Wed, 19 Feb 2014 08:56:16 +0000 (09:56 +0100)
the pipe interface by using the "-" special filename and using
ctrl-Z/newline as an end-of-file indicator.

doc/rrdrestore.pod
src/rrd_restore.c

index e098e0dfc1cfa6cb6275a5c72f3748fe2121ca61..4d17ba687f88cb7368d6399fc730deda93f91e94 100644 (file)
@@ -16,7 +16,16 @@ it to the native B<RRD> format.
 
 =item I<filename.xml>
 
-The name of the B<XML> file you want to restore.
+The name of the B<XML> file you want to restore. The special filename "-" 
+(a single dash) is interpreted as standard input. 
+
+In order to support the restore command in pipe mode (especially when
+using B<RRDtool> over a network connection), when using "-" as a filename
+the end of the file can be signalled either by closing the data
+channel after the file has transferred (as would be the case when
+using input redirection within a suitable shell) or by sending a
+crtl-Z / newline combination. This allows to send more commands to the
+B<RRDtool> server after a restore.
 
 =item I<filename.rrd>
 
index 2447a3eec96b4da4802ce9186a2ceb600d78bdca..b2bfa8a2a83a66c0b7a27b47f8e13ba399e9b149 100644 (file)
@@ -1059,6 +1059,65 @@ static int parse_tag_rrd(
     return (status);
 }                       /* int parse_tag_rrd */
 
+/* helper type for stdioXmlInputReaderForPipeInterface */
+
+typedef struct stdioXmlReaderContext_t {
+    FILE *stream;
+    int freeOnClose;
+    int closed;
+    char eofchar;
+} stdioXmlReaderContext;
+
+/* 
+ * this is a xmlInputReadCallback that is used for the pipe interface
+ * in case the passed filename is "-" (meaning standard input) to take
+ * care it will never actually close the stdio stream stdin. It will
+ * report eof once it reads the eof character (currently set to ctrl-Z
+ * (character code 26, hex 0x1A) in the calling code) anywhere on a line.
+ *
+ * Note that ctrl-Z is not an allowed character in XML 1.0 (which rrdtool
+ * uses). 
+ *
+ */
+static int stdioXmlInputReadCallback(
+    void *context, 
+    char *buffer, 
+    int len)
+{
+    stdioXmlReaderContext *sctx = (stdioXmlReaderContext*) context;
+
+    if (sctx == NULL) return -1;
+    if (sctx->stream == NULL) return -1;
+    if (sctx->closed) return 0;
+
+    char *r = fgets(buffer, len, sctx->stream);
+    if (r == NULL) {
+       sctx->closed = 1;
+       return 0;
+    }
+
+    char *where = strchr(r, sctx->eofchar);
+    if (where != NULL) {
+       sctx->closed = 1;
+       *where = 0;
+    }
+
+    return strlen(r);
+}
+
+static int stdioXmlInputCloseCallback(void *context)
+{
+    stdioXmlReaderContext *sctx = (stdioXmlReaderContext*) context;
+
+    if (sctx == NULL) return 0;
+
+    if (sctx->freeOnClose) {
+       sctx->freeOnClose = 0;
+       free(sctx);
+    }
+    return 0; /* everything is OK */
+}
+
 static rrd_t *parse_file(
     const char *filename)
 {
@@ -1066,15 +1125,43 @@ static rrd_t *parse_file(
     int       status;
 
     rrd_t    *rrd;
-
-    reader = xmlNewTextReaderFilename(filename);
+    stdioXmlReaderContext *sctx = NULL;
+
+    if (strcmp(filename, "-") == 0) {
+       sctx = malloc(sizeof(*sctx));
+       if (sctx == NULL) {
+           rrd_set_error("parse_file: malloc failed.");
+           return (NULL);
+       }
+       sctx->stream = stdin;
+       sctx->freeOnClose = 1;
+       sctx->closed = 0;
+       sctx->eofchar = 0x1A; /* ctrl-Z */
+
+        reader = xmlReaderForIO(stdioXmlInputReadCallback,
+                                stdioXmlInputCloseCallback,
+                                sctx, 
+                                filename,
+                                NULL,
+                                0);
+    } else {
+        reader = xmlNewTextReaderFilename(filename);
+    } 
     if (reader == NULL) {
+       if (sctx != NULL) free(sctx);
+
         rrd_set_error("Could not create xml reader for: %s",filename);
         return (NULL);
     }
 
+    /* NOTE: from now on, sctx will get free'd implicitly through
+     * xmlFreeTextReader and its call to
+     * stdioXmlInputCloseCallback. */
+
     if (expect_element(reader,"rrd") != 0) {
         xmlFreeTextReader(reader);
+
+       if (sctx != NULL) free(sctx);
         return (NULL);
     }