int rrdc_flush (const char *filename) /* {{{ */ { char buffer[4096]; char *buffer_ptr; size_t buffer_free; size_t buffer_size; rrdc_response_t *res; int status; char file_path[PATH_MAX]; if (filename == NULL) return (-1); memset (buffer, 0, sizeof (buffer)); buffer_ptr = &buffer[0]; buffer_free = sizeof (buffer); status = buffer_add_string ("flush", &buffer_ptr, &buffer_free); if (status != 0) return (ENOBUFS); pthread_mutex_lock (&lock); filename = get_path (filename, file_path); if (filename == NULL) { pthread_mutex_unlock (&lock); return (-1); } status = buffer_add_string (filename, &buffer_ptr, &buffer_free); if (status != 0) { pthread_mutex_unlock (&lock); return (ENOBUFS); } assert (buffer_free < sizeof (buffer)); buffer_size = sizeof (buffer) - buffer_free; assert (buffer[buffer_size - 1] == ' '); buffer[buffer_size - 1] = '\n'; res = NULL; status = request (buffer, buffer_size, &res); pthread_mutex_unlock (&lock); if (status != 0) return (status); status = res->status; response_free (res); return (status); } /* }}} int rrdc_flush */
void _process_cmd(int fd, struct request *req) { char sent_buf[BUF_SIZE]; struct response *resp; memset(sent_buf, 0, BUF_SIZE); switch(req->cmd){ case CMD_PING:{ resp = response_new(0,OK_PONG); response_detch(resp,sent_buf); write(fd,sent_buf,strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_SET:{ struct slice sk, sv; if(req->argc == 3) { sk.len = req->argv[1]->len; sk.data = req->argv[1]->data; sv.len = req->argv[2]->len; sv.data = req->argv[2]->data; db_add(_svr.db, &sk, &sv); resp = response_new(0,OK); response_detch(resp,sent_buf); write(fd,sent_buf,strlen(sent_buf)); request_free_value(req); response_free(resp); break; } goto __default; } case CMD_MSET:{ int i; int c = req->argc; for (i = 1; i < c; i += 2) { struct slice sk, sv; sk.len = req->argv[i]->len; sk.data = req->argv[i]->data; sv.len = req->argv[i+1]->len; sv.data = req->argv[i+1]->data; db_add(_svr.db, &sk, &sv); } resp = response_new(0, OK); response_detch(resp, sent_buf); write(fd,sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_GET:{ int ret; struct slice sk; struct slice sv; if (req->argc == 2) { sk.len = req->argv[1]->len; sk.data = req->argv[1]->data; ret = db_get(_svr.db, &sk, &sv); if (ret == 1) { resp = response_new(1,OK_200); resp->argv[0] = sv.data; } else { resp = response_new(0,OK_404); resp->argv[0] = NULL; } response_detch(resp, sent_buf); write(fd,sent_buf,strlen(sent_buf)); request_free_value(req); response_free(resp); if (ret == 1) free(sv.data); break; } goto __default; } case CMD_MGET:{ int i; int ret; int c=req->argc; int sub_c=c-1; char **vals = calloc(c, sizeof(char*)); resp=response_new(sub_c, OK_200); for (i = 1; i < c; i++){ struct slice sk; struct slice sv; sk.len = req->argv[i]->len; sk.data = req->argv[i]->data; ret = db_get(_svr.db, &sk, &sv); if (ret == 1) vals[i-1] = sv.data; else vals[i-1] = NULL; resp->argv[i-1] = vals[i-1]; } response_detch(resp, sent_buf); write(fd, sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); for (i = 0; i < sub_c; i++){ if (vals[i]) free(vals[i]); } free(vals); break; } case CMD_INFO:{ char *infos; infos = db_info(_svr.db); resp = response_new(1, OK_200); resp->argv[0] = infos; response_detch(resp, sent_buf); write(fd,sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_DEL:{ int i; for (i = 1; i < req->argc; i++){ struct slice sk; sk.len = req->argv[i]->len; sk.data = req->argv[i]->data; db_remove(_svr.db, &sk); } resp = response_new(0, OK); response_detch(resp, sent_buf); write(fd, sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_EXISTS:{ struct slice sk; sk.len = req->argv[1]->len; sk.data = req->argv[1]->data; int ret= db_exists(_svr.db, &sk); if(ret) write(fd,":1\r\n",4); else write(fd,":-1\r\n",5); } break; case CMD_SHUTDOWN: __ERROR("siloserver shutdown..."); db_close(_svr.db); exit(2); break; __default: default:{ resp = response_new(0, ERR); response_detch(resp, sent_buf); write(fd, sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } } }
int rrdc_stats_get (rrdc_stats_t **ret_stats) /* {{{ */ { rrdc_stats_t *head; rrdc_stats_t *tail; rrdc_response_t *res; int status; size_t i; /* Protocol example: {{{ * -> STATS * <- 5 Statistics follow * <- QueueLength: 0 * <- UpdatesWritten: 0 * <- DataSetsWritten: 0 * <- TreeNodesNumber: 0 * <- TreeDepth: 0 * }}} */ res = NULL; pthread_mutex_lock (&lock); status = request ("STATS\n", strlen ("STATS\n"), &res); pthread_mutex_unlock (&lock); if (status != 0) return (status); if (res->status <= 0) { response_free (res); return (EIO); } head = NULL; tail = NULL; for (i = 0; i < res->lines_num; i++) { char *key; char *value; char *endptr; rrdc_stats_t *s; key = res->lines[i]; value = strchr (key, ':'); if (value == NULL) continue; *value = 0; value++; while ((value[0] == ' ') || (value[0] == '\t')) value++; s = (rrdc_stats_t *) malloc (sizeof (rrdc_stats_t)); if (s == NULL) continue; memset (s, 0, sizeof (*s)); s->name = strdup (key); endptr = NULL; if ((strcmp ("QueueLength", key) == 0) || (strcmp ("TreeDepth", key) == 0) || (strcmp ("TreeNodesNumber", key) == 0)) { s->type = RRDC_STATS_TYPE_GAUGE; s->value.gauge = strtod (value, &endptr); } else if ((strcmp ("DataSetsWritten", key) == 0) || (strcmp ("FlushesReceived", key) == 0) || (strcmp ("JournalBytes", key) == 0) || (strcmp ("JournalRotate", key) == 0) || (strcmp ("UpdatesReceived", key) == 0) || (strcmp ("UpdatesWritten", key) == 0)) { s->type = RRDC_STATS_TYPE_COUNTER; s->value.counter = (uint64_t) strtoll (value, &endptr, /* base = */ 0); } else { free (s); continue; } /* Conversion failed */ if (endptr == value) { free (s); continue; } if (head == NULL) { head = s; tail = s; s->next = NULL; } else { tail->next = s; tail = s; } } /* for (i = 0; i < res->lines_num; i++) */ response_free (res); if (head == NULL) #ifdef EPROTO return (EPROTO); #else return (EINVAL); #endif *ret_stats = head; return (0); } /* }}} int rrdc_stats_get */
int rrdc_update (const char *filename, int values_num, /* {{{ */ const char * const *values) { char buffer[4096]; char *buffer_ptr; size_t buffer_free; size_t buffer_size; rrdc_response_t *res; int status; int i; char file_path[PATH_MAX]; memset (buffer, 0, sizeof (buffer)); buffer_ptr = &buffer[0]; buffer_free = sizeof (buffer); status = buffer_add_string ("update", &buffer_ptr, &buffer_free); if (status != 0) return (ENOBUFS); pthread_mutex_lock (&lock); filename = get_path (filename, file_path); if (filename == NULL) { pthread_mutex_unlock (&lock); return (-1); } status = buffer_add_string (filename, &buffer_ptr, &buffer_free); if (status != 0) { pthread_mutex_unlock (&lock); return (ENOBUFS); } for (i = 0; i < values_num; i++) { status = buffer_add_value (values[i], &buffer_ptr, &buffer_free); if (status != 0) { pthread_mutex_unlock (&lock); return (ENOBUFS); } } assert (buffer_free < sizeof (buffer)); buffer_size = sizeof (buffer) - buffer_free; assert (buffer[buffer_size - 1] == ' '); buffer[buffer_size - 1] = '\n'; res = NULL; status = request (buffer, buffer_size, &res); pthread_mutex_unlock (&lock); if (status != 0) return (status); status = res->status; response_free (res); return (status); } /* }}} int rrdc_update */
static int response_read (rrdc_response_t **ret_response) /* {{{ */ { rrdc_response_t *ret = NULL; int status = 0; char buffer[4096]; char *buffer_ptr; size_t i; #define DIE(code) do { status = code; goto err_out; } while(0) if (sh == NULL) DIE(-1); ret = (rrdc_response_t *) malloc (sizeof (rrdc_response_t)); if (ret == NULL) DIE(-2); memset (ret, 0, sizeof (*ret)); ret->lines = NULL; ret->lines_num = 0; buffer_ptr = fgets (buffer, sizeof (buffer), sh); if (buffer_ptr == NULL) DIE(-3); chomp (buffer); ret->status = strtol (buffer, &ret->message, 0); if (buffer == ret->message) DIE(-4); /* Skip leading whitespace of the status message */ ret->message += strspn (ret->message, " \t"); if (ret->status <= 0) { if (ret->status < 0) rrd_set_error("rrdcached: %s", ret->message); goto out; } ret->lines = (char **) malloc (sizeof (char *) * ret->status); if (ret->lines == NULL) DIE(-5); memset (ret->lines, 0, sizeof (char *) * ret->status); ret->lines_num = (size_t) ret->status; for (i = 0; i < ret->lines_num; i++) { buffer_ptr = fgets (buffer, sizeof (buffer), sh); if (buffer_ptr == NULL) DIE(-6); chomp (buffer); ret->lines[i] = strdup (buffer); if (ret->lines[i] == NULL) DIE(-7); } out: *ret_response = ret; fflush(sh); return (status); err_out: response_free(ret); close_connection(); return (status); #undef DIE } /* }}} rrdc_response_t *response_read */