Code

* introduce a new rrd_create_r2 call to fix the no-overwrite api mess
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Mon, 11 Oct 2010 07:48:45 +0000 (07:48 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Mon, 11 Oct 2010 07:48:45 +0000 (07:48 +0000)
* various fixes to new rrd_cached comands as suggested by kevin
  1. Remove opt_no_overwrite and the rrd_create_set_no_overwrite function as they are ugly.  Make opt_no_overwrite a local var.
  2. Add 'no_overwrite' param to the rrd_create_r and rename as rrd_create_r2, add rrd_create_r  that calls rrd_create_r2 with a 0 for the no_overwrite function, preserving the API parameter format but allowing an extended arg list that can be used by rrd_create and rrd_handle_request_create
  3. Add -O option to rrdcached command line to force no-overwrite on any creates
  4. Add -O option on create via rrdcached to optionally add no-overwrite (cannot remove it is it was previously set at start)
  5. Fix rrd_handle_request_last to check the queue instead of forcing a flush.  Remove -no-flush option from LAST command since it is now no longer relevant as we're querying the cache chain
  6. Fix ulong/unsigned long issue for compilation under windows
  7. Change rrd_handle_request_create to only accept timestamp parameters, not at-syntax, in order to be threadsafe.  This is no  loss since the rrd_client already pre-parses any at-style syntax
  8. Reinstate missing free() in rrd_info.c and rrd_last.c

-- steve shipway

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk@2136 a5681a0c-68f1-0310-ab6d-d61299d08faa

program/src/librrd.sym.in.in
program/src/rrd.h
program/src/rrd_create.c
program/src/rrd_daemon.c
program/src/rrd_info.c
program/src/rrd_last.c
program/src/rrd_tool.h

index 458601f763f2b4f3c46b7356f19a291aa79478b9..442c8b3562eac0cad7063c96ec0636a804103427 100644 (file)
@@ -6,7 +6,7 @@ rrd_clear_error
 rrd_close
 rrd_create
 rrd_create_r
-rrd_create_set_no_overwrite
+rrd_create_r2
 rrd_dontneed
 rrd_dump
 rrd_dump_r
index 331339dbdfb2f7cfc6bc5f81b4ecd79ae53bf126..7e63110e9222bd7d7b1c47e79507f534e0829b53 100644 (file)
@@ -143,8 +143,6 @@ extern    "C" {
     int       rrd_create(
     int,
     char **);
-    void      rrd_create_set_no_overwrite(
-    int);
     rrd_info_t *rrd_info(
     int,
     char **);
@@ -228,6 +226,14 @@ extern    "C" {
     const char *filename,
     unsigned long pdp_step,
     time_t last_up,
+    /* int no_overwrite, */
+    int argc,
+    const char **argv);
+    int       rrd_create_r2(
+    const char *filename,
+    unsigned long pdp_step,
+    time_t last_up,
+    int no_overwrite,
     int argc,
     const char **argv);
     rrd_info_t *rrd_info_r(
index 707e6013756851e65e8f18b7bef9237303cf838c..f221c99d535491fa511bbfa0eae2b55b13834aff 100644 (file)
@@ -14,7 +14,6 @@
 #include "rrd_client.h"
 
 #include "rrd_is_thread_safe.h"
-static int opt_no_overwrite = 0;
 
 #ifdef WIN32
 # include <process.h>
@@ -34,12 +33,6 @@ void      parseGENERIC_DS(
 static void rrd_free2(
     rrd_t *rrd);        /* our onwn copy, immmune to mmap */
 
-void rrd_create_set_no_overwrite( 
-    int opt ) 
-{
-       opt_no_overwrite = (opt?1:0);
-}
-
 int rrd_create(
     int argc,
     char **argv)
@@ -60,6 +53,7 @@ int rrd_create(
     long      long_tmp;
     int       rc;
     char * opt_daemon = NULL;
+    int       opt_no_overwrite = 0;
 
     optind = 0;
     opterr = 0;         /* initialize getopt */
@@ -135,8 +129,8 @@ int rrd_create(
                       pdp_step, last_up, opt_no_overwrite,
                       argc - optind - 1, (const char **) (argv + optind + 1));
        } else {
-    rc = rrd_create_r(argv[optind],
-                      pdp_step, last_up,
+        rc = rrd_create_r2(argv[optind],
+                      pdp_step, last_up, opt_no_overwrite,
                       argc - optind - 1, (const char **) (argv + optind + 1));
        }
 
@@ -144,12 +138,24 @@ int rrd_create(
 }
 
 /* #define DEBUG */
+/* For backwards compatibility with previous API.  Use rrd_create_r2 if you
+   need to have the no_overwrite parameter.                                */
 int rrd_create_r(
     const char *filename,
     unsigned long pdp_step,
     time_t last_up,
     int argc,
     const char **argv)
+{
+       return rrd_create_r2(filename,pdp_step,last_up,0,argc,argv);
+}
+int rrd_create_r2(
+    const char *filename,
+    unsigned long pdp_step,
+    time_t last_up,
+    int no_overwrite,
+    int argc,
+    const char **argv)
 {
     rrd_t     rrd;
     long      i;
@@ -584,7 +590,7 @@ int rrd_create_r(
         rrd_free2(&rrd);
         return (-1);
     }
-    return rrd_create_fn(filename, &rrd);
+    return rrd_create_fn(filename, &rrd, no_overwrite);
 }
 
 void parseGENERIC_DS(
@@ -708,7 +714,8 @@ int create_hw_contingent_rras(
 
 int rrd_create_fn(
     const char *file_name,
-    rrd_t *rrd)
+    rrd_t *rrd,
+    int no_overwrite )
 {
     unsigned long i, ii;
     rrd_value_t *unknown;
@@ -717,7 +724,7 @@ int rrd_create_fn(
     rrd_t     rrd_dn;
     unsigned  rrd_flags = RRD_READWRITE | RRD_CREAT;
 
-    if (opt_no_overwrite) {
+    if (no_overwrite) {
       rrd_flags |= RRD_EXCL ;
     }
 
index bfcf6a3ce4f7ed1d8da75695264e248a4e075cbc..90629271e3478f1c7f4a9620e918c7d60b0373e3 100644 (file)
@@ -71,7 +71,7 @@
 #endif
 #endif
 
-#include "rrd.h"
+#include "rrd_tool.h"
 #include "rrd_client.h"
 #include "unused.h"
 
@@ -275,7 +275,7 @@ static uint64_t stats_journal_bytes = 0;
 static uint64_t stats_journal_rotate = 0;
 static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static int opt_no_overwrite = 0;
+static int opt_no_overwrite = 0; /* default for the daemon */
 
 /* Journaled updates */
 #define JOURNAL_REPLAY(s) ((s) == NULL)
@@ -1776,13 +1776,17 @@ static int handle_request_first (HANDLER_PROTO) /* {{{ */
     return send_response(sock, RESP_ERR, "RRD Error: %s\n", rrd_get_error());
   }
   return send_response(sock, RESP_OK, "%lu\n",(unsigned)t);
-} /* }}} static int handle_request_last  */
+} /* }}} static int handle_request_first  */
+
 
 static int handle_request_last (HANDLER_PROTO) /* {{{ */
 {
   char *file, file_tmp[PATH_MAX];
   int status;
-  time_t t;
+  time_t t, from_file, step;
+  rrd_file_t * rrd_file;
+  cache_item_t * ci;
+  rrd_t rrd; 
 
   /* obtain filename */
   status = buffer_get_field(&buffer, &buffer_size, &file);
@@ -1793,12 +1797,27 @@ static int handle_request_last (HANDLER_PROTO) /* {{{ */
   if (!check_file_access(file, sock)) {
     return send_response(sock, RESP_ERR, "Cannot read: %s\n", file);
   }
-  /* get data */
-  rrd_clear_error ();
-  t = rrd_last_r(file);
-  if(t<1) {
+  rrd_clear_error();
+  rrd_init(&rrd);
+  rrd_file = rrd_open(file,&rrd,RRD_READONLY);
+  if(!rrd_file) {
     return send_response(sock, RESP_ERR, "RRD Error: %s\n", rrd_get_error());
   }
+  from_file = rrd.live_head->last_up;
+  step = rrd.stat_head->pdp_step;
+  rrd_close(rrd_file);
+  pthread_mutex_lock(&cache_lock);
+  ci = g_tree_lookup(cache_tree, file);
+  if (ci)
+    t = ci->last_update_stamp;
+  else
+    t = from_file;
+  pthread_mutex_unlock(&cache_lock);
+  t -= t % step;
+  rrd_free(&rrd);
+  if(t<1) {
+    return send_response(sock, RESP_ERR, "Error: rrdcached: Invalid timestamp returned\n");
+  }
   return send_response(sock, RESP_OK, "%lu\n",(unsigned)t);
 } /* }}} static int handle_request_last  */
 
@@ -1809,10 +1828,8 @@ static int handle_request_create (HANDLER_PROTO) /* {{{ */
   int ac = 0;
   char *av[128];
   int status;
-  ulong step = 300;
+  unsigned long step = 300;
   time_t last_up = time(NULL)-10;
-  rrd_time_value_t last_up_tv;
-  char     *parsetime_error = NULL;
   int no_overwrite = opt_no_overwrite;
 
 
@@ -1827,19 +1844,11 @@ static int handle_request_create (HANDLER_PROTO) /* {{{ */
   }
   RRDD_LOG(LOG_INFO, "rrdcreate request for %s",file);
 
-  status = buffer_get_field(&buffer, &buffer_size, &tok );
-  for(;(tok && !status);status = buffer_get_field(&buffer, &buffer_size, &tok )) {
+  while ((status = buffer_get_field(&buffer, &buffer_size, &tok)) == 0 && tok) {
     if( ! strncmp(tok,"-b",2) ) {
       status = buffer_get_field(&buffer, &buffer_size, &tok );
       if (status != 0) return syntax_error(sock,cmd);
-      if ((parsetime_error = rrd_parsetime(tok, &last_up_tv))) 
-        return send_response(sock, RESP_ERR, "start time: %s\n", parsetime_error);
-      if (last_up_tv.type == RELATIVE_TO_END_TIME ||
-        last_up_tv.type == RELATIVE_TO_START_TIME) {
-        return send_response(sock, RESP_ERR, "Cannot specify time relative to start or end here.\n");
-      }
-      last_up = mktime(&last_up_tv.tm) +last_up_tv.offset;
-
+      last_up = (time_t) atol(tok);
       continue;
     }
     if( ! strncmp(tok,"-s",2) ) {
@@ -1863,9 +1872,8 @@ static int handle_request_create (HANDLER_PROTO) /* {{{ */
     return send_response(sock, RESP_ERR, "The first entry must be after 1980.\n");
   }
 
-  rrd_create_set_no_overwrite(no_overwrite);
   rrd_clear_error ();
-  status = rrd_create_r(file,step,last_up,ac,(const char **)av);
+  status = rrd_create_r2(file,step,last_up,no_overwrite,ac,(const char **)av);
 
   if(!status) {
     return send_response(sock, RESP_OK, "RRD created OK\n");
@@ -2062,6 +2070,8 @@ static command_t list_of_commands[] = { /* {{{ */
     "CREATE <filename> [-b start] [-s step] [-O] <DS definitions> <RRA definitions>\n",
     "The CREATE command will create an RRD file, overwriting any existing file\n"
     "unless the -O option is given or rrdcached was started with the -O option.\n"
+    "The start parameter needs to be in seconds since 1/1/70 (AT-style syntax is\n"
+    "not acceptable) and the step is in seconds (default is 300).\n"
     "The DS and RRA definitions are as for the 'rrdtool create' command.\n"
   },
   {
index d86a9074d90e631184d04e758652fa7788375c84..2f6c07fff78c1806323807084d9e181e9afb337a 100644 (file)
@@ -152,6 +152,7 @@ rrd_info_t *rrd_info(
     else
     info = rrd_info_r(argv[optind]);
 
+    if (opt_daemon) free(opt_daemon);
     return (info);
 } /* rrd_info_t *rrd_info */
 
index 7fb3cb884344f8c76119d9b7b7c860b092afbcc2..90bcae7afc608997f5a1709f3ee066ae7fe2356e 100644 (file)
@@ -14,9 +14,7 @@ time_t rrd_last(
     char **argv)
 {
     char *opt_daemon = NULL;
-    int status;
     time_t lastupdate;
-    int flushfirst = 1;
 
     optind = 0;
     opterr = 0;         /* initialize getopt */
@@ -26,11 +24,10 @@ time_t rrd_last(
         int       option_index = 0;
         static struct option long_options[] = {
             {"daemon", required_argument, 0, 'd'},
-            {"noflush", no_argument, 0, 'F'},
             {0, 0, 0, 0}
         };
 
-        opt = getopt_long(argc, argv, "d:F", long_options, &option_index);
+        opt = getopt_long(argc, argv, "d:", long_options, &option_index);
 
         if (opt == EOF)
             break;
@@ -47,12 +44,8 @@ time_t rrd_last(
             }
             break;
 
-        case 'F':
-            flushfirst = 0;
-            break;
-
         default:
-            rrd_set_error ("Usage: rrdtool %s [--daemon <addr> [--noflush]] <file>",
+            rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>",
                     argv[0]);
             return (-1);
             break;
@@ -60,16 +53,11 @@ time_t rrd_last(
     }                   /* while (42) */
 
     if ((argc - optind) != 1) {
-        rrd_set_error ("Usage: rrdtool %s [--daemon <addr> [--noflush]] <file>",
+        rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>",
                 argv[0]);
         return (-1);
     }
 
-    if(flushfirst) {
-    status = rrdc_flush_if_daemon(opt_daemon, argv[optind]);
-    if (status) return (-1);
-    }
-
     rrdc_connect (opt_daemon);
     if (rrdc_is_connected (opt_daemon))
         lastupdate = rrdc_last (argv[optind]);
@@ -77,6 +65,7 @@ time_t rrd_last(
     else
         lastupdate = rrd_last_r(argv[optind]);
 
+    if (opt_daemon) free(opt_daemon);
     return (lastupdate);
 }
 
index 7d8368a6a45ebdbba57be8eca32ad109aa97c3d2..de35e46df533a01f881c6cd82b8ce29ce013c191 100644 (file)
@@ -82,7 +82,8 @@ extern    "C" {
 
     int       rrd_create_fn(
     const char *file_name,
-    rrd_t *rrd);
+    rrd_t *rrd,
+    int no_overwrite);
     int rrd_fetch_fn (const char *filename,
             enum cf_en cf_idx,
             time_t *start,