Remove old block cache implementation
This was not used anywhere except the tests written for it (which is also removed).
This commit is contained in:
parent
ace74964f1
commit
a7d444d145
240
src/system/kernel/cache/BlockMap.cpp
vendored
240
src/system/kernel/cache/BlockMap.cpp
vendored
@ -1,240 +0,0 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
|
||||
|
||||
/** The BlockMap stores offset:address pairs; you can map an offset to a specific address.
|
||||
* It has been designed to contain few and mostly contiguous offset mappings - it is used
|
||||
* by the file cache to keep track about which blocks of the file are already in memory.
|
||||
* The offsets may spread over a very large amount.
|
||||
*
|
||||
* Internally, it stores small and contiguous address arrays of a certain size, and
|
||||
* accesses those using a hash table. Address values of NULL are equal to non existing
|
||||
* mappings; that value cannot be stored. At the current size, each hash entry can
|
||||
* map 60 addresses which corresponds to a file range of 240 kB.
|
||||
* It currently does not do any locking; it assumes a safe environment which you are
|
||||
* responsible for to create when you call its functions.
|
||||
*/
|
||||
|
||||
|
||||
#include "BlockMap.h"
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//#define TRACE_BLOCK_MAP
|
||||
#ifdef TRACE_BLOCK_MAP
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x)
|
||||
#endif
|
||||
|
||||
|
||||
// ToDo: when we have a better allocator, change the number of addresses to a power of two
|
||||
// currently, this structure takes 256 bytes total
|
||||
|
||||
struct BlockMap::block_entry {
|
||||
block_entry *next;
|
||||
uint32 used;
|
||||
off_t offset;
|
||||
addr_t address[60];
|
||||
};
|
||||
|
||||
#define BLOCK_ARRAY_SIZE (sizeof(BlockMap::block_entry::address) / sizeof(addr_t))
|
||||
|
||||
static inline off_t
|
||||
to_block_entry_offset(off_t offset, uint32 &index)
|
||||
{
|
||||
// ToDo: improve this once we have a power of two array size
|
||||
off_t baseOffset = (offset / BLOCK_ARRAY_SIZE) * BLOCK_ARRAY_SIZE;
|
||||
index = uint32(offset - baseOffset);
|
||||
|
||||
return baseOffset;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
block_entry_compare(void *_entry, const void *_offset)
|
||||
{
|
||||
BlockMap::block_entry *entry = (BlockMap::block_entry *)_entry;
|
||||
const off_t *offset = (const off_t *)_offset;
|
||||
|
||||
return entry->offset - *offset;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
block_entry_hash(void *_entry, const void *_offset, uint32 range)
|
||||
{
|
||||
BlockMap::block_entry *entry = (BlockMap::block_entry *)_entry;
|
||||
const off_t *offset = (const off_t *)_offset;
|
||||
|
||||
if (entry != NULL)
|
||||
return entry->offset % range;
|
||||
|
||||
return *offset % range;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BlockMap::BlockMap(off_t size)
|
||||
:
|
||||
fSize(size)
|
||||
{
|
||||
fHashTable = hash_init(16, 0, &block_entry_compare, &block_entry_hash);
|
||||
}
|
||||
|
||||
|
||||
BlockMap::~BlockMap()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/** Checks whether or not the construction of the BlockMap were successful.
|
||||
*/
|
||||
|
||||
status_t
|
||||
BlockMap::InitCheck() const
|
||||
{
|
||||
return fHashTable != NULL ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
/** Sets the size of the block map - all existing entries beyond this size will be
|
||||
* removed from the map, and their memory is freed.
|
||||
*/
|
||||
|
||||
void
|
||||
BlockMap::SetSize(off_t size)
|
||||
{
|
||||
TRACE(("BlockMap::SetSize(%Ld)\n", size));
|
||||
|
||||
if (size >= fSize) {
|
||||
// nothing to do
|
||||
fSize = size;
|
||||
return;
|
||||
}
|
||||
|
||||
// ToDo: remove all mappings beyond the file size
|
||||
}
|
||||
|
||||
|
||||
/** Upon successful exit which is indicated by a return value of B_OK, the "_entry"
|
||||
* argument points to a block_entry structure containing the data for the given
|
||||
* offset.
|
||||
* The offset must have been normalized to the base offset values of a block entry
|
||||
* already.
|
||||
*/
|
||||
|
||||
status_t
|
||||
BlockMap::GetBlockEntry(off_t baseOffset, block_entry **_entry)
|
||||
{
|
||||
block_entry *entry = (block_entry *)hash_lookup(fHashTable, &baseOffset);
|
||||
if (entry == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
*_entry = entry;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BlockMap::Remove(off_t offset, off_t count)
|
||||
{
|
||||
TRACE(("BlockMap::Remove(offset = %Ld, count = %Ld)\n", offset, count));
|
||||
|
||||
uint32 index;
|
||||
off_t baseOffset = to_block_entry_offset(offset, index);
|
||||
block_entry *entry;
|
||||
|
||||
while (count > 0) {
|
||||
int32 max = min_c(BLOCK_ARRAY_SIZE, index + count);
|
||||
int32 blocks = max - index;
|
||||
|
||||
if (GetBlockEntry(baseOffset, &entry) == B_OK) {
|
||||
for (int32 i = index; i < max; i++) {
|
||||
if (entry->address[i] != NULL)
|
||||
entry->used--;
|
||||
|
||||
entry->address[i] = NULL;
|
||||
}
|
||||
|
||||
if (entry->used == 0) {
|
||||
// release entry if it's no longer used
|
||||
hash_remove(fHashTable, entry);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
baseOffset += BLOCK_ARRAY_SIZE;
|
||||
count -= blocks;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BlockMap::Set(off_t offset, addr_t address)
|
||||
{
|
||||
TRACE(("BlockMap::Set(offset = %Ld, address = %08lx)\n", offset, address));
|
||||
|
||||
uint32 index;
|
||||
off_t baseOffset = to_block_entry_offset(offset, index);
|
||||
|
||||
block_entry *entry;
|
||||
if (GetBlockEntry(baseOffset, &entry) == B_OK) {
|
||||
// the block already exists, we just need to fill in our new address
|
||||
if (entry->address[index] == NULL && address != NULL)
|
||||
entry->used++;
|
||||
else if (entry->address[index] != NULL && address == NULL)
|
||||
entry->used--;
|
||||
|
||||
entry->address[index] = address;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// allocate new block and fill it
|
||||
|
||||
entry = (block_entry *)malloc(sizeof(struct block_entry));
|
||||
if (entry == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(entry->address, 0, sizeof(entry->address));
|
||||
|
||||
entry->used = 1;
|
||||
entry->offset = baseOffset;
|
||||
|
||||
hash_insert(fHashTable, entry);
|
||||
|
||||
entry->address[index] = address;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BlockMap::Get(off_t offset, addr_t &address)
|
||||
{
|
||||
TRACE(("BlockMap::Get(offset = %Ld)\n", offset));
|
||||
|
||||
uint32 index;
|
||||
off_t baseOffset = to_block_entry_offset(offset, index);
|
||||
|
||||
block_entry *entry;
|
||||
if (GetBlockEntry(baseOffset, &entry) == B_OK
|
||||
&& entry->address[index] != NULL) {
|
||||
address = entry->address[index];
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
35
src/system/kernel/cache/BlockMap.h
vendored
35
src/system/kernel/cache/BlockMap.h
vendored
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BLOCK_MAP_H
|
||||
#define BLOCK_MAP_H
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <util/khash.h>
|
||||
|
||||
|
||||
class BlockMap {
|
||||
public:
|
||||
BlockMap(off_t size);
|
||||
~BlockMap();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
void SetSize(off_t size);
|
||||
off_t Size() const { return fSize; }
|
||||
|
||||
status_t Remove(off_t offset, off_t count = 1);
|
||||
status_t Set(off_t offset, addr_t address);
|
||||
status_t Get(off_t offset, addr_t &address);
|
||||
|
||||
private:
|
||||
struct block_entry;
|
||||
status_t GetBlockEntry(off_t offset, block_entry **_entry);
|
||||
|
||||
hash_table *fHashTable;
|
||||
off_t fSize;
|
||||
};
|
||||
|
||||
#endif /* BLOCK_MAP_H */
|
143
src/tests/system/kernel/cache/BlockMapTest.cpp
vendored
143
src/tests/system/kernel/cache/BlockMapTest.cpp
vendored
@ -1,143 +0,0 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
*/
|
||||
|
||||
|
||||
#include <BlockMap.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static const off_t kSize = 262144; // 4096 * 262144 == 1 GB of file size
|
||||
static const int32 kLoops = 4096; // 4096 * 4096 == 16 MB in cache (completely arbitrary which will never be the case)
|
||||
|
||||
|
||||
int32
|
||||
offset_in_array(off_t *array, int32 maxSize, off_t offset)
|
||||
{
|
||||
for (int32 i = 0; i < maxSize; i++) {
|
||||
if (array[i] == offset)
|
||||
return i;
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
BlockMap map(kSize);
|
||||
|
||||
status_t status = map.InitCheck();
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "map creation failed: %s\n", strerror(status));
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Adding %ld offsets from 0 to %Ld...\n", kLoops, kSize);
|
||||
|
||||
off_t offsets[kLoops];
|
||||
for (int32 i = 0; i < kLoops; i++) {
|
||||
off_t offset;
|
||||
do {
|
||||
offset = rand() * kSize / RAND_MAX;
|
||||
} while (offset_in_array(offsets, i, offset) >= B_OK);
|
||||
|
||||
offsets[i] = offset;
|
||||
map.Set(offsets[i], i + 1);
|
||||
}
|
||||
|
||||
printf("Testing all offsets in the map...\n");
|
||||
|
||||
for (off_t offset = 0; offset < kSize; offset++) {
|
||||
// look for offset in array
|
||||
int32 index = offset_in_array(offsets, kLoops, offset);
|
||||
|
||||
addr_t address;
|
||||
if (map.Get(offset, address) == B_OK) {
|
||||
if (index >= 0) {
|
||||
if (address != (uint32)index + 1)
|
||||
fprintf(stderr, " offset %Ld contains wrong address %lx, should have been %lx\n", offset, address, index + 1);
|
||||
} else
|
||||
fprintf(stderr, " offset %Ld found in map but never added\n", offset);
|
||||
} else {
|
||||
if (index >= 0)
|
||||
fprintf(stderr, " offset %Ld not found in map but should be there\n", offset);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Remove last offset...\n");
|
||||
|
||||
// remove last offset
|
||||
map.Remove(offsets[kLoops - 1]);
|
||||
addr_t address;
|
||||
if (map.Get(offsets[kLoops - 1], address) == B_OK)
|
||||
fprintf(stderr, " Removing offset %Ld failed (got address %lx)!\n", offsets[kLoops - 1], address);
|
||||
|
||||
// remove offsets in the middle
|
||||
off_t start = kSize / 4;
|
||||
off_t num = kSize / 2;
|
||||
off_t end = start + num;
|
||||
|
||||
printf("Remove all offsets from %Ld to %Ld (and add bounds check offsets)...\n", start, end);
|
||||
|
||||
bool startWall[3] = {false};
|
||||
for (int32 i = 0; i < 3; i++) {
|
||||
if (offset_in_array(offsets, kLoops, start - 1 + i) < B_OK) {
|
||||
startWall[i] = true;
|
||||
map.Set(start - 1 + i, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool endWall[3] = {false};
|
||||
for (int32 i = 0; i < 3; i++) {
|
||||
if (offset_in_array(offsets, kLoops, end - 1 + i) < B_OK) {
|
||||
endWall[i] = true;
|
||||
map.Set(end - 1 + i, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
map.Remove(start, num);
|
||||
|
||||
printf("Testing all offsets in the map...\n");
|
||||
|
||||
for (off_t offset = 0; offset < kSize; offset++) {
|
||||
// look for offset in array
|
||||
int32 index = offset_in_array(offsets, kLoops - 1, offset);
|
||||
|
||||
addr_t address;
|
||||
if (map.Get(offset, address) == B_OK) {
|
||||
if (offset >= start && offset < end) {
|
||||
fprintf(stderr, " should not contain removed offset %Ld:%lx!\n", offset, address);
|
||||
} else if (index >= 0) {
|
||||
if (address != (uint32)index + 1)
|
||||
fprintf(stderr, " offset %Ld contains wrong address %lx, should have been %lx\n", offset, address, index + 1);
|
||||
} else {
|
||||
if (offset >= start -1 && offset <= start + 1) {
|
||||
// start && start + 1 must not be in the map anymore
|
||||
if (offset >= start && offset <= start + 1)
|
||||
fprintf(stderr, " start wall %Ld in map\n", offset);
|
||||
} else if (offset >= end - 1 && offset <= end + 1) {
|
||||
// end - 1 must not be in the map anymore
|
||||
if (offset == end - 1)
|
||||
fprintf(stderr, " end wall %Ld in map\n", offset);
|
||||
} else
|
||||
fprintf(stderr, " offset %Ld found in map but never added\n", offset);
|
||||
}
|
||||
} else {
|
||||
if (index >= 0 && (offset < start || offset >= end))
|
||||
fprintf(stderr, " offset %Ld not found in map but should be there\n", offset);
|
||||
|
||||
if (offset == start - 1 && startWall[offset - start - 1])
|
||||
fprintf(stderr, " start wall %Ld not in map\n", offset);
|
||||
else if (offset >= end && offset <= end + 1 && endWall[offset - end - 1])
|
||||
fprintf(stderr, " end wall %Ld not in map\n", offset);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
5
src/tests/system/kernel/cache/Jamfile
vendored
5
src/tests/system/kernel/cache/Jamfile
vendored
@ -11,11 +11,6 @@ StdBinCommands
|
||||
cache_control.cpp
|
||||
;
|
||||
|
||||
SimpleTest BlockMapTest :
|
||||
BlockMapTest.cpp
|
||||
BlockMap.cpp
|
||||
: libkernelland_emu.so ;
|
||||
|
||||
SimpleTest block_cache_test :
|
||||
block_cache_test.cpp
|
||||
: libkernelland_emu.so ;
|
||||
|
Loading…
Reference in New Issue
Block a user