int mtev_rest_eventer_logs(mtev_http_rest_closure_t *restc, int n, char **p) { char *endptr = NULL; const char *since_s, *last_s; const char *jsonstr; char errbuf[128]; unsigned long long since; int last = 0; struct json_object *doc; mtev_log_stream_t ls; mtev_http_request *req = mtev_http_session_request(restc->http_ctx); since_s = mtev_http_request_querystring(req, "since"); if(since_s) since = strtoull(since_s, &endptr, 10); last_s = mtev_http_request_querystring(req, "last"); if(last_s) last = atoi(last_s); assert(n==1); ls = mtev_log_stream_find(p[0]); if(!ls || strcmp(mtev_log_stream_get_type(ls),"memory")) goto not_found; doc = json_object_new_array(); if(endptr != since_s) mtev_log_memory_lines_since(ls, since, json_spit_log, doc); else mtev_log_memory_lines(ls, last, json_spit_log, doc); mtev_http_response_ok(restc->http_ctx, "application/json"); jsonstr = json_object_to_json_string(doc); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; not_found: doc = json_object_new_object(); snprintf(errbuf, sizeof(errbuf), "log '%s' not found", p[0]); json_object_object_add(doc, "error", json_object_new_string(errbuf)); jsonstr = json_object_to_json_string(doc); mtev_http_response_not_found(restc->http_ctx, "application/json"); mtev_http_response_append(restc->http_ctx, jsonstr, strlen(jsonstr)); mtev_http_response_append(restc->http_ctx, "\n", 1); json_object_put(doc); mtev_http_response_end(restc->http_ctx); return 0; }
int noit_jlog_handler(eventer_t e, int mask, void *closure, struct timeval *now) { eventer_t newe; pthread_t tid; pthread_attr_t tattr; int newmask = EVENTER_READ | EVENTER_EXCEPTION; acceptor_closure_t *ac = closure; noit_jlog_closure_t *jcl = ac->service_ctx; char errbuff[256]; const char *errstr = "unknown error"; if(mask & EVENTER_EXCEPTION || (jcl && jcl->wants_shutdown)) { int len, nlen; socket_error: /* Exceptions cause us to simply snip the connection */ len = strlen(errstr); nlen = htonl(0 - len); e->opset->write(e->fd, &nlen, sizeof(nlen), &newmask, e); e->opset->write(e->fd, errstr, strlen(errstr), &newmask, e); eventer_remove_fd(e->fd); e->opset->close(e->fd, &newmask, e); if(jcl) noit_jlog_closure_free(jcl); acceptor_closure_free(ac); return 0; } if(!ac->service_ctx) { mtev_log_stream_t ls; const char *logname, *type; int first_attempt = 1; char path[PATH_MAX], subscriber[256], *sub; jcl = ac->service_ctx = noit_jlog_closure_alloc(); if(!mtev_hash_retr_str(ac->config, "log_transit_feed_name", strlen("log_transit_feed_name"), &logname)) { errstr = "No 'log_transit_feed_name' specified in log_transit."; mtevL(noit_error, "%s\n", errstr); goto socket_error; } ls = mtev_log_stream_find(logname); if(!ls) { snprintf(errbuff, sizeof(errbuff), "Could not find log '%s' for log_transit.", logname); errstr = errbuff; mtevL(noit_error, "%s\n", errstr); goto socket_error; } type = mtev_log_stream_get_type(ls); if(!type || strcmp(type, "jlog")) { snprintf(errbuff, sizeof(errbuff), "Log '%s' for log_transit is not a jlog.", logname); errstr = errbuff; mtevL(noit_error, "%s\n", errstr); goto socket_error; } if(ac->cmd == NOIT_JLOG_DATA_FEED) { if(!ac->remote_cn) { errstr = "jlog transit started to unidentified party."; mtevL(noit_error, "%s\n", errstr); goto socket_error; } strlcpy(subscriber, ac->remote_cn, sizeof(subscriber)); jcl->feed_stats = noit_jlog_feed_stats(subscriber); } else { jcl->feed_stats = noit_jlog_feed_stats("~"); snprintf(subscriber, sizeof(subscriber), "~%07d", mtev_atomic_inc32(&tmpfeedcounter)); } jcl->subscriber = strdup(subscriber); strlcpy(path, mtev_log_stream_get_path(ls), sizeof(path)); sub = strchr(path, '('); if(sub) { char *esub = strchr(sub, ')'); if(esub) { *esub = '\0'; *sub++ = '\0'; } } jcl->jlog = jlog_new(path); if(ac->cmd == NOIT_JLOG_DATA_TEMP_FEED) { add_sub: if(jlog_ctx_add_subscriber(jcl->jlog, jcl->subscriber, JLOG_END) == -1) { snprintf(errbuff, sizeof(errbuff), "jlog reader[%s] error: %s", jcl->subscriber, jlog_ctx_err_string(jcl->jlog)); errstr = errbuff; mtevL(noit_error, "%s\n", errstr); } } if(jlog_ctx_open_reader(jcl->jlog, jcl->subscriber) == -1) { if(sub && !strcmp(sub, "*")) { if(first_attempt) { jlog_ctx_close(jcl->jlog); jcl->jlog = jlog_new(path); first_attempt = 0; goto add_sub; } } snprintf(errbuff, sizeof(errbuff), "jlog reader[%s] error: %s", jcl->subscriber, jlog_ctx_err_string(jcl->jlog)); errstr = errbuff; mtevL(noit_error, "%s\n", errstr); goto socket_error; } } /* The jlog stuff is disk I/O and can block us. * We'll create a new thread to just handle this connection. */ eventer_remove_fd(e->fd); newe = eventer_alloc(); memcpy(newe, e, sizeof(*e)); pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); mtev_gettimeofday(&jcl->feed_stats->last_connection, NULL); mtev_atomic_inc32(&jcl->feed_stats->connections); if(pthread_create(&tid, &tattr, noit_jlog_thread_main, newe) == 0) { return 0; } /* Undo our dup */ eventer_free(newe); /* Creating the thread failed, close it down and deschedule. */ e->opset->close(e->fd, &newmask, e); return 0; }