not used outside of it. Added tracking for the last transaction in the block cache; that way it can test if the last transaction has been closed before opening a new one. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13022 a95241bf-73f2-0310-859d-f6bbb57e9c96
135 lines
3.2 KiB
C
135 lines
3.2 KiB
C
/*
|
|
* Copyright 2004-2005, Axel Dörfler, [email protected]. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
#ifndef BLOCK_CACHE_PRIVATE_H
|
|
#define BLOCK_CACHE_PRIVATE_H
|
|
|
|
|
|
#include <lock.h>
|
|
#include <util/DoublyLinkedList.h>
|
|
|
|
struct hash_table;
|
|
struct vm_page;
|
|
|
|
|
|
#define DEBUG_CHANGED
|
|
|
|
|
|
static const size_t kBlockAddressSize = 128 * 1024 * 1024; // 128 MB
|
|
static const size_t kBlockRangeSize = 64 * 1024; // 64 kB
|
|
static const size_t kBlockRangeShift = 16;
|
|
static const size_t kNumBlockRangePages = kBlockRangeSize / B_PAGE_SIZE;
|
|
|
|
struct cache_transaction;
|
|
struct cached_block;
|
|
struct block_chunk;
|
|
struct block_cache;
|
|
typedef DoublyLinkedListLink<cached_block> block_link;
|
|
|
|
|
|
struct cached_block {
|
|
cached_block *next; // next in hash
|
|
cached_block *transaction_next;
|
|
block_link previous_transaction_link;
|
|
cached_block *chunk_next;
|
|
block_chunk *chunk;
|
|
off_t block_number;
|
|
void *data;
|
|
void *original;
|
|
#ifdef DEBUG_CHANGED
|
|
void *compare;
|
|
#endif
|
|
int32 ref_count;
|
|
int32 lock;
|
|
bool busy : 1;
|
|
bool is_writing : 1;
|
|
bool is_dirty : 1;
|
|
bool unmapped : 1;
|
|
cache_transaction *transaction;
|
|
cache_transaction *previous_transaction;
|
|
|
|
static int Compare(void *_cacheEntry, const void *_block);
|
|
static uint32 Hash(void *_cacheEntry, const void *_block, uint32 range);
|
|
};
|
|
|
|
typedef DoublyLinkedList<cached_block,
|
|
DoublyLinkedListMemberGetLink<cached_block,
|
|
&cached_block::previous_transaction_link> > block_list;
|
|
|
|
struct block_chunk {
|
|
cached_block *blocks;
|
|
bool mapped;
|
|
uint16 used_mask; // min chunk size is 4096 bytes; min block size is 256 bytes
|
|
};
|
|
|
|
struct block_range {
|
|
block_range *next; // next in hash
|
|
block_range *free_next;
|
|
addr_t base;
|
|
uint32 used_mask;
|
|
vm_page *pages[kNumBlockRangePages];
|
|
block_chunk chunks[0];
|
|
|
|
static status_t NewBlockRange(block_cache *cache, block_range **_range);
|
|
|
|
status_t Allocate(block_cache *cache, cached_block *block);
|
|
void Free(block_cache *cache, cached_block *block);
|
|
|
|
void *Allocate(block_cache *cache, block_chunk **_chunk = NULL);
|
|
void Free(block_cache *cache, void *address);
|
|
|
|
uint32 BlockIndex(block_cache *cache, void *address);
|
|
uint32 ChunkIndex(block_cache *cache, void *address);
|
|
block_chunk *Chunk(block_cache *cache, void *address);
|
|
|
|
static int Compare(void *_blockRange, const void *_address);
|
|
static uint32 Hash(void *_blockRange, const void *_address, uint32 range);
|
|
|
|
//bool HasFreeBlocks() const { return (1L << num_chunks) - 1 != used_mask; }
|
|
};
|
|
|
|
struct block_cache {
|
|
hash_table *hash;
|
|
benaphore lock;
|
|
int fd;
|
|
off_t max_blocks;
|
|
size_t block_size;
|
|
int32 next_transaction_id;
|
|
cache_transaction *last_transaction;
|
|
hash_table *transaction_hash;
|
|
|
|
hash_table *ranges_hash;
|
|
block_range *free_ranges;
|
|
uint32 chunks_per_range;
|
|
size_t chunk_size;
|
|
uint32 range_mask;
|
|
uint32 chunk_mask;
|
|
block_list unmapped_blocks;
|
|
|
|
block_cache(int fd, off_t numBlocks, size_t blockSize);
|
|
~block_cache();
|
|
|
|
status_t InitCheck();
|
|
|
|
block_range *GetFreeRange();
|
|
block_range *GetRange(void *address);
|
|
void FreeBlock(cached_block *block);
|
|
cached_block *NewBlock(off_t blockNumber);
|
|
void Free(void *address);
|
|
void *Allocate();
|
|
};
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
status_t init_block_allocator();
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* BLOCK_CACHE_PRIVATE_H */
|