Some more PPC big endian fixes, mostly array handling (b+tree duplicates and

log). Still doesn't seem to work correctly, though (but it's definitely
getting closer :-)).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17560 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-05-23 01:24:38 +00:00
parent 669b14d756
commit f7769aa482
5 changed files with 71 additions and 69 deletions

View File

@ -676,16 +676,16 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
return B_IO_ERROR; return B_IO_ERROR;
duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue)); duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue));
if (array->count > NUM_FRAGMENT_VALUES if (array->CountItems() > NUM_FRAGMENT_VALUES
|| array->count < 1) { || array->CountItems() < 1) {
FATAL(("insertDuplicate: Invalid array[%ld] size in fragment %Ld == %Ld!\n", FATAL(("insertDuplicate: Invalid array[%ld] size in fragment %Ld == %Ld!\n",
bplustree_node::FragmentIndex(oldValue), bplustree_node::FragmentIndex(oldValue),
bplustree_node::FragmentOffset(oldValue), bplustree_node::FragmentOffset(oldValue),
array->count)); array->CountItems()));
return B_BAD_DATA; return B_BAD_DATA;
} }
if (array->count < NUM_FRAGMENT_VALUES) { if (array->CountItems() < NUM_FRAGMENT_VALUES) {
array->Insert(value); array->Insert(value);
} else { } else {
// test if the fragment will be empty if we remove this key's values // test if the fragment will be empty if we remove this key's values
@ -710,9 +710,9 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
// copy the array from the fragment node to the duplicate node // copy the array from the fragment node to the duplicate node
// and free the old entry (by zero'ing all values) // and free the old entry (by zero'ing all values)
newDuplicate->overflow_link = HOST_ENDIAN_TO_BFS_INT64(array->count); newDuplicate->overflow_link = array->count;
memcpy(&newDuplicate->all_key_count, &array->values[0], memcpy(&newDuplicate->all_key_count, &array->values[0],
array->count * sizeof(off_t)); array->CountItems() * sizeof(off_t));
memset(array, 0, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); memset(array, 0, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
array = newDuplicate->DuplicateArray(); array = newDuplicate->DuplicateArray();
@ -748,15 +748,15 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
return B_IO_ERROR; return B_IO_ERROR;
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (array->count > NUM_DUPLICATE_VALUES || array->count < 0) { if (array->CountItems() > NUM_DUPLICATE_VALUES || array->CountItems() < 0) {
FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n", FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n",
duplicateOffset, array->count)); duplicateOffset, array->CountItems()));
return B_BAD_DATA; return B_BAD_DATA;
} }
} while (array->count >= NUM_DUPLICATE_VALUES } while (array->CountItems() >= NUM_DUPLICATE_VALUES
&& (oldValue = duplicate->RightLink()) != BPLUSTREE_NULL); && (oldValue = duplicate->RightLink()) != BPLUSTREE_NULL);
if (array->count < NUM_DUPLICATE_VALUES) { if (array->CountItems() < NUM_DUPLICATE_VALUES) {
array->Insert(value); array->Insert(value);
} else { } else {
// no space left - add a new duplicate node // no space left - add a new duplicate node
@ -770,11 +770,11 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
// link the two nodes together // link the two nodes together
duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(offset); duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(offset);
newDuplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(duplicateOffset); newDuplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(duplicateOffset);
array = newDuplicate->DuplicateArray(); array = newDuplicate->DuplicateArray();
array->count = 0; array->count = 0;
array->Insert(value); array->Insert(value);
status = cachedNewDuplicate.WriteBack(transaction); status = cachedNewDuplicate.WriteBack(transaction);
if (status < B_OK) if (status < B_OK)
return status; return status;
@ -1214,10 +1214,10 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
if (bplustree_node::LinkType(oldValue) == BPLUSTREE_DUPLICATE_FRAGMENT) { if (bplustree_node::LinkType(oldValue) == BPLUSTREE_DUPLICATE_FRAGMENT) {
duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue)); duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue));
if (array->count > NUM_FRAGMENT_VALUES if (array->CountItems() > NUM_FRAGMENT_VALUES
|| array->count < 1) { || array->CountItems() < 1) {
FATAL(("removeDuplicate: Invalid array[%ld] size in fragment %Ld == %Ld!\n", FATAL(("removeDuplicate: Invalid array[%ld] size in fragment %Ld == %Ld!\n",
bplustree_node::FragmentIndex(oldValue), duplicateOffset, array->count)); bplustree_node::FragmentIndex(oldValue), duplicateOffset, array->CountItems()));
return B_BAD_DATA; return B_BAD_DATA;
} }
if (!array->Remove(value)) { if (!array->Remove(value)) {
@ -1227,7 +1227,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
} }
// remove the array from the fragment node if it is empty // remove the array from the fragment node if it is empty
if (array->count == 1) { if (array->CountItems() == 1) {
// set the link to the remaining value // set the link to the remaining value
values[index] = array->values[0]; values[index] = array->values[0];
@ -1259,10 +1259,10 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
// Search the duplicate nodes until the entry could be found (and removed) // Search the duplicate nodes until the entry could be found (and removed)
while (duplicate != NULL) { while (duplicate != NULL) {
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (array->count > NUM_DUPLICATE_VALUES if (array->CountItems() > NUM_DUPLICATE_VALUES
|| array->count < 0) { || array->CountItems() < 0) {
FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n", FATAL(("removeDuplicate: Invalid array size in duplicate %Ld == %Ld!\n",
duplicateOffset, array->count)); duplicateOffset, array->CountItems()));
return B_BAD_DATA; return B_BAD_DATA;
} }
@ -1281,15 +1281,15 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
off_t left = duplicate->LeftLink(); off_t left = duplicate->LeftLink();
off_t right = duplicate->RightLink(); off_t right = duplicate->RightLink();
bool isLast = left == BPLUSTREE_NULL && right == BPLUSTREE_NULL; bool isLast = left == BPLUSTREE_NULL && right == BPLUSTREE_NULL;
if (isLast && array->count == 1 || array->count == 0) { if (isLast && array->CountItems() == 1 || array->CountItems() == 0) {
// Free empty duplicate page, link their siblings together, and // Free empty duplicate page, link their siblings together, and
// update the duplicate link if needed (which should not be, if // update the duplicate link if needed (which should not be, if
// we are the only one working on that tree...) // we are the only one working on that tree...)
if (duplicateOffset == bplustree_node::FragmentOffset(oldValue) if (duplicateOffset == bplustree_node::FragmentOffset(oldValue)
|| array->count == 1) { || array->CountItems() == 1) {
if (array->count == 1 && isLast) if (array->CountItems() == 1 && isLast)
values[index] = array->values[0]; values[index] = array->values[0];
else if (isLast) { else if (isLast) {
FATAL(("removed last value from duplicate!\n")); FATAL(("removed last value from duplicate!\n"));
@ -1297,7 +1297,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
values[index] = HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink( values[index] = HOST_ENDIAN_TO_BFS_INT64(bplustree_node::MakeLink(
BPLUSTREE_DUPLICATE_NODE, right)); BPLUSTREE_DUPLICATE_NODE, right));
} }
if ((status = cached->WriteBack(transaction)) < B_OK) if ((status = cached->WriteBack(transaction)) < B_OK)
return status; return status;
} }
@ -1329,7 +1329,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
// Again, we may need to turn the duplicate entry back into a normal entry // Again, we may need to turn the duplicate entry back into a normal entry
array = duplicate->DuplicateArray(); array = duplicate->DuplicateArray();
if (left == BPLUSTREE_NULL && duplicate->RightLink() == BPLUSTREE_NULL if (left == BPLUSTREE_NULL && duplicate->RightLink() == BPLUSTREE_NULL
&& duplicate->DuplicateArray()->count <= NUM_FRAGMENT_VALUES) { && duplicate->DuplicateArray()->CountItems() <= NUM_FRAGMENT_VALUES) {
duplicateOffset = right; duplicateOffset = right;
continue; continue;
} }
@ -1337,7 +1337,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
return cachedDuplicate.WriteBack(transaction); return cachedDuplicate.WriteBack(transaction);
} }
return status; return status;
} else if (isLast && array->count <= NUM_FRAGMENT_VALUES) { } else if (isLast && array->CountItems() <= NUM_FRAGMENT_VALUES) {
// If the number of entries fits in a duplicate fragment, then // If the number of entries fits in a duplicate fragment, then
// either find a free fragment node, or convert this node to a // either find a free fragment node, or convert this node to a
// fragment node. // fragment node.
@ -2023,7 +2023,7 @@ bplustree_node::FragmentsUsed(uint32 nodeSize)
uint32 used = 0; uint32 used = 0;
for (uint32 i = 0; i < nodeSize / ((NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); i++) { for (uint32 i = 0; i < nodeSize / ((NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); i++) {
duplicate_array *array = FragmentAt(i); duplicate_array *array = FragmentAt(i);
if (array->count > 0 && ++used > 1) if (array->CountItems() > 0 && ++used > 1)
return used; return used;
} }
return used; return used;

View File

@ -121,7 +121,7 @@ Journal::Journal(Volume *volume)
fLock("bfs journal"), fLock("bfs journal"),
fOwner(NULL), fOwner(NULL),
fArray(volume->BlockSize()), fArray(volume->BlockSize()),
fLogSize(volume->Log().length), fLogSize(volume->Log().Length()),
fMaxTransactionSize(fLogSize / 4 - 5), fMaxTransactionSize(fLogSize / 4 - 5),
fUsed(0), fUsed(0),
fTransactionsInEntry(0) fTransactionsInEntry(0)
@ -259,9 +259,9 @@ Journal::ReplayLog()
} }
PRINT(("replaying worked fine!\n")); PRINT(("replaying worked fine!\n"));
fVolume->SuperBlock().log_start = fVolume->LogEnd(); fVolume->SuperBlock().log_start = HOST_ENDIAN_TO_BFS_INT64(fVolume->LogEnd());
fVolume->LogStart() = fVolume->LogEnd(); fVolume->LogStart() = fVolume->LogEnd();
fVolume->SuperBlock().flags = SUPER_BLOCK_DISK_CLEAN; fVolume->SuperBlock().flags = HOST_ENDIAN_TO_BFS_INT32(SUPER_BLOCK_DISK_CLEAN);
return fVolume->WriteSuperBlock(); return fVolume->WriteSuperBlock();
} }
@ -295,9 +295,9 @@ Journal::blockNotify(off_t blockNumber, size_t numBlocks, void *arg)
LogEntry *next = journal->fEntries.GetNext(logEntry); LogEntry *next = journal->fEntries.GetNext(logEntry);
if (next != NULL) { if (next != NULL) {
int32 length = next->Start() - logEntry->Start(); int32 length = next->Start() - logEntry->Start();
superBlock.log_start = (superBlock.log_start + length) % journal->fLogSize; superBlock.log_start = HOST_ENDIAN_TO_BFS_INT64((superBlock.LogStart() + length) % journal->fLogSize);
} else } else
superBlock.log_start = journal->fVolume->LogEnd(); superBlock.log_start = HOST_ENDIAN_TO_BFS_INT64(journal->fVolume->LogEnd());
update = true; update = true;
} }
@ -354,7 +354,7 @@ Journal::WriteLogEntry()
LogEntry *logEntry = NULL, *firstEntry = NULL, *lastAdded = NULL; LogEntry *logEntry = NULL, *firstEntry = NULL, *lastAdded = NULL;
for (int32 i = 0; i < array->count; i++) { for (int32 i = 0; i < array->CountItems(); i++) {
retry: retry:
if (logEntry == NULL) { if (logEntry == NULL) {
logEntry = new LogEntry(this, logStart); logEntry = new LogEntry(this, logStart);
@ -370,7 +370,7 @@ Journal::WriteLogEntry()
logStart++; logStart++;
} }
if (!logEntry->InsertBlock(array->values[i])) { if (!logEntry->InsertBlock(array->ValueAt(i))) {
// log entry is full - start a new one // log entry is full - start a new one
fEntriesLock.Lock(); fEntriesLock.Lock();
fEntries.Add(logEntry); fEntries.Add(logEntry);
@ -410,7 +410,7 @@ Journal::WriteLogEntry()
if (block == NULL) if (block == NULL)
return B_IO_ERROR; return B_IO_ERROR;
// write blocks // write blocks
write_pos(fVolume->Device(), logOffset + (logPosition << blockShift), write_pos(fVolume->Device(), logOffset + (logPosition << blockShift),
block, fVolume->BlockSize()); block, fVolume->BlockSize());
@ -420,11 +420,11 @@ Journal::WriteLogEntry()
fEntriesLock.Unlock(); fEntriesLock.Unlock();
fUsed += array->count; fUsed += array->CountItems();
// Update the log end pointer in the super block // Update the log end pointer in the super block
fVolume->SuperBlock().flags = SUPER_BLOCK_DISK_DIRTY; fVolume->SuperBlock().flags = HOST_ENDIAN_TO_BFS_INT32(SUPER_BLOCK_DISK_DIRTY);
fVolume->SuperBlock().log_end = logPosition; fVolume->SuperBlock().log_end = HOST_ENDIAN_TO_BFS_INT64(logPosition);
fVolume->LogEnd() = logPosition; fVolume->LogEnd() = logPosition;
status_t status = fVolume->WriteSuperBlock(); status_t status = fVolume->WriteSuperBlock();
@ -543,8 +543,8 @@ Journal::TransactionDone(bool success)
if (array != NULL) { if (array != NULL) {
// release the lock for all blocks in the array (we don't need // release the lock for all blocks in the array (we don't need
// to be notified when they are actually written to disk) // to be notified when they are actually written to disk)
for (int32 i = 0; i < array->count; i++) for (int32 i = 0; i < array->CountItems(); i++)
release_block(fVolume->Device(), array->values[i]); release_block(fVolume->Device(), array->ValueAt(i));
} }
return B_OK; return B_OK;

View File

@ -1,6 +1,6 @@
/* Utility - some helper classes /* Utility - some helper classes
* *
* Copyright 2001-2005, Axel Dörfler, axeld@pinc-software.de. * Copyright 2001-2006, Axel Dörfler, axeld@pinc-software.de.
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
@ -15,14 +15,14 @@
bool bool
sorted_array::FindInternal(off_t value, int32 &index) const sorted_array::_FindInternal(off_t value, int32 &index) const
{ {
int32 min = 0, max = count-1; int32 min = 0, max = CountItems() - 1;
off_t cmp; off_t cmp;
while (min <= max) { while (min <= max) {
index = (min + max) / 2; index = (min + max) / 2;
cmp = values[index] - value; cmp = ValueAt(index) - value;
if (cmp < 0) if (cmp < 0)
min = index + 1; min = index + 1;
else if (cmp > 0) else if (cmp > 0)
@ -41,19 +41,19 @@ sorted_array::Insert(off_t value)
// binary search, if not, just iterate linearly to find // binary search, if not, just iterate linearly to find
// the insertion point // the insertion point
int32 i; int32 i;
if (count > 8 ) { if (CountItems() > 8 ) {
if (!FindInternal(value,i) if (!_FindInternal(value, i) && ValueAt(i) <= value)
&& values[i] <= value)
i++; i++;
} else { } else {
for (i = 0;i < count; i++) for (i = 0; i < CountItems(); i++) {
if (values[i] > value) if (ValueAt(i) > value)
break; break;
}
} }
memmove(&values[i+1],&values[i],(count - i) * sizeof(off_t)); memmove(&values[i + 1], &values[i], (CountItems() - i) * sizeof(off_t));
values[i] = value; values[i] = HOST_ENDIAN_TO_BFS_INT64(value);
count++; count = HOST_ENDIAN_TO_BFS_INT64(CountItems() + 1);
} }
@ -64,8 +64,8 @@ sorted_array::Remove(off_t value)
if (index == -1) if (index == -1)
return false; return false;
memmove(&values[index],&values[index + 1],(count - index) * sizeof(off_t)); memmove(&values[index], &values[index + 1], (CountItems() - index) * sizeof(off_t));
count--; count = HOST_ENDIAN_TO_BFS_INT64(CountItems() - 1);
return true; return true;
} }
@ -103,11 +103,11 @@ BlockArray::Find(off_t value)
status_t status_t
BlockArray::Insert(off_t value) BlockArray::Insert(off_t value)
{ {
if (fArray == NULL || fArray->count + 1 > fMaxBlocks) { if (fArray == NULL || fArray->CountItems() + 1 > fMaxBlocks) {
sorted_array *array = (sorted_array *)realloc(fArray,fSize + fBlockSize); sorted_array *array = (sorted_array *)realloc(fArray, fSize + fBlockSize);
if (array == NULL) if (array == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
if (fArray == NULL) if (fArray == NULL)
array->count = 0; array->count = 0;

View File

@ -1,13 +1,13 @@
/* Utility - some helper classes /* Utility - some helper classes
* *
* Copyright 2001-2005, Axel Dörfler, axeld@pinc-software.de * Copyright 2001-2006, Axel Dörfler, axeld@pinc-software.de
* This file may be used under the terms of the MIT License. * This file may be used under the terms of the MIT License.
*/ */
#ifndef UTILITY_H #ifndef UTILITY_H
#define UTILITY_H #define UTILITY_H
#include <SupportDefs.h> #include "bfs_endian.h"
// Simple array, used for the duplicate handling in the B+Tree, // Simple array, used for the duplicate handling in the B+Tree,
@ -17,18 +17,20 @@ struct sorted_array {
public: public:
off_t count; off_t count;
#if __MWERKS__ #if __MWERKS__
off_t values[1]; off_t values[1];
#else #else
off_t values[0]; off_t values[0];
#endif #endif
off_t CountItems() const { return BFS_ENDIAN_TO_HOST_INT64(count); }
off_t ValueAt(int32 index) const { return BFS_ENDIAN_TO_HOST_INT64(values[index]); }
inline int32 Find(off_t value) const; inline int32 Find(off_t value) const;
void Insert(off_t value); void Insert(off_t value);
bool Remove(off_t value); bool Remove(off_t value);
private: private:
bool FindInternal(off_t value,int32 &index) const; bool _FindInternal(off_t value, int32 &index) const;
}; };
@ -36,7 +38,7 @@ inline int32
sorted_array::Find(off_t value) const sorted_array::Find(off_t value) const
{ {
int32 i; int32 i;
return FindInternal(value,i) ? i : -1; return _FindInternal(value, i) ? i : -1;
} }
@ -56,8 +58,8 @@ class BlockArray {
void MakeEmpty(); void MakeEmpty();
int32 CountItems() const { return fArray != NULL ? fArray->count : 0; } int32 CountItems() const { return fArray != NULL ? fArray->CountItems() : 0; }
int32 BlocksUsed() const { return fArray != NULL ? ((fArray->count + 1) * sizeof(off_t) + fBlockSize - 1) / fBlockSize : 0; } int32 BlocksUsed() const { return fArray != NULL ? ((fArray->CountItems() + 1) * sizeof(off_t) + fBlockSize - 1) / fBlockSize : 0; }
sorted_array *Array() const { return fArray; } sorted_array *Array() const { return fArray; }
int32 Size() const { return fSize; } int32 Size() const { return fSize; }

View File

@ -596,7 +596,7 @@ Volume::Initialize(const char *device, const char *name, uint32 blockSize, uint3
// cannot use BlockAllocator::BitmapSize() here // cannot use BlockAllocator::BitmapSize() here
fSuperBlock.log_blocks = ToBlockRun(AllocationGroups() fSuperBlock.log_blocks = ToBlockRun(AllocationGroups()
* fSuperBlock.BlocksPerAllocationGroup() + 1); * fSuperBlock.BlocksPerAllocationGroup() + 1);
fSuperBlock.log_blocks.length = 2048; fSuperBlock.log_blocks.length = HOST_ENDIAN_TO_BFS_INT16(2048);
// ToDo: set the log size depending on the disk size // ToDo: set the log size depending on the disk size
fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(ToBlock(Log())); fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(ToBlock(Log()));