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;
duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue));
if (array->count > NUM_FRAGMENT_VALUES
|| array->count < 1) {
if (array->CountItems() > NUM_FRAGMENT_VALUES
|| array->CountItems() < 1) {
FATAL(("insertDuplicate: Invalid array[%ld] size in fragment %Ld == %Ld!\n",
bplustree_node::FragmentIndex(oldValue),
bplustree_node::FragmentOffset(oldValue),
array->count));
array->CountItems()));
return B_BAD_DATA;
}
if (array->count < NUM_FRAGMENT_VALUES) {
if (array->CountItems() < NUM_FRAGMENT_VALUES) {
array->Insert(value);
} else {
// 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
// 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],
array->count * sizeof(off_t));
array->CountItems() * sizeof(off_t));
memset(array, 0, (NUM_FRAGMENT_VALUES + 1) * sizeof(off_t));
array = newDuplicate->DuplicateArray();
@ -748,15 +748,15 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
return B_IO_ERROR;
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",
duplicateOffset, array->count));
duplicateOffset, array->CountItems()));
return B_BAD_DATA;
}
} while (array->count >= NUM_DUPLICATE_VALUES
} while (array->CountItems() >= NUM_DUPLICATE_VALUES
&& (oldValue = duplicate->RightLink()) != BPLUSTREE_NULL);
if (array->count < NUM_DUPLICATE_VALUES) {
if (array->CountItems() < NUM_DUPLICATE_VALUES) {
array->Insert(value);
} else {
// no space left - add a new duplicate node
@ -770,11 +770,11 @@ BPlusTree::InsertDuplicate(Transaction *transaction, CachedNode *cached, bplustr
// link the two nodes together
duplicate->right_link = HOST_ENDIAN_TO_BFS_INT64(offset);
newDuplicate->left_link = HOST_ENDIAN_TO_BFS_INT64(duplicateOffset);
array = newDuplicate->DuplicateArray();
array->count = 0;
array->Insert(value);
status = cachedNewDuplicate.WriteBack(transaction);
if (status < B_OK)
return status;
@ -1214,10 +1214,10 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
if (bplustree_node::LinkType(oldValue) == BPLUSTREE_DUPLICATE_FRAGMENT) {
duplicate_array *array = duplicate->FragmentAt(bplustree_node::FragmentIndex(oldValue));
if (array->count > NUM_FRAGMENT_VALUES
|| array->count < 1) {
if (array->CountItems() > NUM_FRAGMENT_VALUES
|| array->CountItems() < 1) {
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;
}
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
if (array->count == 1) {
if (array->CountItems() == 1) {
// set the link to the remaining value
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)
while (duplicate != NULL) {
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",
duplicateOffset, array->count));
duplicateOffset, array->CountItems()));
return B_BAD_DATA;
}
@ -1281,15 +1281,15 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
off_t left = duplicate->LeftLink();
off_t right = duplicate->RightLink();
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
// update the duplicate link if needed (which should not be, if
// we are the only one working on that tree...)
if (duplicateOffset == bplustree_node::FragmentOffset(oldValue)
|| array->count == 1) {
if (array->count == 1 && isLast)
|| array->CountItems() == 1) {
if (array->CountItems() == 1 && isLast)
values[index] = array->values[0];
else if (isLast) {
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(
BPLUSTREE_DUPLICATE_NODE, right));
}
if ((status = cached->WriteBack(transaction)) < B_OK)
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
array = duplicate->DuplicateArray();
if (left == BPLUSTREE_NULL && duplicate->RightLink() == BPLUSTREE_NULL
&& duplicate->DuplicateArray()->count <= NUM_FRAGMENT_VALUES) {
&& duplicate->DuplicateArray()->CountItems() <= NUM_FRAGMENT_VALUES) {
duplicateOffset = right;
continue;
}
@ -1337,7 +1337,7 @@ BPlusTree::RemoveDuplicate(Transaction *transaction, bplustree_node *node, Cache
return cachedDuplicate.WriteBack(transaction);
}
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
// either find a free fragment node, or convert this node to a
// fragment node.
@ -2023,7 +2023,7 @@ bplustree_node::FragmentsUsed(uint32 nodeSize)
uint32 used = 0;
for (uint32 i = 0; i < nodeSize / ((NUM_FRAGMENT_VALUES + 1) * sizeof(off_t)); i++) {
duplicate_array *array = FragmentAt(i);
if (array->count > 0 && ++used > 1)
if (array->CountItems() > 0 && ++used > 1)
return used;
}
return used;

View File

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

View File

@ -1,6 +1,6 @@
/* 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.
*/
@ -15,14 +15,14 @@
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;
while (min <= max) {
index = (min + max) / 2;
cmp = values[index] - value;
cmp = ValueAt(index) - value;
if (cmp < 0)
min = index + 1;
else if (cmp > 0)
@ -41,19 +41,19 @@ sorted_array::Insert(off_t value)
// binary search, if not, just iterate linearly to find
// the insertion point
int32 i;
if (count > 8 ) {
if (!FindInternal(value,i)
&& values[i] <= value)
if (CountItems() > 8 ) {
if (!_FindInternal(value, i) && ValueAt(i) <= value)
i++;
} else {
for (i = 0;i < count; i++)
if (values[i] > value)
for (i = 0; i < CountItems(); i++) {
if (ValueAt(i) > value)
break;
}
}
memmove(&values[i+1],&values[i],(count - i) * sizeof(off_t));
values[i] = value;
count++;
memmove(&values[i + 1], &values[i], (CountItems() - i) * sizeof(off_t));
values[i] = HOST_ENDIAN_TO_BFS_INT64(value);
count = HOST_ENDIAN_TO_BFS_INT64(CountItems() + 1);
}
@ -64,8 +64,8 @@ sorted_array::Remove(off_t value)
if (index == -1)
return false;
memmove(&values[index],&values[index + 1],(count - index) * sizeof(off_t));
count--;
memmove(&values[index], &values[index + 1], (CountItems() - index) * sizeof(off_t));
count = HOST_ENDIAN_TO_BFS_INT64(CountItems() - 1);
return true;
}
@ -103,11 +103,11 @@ BlockArray::Find(off_t value)
status_t
BlockArray::Insert(off_t value)
{
if (fArray == NULL || fArray->count + 1 > fMaxBlocks) {
sorted_array *array = (sorted_array *)realloc(fArray,fSize + fBlockSize);
if (fArray == NULL || fArray->CountItems() + 1 > fMaxBlocks) {
sorted_array *array = (sorted_array *)realloc(fArray, fSize + fBlockSize);
if (array == NULL)
return B_NO_MEMORY;
if (fArray == NULL)
array->count = 0;

View File

@ -1,13 +1,13 @@
/* 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.
*/
#ifndef UTILITY_H
#define UTILITY_H
#include <SupportDefs.h>
#include "bfs_endian.h"
// Simple array, used for the duplicate handling in the B+Tree,
@ -17,18 +17,20 @@ struct sorted_array {
public:
off_t count;
#if __MWERKS__
off_t values[1];
#else
off_t values[0];
#endif
#if __MWERKS__
off_t values[1];
#else
off_t values[0];
#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;
void Insert(off_t value);
bool Remove(off_t value);
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
{
int32 i;
return FindInternal(value,i) ? i : -1;
return _FindInternal(value, i) ? i : -1;
}
@ -56,8 +58,8 @@ class BlockArray {
void MakeEmpty();
int32 CountItems() const { return fArray != NULL ? fArray->count : 0; }
int32 BlocksUsed() const { return fArray != NULL ? ((fArray->count + 1) * sizeof(off_t) + fBlockSize - 1) / fBlockSize : 0; }
int32 CountItems() const { return fArray != NULL ? fArray->CountItems() : 0; }
int32 BlocksUsed() const { return fArray != NULL ? ((fArray->CountItems() + 1) * sizeof(off_t) + fBlockSize - 1) / fBlockSize : 0; }
sorted_array *Array() const { return fArray; }
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
fSuperBlock.log_blocks = ToBlockRun(AllocationGroups()
* 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
fSuperBlock.log_start = fSuperBlock.log_end = HOST_ENDIAN_TO_BFS_INT64(ToBlock(Log()));