/* * Turn a scalar Datum into JSON, appending the string to "result". * * Hand off a non-scalar datum to composite_to_json or array_to_json_internal * as appropriate. */ static void datum_to_json(Datum val, bool is_null, StringInfo result, TYPCATEGORY tcategory, Oid typoutputfunc) { char *outputstr; if (is_null) { appendStringInfoString(result, "null"); return; } switch (tcategory) { case TYPCATEGORY_ARRAY: array_to_json_internal(val, result, false); break; case TYPCATEGORY_COMPOSITE: composite_to_json(val, result, false); break; case TYPCATEGORY_BOOLEAN: if (DatumGetBool(val)) appendStringInfoString(result, "true"); else appendStringInfoString(result, "false"); break; case TYPCATEGORY_NUMERIC: outputstr = OidOutputFunctionCall(typoutputfunc, val); /* * Don't call escape_json here if it's a valid JSON number. * Numeric output should usually be a valid JSON number and JSON * numbers shouldn't be quoted. Quote cases like "Nan" and * "Infinity", however. */ if (strpbrk(outputstr, NON_NUMERIC_LETTER) == NULL) appendStringInfoString(result, outputstr); else escape_json(result, outputstr); pfree(outputstr); break; case TYPCATEGORY_JSON: /* JSON will already be escaped */ outputstr = OidOutputFunctionCall(typoutputfunc, val); appendStringInfoString(result, outputstr); pfree(outputstr); break; default: outputstr = OidOutputFunctionCall(typoutputfunc, val); escape_json(result, outputstr); pfree(outputstr); break; } }
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal) { switch (scalarVal->type) { case jbvNull: appendBinaryStringInfo(out, "null", 4); break; case jbvString: escape_json(out, pnstrdup(scalarVal->val.string.val, scalarVal->val.string.len)); break; case jbvNumeric: appendStringInfoString(out, DatumGetCString(DirectFunctionCall1(numeric_out, PointerGetDatum(scalarVal->val.numeric)))); break; case jbvBool: if (scalarVal->val.boolean) appendBinaryStringInfo(out, "true", 4); else appendBinaryStringInfo(out, "false", 5); break; default: elog(ERROR, "unknown jsonb scalar type"); } }
/* * appendJSONLiteral * Append to given StringInfo a JSON with a given key and a value * not yet made literal. */ static void appendJSONLiteral(StringInfo buf, const char *key, const char *value, bool is_comma) { StringInfoData literal_json; initStringInfo(&literal_json); Assert(key && value); /* * Call in-core function able to generate wanted strings, there is * no need to reinvent the wheel. */ escape_json(&literal_json, value); /* Now append the field */ appendStringInfo(buf, "\"%s\":%s", key, literal_json.data); /* Add comma if necessary */ if (is_comma) appendStringInfoChar(buf, ','); /* Clean up */ pfree(literal_json.data); }
Datum hstore_to_json(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); StringInfoData tmp, dst; if (count == 0) PG_RETURN_TEXT_P(cstring_to_text_with_len("{}",2)); initStringInfo(&tmp); initStringInfo(&dst); appendStringInfoChar(&dst, '{'); for (i = 0; i < count; i++) { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); escape_json(&dst, tmp.data); appendStringInfoString(&dst, ": "); if (HS_VALISNULL(entries, i)) appendStringInfoString(&dst, "null"); else { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_VAL(entries, base, i), HS_VALLEN(entries, i)); escape_json(&dst, tmp.data); } if (i + 1 != count) appendStringInfoString(&dst, ", "); } appendStringInfoChar(&dst, '}'); PG_RETURN_TEXT_P(cstring_to_text(dst.data)); }
static void json_ofstart(void *state, char *fname, bool isnull) { word_table *p; pgspParserContext *ctx = (pgspParserContext *)state; char *fn; ctx->remove = false; p = search_word_table(propfields, fname, ctx->mode); if (!p) { ereport(DEBUG1, (errmsg("JSON parser encoutered unknown field name: \"%s\".", fname), errdetail_log("INPUT: \"%s\"", ctx->org_string))); } ctx->remove = (ctx->mode == PGSP_JSON_NORMALIZE && (!p || !p->normalize_use)); if (ctx->remove) return; if (!bms_is_member(ctx->level, ctx->first)) { appendStringInfoChar(ctx->dest, ','); if (ctx->mode == PGSP_JSON_INFLATE) appendStringInfoChar(ctx->dest, '\n'); } else ctx->first = bms_del_member(ctx->first, ctx->level); if (ctx->mode == PGSP_JSON_INFLATE) appendStringInfoSpaces(ctx->dest, ctx->level * INDENT_STEP); if (!p || !p->longname) fn = fname; else if (ctx->mode == PGSP_JSON_INFLATE) fn = p->longname; else fn = p->shortname; escape_json(ctx->dest, fn); ctx->fname = fn; ctx->valconverter = (p ? p->converter : NULL); appendStringInfoChar(ctx->dest, ':'); if (ctx->mode == PGSP_JSON_INFLATE) appendStringInfoChar(ctx->dest, ' '); }
static void json_scalar(void *state, char *token, JsonTokenType tokentype) { pgspParserContext *ctx = (pgspParserContext *)state; const char *val = token; if (ctx->remove) return; if (ctx->valconverter) val = ctx->valconverter(token, ctx->mode); if (tokentype == JSON_TOKEN_STRING) escape_json(ctx->dest, val); else appendStringInfoString(ctx->dest, val); ctx->last_elem_is_object = false; }
/* * Turn a scalar Datum into JSON. Hand off a non-scalar datum to * composite_to_json or array_to_json_internal as appropriate. */ static inline void datum_to_json(Datum val, StringInfo result, TYPCATEGORY tcategory, Oid typoutputfunc) { char *outputstr; if (val == (Datum) NULL) { appendStringInfoString(result,"null"); return; } switch (tcategory) { case TYPCATEGORY_ARRAY: array_to_json_internal(val, result, false); break; case TYPCATEGORY_COMPOSITE: composite_to_json(val, result, false); break; case TYPCATEGORY_BOOLEAN: if (DatumGetBool(val)) appendStringInfoString(result,"true"); else appendStringInfoString(result,"false"); break; case TYPCATEGORY_NUMERIC: outputstr = OidOutputFunctionCall(typoutputfunc, val); /* * Don't call escape_json here. Numeric output should * be a valid JSON number and JSON numbers shouldn't * be quoted. */ appendStringInfoString(result, outputstr); pfree(outputstr); break; default: outputstr = OidOutputFunctionCall(typoutputfunc, val); escape_json(result, outputstr); pfree(outputstr); } }
/* * We output to the log file as json. * ex. for string 'msg\n' on the zone's stdout: * {"log":"msg\n","stream":"stdout","time":"2014-10-24T20:12:11.101973117Z"} * * We use ns in the last field of the timestamp for compatability. */ static void wr_log_msg(char *buf, int len, int from) { struct timeval tv; int olen; char ts[64]; char nbuf[BUFSIZ * 2]; char obuf[BUFSIZ * 2]; escape_json(buf, len, nbuf, sizeof (nbuf)); if (gettimeofday(&tv, NULL) != 0) return; (void) strftime(ts, sizeof (ts), "%FT%T", gmtime(&tv.tv_sec)); olen = snprintf(obuf, sizeof (obuf), "{\"log\":\"%s\",\"stream\":\"%s\",\"time\":\"%s.%ldZ\"}\n", nbuf, (from == 1) ? "stdout" : "stderr", ts, tv.tv_usec * 1000); (void) write(logfd, obuf, olen); }
Datum hstore_to_json_loose(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int i; int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); bool is_number; StringInfoData tmp, dst; if (count == 0) PG_RETURN_TEXT_P(cstring_to_text_with_len("{}",2)); initStringInfo(&tmp); initStringInfo(&dst); appendStringInfoChar(&dst, '{'); for (i = 0; i < count; i++) { resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); escape_json(&dst, tmp.data); appendStringInfoString(&dst, ": "); if (HS_VALISNULL(entries, i)) appendStringInfoString(&dst, "null"); /* guess that values of 't' or 'f' are booleans */ else if (HS_VALLEN(entries, i) == 1 && *(HS_VAL(entries, base, i)) == 't') appendStringInfoString(&dst, "true"); else if (HS_VALLEN(entries, i) == 1 && *(HS_VAL(entries, base, i)) == 'f') appendStringInfoString(&dst, "false"); else { is_number = false; resetStringInfo(&tmp); appendBinaryStringInfo(&tmp, HS_VAL(entries, base, i), HS_VALLEN(entries, i)); /* * don't treat something with a leading zero followed by another * digit as numeric - could be a zip code or similar */ if (tmp.len > 0 && !(tmp.data[0] == '0' && isdigit((unsigned char) tmp.data[1])) && strspn(tmp.data, "+-0123456789Ee.") == tmp.len) { /* * might be a number. See if we can input it as a numeric * value. Ignore any actual parsed value. */ char *endptr = "junk"; long lval; lval = strtol(tmp.data, &endptr, 10); (void) lval; if (*endptr == '\0') { /* * strol man page says this means the whole string is * valid */ is_number = true; } else { /* not an int - try a double */ double dval; dval = strtod(tmp.data, &endptr); (void) dval; if (*endptr == '\0') is_number = true; } } if (is_number) appendBinaryStringInfo(&dst, tmp.data, tmp.len); else escape_json(&dst, tmp.data); } if (i + 1 != count) appendStringInfoString(&dst, ", "); } appendStringInfoChar(&dst, '}'); PG_RETURN_TEXT_P(cstring_to_text(dst.data)); }
struct uwsgi_stats *uwsgi_master_generate_stats() { int i; struct uwsgi_stats *us = uwsgi_stats_new(8192); if (uwsgi_stats_keyval_comma(us, "version", UWSGI_VERSION)) goto end; #ifdef __linux__ if (uwsgi_stats_keylong_comma(us, "listen_queue", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS])) goto end; if (uwsgi_stats_keylong_comma(us, "listen_queue_errors", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS])) goto end; #endif int signal_queue = 0; if (ioctl(uwsgi.shared->worker_signal_pipe[1], FIONREAD, &signal_queue)) { uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n"); } if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue)) goto end; if (uwsgi_stats_keylong_comma(us, "load", (unsigned long long) uwsgi.shared->load)) goto end; if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) getpid())) goto end; if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) getuid())) goto end; if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) getgid())) goto end; char *cwd = uwsgi_get_cwd(); if (uwsgi_stats_keyval_comma(us, "cwd", cwd)) { free(cwd); goto end; } free(cwd); if (uwsgi.daemons) { if (uwsgi_stats_key(us, "daemons")) goto end; if (uwsgi_stats_list_open(us)) goto end; struct uwsgi_daemon *ud = uwsgi.daemons; while (ud) { if (uwsgi_stats_object_open(us)) goto end; // allocate 2x the size of original command // in case we need to escape all chars char *cmd = uwsgi_malloc(strlen(ud->command)*2); escape_json(ud->command, strlen(ud->command), cmd); if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) { free(cmd); goto end; } free(cmd); if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid)) goto end; if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns)) goto end; if (uwsgi_stats_object_close(us)) goto end; if (ud->next) { if (uwsgi_stats_comma(us)) goto end; } ud = ud->next; } if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_comma(us)) goto end; } if (uwsgi_stats_key(us, "locks")) goto end; if (uwsgi_stats_list_open(us)) goto end; struct uwsgi_lock_item *uli = uwsgi.registered_locks; while (uli) { if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keylong(us, uli->id, (unsigned long long) uli->pid)) goto end; if (uwsgi_stats_object_close(us)) goto end; if (uli->next) { if (uwsgi_stats_comma(us)) goto end; } uli = uli->next; } if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_comma(us)) goto end; if (uwsgi.caches) { if (uwsgi_stats_key(us, "caches")) goto end; if (uwsgi_stats_list_open(us)) goto end; struct uwsgi_cache *uc = uwsgi.caches; while(uc) { if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keyval_comma(us, "name", uc->name ? uc->name : "default")) goto end; if (uwsgi_stats_keyval_comma(us, "hash", uc->hash->name)) goto end; if (uwsgi_stats_keylong_comma(us, "hashsize", (unsigned long long) uc->hashsize)) goto end; if (uwsgi_stats_keylong_comma(us, "keysize", (unsigned long long) uc->keysize)) goto end; if (uwsgi_stats_keylong_comma(us, "max_items", (unsigned long long) uc->max_items)) goto end; if (uwsgi_stats_keylong_comma(us, "blocks", (unsigned long long) uc->blocks)) goto end; if (uwsgi_stats_keylong_comma(us, "blocksize", (unsigned long long) uc->blocksize)) goto end; if (uwsgi_stats_keylong_comma(us, "items", (unsigned long long) uc->n_items)) goto end; if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) uc->hits)) goto end; if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss)) goto end; if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full)) goto end; if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at)) goto end; if (uwsgi_stats_object_close(us)) goto end; if (uc->next) { if (uwsgi_stats_comma(us)) goto end; } uc = uc->next; } if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_comma(us)) goto end; } if (uwsgi_stats_key(us, "sockets")) goto end; if (uwsgi_stats_list_open(us)) goto end; struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; while (uwsgi_sock) { if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keyval_comma(us, "name", uwsgi_sock->name)) goto end; if (uwsgi_stats_keyval_comma(us, "proto", uwsgi_sock->proto_name ? uwsgi_sock->proto_name : "uwsgi")) goto end; if (uwsgi_stats_keylong_comma(us, "queue", (unsigned long long) uwsgi_sock->queue)) goto end; if (uwsgi_stats_keylong_comma(us, "shared", (unsigned long long) uwsgi_sock->shared)) goto end; if (uwsgi_stats_keylong(us, "can_offload", (unsigned long long) uwsgi_sock->can_offload)) goto end; if (uwsgi_stats_object_close(us)) goto end; uwsgi_sock = uwsgi_sock->next; if (uwsgi_sock) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_comma(us)) goto end; if (uwsgi_stats_key(us, "workers")) goto end; if (uwsgi_stats_list_open(us)) goto end; for (i = 0; i < uwsgi.numproc; i++) { if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) uwsgi.workers[i + 1].id)) goto end; if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid)) goto end; if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests)) goto end; if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests)) goto end; if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi_worker_exceptions(i + 1))) goto end; if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count)) goto end; if (uwsgi_stats_keylong_comma(us, "signals", (unsigned long long) uwsgi.workers[i + 1].signals)) goto end; if (ioctl(uwsgi.workers[i + 1].signal_pipe[1], FIONREAD, &signal_queue)) { uwsgi_error("uwsgi_master_generate_stats() -> ioctl()\n"); } if (uwsgi_stats_keylong_comma(us, "signal_queue", (unsigned long long) signal_queue)) goto end; if (uwsgi.workers[i + 1].cheaped) { if (uwsgi_stats_keyval_comma(us, "status", "cheap")) goto end; } else if (uwsgi.workers[i + 1].suspended && !uwsgi_worker_is_busy(i+1)) { if (uwsgi_stats_keyval_comma(us, "status", "pause")) goto end; } else { if (uwsgi.workers[i + 1].sig) { if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum)) goto end; } else if (uwsgi_worker_is_busy(i+1)) { if (uwsgi_stats_keyval_comma(us, "status", "busy")) goto end; } else { if (uwsgi_stats_keyval_comma(us, "status", "idle")) goto end; } } if (uwsgi_stats_keylong_comma(us, "rss", (unsigned long long) uwsgi.workers[i + 1].rss_size)) goto end; if (uwsgi_stats_keylong_comma(us, "vsz", (unsigned long long) uwsgi.workers[i + 1].vsz_size)) goto end; if (uwsgi_stats_keylong_comma(us, "running_time", (unsigned long long) uwsgi.workers[i + 1].running_time)) goto end; if (uwsgi_stats_keylong_comma(us, "last_spawn", (unsigned long long) uwsgi.workers[i + 1].last_spawn)) goto end; if (uwsgi_stats_keylong_comma(us, "respawn_count", (unsigned long long) uwsgi.workers[i + 1].respawn_count)) goto end; if (uwsgi_stats_keylong_comma(us, "tx", (unsigned long long) uwsgi.workers[i + 1].tx)) goto end; if (uwsgi_stats_keylong_comma(us, "avg_rt", (unsigned long long) uwsgi.workers[i + 1].avg_response_time)) goto end; // applications list if (uwsgi_stats_key(us, "apps")) goto end; if (uwsgi_stats_list_open(us)) goto end; int j; for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) { struct uwsgi_app *ua = &uwsgi.workers[i + 1].apps[j]; if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j)) goto end; if (uwsgi_stats_keylong_comma(us, "modifier1", (unsigned long long) ua->modifier1)) goto end; if (uwsgi_stats_keyvaln_comma(us, "mountpoint", ua->mountpoint, ua->mountpoint_len)) goto end; if (uwsgi_stats_keylong_comma(us, "startup_time", ua->startup_time)) goto end; if (uwsgi_stats_keylong_comma(us, "requests", ua->requests)) goto end; if (uwsgi_stats_keylong_comma(us, "exceptions", ua->exceptions)) goto end; if (ua->chdir) { if (uwsgi_stats_keyval(us, "chdir", ua->chdir)) goto end; } else { if (uwsgi_stats_keyval(us, "chdir", "")) goto end; } if (uwsgi_stats_object_close(us)) goto end; if (j < uwsgi.workers[i + 1].apps_cnt - 1) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_comma(us)) goto end; // cores list if (uwsgi_stats_key(us, "cores")) goto end; if (uwsgi_stats_list_open(us)) goto end; for (j = 0; j < uwsgi.cores; j++) { struct uwsgi_core *uc = &uwsgi.workers[i + 1].cores[j]; if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keylong_comma(us, "id", (unsigned long long) j)) goto end; if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uc->requests)) goto end; if (uwsgi_stats_keylong_comma(us, "static_requests", (unsigned long long) uc->static_requests)) goto end; if (uwsgi_stats_keylong_comma(us, "routed_requests", (unsigned long long) uc->routed_requests)) goto end; if (uwsgi_stats_keylong_comma(us, "offloaded_requests", (unsigned long long) uc->offloaded_requests)) goto end; if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors)) goto end; if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request)) goto end; if (uwsgi_stats_key(us, "vars")) goto end; if (uwsgi_stats_list_open(us)) goto end; if (uwsgi_stats_dump_vars(us, uc)) goto end; if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_object_close(us)) goto end; if (j < uwsgi.cores - 1) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_object_close(us)) goto end; if (i < uwsgi.numproc - 1) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; struct uwsgi_spooler *uspool = uwsgi.spoolers; if (uspool) { if (uwsgi_stats_comma(us)) goto end; if (uwsgi_stats_key(us, "spoolers")) goto end; if (uwsgi_stats_list_open(us)) goto end; while (uspool) { if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keyval_comma(us, "dir", uspool->dir)) goto end; if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uspool->pid)) goto end; if (uwsgi_stats_keylong_comma(us, "tasks", (unsigned long long) uspool->tasks)) goto end; if (uwsgi_stats_keylong_comma(us, "respawns", (unsigned long long) uspool->respawned)) goto end; if (uwsgi_stats_keylong(us, "running", (unsigned long long) uspool->running)) goto end; if (uwsgi_stats_object_close(us)) goto end; uspool = uspool->next; if (uspool) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; } struct uwsgi_cron *ucron = uwsgi.crons; if (ucron) { if (uwsgi_stats_comma(us)) goto end; if (uwsgi_stats_key(us, "crons")) goto end; if (uwsgi_stats_list_open(us)) goto end; while (ucron) { if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute)) goto end; if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour)) goto end; if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day)) goto end; if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month)) goto end; if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week)) goto end; char *cmd = uwsgi_malloc(strlen(ucron->command)*2); escape_json(ucron->command, strlen(ucron->command), cmd); if (uwsgi_stats_keyval_comma(us, "command", cmd)) { free(cmd); goto end; } free(cmd); if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique)) goto end; #ifdef UWSGI_SSL if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : "")) goto end; #endif if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid)) goto end; if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at)) goto end; if (uwsgi_stats_object_close(us)) goto end; ucron = ucron->next; if (ucron) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; } #ifdef UWSGI_SSL struct uwsgi_legion *legion = NULL; if (uwsgi.legions) { if (uwsgi_stats_comma(us)) goto end; if (uwsgi_stats_key(us, "legions")) goto end; if (uwsgi_stats_list_open(us)) goto end; legion = uwsgi.legions; while (legion) { if (uwsgi_stats_object_open(us)) goto end; if (uwsgi_stats_keyval_comma(us, "legion", legion->legion)) goto end; if (uwsgi_stats_keyval_comma(us, "addr", legion->addr)) goto end; if (uwsgi_stats_keyval_comma(us, "uuid", legion->uuid)) goto end; if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) legion->valor)) goto end; if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) legion->checksum)) goto end; if (uwsgi_stats_keylong_comma(us, "quorum", (unsigned long long) legion->quorum)) goto end; if (uwsgi_stats_keylong_comma(us, "i_am_the_lord", (unsigned long long) legion->i_am_the_lord)) goto end; if (uwsgi_stats_keylong_comma(us, "lord_valor", (unsigned long long) legion->lord_valor)) goto end; if (uwsgi_stats_keyvaln_comma(us, "lord_uuid", legion->lord_uuid, 36)) goto end; // legion nodes start if (uwsgi_stats_key(us, "nodes")) goto end; if (uwsgi_stats_list_open(us)) goto end; struct uwsgi_string_list *nodes = legion->nodes; while (nodes) { if (uwsgi_stats_str(us, nodes->value)) goto end; nodes = nodes->next; if (nodes) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; if (uwsgi_stats_comma(us)) goto end; // legion members start if (uwsgi_stats_key(us, "members")) goto end; if (uwsgi_stats_list_open(us)) goto end; uwsgi_rlock(legion->lock); struct uwsgi_legion_node *node = legion->nodes_head; while (node) { if (uwsgi_stats_object_open(us)) goto unlock_legion_mutex; if (uwsgi_stats_keyvaln_comma(us, "name", node->name, node->name_len)) goto unlock_legion_mutex; if (uwsgi_stats_keyval_comma(us, "uuid", node->uuid)) goto unlock_legion_mutex; if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) node->valor)) goto unlock_legion_mutex; if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) node->checksum)) goto unlock_legion_mutex; if (uwsgi_stats_keylong(us, "last_seen", (unsigned long long) node->last_seen)) goto unlock_legion_mutex; if (uwsgi_stats_object_close(us)) goto unlock_legion_mutex; node = node->next; if (node) { if (uwsgi_stats_comma(us)) goto unlock_legion_mutex; } } uwsgi_rwunlock(legion->lock); if (uwsgi_stats_list_close(us)) goto end; // legion nodes end if (uwsgi_stats_object_close(us)) goto end; legion = legion->next; if (legion) { if (uwsgi_stats_comma(us)) goto end; } } if (uwsgi_stats_list_close(us)) goto end; } #endif if (uwsgi_stats_object_close(us)) goto end; return us; #ifdef UWSGI_SSL unlock_legion_mutex: if (legion) uwsgi_rwunlock(legion->lock); #endif end: free(us->base); free(us); return NULL; }
/* * Turn a composite / record into JSON. */ static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds) { HeapTupleHeader td; Oid tupType; int32 tupTypmod; TupleDesc tupdesc; HeapTupleData tmptup, *tuple; int i; bool needsep = false; char *sep; sep = use_line_feeds ? ",\n " : ","; td = DatumGetHeapTupleHeader(composite); /* Extract rowtype info and find a tupdesc */ tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); /* Build a temporary HeapTuple control structure */ tmptup.t_len = HeapTupleHeaderGetDatumLength(td); tmptup.t_data = td; tuple = &tmptup; appendStringInfoChar(result,'{'); for (i = 0; i < tupdesc->natts; i++) { Datum val, origval; bool isnull; char *attname; TYPCATEGORY tcategory; Oid typoutput; bool typisvarlena; if (tupdesc->attrs[i]->attisdropped) continue; if (needsep) appendStringInfoString(result,sep); needsep = true; attname = NameStr(tupdesc->attrs[i]->attname); escape_json(result,attname); appendStringInfoChar(result,':'); origval = heap_getattr(tuple, i + 1, tupdesc, &isnull); if (tupdesc->attrs[i]->atttypid == RECORDARRAYOID) tcategory = TYPCATEGORY_ARRAY; else if (tupdesc->attrs[i]->atttypid == RECORDOID) tcategory = TYPCATEGORY_COMPOSITE; else if (tupdesc->attrs[i]->atttypid == JSONOID) tcategory = TYPCATEGORY_JSON; else tcategory = TypeCategory(tupdesc->attrs[i]->atttypid); getTypeOutputInfo(tupdesc->attrs[i]->atttypid, &typoutput, &typisvarlena); /* * If we have a toasted datum, forcibly detoast it here to avoid memory * leakage inside the type's output routine. */ if (typisvarlena && ! isnull) val = PointerGetDatum(PG_DETOAST_DATUM(origval)); else val = origval; datum_to_json(val, result, tcategory, typoutput); /* Clean up detoasted copy, if any */ if (val != origval) pfree(DatumGetPointer(val)); } appendStringInfoChar(result,'}'); ReleaseTupleDesc(tupdesc); }
/* * Turn a composite / record into JSON. */ static void composite_to_json(Datum composite, StringInfo result, bool use_line_feeds) { HeapTupleHeader td; Oid tupType; int32 tupTypmod; TupleDesc tupdesc; HeapTupleData tmptup, *tuple; int i; bool needsep = false; const char *sep; sep = use_line_feeds ? ",\n " : ","; td = DatumGetHeapTupleHeader(composite); /* Extract rowtype info and find a tupdesc */ tupType = HeapTupleHeaderGetTypeId(td); tupTypmod = HeapTupleHeaderGetTypMod(td); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); /* Build a temporary HeapTuple control structure */ tmptup.t_len = HeapTupleHeaderGetDatumLength(td); tmptup.t_data = td; tuple = &tmptup; appendStringInfoChar(result, '{'); for (i = 0; i < tupdesc->natts; i++) { Datum val; bool isnull; char *attname; TYPCATEGORY tcategory; Oid typoutput; bool typisvarlena; Oid castfunc = InvalidOid; if (tupdesc->attrs[i]->attisdropped) continue; if (needsep) appendStringInfoString(result, sep); needsep = true; attname = NameStr(tupdesc->attrs[i]->attname); escape_json(result, attname); appendStringInfoChar(result, ':'); val = heap_getattr(tuple, i + 1, tupdesc, &isnull); getTypeOutputInfo(tupdesc->attrs[i]->atttypid, &typoutput, &typisvarlena); if (tupdesc->attrs[i]->atttypid > FirstNormalObjectId) { HeapTuple cast_tuple; Form_pg_cast castForm; cast_tuple = SearchSysCache2(CASTSOURCETARGET, ObjectIdGetDatum(tupdesc->attrs[i]->atttypid), ObjectIdGetDatum(JSONOID)); if (HeapTupleIsValid(cast_tuple)) { castForm = (Form_pg_cast) GETSTRUCT(cast_tuple); if (castForm->castmethod == COERCION_METHOD_FUNCTION) castfunc = typoutput = castForm->castfunc; ReleaseSysCache(cast_tuple); } } if (castfunc != InvalidOid) tcategory = TYPCATEGORY_JSON_CAST; else if (tupdesc->attrs[i]->atttypid == RECORDARRAYOID) tcategory = TYPCATEGORY_ARRAY; else if (tupdesc->attrs[i]->atttypid == RECORDOID) tcategory = TYPCATEGORY_COMPOSITE; else if (tupdesc->attrs[i]->atttypid == JSONOID) tcategory = TYPCATEGORY_JSON; else tcategory = TypeCategory(tupdesc->attrs[i]->atttypid); datum_to_json(val, isnull, result, tcategory, typoutput); } appendStringInfoChar(result, '}'); ReleaseTupleDesc(tupdesc); }
static void json_ofstart(void *state, char *fname, bool isnull) { word_table *p; pgspParserContext *ctx = (pgspParserContext *)state; char *fn; ctx->remove = false; p = search_word_table(propfields, fname, ctx->mode); if (!p) { ereport(DEBUG1, (errmsg("JSON parser encoutered unknown field name: \"%s\".", fname), errdetail_log("INPUT: \"%s\"", ctx->org_string))); } ctx->remove = (ctx->mode == PGSP_JSON_NORMALIZE && (!p || !p->normalize_use)); if (ctx->remove) return; if (!bms_is_member(ctx->level, ctx->first)) { appendStringInfoChar(ctx->dest, ','); if (ctx->mode == PGSP_JSON_INFLATE) appendStringInfoChar(ctx->dest, '\n'); } else ctx->first = bms_del_member(ctx->first, ctx->level); if (ctx->mode == PGSP_JSON_INFLATE) appendStringInfoSpaces(ctx->dest, ctx->level * INDENT_STEP); /* * We intentionally let some property names not have a short name. Use long * name for the cases. */ if (!p || !p->longname) fn = fname; else if (ctx->mode == PGSP_JSON_INFLATE || !(p->shortname && p->shortname[0])) fn = p->longname; else fn = p->shortname; escape_json(ctx->dest, fn); ctx->fname = fn; ctx->valconverter = (p ? p->converter : NULL); appendStringInfoChar(ctx->dest, ':'); if (ctx->mode == PGSP_JSON_INFLATE) appendStringInfoChar(ctx->dest, ' '); if (p && IS_INDENTED_ARRAY(p->tag)) { ctx->current_list = p->tag; ctx->list_fname = fname; ctx->wlist_level = 0; } }