void VertexServer_requestHandler(void *arg) { VertexServer *self = (VertexServer *)arg; VertexServer_setupYajl(self); HttpResponse_setContentType_(self->httpResponse, "application/json;charset=utf-8"); int result = VertexServer_process(self); Datum *content = HttpResponse_content(self->httpResponse); if (result == 0) { if (!Datum_size(content)) { Datum_setCString_(content, "null"); } Datum_nullTerminate(content); } else { if (!Datum_size(content)) { Datum_setCString_(content, "\"unknown error\""); } Datum_nullTerminate(content); yajl_gen_clear(self->yajl); yajl_gen_datum(self->yajl, content); Datum_setYajl_(content, self->yajl); if(self->debug) { Log_Printf_("REQUEST ERROR: %s\n", Datum_data(content)); } } }
int PNode_atCat_(PNode *self, Datum *k, Datum *v) { int hasKey = PNode_at_(self, k) != NULL; if (!PDB_at_cat_(self->pdb, Datum_data(self->keyPath), (int)Datum_size(self->keyPath), Datum_data(v), (int)Datum_size(v))) { printf("PNode_atCat_ error\n"); return -1; } if (!hasKey) return PNode_incrementSize(self); return 0; }
void PNode_first(PNode *self) // returns 0 when at end { StoreCursor_jump(self->storeCursor, Datum_data(self->pidPath), (int)Datum_size(self->pidPath)); if(!PNode_key(self)) { StoreCursor_next(self->storeCursor); } }
int PNode_op_values(PNode *self, Datum *d) { PQuery *q = PNode_startQuery(self); PNode *tmpNode = PDB_allocNode(self->pdb); Datum *k; Datum *attribute = PQuery_attribute(q); int hasAttribute = Datum_size(attribute) != 0; yajl_gen_array_open(self->yajl); while (k = PQuery_key(q)) { if(!Datum_beginsWithCString_(k, "_")) { PNode_setPid_(tmpNode, PNode_value(self)); if(hasAttribute) { //Datum *a = PQuery_attributeValue(q); Datum *a = PNode_at_(tmpNode, attribute); yajl_gen_array_open(self->yajl); yajl_gen_datum(self->yajl, k); if(a) { yajl_gen_datum(self->yajl, a); } else { yajl_gen_null(self->yajl); } yajl_gen_array_close(self->yajl); } else { PNode_setPid_(tmpNode, PNode_value(self)); PNode_op_object(tmpNode, 0x0); } } else { yajl_gen_datum(self->yajl, PNode_value(self)); } PQuery_enumerate(q); } yajl_gen_array_close(self->yajl); Datum_appendYajl_(d, self->yajl); return 0; }
int PNode_metaAt_put_(PNode *self, Datum *key, Datum *value) { Datum *slot = PNode_metaSlotFor_(self, key); if(!PDB_at_put_(self->pdb, Datum_data(slot), (int)Datum_size(slot), Datum_data(value), (int)Datum_size(value))) { return -1; } return 0; }
void PNode_create(PNode *self) { int size; int tryCount = 0; char *k = 0x0; do { if(k) free(k); Datum_makePid32(self->pid); //Datum_makePid64(self->pid); PNode_setPathsFromPid(self); tryCount ++; } while (k = PDB_at_(self->pdb, Datum_data(self->sizePath), (int)Datum_size(self->sizePath), &size)); if(tryCount > 3) { printf("WARNING: pid creation tryCount: %i %s\n", tryCount, Datum_data(self->pid)); } PDB_at_put_(self->pdb, Datum_data(self->sizePath), (int)Datum_size(self->sizePath), "", 0); }
IoObject *IoTagDB_symbolForId(IoTagDB *self, IoObject *locals, IoMessage *m) { /*doc TagDB symbolForId(aNumber) Returns the TagDB symbol for aNumber. */ symbolid_t id = IoMessage_locals_sizetArgAt_(m, locals, 0); Datum *d = TagDB_symbolForId_(DATA(self), id); IoSeq *s = IoSeq_newWithData_length_(IOSTATE, Datum_data(d), Datum_size(d)); Datum_free(d); return s; }
void HttpRequest_parseUri_(HttpRequest *self, const char *uri) { Datum_setCString_(self->uri, uri); int index; Datum *uriDatum = Datum_poolNew(); Datum_setCString_(uriDatum, uri); //if (self->debug) { Log_Printf_("request: %s\n", uri); } CHash_clear(self->query); Datum_setSize_(self->uriPath, 0); index = Datum_from_beforeChar_into_(uriDatum, 1, '?', self->uriPath); Datum_decodeUri(self->uriPath); for (;;) { Datum *key = Datum_poolNew(); Datum *value = Datum_poolNew(); index = Datum_from_beforeChar_into_(uriDatum, index + 1, '=', key); Datum_decodeUri(key); Datum_nullTerminate(key); if (Datum_size(key) == 0) break; index = Datum_from_beforeChar_into_(uriDatum, index + 1, '&', value); Datum_decodeUri(value); Datum_nullTerminate(value); CHash_at_put_(self->query, key, value); if(self->requestParameterCallback) { self->requestParameterCallback(self->delegate, key, value); } if (Datum_size(value) == 0) break; } }
int PNode_removeAt_(PNode *self, Datum *k) { if ((!Datum_isEmpty(k)) && (PNode_at_(self, k) != 0x0)) { if(!PDB_removeAt_(self->pdb, Datum_data(self->keyPath), (int)Datum_size(self->keyPath))) { printf("PNode_removeAt_ error\n"); return -1; } return PNode_decrementSize(self); } return 0; }
long PNode_size(PNode *self) { int size; void *value; value = PDB_at_(self->pdb, Datum_data(self->sizePath), (int)Datum_size(self->sizePath), &size); if (value) { long sizeValue = atoi(value); free(value); return sizeValue; } return 0; }
Datum *PNode_metaAt_(PNode *self, Datum *d) { Datum *slot = PNode_metaSlotFor_(self, d); { int vSize; void *v = PDB_at_(self->pdb, Datum_data(slot), (int)Datum_size(slot), &vSize); if (v) { Datum *value = Datum_poolNewWithData_size_(v, vSize); free(v); return value; } } return 0x0; }
int PNode_setSize_(PNode *self, long s) { Datum_copy_(self->sizePath, self->pid); Datum_appendCString_(self->sizePath, "/m/size"); { char ns[128]; snprintf(ns, 127, "%u", (unsigned int)s); //printf("%s <- %s\n", Datum_data(self->sizePath), ns); if(!PDB_at_put_(self->pdb, Datum_data(self->sizePath), (int)Datum_size(self->sizePath), (const void *)ns, (int)strlen(ns))) { return -1; } } return 0; }
Datum *PNode_atCString_(PNode *self, const char *k) { int size; void *v; Datum_copy_(self->keyPath, self->pidPath); Datum_appendCString_(self->keyPath, k); v = PDB_at_(self->pdb, Datum_data(self->keyPath), (int)Datum_size(self->keyPath), &size); if (v != 0x0) { Datum *value = Datum_poolNewWithData_size_(v, size); free(v); return value; } return 0x0; }
int PNode_remove(PNode *self) { Datum *k; long removeCount = 0; while ((k = PNode_key(self))) { PDB_willWrite(self->pdb); if(!StoreCursor_remove(self->storeCursor)) break; removeCount ++; } Datum_copy_(self->sizePath, self->pid); Datum_appendCString_(self->sizePath, "/m/size"); PDB_removeAt_(self->pdb, Datum_data(self->sizePath), Datum_size(self->sizePath)); return removeCount; }
Datum *PNode_key(PNode *self) { int size; char *ks = StoreCursor_key(self->storeCursor, &size); //if (ks == 0x0 || size == 0) return 0x0; if (ks == 0x0) return 0x0; if(Datum_isBeginningOfCString_(self->pidPath, ks)) { const char *subpath = ks + Datum_size(self->pidPath); Datum *key = Datum_poolNewWithCString_(subpath); free(ks); return key; } free(ks); return 0x0; }
int VertexServer_api_transaction(VertexServer *self) { Datum *uri = Datum_new(); Datum *post = Datum_new(); int error = 0; int r, result; PDB_commit(self->pdb); Datum_copy_(post, HttpRequest_postData(self->httpRequest)); do { Datum_copy_(uri, post); r = Datum_sepOnChars_with_(uri, "\n", post); if (Datum_size(uri) == 0) { VertexServer_setErrorCString_(self, "empty line in transaction"); error = 1; break; } HttpRequest_parseUri_(self->httpRequest, Datum_data(uri)); error = VertexServer_process(self); Pool_globalPoolFreeRefs(); } while ((r != -1) && (!error)); if (error) { PDB_abort(self->pdb); result = -1; } else { PDB_commit(self->pdb); result = 0; } Datum_free(uri); return result; }
IoObject *IoSkipDB_at(IoObject *self, IoObject *locals, IoMessage *m) { /*doc SkipDB at(keySymbol) Returns a Sequence for the value at the given key or nil if there is no such key. */ IoSeq *key = IoMessage_locals_seqArgAt_(m, locals, 0); Datum v; IOASSERT(SKIPDB(self) && SkipDB_isOpen(SKIPDB(self)), "invalid skipdb"); v = SkipDB_at_(SKIPDB(self), IoSeq_asDatum(key)); if (Datum_size(&v)) { return IoSeq_newWithDatum_(IOSTATE, &v); } return IONIL(self); }
int VertexServer_process(VertexServer *self) { Datum *actionName = (Datum *)HttpRequest_queryValue_(self->httpRequest, "action"); //if(self->debug) { Log_Printf_("REQUEST ERROR: %s\n", HttpRequest_uri(self->httpRequest)); } if (Datum_size(actionName)) { VertexAction *action = (VertexAction *)CHash_at_(self->actions, actionName); if (action) { return action(self); } } else { return VertexServer_api_view(self); } VertexServer_setErrorCString_(self, "invalid action"); return -1; }
int VertexServer_api_view(VertexServer *self) { Datum *before = HttpRequest_queryValue_(self->httpRequest, "before"); Datum *after = HttpRequest_queryValue_(self->httpRequest, "after"); Datum *mode = HttpRequest_queryValue_(self->httpRequest, "mode"); PNode *node = PDB_allocNode(self->pdb); PNode *tmpNode = PDB_allocNode(self->pdb); Datum *d = self->result; int maxCount = 200; if (PNode_moveToPathIfExists_(node, HttpRequest_uriPath(self->httpRequest)) != 0) { VertexServer_setErrorCString_(self, "path does not exist: "); VertexServer_appendError_(self, HttpRequest_uriPath(self->httpRequest)); return -1; } Datum_appendCString_(d, "<!DOCTYPE html>\n"); Datum_appendCString_(d, "<html>\n"); Datum_appendCString_(d, "<head>\n"); Datum_appendCString_(d, "<title>"); Datum_append_(d, HttpRequest_uriPath(self->httpRequest)); Datum_appendCString_(d, "</title>\n"); Datum_appendCString_(d, "<meta charset=\"utf-8\">\n"); Datum_appendCString_(d, "<style>"); Datum_appendCString_(d, "body, td { font-family: Helvetica; font-size: 12px; margin-top:2em; margin-left:2em; }"); Datum_appendCString_(d, ".path { font-weight: normal; }"); Datum_appendCString_(d, ".note { color:#aaaaaa; }"); Datum_appendCString_(d, ".key { color:#000000; }"); Datum_appendCString_(d, ".value { color:#888888; white-space:pre; }"); Datum_appendCString_(d, "a { color: #0000aa; text-decoration: none; }"); Datum_appendCString_(d, "</style>\n"); Datum_appendCString_(d, "</head>\n"); Datum_appendCString_(d, "<body>\n"); /* if(Datum_size(HttpRequest_uriPath(self->httpRequest)) == 0) { Datum_appendCString_(d, "/"); } else { */ Datum_appendCString_(d, "<font class=path>"); Datum_appendCString_(d, "/"); Datum_append_(d, HttpRequest_uriPath(self->httpRequest)); Datum_appendCString_(d, "</font>"); Datum_appendCString_(d, "<br>\n"); //} PNode_first(node); if(Datum_size(before)) { PNode_jump_(node, before); int i; for(i = 0; i < maxCount; i++) { PNode_previous(node); } PNode_next(node); } else if(Datum_size(after)) { PNode_jump_(node, after); } if (Datum_size(after) && PNode_key(node)) { Datum_appendCString_(d, "<a href=/"); Datum_append_(d, HttpRequest_uriPath(self->httpRequest)); Datum_appendCString_(d, "?before="); Datum_append_(d, PNode_key(node)); Datum_appendCString_(d, ">previous</a>"); } Datum_appendCString_(d, "<ul>\n"); Datum_appendCString_(d, "<table cellpadding=0 cellspacing=0 border=0>"); { Datum *k; int count = 0; while ((k = PNode_key(node)) && count < maxCount) { if (Datum_beginsWithCString_(k , "_")) { Datum_appendCString_(d, "<tr>"); Datum_appendCString_(d, "<td align=right style=\"line-height:1.5em\">"); Datum_appendCString_(d, "<font class=key>"); Datum_append_(d, k); Datum_appendCString_(d, "</font>"); Datum_appendCString_(d, " "); Datum_appendCString_(d, "</td>"); Datum_appendCString_(d, "<td>"); Datum_appendCString_(d, " <span class=value>"); Datum_append_(d, PNode_value(node)); Datum_appendCString_(d, "</span>"); Datum_appendCString_(d, "<br>\n"); Datum_appendCString_(d, "</td>"); Datum_appendCString_(d, "</tr>"); } else { if(Datum_equalsCString_(mode, "table")) { PNode_setPid_(tmpNode, PNode_value(node)); PNode_asHtmlRow(tmpNode, d); } else { Datum_appendCString_(d, "<tr>"); Datum_appendCString_(d, "<td align=right>"); Datum_appendCString_(d, "<font class=key>"); Datum_append_(d, k); Datum_appendCString_(d, "</font><br>\n"); Datum_appendCString_(d, "</td>"); Datum_appendCString_(d, "<td style=\"line-height:1.5em\">"); Datum_appendCString_(d, " <a href="); if(Datum_size(HttpRequest_uriPath(self->httpRequest)) != 0) Datum_appendCString_(d, "/"); Datum_append_(d, HttpRequest_uriPath(self->httpRequest)); Datum_appendCString_(d, "/"); Datum_append_(d, k); Datum_appendCString_(d, "> ↠ "); Datum_appendLong_(d, PNode_nodeSizeAtCursor(node)); Datum_appendCString_(d, "</a> "); Datum_appendCString_(d, "<font class=value>"); Datum_appendCString_(d, "</td>"); Datum_appendCString_(d, "</tr>"); } } PNode_next(node); count ++; } } Datum_appendCString_(d, "</table>"); Datum_appendCString_(d, "</ul>\n"); if(PNode_key(node)) { Datum_appendCString_(d, "<a href=/"); Datum_append_(d, HttpRequest_uriPath(self->httpRequest)); Datum_appendCString_(d, "?after="); Datum_append_(d, PNode_key(node)); Datum_appendCString_(d, ">next</a><br>"); } Datum_appendCString_(d, "</body>\n"); Datum_appendCString_(d, "</html>\n"); HttpResponse_setContentType_(self->httpResponse, "text/html; charset=utf-8"); return 0; }
void PNode_jump_(PNode *self, Datum *k) { Datum_copy_(self->keyPath, self->pidPath); Datum_append_(self->keyPath, k); StoreCursor_jump(self->storeCursor, Datum_data(self->keyPath), (int)Datum_size(self->keyPath)); }
int VertexServer_api_amchart(VertexServer *self) { Datum *slot1 = HttpRequest_queryValue_(self->httpRequest, "slot1"); //Datum *slot2 = HttpRequest_queryValue_(self->httpRequest, "slot2"); //Datum *slot3 = HttpRequest_queryValue_(self->httpRequest, "slot3"); Datum *subpath = HttpRequest_queryValue_(self->httpRequest, "subpath"); PNode *node = PDB_allocNode(self->pdb); PQuery *q = PNode_query(node); VertexServer_setupPQuery_(self, q); PNode *tmpNode = PDB_allocNode(self->pdb); Datum *d = self->result; Datum *title = 0x0; //int isFirst = 1; if (PNode_moveToPathIfExists_(node, HttpRequest_uriPath(self->httpRequest)) != 0) { VertexServer_setErrorCString_(self, "path does not exist: "); VertexServer_appendError_(self, HttpRequest_uriPath(self->httpRequest)); return -1; } Datum_appendCString_(d, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); Datum_appendCString_(d, "<chart approx_count=\""); // series ----------------- if(Datum_size(subpath)) PNode_moveToPathIfExists_(node, subpath); Datum_appendLong_(d, PNode_size(node)); Datum_appendCString_(d, "\">\n"); PNode_startQuery(node); PNode_amSeries(node, d); PNode_moveToPathIfExists_(node, HttpRequest_uriPath(self->httpRequest)); // series ----------------- Datum_appendCString_(d, "<graphs>\n"); PNode_first(node); if(Datum_size(subpath)) { Datum *k; while(k = PNode_key(node)) { Datum *title = Datum_poolNew(); PNode_setPid_(tmpNode, PNode_value(node)); PNode_moveToSubpathIfExists_(tmpNode, subpath); Datum_encodeUri(k); Datum_copy_(title, k); //Datum_appendCString_(title, "-"); //Datum_append_(title, slot1); PNode_amGraphKey_(tmpNode, title, slot1, d); //printf("graph: %s\n", Datum_data(k)); PNode_next(node); } } else if(Datum_size(slot1)) { char slotKey[64]; int slotNumber = 1; for (;;) { sprintf(slotKey, "slot%i", slotNumber); Datum *slotName = HttpRequest_queryValue_(self->httpRequest, slotKey); if(Datum_size(slotName) == 0) break; PNode_amGraphKey_(node, title, slotName, d); slotNumber ++; } } Datum_appendCString_(d, "</graphs>\n"); Datum_appendCString_(d, "</chart>\n"); HttpResponse_setContentType_(self->httpResponse, "text/xml"); //HttpResponse_setContentType_(self->httpResponse, "text/xml; charset=utf-8"); return 0; }
void PNode_jumpToCurrentKey(PNode *self) { StoreCursor_jump(self->storeCursor, Datum_data(self->keyPath), (int)Datum_size(self->keyPath)); }
void yajl_gen_datum(yajl_gen self, Datum *d) { yajl_gen_string(self, (const unsigned char *)Datum_data(d), Datum_size(d)); }
int PNode_doesExist(PNode *self) { StoreCursor_jump(self->storeCursor, Datum_data(self->pid), (int)Datum_size(self->pid)); return PNode_key(self) != 0x0; }