From 3ab278ee205842906ccf34269862552687b5880a Mon Sep 17 00:00:00 2001
From: Michael Lotz <mmlr@mlotz.ch>
Date: Sun, 2 Dec 2012 14:11:37 +0100
Subject: [PATCH] Use memcpy to get and set unaligned BPlusTree elements.
---
src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp | 192 +++++++++++----------
src/add-ons/kernel/file_systems/bfs/BPlusTree.h | 59 +++++--
src/add-ons/kernel/file_systems/bfs/Debug.cpp | 15 +-
3 files changed, 158 insertions(+), 108 deletions(-)
diff --git a/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp b/src/add-ons/kernel/file_systems/bfs/BPlusTree.cpp
index df5d999..848105d 100644
a
|
b
|
BPlusTree::_FindKey(const bplustree_node* node, const uint8* key,
|
994 | 994 | return B_ENTRY_NOT_FOUND; |
995 | 995 | } |
996 | 996 | |
997 | | off_t* values = node->Values(); |
998 | 997 | int16 saveIndex = -1; |
999 | 998 | |
1000 | 999 | // binary search in the key array |
… |
… |
BPlusTree::_FindKey(const bplustree_node* node, const uint8* key,
|
1020 | 1019 | if (_index) |
1021 | 1020 | *_index = i; |
1022 | 1021 | if (_next) |
1023 | | *_next = BFS_ENDIAN_TO_HOST_INT64(values[i]); |
| 1022 | *_next = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(i)); |
1024 | 1023 | return B_OK; |
1025 | 1024 | } |
1026 | 1025 | } |
… |
… |
BPlusTree::_FindKey(const bplustree_node* node, const uint8* key,
|
1031 | 1030 | if (saveIndex == node->NumKeys()) |
1032 | 1031 | *_next = node->OverflowLink(); |
1033 | 1032 | else |
1034 | | *_next = BFS_ENDIAN_TO_HOST_INT64(values[saveIndex]); |
| 1033 | *_next = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(saveIndex)); |
1035 | 1034 | } |
1036 | 1035 | return B_ENTRY_NOT_FOUND; |
1037 | 1036 | } |
… |
… |
BPlusTree::_FindFreeDuplicateFragment(Transaction& transaction,
|
1093 | 1092 | const bplustree_node* node, CachedNode& cached, |
1094 | 1093 | off_t* _offset, bplustree_node** _fragment, uint32* _index) |
1095 | 1094 | { |
1096 | | off_t* values = node->Values(); |
1097 | 1095 | for (int32 i = 0; i < node->NumKeys(); i++) { |
1098 | | off_t value = BFS_ENDIAN_TO_HOST_INT64(values[i]); |
| 1096 | off_t value = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(i)); |
1099 | 1097 | |
1100 | 1098 | // does the value link to a duplicate fragment? |
1101 | 1099 | if (bplustree_node::LinkType(value) != BPLUSTREE_DUPLICATE_FRAGMENT) |
… |
… |
BPlusTree::_InsertDuplicate(Transaction& transaction, CachedNode& cached,
|
1135 | 1133 | const bplustree_node* node, uint16 index, off_t value) |
1136 | 1134 | { |
1137 | 1135 | CachedNode cachedDuplicate(this); |
1138 | | off_t* values = node->Values(); |
1139 | | off_t oldValue = BFS_ENDIAN_TO_HOST_INT64(values[index]); |
| 1136 | off_t oldValue = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(index)); |
1140 | 1137 | status_t status; |
1141 | 1138 | off_t offset; |
1142 | 1139 | |
… |
… |
BPlusTree::_InsertDuplicate(Transaction& transaction, CachedNode& cached,
|
1208 | 1205 | if (cached.MakeWritable(transaction) == NULL) |
1209 | 1206 | return B_IO_ERROR; |
1210 | 1207 | |
1211 | | values[index] |
1212 | | = HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( |
1213 | | BPLUSTREE_DUPLICATE_NODE, offset)); |
| 1208 | node->SetValueAt(index, |
| 1209 | HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( |
| 1210 | BPLUSTREE_DUPLICATE_NODE, offset))); |
1214 | 1211 | } |
1215 | 1212 | |
1216 | 1213 | return B_OK; |
… |
… |
BPlusTree::_InsertDuplicate(Transaction& transaction, CachedNode& cached,
|
1290 | 1287 | if (cached.MakeWritable(transaction) == NULL) |
1291 | 1288 | return B_IO_ERROR; |
1292 | 1289 | |
1293 | | values[index] = HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( |
1294 | | BPLUSTREE_DUPLICATE_FRAGMENT, offset, fragmentIndex)); |
| 1290 | node->SetValueAt(index, HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( |
| 1291 | BPLUSTREE_DUPLICATE_FRAGMENT, offset, fragmentIndex))); |
1295 | 1292 | |
1296 | 1293 | return B_OK; |
1297 | 1294 | } |
… |
… |
BPlusTree::_InsertKey(bplustree_node* node, uint16 index, uint8* key,
|
1305 | 1302 | if (index > node->NumKeys()) |
1306 | 1303 | return; |
1307 | 1304 | |
1308 | | off_t* values = node->Values(); |
1309 | | uint16* keyLengths = node->KeyLengths(); |
| 1305 | uint8* values = (uint8*)node->ValuesBase(); |
| 1306 | uint8* keyLengths = (uint8*)node->KeyLengthsBase(); |
1310 | 1307 | uint8* keys = node->Keys(); |
1311 | 1308 | |
1312 | 1309 | node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() + 1); |
1313 | 1310 | node->all_key_length = HOST_ENDIAN_TO_BFS_INT16(node->AllKeyLength() |
1314 | 1311 | + keyLength); |
1315 | 1312 | |
1316 | | off_t* newValues = node->Values(); |
1317 | | uint16* newKeyLengths = node->KeyLengths(); |
| 1313 | uint8* newValues = (uint8*)node->ValuesBase(); |
| 1314 | uint8* newKeyLengths = (uint8*)node->KeyLengthsBase(); |
1318 | 1315 | |
1319 | 1316 | // move values and copy new value into them |
1320 | | memmove(newValues + index + 1, values + index, |
1321 | | sizeof(off_t) * (node->NumKeys() - 1 - index)); |
| 1317 | memmove(newValues + (index + 1) * sizeof(off_t), values + index |
| 1318 | * sizeof(off_t), sizeof(off_t) * (node->NumKeys() - 1 - index)); |
1322 | 1319 | memmove(newValues, values, sizeof(off_t) * index); |
1323 | 1320 | |
1324 | | newValues[index] = HOST_ENDIAN_TO_BFS_INT64(value); |
| 1321 | node->SetValueAt(index, HOST_ENDIAN_TO_BFS_INT64(value)); |
1325 | 1322 | |
1326 | | // move and update key length index |
| 1323 | memmove(newKeyLengths + (index + 1) * sizeof(uint16), keyLengths + index |
| 1324 | * sizeof(uint16), sizeof(uint16) * (node->NumKeys() - 1 - index)); |
| 1325 | |
| 1326 | // update key length index |
1327 | 1327 | for (uint16 i = node->NumKeys(); i-- > index + 1;) { |
1328 | | newKeyLengths[i] = HOST_ENDIAN_TO_BFS_INT16( |
1329 | | BFS_ENDIAN_TO_HOST_INT16(keyLengths[i - 1]) + keyLength); |
| 1328 | node->SetKeyLengthAt(i, HOST_ENDIAN_TO_BFS_INT16( |
| 1329 | BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(i) + keyLength))); |
1330 | 1330 | } |
| 1331 | |
1331 | 1332 | memmove(newKeyLengths, keyLengths, sizeof(uint16) * index); |
1332 | 1333 | |
1333 | 1334 | int32 keyStart; |
1334 | | newKeyLengths[index] = HOST_ENDIAN_TO_BFS_INT16(keyLength |
| 1335 | node->SetKeyLengthAt(index, HOST_ENDIAN_TO_BFS_INT16(keyLength |
1335 | 1336 | + (keyStart = index > 0 |
1336 | | ? BFS_ENDIAN_TO_HOST_INT16(newKeyLengths[index - 1]) : 0)); |
| 1337 | ? BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(index - 1)) : 0))); |
1337 | 1338 | |
1338 | 1339 | // move keys and copy new key into them |
1339 | | uint16 length = BFS_ENDIAN_TO_HOST_INT16(newKeyLengths[index]); |
| 1340 | uint16 length = BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(index)); |
1340 | 1341 | int32 size = node->AllKeyLength() - length; |
1341 | 1342 | if (size > 0) |
1342 | 1343 | memmove(keys + length, keys + length - keyLength, size); |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1357 | 1358 | if (*_keyIndex > node->NumKeys() + 1) |
1358 | 1359 | return B_BAD_VALUE; |
1359 | 1360 | |
1360 | | uint16* inKeyLengths = node->KeyLengths(); |
1361 | | off_t* inKeyValues = node->Values(); |
| 1361 | uint8* inKeyLengths = (uint8*)node->KeyLengthsBase(); |
| 1362 | uint8* inKeyValues = (uint8*)node->ValuesBase(); |
1362 | 1363 | uint8* inKeys = node->Keys(); |
1363 | 1364 | uint8* outKeys = other->Keys(); |
1364 | 1365 | int32 keyIndex = *_keyIndex; // can become less than zero! |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1383 | 1384 | for (in = out = 0; in < node->NumKeys() + 1;) { |
1384 | 1385 | if (!bytes) { |
1385 | 1386 | bytesBefore = in > 0 |
1386 | | ? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0; |
| 1387 | ? BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in - 1)) : 0; |
1387 | 1388 | } |
1388 | 1389 | |
1389 | 1390 | if (in == keyIndex && !bytes) { |
1390 | 1391 | bytes = *_keyLength; |
1391 | 1392 | } else { |
1392 | 1393 | if (keyIndex < out) { |
1393 | | bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in]) |
| 1394 | bytesAfter = BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in)) |
1394 | 1395 | - bytesBefore; |
1395 | 1396 | } |
1396 | 1397 | |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1408 | 1409 | // if the new key was not inserted, set the length of the keys |
1409 | 1410 | // that can be copied directly |
1410 | 1411 | if (keyIndex >= out && in > 0) |
1411 | | bytesBefore = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]); |
| 1412 | bytesBefore = BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in - 1)); |
1412 | 1413 | |
1413 | 1414 | if (bytesBefore < 0 || bytesAfter < 0) |
1414 | 1415 | return B_BAD_DATA; |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1419 | 1420 | + bytesAfter); |
1420 | 1421 | other->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out); |
1421 | 1422 | |
1422 | | uint16* outKeyLengths = other->KeyLengths(); |
1423 | | off_t* outKeyValues = other->Values(); |
| 1423 | uint8* outKeyLengths = (uint8*)other->KeyLengthsBase(); |
| 1424 | uint8* outKeyValues = (uint8*)other->ValuesBase(); |
1424 | 1425 | int32 keys = out > keyIndex ? keyIndex : out; |
1425 | 1426 | |
1426 | 1427 | if (bytesBefore) { |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1432 | 1433 | if (bytes) { |
1433 | 1434 | // copy the newly inserted key |
1434 | 1435 | memcpy(outKeys + bytesBefore, key, bytes); |
1435 | | outKeyLengths[keyIndex] = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore); |
1436 | | outKeyValues[keyIndex] = HOST_ENDIAN_TO_BFS_INT64(*_value); |
| 1436 | other->SetKeyLengthAt(keyIndex, |
| 1437 | HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore)); |
| 1438 | other->SetValueAt(keyIndex, HOST_ENDIAN_TO_BFS_INT64(*_value)); |
1437 | 1439 | |
1438 | 1440 | if (bytesAfter) { |
1439 | 1441 | // copy the keys after the new key |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1441 | 1443 | bytesAfter); |
1442 | 1444 | keys = out - keyIndex - 1; |
1443 | 1445 | for (int32 i = 0;i < keys;i++) { |
1444 | | outKeyLengths[keyIndex + i + 1] = HOST_ENDIAN_TO_BFS_INT16( |
1445 | | BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[keyIndex + i]) |
1446 | | + bytes); |
| 1446 | other->SetKeyLengthAt(keyIndex + i + 1, |
| 1447 | HOST_ENDIAN_TO_BFS_INT16(BFS_ENDIAN_TO_HOST_INT16( |
| 1448 | node->KeyLengthAt(keyIndex + i)) + bytes)); |
1447 | 1449 | } |
1448 | | memcpy(outKeyValues + keyIndex + 1, inKeyValues + keyIndex, |
1449 | | keys * sizeof(off_t)); |
| 1450 | memcpy(outKeyValues + (keyIndex + 1) * sizeof(off_t), |
| 1451 | inKeyValues + keyIndex * sizeof(off_t), keys * sizeof(off_t)); |
1450 | 1452 | } |
1451 | 1453 | } |
1452 | 1454 | |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1490 | 1492 | newAllocated = true; |
1491 | 1493 | memcpy(newKey, droppedKey, newLength); |
1492 | 1494 | |
1493 | | other->overflow_link = inKeyValues[in]; |
1494 | | total = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in++]); |
| 1495 | other->overflow_link = node->ValueAt(in); |
| 1496 | total = BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in++)); |
1495 | 1497 | } |
1496 | 1498 | } |
1497 | 1499 | |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1507 | 1509 | // not need to know the exact length of all keys in this |
1508 | 1510 | // loop |
1509 | 1511 | bytesBefore = in > skip |
1510 | | ? BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in - 1]) : 0; |
| 1512 | ? BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in - 1)) : 0; |
1511 | 1513 | bytes = *_keyLength; |
1512 | 1514 | out++; |
1513 | 1515 | } else { |
1514 | 1516 | if (in < node->NumKeys()) { |
1515 | | inKeyLengths[in] = HOST_ENDIAN_TO_BFS_INT16( |
1516 | | BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in]) - total); |
| 1517 | node->SetKeyLengthAt(in, HOST_ENDIAN_TO_BFS_INT16( |
| 1518 | BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in)) - total)); |
1517 | 1519 | |
1518 | 1520 | if (bytes) { |
1519 | | inKeyLengths[in] = HOST_ENDIAN_TO_BFS_INT16( |
1520 | | BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in]) + bytes); |
| 1521 | node->SetKeyLengthAt(in, HOST_ENDIAN_TO_BFS_INT16( |
| 1522 | BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in)) |
| 1523 | + bytes)); |
1521 | 1524 | |
1522 | | bytesAfter = BFS_ENDIAN_TO_HOST_INT16(inKeyLengths[in]) |
| 1525 | bytesAfter = BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(in)) |
1523 | 1526 | - bytesBefore - bytes; |
1524 | 1527 | } |
1525 | 1528 | out++; |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1545 | 1548 | node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(out); |
1546 | 1549 | |
1547 | 1550 | // array positions have changed |
1548 | | outKeyLengths = node->KeyLengths(); |
1549 | | outKeyValues = node->Values(); |
| 1551 | outKeyLengths = (uint8*)node->KeyLengthsBase(); |
| 1552 | outKeyValues = (uint8*)node->ValuesBase(); |
1550 | 1553 | |
1551 | 1554 | // move the keys in the old node: the order is important here, |
1552 | 1555 | // because we don't want to overwrite any contents |
… |
… |
BPlusTree::_SplitNode(bplustree_node* node, off_t nodeOffset,
|
1565 | 1568 | bytesAfter); |
1566 | 1569 | } |
1567 | 1570 | |
1568 | | if (bytesBefore) |
1569 | | memmove(outKeyLengths, inKeyLengths + skip, keys * sizeof(uint16)); |
| 1571 | if (bytesBefore) { |
| 1572 | memmove(outKeyLengths, inKeyLengths + skip * sizeof(uint16), |
| 1573 | keys * sizeof(uint16)); |
| 1574 | } |
| 1575 | |
1570 | 1576 | if (bytesAfter) { |
1571 | 1577 | // if byteAfter is > 0, keyIndex is larger than skip |
1572 | | memmove(outKeyLengths + keyIndex + 1, inKeyLengths + skip + keyIndex, |
| 1578 | memmove(outKeyLengths + (keyIndex + 1) * sizeof(uint16), |
| 1579 | inKeyLengths + (skip + keyIndex) * sizeof(uint16), |
1573 | 1580 | in * sizeof(uint16)); |
1574 | 1581 | } |
1575 | 1582 | |
1576 | 1583 | if (bytesBefore) |
1577 | | memmove(outKeyValues, inKeyValues + skip, keys * sizeof(off_t)); |
| 1584 | memmove(outKeyValues, inKeyValues + skip * sizeof(off_t), |
| 1585 | keys * sizeof(off_t)); |
1578 | 1586 | if (bytesAfter) { |
1579 | | memmove(outKeyValues + keyIndex + 1, inKeyValues + skip + keyIndex, |
| 1587 | memmove(outKeyValues + (keyIndex + 1) * sizeof(off_t), |
| 1588 | inKeyValues + (skip + keyIndex) * sizeof(off_t), |
1580 | 1589 | in * sizeof(off_t)); |
1581 | 1590 | } |
1582 | 1591 | |
1583 | 1592 | if (bytes) { |
1584 | 1593 | // finally, copy the newly inserted key (don't overwrite anything) |
1585 | 1594 | memcpy(inKeys + bytesBefore, key, bytes); |
1586 | | outKeyLengths[keyIndex] = HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore); |
1587 | | outKeyValues[keyIndex] = HOST_ENDIAN_TO_BFS_INT64(*_value); |
| 1595 | node->SetKeyLengthAt(keyIndex, |
| 1596 | HOST_ENDIAN_TO_BFS_INT16(bytes + bytesBefore)); |
| 1597 | node->SetValueAt(keyIndex, HOST_ENDIAN_TO_BFS_INT64(*_value)); |
1588 | 1598 | } |
1589 | 1599 | |
1590 | 1600 | // Prepare the key that will be inserted in the parent node which |
… |
… |
BPlusTree::_RemoveDuplicate(Transaction& transaction,
|
1766 | 1776 | const bplustree_node* node, CachedNode& cached, uint16 index, |
1767 | 1777 | off_t value) |
1768 | 1778 | { |
1769 | | off_t* values = node->Values(); |
1770 | | off_t oldValue = BFS_ENDIAN_TO_HOST_INT64(values[index]); |
| 1779 | off_t oldValue = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(index)); |
1771 | 1780 | |
1772 | 1781 | CachedNode cachedDuplicate(this); |
1773 | 1782 | off_t duplicateOffset = bplustree_node::FragmentOffset(oldValue); |
… |
… |
BPlusTree::_RemoveDuplicate(Transaction& transaction,
|
1802 | 1811 | if (cached.MakeWritable(transaction) == NULL) |
1803 | 1812 | return B_IO_ERROR; |
1804 | 1813 | |
1805 | | values[index] = array->values[0]; |
| 1814 | node->SetValueAt(index, array->values[0]); |
1806 | 1815 | |
1807 | 1816 | // Remove the whole fragment node, if this was the only array, |
1808 | 1817 | // otherwise free just the array |
… |
… |
BPlusTree::_RemoveDuplicate(Transaction& transaction,
|
1877 | 1886 | // This is the last node, and there is only one value left; |
1878 | 1887 | // replace the duplicate link with that value, it's no |
1879 | 1888 | // duplicate anymore |
1880 | | values[index] = array->values[0]; |
| 1889 | node->SetValueAt(index, array->values[0]); |
1881 | 1890 | } else { |
1882 | 1891 | // Move the duplicate link to the next node |
1883 | | values[index] = HOST_ENDIAN_TO_BFS_INT64( |
| 1892 | node->SetValueAt(index, HOST_ENDIAN_TO_BFS_INT64( |
1884 | 1893 | bplustree_node::MakeLink( |
1885 | | BPLUSTREE_DUPLICATE_NODE, right)); |
| 1894 | BPLUSTREE_DUPLICATE_NODE, right))); |
1886 | 1895 | } |
1887 | 1896 | } |
1888 | 1897 | |
… |
… |
BPlusTree::_RemoveDuplicate(Transaction& transaction,
|
1954 | 1963 | if (cached.MakeWritable(transaction) == NULL) |
1955 | 1964 | return B_IO_ERROR; |
1956 | 1965 | |
1957 | | values[index] = HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( |
1958 | | BPLUSTREE_DUPLICATE_FRAGMENT, duplicateOffset, fragmentIndex)); |
| 1966 | node->SetValueAt(index, |
| 1967 | HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( |
| 1968 | BPLUSTREE_DUPLICATE_FRAGMENT, duplicateOffset, |
| 1969 | fragmentIndex))); |
1959 | 1970 | } |
1960 | 1971 | return B_OK; |
1961 | 1972 | } |
… |
… |
BPlusTree::_RemoveKey(bplustree_node* node, uint16 index)
|
1977 | 1988 | return; |
1978 | 1989 | } |
1979 | 1990 | |
1980 | | off_t* values = node->Values(); |
1981 | | |
1982 | 1991 | // if we would have to drop the overflow link, drop |
1983 | 1992 | // the last key instead and update the overflow link |
1984 | 1993 | // to the value of that one |
1985 | 1994 | if (!node->IsLeaf() && index == node->NumKeys()) |
1986 | | node->overflow_link = values[--index]; |
| 1995 | node->overflow_link = node->ValueAt(--index); |
1987 | 1996 | |
1988 | 1997 | uint16 length; |
1989 | 1998 | uint8* key = node->KeyAt(index, &length); |
… |
… |
BPlusTree::_RemoveKey(bplustree_node* node, uint16 index)
|
1995 | 2004 | return; |
1996 | 2005 | } |
1997 | 2006 | |
1998 | | uint16* keyLengths = node->KeyLengths(); |
| 2007 | uint8* values = (uint8*)node->ValuesBase(); |
| 2008 | uint8* keyLengths = (uint8*)node->KeyLengthsBase(); |
1999 | 2009 | uint8* keys = node->Keys(); |
2000 | 2010 | |
2001 | 2011 | node->all_key_count = HOST_ENDIAN_TO_BFS_INT16(node->NumKeys() - 1); |
2002 | 2012 | node->all_key_length = HOST_ENDIAN_TO_BFS_INT64( |
2003 | 2013 | node->AllKeyLength() - length); |
2004 | 2014 | |
2005 | | off_t* newValues = node->Values(); |
2006 | | uint16* newKeyLengths = node->KeyLengths(); |
| 2015 | uint8* newValues = (uint8*)node->ValuesBase(); |
| 2016 | uint8* newKeyLengths = (uint8*)node->KeyLengthsBase(); |
2007 | 2017 | |
2008 | 2018 | // move key data |
2009 | 2019 | memmove(key, key + length, node->AllKeyLength() - (key - keys)); |
… |
… |
BPlusTree::_RemoveKey(bplustree_node* node, uint16 index)
|
2011 | 2021 | // move and update key lengths |
2012 | 2022 | if (index > 0 && newKeyLengths != keyLengths) |
2013 | 2023 | memmove(newKeyLengths, keyLengths, index * sizeof(uint16)); |
| 2024 | memmove(newKeyLengths + index * sizeof(uint16), keyLengths + (index + 1) |
| 2025 | * sizeof(uint16), (node->NumKeys() - index) * sizeof(uint16)); |
2014 | 2026 | for (uint16 i = index; i < node->NumKeys(); i++) { |
2015 | | newKeyLengths[i] = HOST_ENDIAN_TO_BFS_INT16( |
2016 | | BFS_ENDIAN_TO_HOST_INT16(keyLengths[i + 1]) - length); |
| 2027 | node->SetKeyLengthAt(i, HOST_ENDIAN_TO_BFS_INT16( |
| 2028 | BFS_ENDIAN_TO_HOST_INT16(node->KeyLengthAt(i)) - length)); |
2017 | 2029 | } |
2018 | 2030 | |
2019 | 2031 | // move values |
2020 | 2032 | if (index > 0) |
2021 | 2033 | memmove(newValues, values, index * sizeof(off_t)); |
2022 | 2034 | if (node->NumKeys() > index) { |
2023 | | memmove(newValues + index, values + index + 1, |
2024 | | (node->NumKeys() - index) * sizeof(off_t)); |
| 2035 | memmove(newValues + index * sizeof(off_t), values + (index + 1) |
| 2036 | * sizeof(off_t), (node->NumKeys() - index) * sizeof(off_t)); |
2025 | 2037 | } |
2026 | 2038 | } |
2027 | 2039 | |
… |
… |
BPlusTree::Remove(Transaction& transaction, const uint8* key, uint16 keyLength,
|
2063 | 2075 | |
2064 | 2076 | // Is this a duplicate entry? |
2065 | 2077 | if (bplustree_node::IsDuplicate(BFS_ENDIAN_TO_HOST_INT64( |
2066 | | node->Values()[nodeAndKey.keyIndex]))) { |
| 2078 | node->ValueAt(nodeAndKey.keyIndex)))) { |
2067 | 2079 | if (fAllowDuplicates) { |
2068 | 2080 | return _RemoveDuplicate(transaction, node, cached, |
2069 | 2081 | nodeAndKey.keyIndex, value); |
… |
… |
BPlusTree::Remove(Transaction& transaction, const uint8* key, uint16 keyLength,
|
2073 | 2085 | "allowed, inode %" B_PRIdOFF "!\n", fStream->ID())); |
2074 | 2086 | RETURN_ERROR(B_ERROR); |
2075 | 2087 | } else { |
2076 | | if (node->Values()[nodeAndKey.keyIndex] != value) |
| 2088 | if (node->ValueAt(nodeAndKey.keyIndex) != value) |
2077 | 2089 | return B_ENTRY_NOT_FOUND; |
2078 | 2090 | |
2079 | 2091 | // If we will remove the last key, the iterator will be set |
… |
… |
BPlusTree::Replace(Transaction& transaction, const uint8* key, uint16 keyLength,
|
2182 | 2194 | if (status == B_OK) { |
2183 | 2195 | bplustree_node* writableNode = cached.MakeWritable(transaction); |
2184 | 2196 | if (writableNode != NULL) { |
2185 | | writableNode->Values()[keyIndex] |
2186 | | = HOST_ENDIAN_TO_BFS_INT64(value); |
| 2197 | writableNode->SetValueAt(keyIndex, |
| 2198 | HOST_ENDIAN_TO_BFS_INT64(value)); |
2187 | 2199 | } else |
2188 | 2200 | status = B_IO_ERROR; |
2189 | 2201 | } |
… |
… |
BPlusTree::Find(const uint8* key, uint16 keyLength, off_t* _value)
|
2241 | 2253 | #endif |
2242 | 2254 | if (node->OverflowLink() == BPLUSTREE_NULL) { |
2243 | 2255 | if (status == B_OK && _value != NULL) |
2244 | | *_value = BFS_ENDIAN_TO_HOST_INT64(node->Values()[keyIndex]); |
| 2256 | *_value = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(keyIndex)); |
2245 | 2257 | |
2246 | 2258 | #ifdef DEBUG |
2247 | 2259 | if (levels != (int32)fHeader.MaxNumberOfLevels()) |
… |
… |
BPlusTree::_ValidateChildren(TreeCheck& check, uint32 level, off_t offset,
|
2289 | 2301 | check.SetVisited(offset); |
2290 | 2302 | |
2291 | 2303 | uint32 count = parent->NumKeys(); |
2292 | | off_t* values = parent->Values(); |
2293 | 2304 | off_t lastOffset = check.PreviousOffset(level); |
2294 | 2305 | CachedNode cached(this); |
2295 | 2306 | |
… |
… |
BPlusTree::_ValidateChildren(TreeCheck& check, uint32 level, off_t offset,
|
2307 | 2318 | } |
2308 | 2319 | } |
2309 | 2320 | |
2310 | | off_t childOffset = BFS_ENDIAN_TO_HOST_INT64(values[i]); |
| 2321 | off_t childOffset = BFS_ENDIAN_TO_HOST_INT64(parent->ValueAt(i)); |
2311 | 2322 | if (bplustree_node::IsDuplicate(childOffset)) { |
2312 | 2323 | // Walk the duplicate nodes |
2313 | 2324 | off_t duplicateOffset = bplustree_node::FragmentOffset(childOffset); |
… |
… |
BPlusTree::_ValidateChildren(TreeCheck& check, uint32 level, off_t offset,
|
2403 | 2414 | // Test a regular child node recursively |
2404 | 2415 | off_t nextOffset = parent->OverflowLink(); |
2405 | 2416 | if (i < count - 1) |
2406 | | nextOffset = BFS_ENDIAN_TO_HOST_INT64(values[i + 1]); |
| 2417 | nextOffset = BFS_ENDIAN_TO_HOST_INT64(parent->ValueAt(i + 1)); |
2407 | 2418 | |
2408 | 2419 | if (i == 0 && lastOffset != BPLUSTREE_NULL) { |
2409 | 2420 | // Test right link of the previous node |
… |
… |
TreeIterator::Goto(int8 to)
|
2533 | 2544 | nextOffset = node->OverflowLink(); |
2534 | 2545 | else { |
2535 | 2546 | if (node->AllKeyLength() > fTree->fNodeSize |
2536 | | || (addr_t)node->Values() > (addr_t)node + fTree->fNodeSize |
| 2547 | || (addr_t)node->ValuesBase() > (addr_t)node + fTree->fNodeSize |
2537 | 2548 | - 8 * node->NumKeys()) |
2538 | 2549 | RETURN_ERROR(B_ERROR); |
2539 | 2550 | |
2540 | | nextOffset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[0]); |
| 2551 | nextOffset = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(0)); |
2541 | 2552 | } |
2542 | 2553 | if (nextOffset == nodeOffset) |
2543 | 2554 | break; |
… |
… |
TreeIterator::Traverse(int8 direction, void* key, uint16* keyLength,
|
2674 | 2685 | } |
2675 | 2686 | *keyLength = length; |
2676 | 2687 | |
2677 | | off_t offset = BFS_ENDIAN_TO_HOST_INT64(node->Values()[fCurrentKey]); |
| 2688 | off_t offset = BFS_ENDIAN_TO_HOST_INT64(node->ValueAt(fCurrentKey)); |
2678 | 2689 | |
2679 | 2690 | // duplicate fragments? |
2680 | 2691 | uint8 type = bplustree_node::LinkType(offset); |
… |
… |
bplustree_node::KeyAt(int32 index, uint16* keyLength) const
|
2840 | 2851 | return NULL; |
2841 | 2852 | |
2842 | 2853 | uint8* keyStart = Keys(); |
2843 | | uint16* keyLengths = KeyLengths(); |
2844 | 2854 | |
2845 | | *keyLength = BFS_ENDIAN_TO_HOST_INT16(keyLengths[index]) |
2846 | | - (index != 0 ? BFS_ENDIAN_TO_HOST_INT16(keyLengths[index - 1]) : 0); |
| 2855 | *keyLength = BFS_ENDIAN_TO_HOST_INT16(KeyLengthAt(index)) |
| 2856 | - (index != 0 ? BFS_ENDIAN_TO_HOST_INT16(KeyLengthAt(index - 1)) : 0); |
2847 | 2857 | if (index > 0) |
2848 | | keyStart += BFS_ENDIAN_TO_HOST_INT16(keyLengths[index - 1]); |
| 2858 | keyStart += BFS_ENDIAN_TO_HOST_INT16(KeyLengthAt(index - 1)); |
2849 | 2859 | |
2850 | 2860 | return keyStart; |
2851 | 2861 | } |
… |
… |
bplustree_node::CheckIntegrity(uint32 nodeSize) const
|
2912 | 2922 | dprintf("invalid node %p, key %d: keys corrupted\n", this, (int)i); |
2913 | 2923 | return B_BAD_DATA; |
2914 | 2924 | } |
2915 | | if (Values()[i] == -1) { |
| 2925 | if (ValueAt(i) == -1) { |
2916 | 2926 | dprintf("invalid node %p, value %d: %" B_PRIdOFF ": values " |
2917 | | "corrupted\n", this, (int)i, Values()[i]); |
| 2927 | "corrupted\n", this, (int)i, ValueAt(i)); |
2918 | 2928 | return B_BAD_DATA; |
2919 | 2929 | } |
2920 | 2930 | } |
diff --git a/src/add-ons/kernel/file_systems/bfs/BPlusTree.h b/src/add-ons/kernel/file_systems/bfs/BPlusTree.h
index c1e1ad2..096e57f 100644
a
|
b
|
struct bplustree_node {
|
84 | 84 | { return BFS_ENDIAN_TO_HOST_INT16( |
85 | 85 | all_key_length); } |
86 | 86 | |
87 | | inline uint16* KeyLengths() const; |
88 | | inline off_t* Values() const; |
| 87 | inline void* KeyLengthsBase() const; |
| 88 | inline uint16 KeyLengthAt(uint16 index) const; |
| 89 | inline void SetKeyLengthAt(uint16 index, |
| 90 | uint16 value) const; |
| 91 | inline void* ValuesBase() const; |
| 92 | inline off_t ValueAt(uint16 index) const; |
| 93 | inline void SetValueAt(uint16 index, off_t value) const; |
89 | 94 | inline uint8* Keys() const; |
90 | 95 | inline int32 Used() const; |
91 | 96 | uint8* KeyAt(int32 index, uint16* keyLength) const; |
… |
… |
bplustree_header::CheckNode(bplustree_node* node) const
|
495 | 500 | return IsValidLink(node->LeftLink()) |
496 | 501 | && IsValidLink(node->RightLink()) |
497 | 502 | && IsValidLink(node->OverflowLink()) |
498 | | && (int8*)node->Values() + node->NumKeys() * sizeof(off_t) |
| 503 | && (int8*)node->ValuesBase() + node->NumKeys() * sizeof(off_t) |
499 | 504 | <= (int8*)node + NodeSize(); |
500 | 505 | } |
501 | 506 | |
… |
… |
bplustree_header::IsValidLink(off_t link) const
|
511 | 516 | // #pragma mark - bplustree_node inline functions |
512 | 517 | |
513 | 518 | |
514 | | inline uint16* |
515 | | bplustree_node::KeyLengths() const |
| 519 | inline void* |
| 520 | bplustree_node::KeyLengthsBase() const |
516 | 521 | { |
517 | | return (uint16*)(((char*)this) + key_align(sizeof(bplustree_node) |
518 | | + AllKeyLength())); |
| 522 | return (uint8*)this + key_align(sizeof(bplustree_node) + AllKeyLength()); |
519 | 523 | } |
520 | 524 | |
521 | 525 | |
522 | | inline off_t* |
523 | | bplustree_node::Values() const |
| 526 | inline uint16 |
| 527 | bplustree_node::KeyLengthAt(uint16 index) const |
524 | 528 | { |
525 | | return (off_t*)((char*)KeyLengths() + NumKeys() * sizeof(uint16)); |
| 529 | uint16 result; |
| 530 | memcpy(&result, (uint8*)KeyLengthsBase() + index * sizeof(uint16), |
| 531 | sizeof(uint16)); |
| 532 | return result; |
| 533 | } |
| 534 | |
| 535 | |
| 536 | inline void |
| 537 | bplustree_node::SetKeyLengthAt(uint16 index, uint16 value) const |
| 538 | { |
| 539 | memcpy((uint8*)KeyLengthsBase() + index * sizeof(uint16), &value, |
| 540 | sizeof(uint16)); |
| 541 | } |
| 542 | |
| 543 | |
| 544 | inline void* |
| 545 | bplustree_node::ValuesBase() const |
| 546 | { |
| 547 | return (uint8*)KeyLengthsBase() + NumKeys() * sizeof(uint16); |
| 548 | } |
| 549 | |
| 550 | |
| 551 | inline off_t |
| 552 | bplustree_node::ValueAt(uint16 index) const |
| 553 | { |
| 554 | off_t result; |
| 555 | memcpy(&result, (uint8*)ValuesBase() + index * sizeof(off_t), |
| 556 | sizeof(off_t)); |
| 557 | return result; |
| 558 | } |
| 559 | |
| 560 | |
| 561 | inline void |
| 562 | bplustree_node::SetValueAt(uint16 index, off_t value) const |
| 563 | { |
| 564 | memcpy((uint8*)ValuesBase() + index * sizeof(off_t), &value, sizeof(off_t)); |
526 | 565 | } |
527 | 566 | |
528 | 567 | |
diff --git a/src/add-ons/kernel/file_systems/bfs/Debug.cpp b/src/add-ons/kernel/file_systems/bfs/Debug.cpp
index 02a8a58..d98f10b 100644
a
|
b
|
dump_bplustree_node(const bplustree_node* node, const bplustree_header* header,
|
227 | 227 | memcpy(buffer, key, length); |
228 | 228 | buffer[length] = '\0'; |
229 | 229 | |
230 | | off_t* value = node->Values() + i; |
231 | | if ((addr_t)value < (addr_t)node |
232 | | || (addr_t)value > (addr_t)node + header->node_size) |
| 230 | uint8* valueAddress = (uint8*)node->ValuesBase() + i * sizeof(off_t); |
| 231 | if ((addr_t)valueAddress < (addr_t)node |
| 232 | || (addr_t)valueAddress > (addr_t)node + header->node_size) |
233 | 233 | kprintf(" %2d. Invalid Offset!!\n", (int)i); |
234 | 234 | else { |
235 | 235 | kprintf(" %2d. ", (int)i); |
… |
… |
dump_bplustree_node(const bplustree_node* node, const bplustree_header* header,
|
247 | 247 | } else |
248 | 248 | kprintf("???"); |
249 | 249 | |
250 | | off_t offset = *value & 0x3fffffffffffffffLL; |
| 250 | off_t value = node->ValueAt(i); |
| 251 | off_t offset = value & 0x3fffffffffffffffLL; |
251 | 252 | kprintf(" (%d bytes) -> %" B_PRIdOFF, length, offset); |
252 | 253 | if (volume != NULL) { |
253 | 254 | block_run run = volume->ToBlockRun(offset); |
254 | 255 | kprintf(" (%d, %d)", (int)run.allocation_group, run.start); |
255 | 256 | } |
256 | | if (bplustree_node::LinkType(*value) |
| 257 | if (bplustree_node::LinkType(value) |
257 | 258 | == BPLUSTREE_DUPLICATE_FRAGMENT) { |
258 | 259 | kprintf(" (duplicate fragment %" B_PRIdOFF ")\n", |
259 | | *value & 0x3ff); |
260 | | } else if (bplustree_node::LinkType(*value) |
| 260 | value & 0x3ff); |
| 261 | } else if (bplustree_node::LinkType(value) |
261 | 262 | == BPLUSTREE_DUPLICATE_NODE) { |
262 | 263 | kprintf(" (duplicate node)\n"); |
263 | 264 | } else |