**
** Initial version by Axel DΓΆrfler, axeld@pinc-software.de
** This file may be used under the terms of the MIT License.
*/
#include "cache.h"
#include "BPlusTree.h"
#include <File.h>
#include <List.h>
#include <malloc.h>
#include <stdio.h>
* with the test program, it really suites no other needs.
* It's very simple and not that efficient, and simple holds the whole
* file in memory, all the time.
*/
#define TRACE(x)
static size_t sBlockSize;
BList gBlocks;
void
init_cache(BFile* , int32 blockSize)
{
sBlockSize = blockSize;
}
void
shutdown_cache(BFile* file, int32 blockSize)
{
for (int32 i = 0; i < gBlocks.CountItems(); i++) {
void* buffer = gBlocks.ItemAt(i);
if (buffer == NULL) {
debugger("cache is corrupt!");
exit(-1);
}
file->WriteAt(i * blockSize, buffer, blockSize);
free(buffer);
}
}
status_t
cached_write(void* cache, off_t num, const void* _data, off_t numBlocks)
{
if (num + numBlocks > gBlocks.CountItems()) {
debugger("cached write beyond loaded blocks");
exit(1);
}
for (off_t i = 0; i < numBlocks; i++) {
void* buffer = gBlocks.ItemAt(num + i);
const void* data = (uint8*)_data + i * sBlockSize;
if (buffer != data)
memcpy(buffer, data, sBlockSize);
}
return B_OK;
}
static status_t
read_blocks(void* cache, off_t num)
{
BFile* file = (BFile*)cache;
for (uint32 i = gBlocks.CountItems(); i <= num; i++) {
void* buffer = malloc(sBlockSize);
if (buffer == NULL)
return B_NO_MEMORY;
gBlocks.AddItem(buffer);
if (file->ReadAt(i * sBlockSize, buffer, sBlockSize) < 0)
return B_IO_ERROR;
}
return B_OK;
}
static void*
get_block(void* cache, off_t num)
{
if (num >= gBlocks.CountItems())
read_blocks(cache, num);
return gBlocks.ItemAt(num);
}
static void
release_block(void* cache, off_t num)
{
}
const void*
block_cache_get(void* _cache, off_t blockNumber)
{
TRACE(("block_cache_get(block = %" B_PRIdOFF ")\n", blockNumber));
return get_block(_cache, blockNumber);
}
status_t
block_cache_make_writable(void* _cache, off_t blockNumber, int32 transaction)
{
TRACE(("block_cache_make_writable(block = %" B_PRIdOFF ", transaction = %"
B_PRId32 ")\n", blockNumber, transaction));
return B_OK;
}
void*
block_cache_get_writable(void* _cache, off_t blockNumber, int32 transaction)
{
TRACE(("block_cache_get_writable(block = %" B_PRIdOFF
", transaction = %" B_PRId32 ")\n", blockNumber, transaction));
return get_block(_cache, blockNumber);
}
status_t
block_cache_set_dirty(void* _cache, off_t blockNumber, bool dirty,
int32 transaction)
{
TRACE(("block_cache_set_dirty(block = %" B_PRIdOFF
", dirty = %s, transaction = %" B_PRId32 ")\n", blockNumber,
dirty ? "yes" : "no", transaction));
if (dirty)
debugger("setting to dirty not implemented\n");
return B_OK;
}
void
block_cache_put(void* _cache, off_t blockNumber)
{
TRACE(("block_cache_put(block = %" B_PRIdOFF ")\n", blockNumber));
release_block(_cache, blockNumber);
}