for, so describing the mechanism again is unnecessary. Read L<HOW IT WORKS>
above for a detailed explanation.
+Note that rrdcached only accepts absolute timestamps in the update values.
+Updates strings like "N:1:2:3" are automatically converted to absolute
+time by the RRD client library before sending to rrdcached.
+
=item B<WROTE> I<filename>
This command is written to the journal after a file is successfully
client: BATCH
server: 0 Go ahead. End with dot '.' on its own line.
- client: UPDATE x.rrd N:1:2:3 <--- command #1
- client: UPDATE y.rrd N:3:4:5 <--- command #2
+ client: UPDATE x.rrd 1223661439:1:2:3 <--- command #1
+ client: UPDATE y.rrd 1223661440:3:4:5 <--- command #2
client: and so on...
client: .
server: 2 Errors
=item B<DataSetsWritten> I<(unsigned 64bit integer)>
-Total number of "data sets" written to disk since the daemon was started. A
-data set is one or more values passed to the B<UPDATE> command. For example:
-C<N:123:456> is one data set with two values. The term "data set" is used to
-prevent confusion whether individual values or groups of values are counted.
+Total number of "data sets" written to disk since the daemon was
+started. A data set is one or more values passed to the B<UPDATE>
+command. For example: C<1223661439:123:456> is one data set with two
+values. The term "data set" is used to prevent confusion whether
+individual values or groups of values are counted.
=item B<TreeNodesNumber> I<(unsigned 64bit integer)>
char **values;
int values_num;
time_t last_flush_time;
+ time_t last_update_stamp;
#define CI_FLAGS_IN_TREE (1<<0)
#define CI_FLAGS_IN_QUEUE (1<<1)
int flags;
{
char *file;
int values_num = 0;
+ int bad_timestamps = 0;
int status;
char orig_buf[CMD_MAX];
{
char **temp;
char *value;
+ time_t stamp;
+ char *eostamp;
status = buffer_get_field (&buffer, &buffer_size, &value);
if (status != 0)
break;
}
+ /* make sure update time is always moving forward */
+ stamp = strtol(value, &eostamp, 10);
+ if (eostamp == value || eostamp == NULL || *eostamp != ':')
+ {
+ ++bad_timestamps;
+ add_response_info(sock, "Cannot find timestamp in '%s'!\n", value);
+ continue;
+ }
+ else if (stamp <= ci->last_update_stamp)
+ {
+ ++bad_timestamps;
+ add_response_info(sock,
+ "illegal attempt to update using time %ld when"
+ " last update time is %ld (minimum one second step)\n",
+ stamp, ci->last_update_stamp);
+ continue;
+ }
+ else
+ ci->last_update_stamp = stamp;
+
temp = (char **) realloc (ci->values,
sizeof (char *) * (ci->values_num + 1));
if (temp == NULL)
pthread_mutex_unlock (&cache_lock);
if (values_num < 1)
- return send_response(sock, RESP_ERR, "No values updated.\n");
+ {
+ /* if we had only one update attempt, then return the full
+ error message... try to get the most information out
+ of the limited error space allowed by the protocol
+ */
+ if (bad_timestamps == 1)
+ return send_response(sock, RESP_ERR, "%s", sock->wbuf);
+ else
+ return send_response(sock, RESP_ERR,
+ "No values updated (%d bad timestamps).\n",
+ bad_timestamps);
+ }
else
- return send_response(sock, RESP_OK, "Enqueued %i value(s).\n", values_num);
+ return send_response(sock, RESP_OK,
+ "errors, enqueued %i value(s).\n", values_num);
/* NOTREACHED */
assert(1==0);