static void recurse_print(fs_ptree *pt, nodeid n, char *buffer, int pos, struct ptree_stats *stats, FILE *out, int verbosity) { unsigned int len = 0; node *no = node_ref(pt, n); int branches = 0; int leaves = 0; for (int b=0; b<FS_PTREE_BRANCHES; b++) { sprintf(buffer+pos, "%x", b); if (no->branch[b] == FS_PTREE_NULL_NODE) { (stats->deadends)++; } else if (IS_LEAF(no->branch[b])) { branches++; leaves++; (stats->leaves)++; buffer[pos+1] ='\0'; fprintf(out, "%-32s [B%08x, %016llx x %d]\n", buffer, LEAF_REF(pt, no->branch[b])->block, LEAF_REF(pt, no->branch[b])->pk, LEAF_REF(pt, no->branch[b])->length); if (pt->table) { int check_len = 0; fs_ptable_check_consistency(pt->table, out, no->branch[b], LEAF_REF(pt, no->branch[b])->block, &check_len); if (LEAF_REF(pt, no->branch[b])->length != check_len) { fprintf(out, "ERROR: tree leaf has length %d, but consistency check says %d\n", LEAF_REF(pt, no->branch[b])->length, check_len); } if (LEAF_REF(pt, no->branch[b])->length == 0) { if (LEAF_REF(pt, no->branch[b])->block != 0) { fprintf(out, "ERROR: tree leaf has 0 length, but block is non-zero\n"); } else { fprintf(out, "ERROR: tree leaf has 0 length, should have been colected\n"); } } else if (LEAF_REF(pt, no->branch[b])->length < 0) { fprintf(out, "ERROR: tree node length is %d\n", LEAF_REF(pt, no->branch[b])->length < 0); } else if (LEAF_REF(pt, no->branch[b])->block == 0) { fprintf(out, "ERROR: tree node references block zero, but has non-zero length\n"); } else if ((len = fs_ptable_chain_length(pt->table, LEAF_REF(pt, no->branch[b])->block, LEAF_REF(pt, no->branch[b])->length + 100)) != LEAF_REF(pt, no->branch[b])->length) { if (LEAF_REF(pt, no->branch[b])->length + 101 == len) { fprintf(out, "ERROR: probable loop in table, tree node length %d, table length > %d\n", LEAF_REF(pt, no->branch[b])->length, len); } else { fprintf(out, "ERROR: tree node length %d != table length %d\n", LEAF_REF(pt, no->branch[b])->length, len); } } } stats->count += LEAF_REF(pt, no->branch[b])->length; for (int c=0; c<pos; c++) { buffer[c] = '.'; } } else { (stats->nodes)++; branches++; recurse_print(pt, no->branch[b], buffer, pos+1, stats, out, verbosity); } } if (branches == 1 && leaves == 1 && pos > 2 && n != FS_PTREE_ROOT_NODE) { fprintf(out, "ERROR: node %08x has 1 leaf at depth %d, should have " "been merged up\n", n, pos); } else if (branches == 0 && n != FS_PTREE_ROOT_NODE) { fprintf(out, "ERROR: node %08x has 0 branches at depth %d, should " "have been culled\n", n, pos); } }
fs_row_id fs_ptable_remove_pair(fs_ptable *pt, fs_row_id b, fs_rid pair[2], int *removed) { fs_row_id ret = b; if (b == 0) { fs_error(LOG_CRIT, "tried to read row 0"); return ret; } if (b > pt->header->length) { fs_error(LOG_CRIT, "tried to read off end of ptable (%d > %d)", b, pt->header->length); return ret; } /* NULL, NULL means remove everything */ if (pair[0] == FS_RID_NULL && pair[1] == FS_RID_NULL) { *removed += fs_ptable_chain_length(pt, b, 0); fs_ptable_remove_chain(pt, b); return 0; } row *prevr = NULL; while (b != 0) { row *r = &(pt->data[b]); fs_row_id nextb = r->cont; if (pair[0] != FS_RID_NULL && pair[1] == FS_RID_NULL) { if (r->data[0] == pair[0]) { if (prevr) { prevr->cont = nextb; } else { ret = nextb; } fs_ptable_free_row(pt, b); (*removed)++; } else { prevr = r; } } else if (pair[0] == FS_RID_NULL && pair[1] != FS_RID_NULL) { if (r->data[1] == pair[1]) { if (prevr) { prevr->cont = nextb; } else { ret = nextb; } fs_ptable_free_row(pt, b); (*removed)++; } else { prevr = r; } } else if (pair[0] != FS_RID_NULL && pair[1] != FS_RID_NULL) { if (r->data[0] == pair[0] && r->data[1] == pair[1]) { if (prevr) { prevr->cont = nextb; } else { ret = nextb; } fs_ptable_free_row(pt, b); (*removed)++; } else { prevr = r; } } else { fs_error(LOG_CRIT, "trying to remove with unsupported pattern"); } b = nextb; } return ret; }