static bool recursive_dump(struct VirtualContainer *const vc, FILE *const out) { // only the metatable's id is dumpped :) if (!vc) { fprintf(out, "[]\n"); return true; } fprintf(out, "[ %" PRIu64 "\n", vc->start_bit); if (vc->cc.bc) { fprintf(out, "<!\n"); } else { fprintf(out, "<\n"); } // dump at most 8 MetaTable for (uint64_t j = 0; j < vc->cc.count; j++) { if (vc->cc.metatables[j]) { const uint64_t mtid = vc->cc.metatables[j]->mtid; fprintf(out, "%016" PRIx64 "\n", mtid); } } if (vc->cc.bc) { fprintf(out, ">!%016" PRIx64 "\n", vc->cc.bc->mtid); } else { fprintf(out, ">\n"); } for (uint64_t j = 0; j < 8; j++) { recursive_dump(vc->sub_vc[j], out); } fprintf(out, "]\n"); return true; }
// backup db metadata static bool db_dump_meta(struct DB *const db) { char path_meta[256]; char path_sym[256]; const double sec0 = debug_time_sec(); // prepare files sprintf(path_meta, "%s/%s/%s-%018.6lf", db->persist_dir, DB_META_BACKUP_DIR, DB_META_MAIN, sec0); FILE *const meta_out = fopen(path_meta, "w"); assert(meta_out); const uint64_t ticket = rwlock_reader_lock(&(db->rwlock)); // dump meta // write vc const bool r_meta = recursive_dump(db->vcroot, meta_out); assert(r_meta); // write mtid const uint64_t db_next_mtid = db->next_mtid; fprintf(meta_out, "%" PRIu64 "\n", db_next_mtid); fclose(meta_out); // create symlink for newest meta sprintf(path_sym, "%s/%s", db->persist_dir, DB_META_MAIN); if (access(path_sym, F_OK) == 0) { const int ru = unlink(path_sym); assert(ru == 0); } const int rsm = symlink(path_meta, path_sym); assert(rsm == 0); // dump container-maps for (int i = 0; db->cms_dump[i]; i++) { char path_cm_dump[256]; sprintf(path_cm_dump, "%s/%s/%s-%01d-%018.6lf", db->persist_dir, DB_META_BACKUP_DIR, DB_META_CMAP_PREFIX, i, sec0); containermap_dump(db->cms_dump[i], path_cm_dump); // create symlink for newest meta sprintf(path_sym, "%s/%s-%01d", db->persist_dir, DB_META_CMAP_PREFIX, i); if (access(path_sym, F_OK) == 0) { const int ru = unlink(path_sym); assert(ru == 0); } const int rs = symlink(path_cm_dump, path_sym); assert(rs == 0); } // done rwlock_reader_unlock(&(db->rwlock), ticket); db_log_diff(db, sec0, "Dumping Metadata Finished (%06" PRIx64 ")", db_next_mtid); fflush(db->log); return true; }
void recursive_dump(const char *json, int length, int padding_n, int needs_separator, int recursion_level) { if (recursion_level > 15) { /* * nested too deep */ printf("ERROR: nested too deep\n"); exit(1); } jsonz_result_t *buf = jsonz_parse(json, length); jsonz_type_t root = jsonz_result_get_root_type(buf); const char *padding_str = padding_s + strlen(padding_s) - padding_n * 4; char separator = needs_separator ? ',' : '\0'; switch (root) { case jsonz_type_array: printf("[\n"); break; case jsonz_type_object: printf("{\n"); break; default: break; } int i; for (i = 0; i < jsonz_result_get_count(buf); i++) { int pos = jsonz_result_get_position(buf, i); int len = jsonz_result_get_length(buf, i); jsonz_type_t type = jsonz_result_get_type(buf, i); char comma = i < jsonz_result_get_count(buf) - 1 ? ',' : '\0'; switch (type) { case jsonz_type_null: { printf("%snull%c\n", root == jsonz_type_object && (i % 2) ? "" : padding_str - 4, comma); break; } case jsonz_type_bool: { char b[6]; strncpy(b, json + pos, len); b[len] = 0; printf("%s%s%c\n", root == jsonz_type_object && (i % 2) ? "" : padding_str - 4, b, comma); break; } case jsonz_type_number: { char ns[24]; strncpy(ns, json + pos, len); ns[len] = 0; printf("%s%s%c\n", root == jsonz_type_object && (i % 2) ? "" : padding_str - 4, ns, comma); break; } case jsonz_type_string: { char s[100]; strncpy(s, json + pos, len); s[len] = 0; switch (root) { case jsonz_type_array: printf("%s\"%s\"%c\n", padding_str - 4, s, comma); break; case jsonz_type_object: if (i % 2) { /* * value */ printf("\"%s\"%c\n", s, comma); } else { /* * key */ printf("%s\"%s\": ", padding_str - 4, s); } break; default: break; } break; } case jsonz_type_array: { if (root == jsonz_type_array) { /* * printf(" "); */ printf("%s", padding_str - 4); } recursive_dump(json + pos, len, padding_n + 1, comma == ',', recursion_level + 1); break; } case jsonz_type_object: { if (root == jsonz_type_array) { /* * printf(" "); */ printf("%s", padding_str - 4); } recursive_dump(json + pos, len, padding_n + 1, comma == ',', recursion_level + 1); break; } default: { break; } } } if (buf) { if (root == jsonz_type_object) { printf("%s}%c\n", padding_str, separator); } else { printf("%s]%c\n", padding_str, separator); } } jsonz_result_free(buf); }
int main(int argc, char **argv) { const char *json = argv[1]; recursive_dump(json, -1, 0, 0, 0); return 0; }