| 1439 | #endif |
| 1440 | |
| 1441 | Validation::RTN Validation::walk_blob(jrd_rel* relation, const blh* header, USHORT length, |
| 1442 | RecordNumber number) |
| 1443 | { |
| 1444 | /************************************** |
| 1445 | * |
| 1446 | * w a l k _ b l o b |
| 1447 | * |
| 1448 | ************************************** |
| 1449 | * |
| 1450 | * Functional description |
| 1451 | * Walk a blob. |
| 1452 | * |
| 1453 | **************************************/ |
| 1454 | |
| 1455 | #ifdef DEBUG_VAL_VERBOSE |
| 1456 | if (VAL_debug_level) |
| 1457 | { |
| 1458 | fprintf(stdout, |
| 1459 | "walk_blob: level %d lead page %d max pages %d max segment %d\n", |
| 1460 | header->blh_level, header->blh_lead_page, |
| 1461 | header->blh_max_sequence, header->blh_max_segment); |
| 1462 | fprintf(stdout, " count %d, length %d sub_type %d\n", |
| 1463 | header->blh_count, header->blh_length, |
| 1464 | header->blh_sub_type); |
| 1465 | } |
| 1466 | #endif |
| 1467 | |
| 1468 | switch (header->blh_level) |
| 1469 | { |
| 1470 | case 0: |
| 1471 | // Level 0 blobs have no work to do. |
| 1472 | return rtn_ok; |
| 1473 | case 1: |
| 1474 | case 2: |
| 1475 | break; |
| 1476 | default: |
| 1477 | corrupt(VAL_BLOB_UNKNOWN_LEVEL, relation, number.getValue(), header->blh_level); |
| 1478 | } |
| 1479 | |
| 1480 | // Level 1 blobs are a little more complicated |
| 1481 | WIN window1(DB_PAGE_SPACE, -1), window2(DB_PAGE_SPACE, -1); |
| 1482 | window1.win_flags = window2.win_flags = WIN_garbage_collector; |
| 1483 | |
| 1484 | const ULONG* pages1 = header->blh_page; |
| 1485 | const ULONG* const end1 = pages1 + ((USHORT) (length - BLH_SIZE) >> SHIFTLONG); |
| 1486 | ULONG sequence = 0; |
| 1487 | |
| 1488 | for (; pages1 < end1; pages1++) |
| 1489 | { |
| 1490 | blob_page* page1 = 0; |
| 1491 | fetch_page(true, *pages1, pag_blob, &window1, &page1); |
| 1492 | if (page1->blp_lead_page != header->blh_lead_page) { |
| 1493 | corrupt(VAL_BLOB_INCONSISTENT, relation, number.getValue()); |
| 1494 | } |
| 1495 | if ((header->blh_level == 1 && page1->blp_sequence != sequence)) |
| 1496 | { |
| 1497 | corrupt(VAL_BLOB_CORRUPT, relation, number.getValue()); |
| 1498 | release_page(&window1); |