* Implemented binary search for the disk offsets.

* Moved the file_extent array into its own structure (unnamed union problem
  with GCC4), and added max_count field (currently unused).
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26259 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-07-05 13:38:38 +00:00
parent dde0ba6223
commit 609865fd21
+59 -38
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2007, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2004-2008, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -39,18 +39,25 @@ struct file_extent {
file_io_vec disk;
};
struct file_extent_array {
file_extent *array;
size_t max_count;
};
struct file_map {
file_map(off_t size);
~file_map();
file_extent *operator[](uint32 index);
file_extent *ExtentAt(uint32 index);
file_extent *FindExtent(off_t offset, uint32 *_index);
status_t Add(file_io_vec *vecs, size_t vecCount, off_t &lastOffset);
void Invalidate(off_t offset, off_t size);
void Free();
union {
file_extent direct[CACHED_FILE_EXTENTS];
file_extent *array;
file_extent_array indirect;
};
size_t count;
struct vnode *vnode;
@@ -60,7 +67,7 @@ struct file_map {
file_map::file_map(off_t _size)
{
array = NULL;
indirect.array = NULL;
count = 0;
size = _size;
}
@@ -86,16 +93,45 @@ file_map::ExtentAt(uint32 index)
return NULL;
if (count > CACHED_FILE_EXTENTS)
return &array[index];
return &indirect.array[index];
return &direct[index];
}
file_extent *
file_map::FindExtent(off_t offset, uint32 *_index)
{
int32 left = 0;
int32 right = count - 1;
while (left <= right) {
int32 index = (left + right) / 2;
file_extent *extent = ExtentAt(index);
if (extent->offset > offset) {
// search in left part
right = index - 1;
} else if (extent->offset + extent->disk.length <= offset) {
// search in right part
left = index + 1;
} else {
// found extent
if (_index)
*_index = index;
return extent;
}
}
return NULL;
}
status_t
file_map::Add(file_io_vec *vecs, size_t vecCount, off_t &lastOffset)
{
TRACE(("file_map::Add(vecCount = %ld)\n", vecCount));
TRACE(("file_map@%p::Add(vecCount = %ld)\n", this, vecCount));
off_t offset = 0;
@@ -105,12 +141,12 @@ file_map::Add(file_io_vec *vecs, size_t vecCount, off_t &lastOffset)
// TODO: once we can invalidate only parts of the file map,
// we might need to copy the previously cached file extends
// from the direct range
file_extent *newMap = (file_extent *)realloc(array,
file_extent *newMap = (file_extent *)realloc(indirect.array,
(count + vecCount) * sizeof(file_extent));
if (newMap == NULL)
return B_NO_MEMORY;
array = newMap;
indirect.array = newMap;
if (count != 0) {
file_extent *extent = ExtentAt(count - 1);
@@ -131,7 +167,7 @@ file_map::Add(file_io_vec *vecs, size_t vecCount, off_t &lastOffset)
}
#ifdef TRACE_FILE_MAP
for (uint32 i = 0; i < count; i++) {
for (uint32 i = start; i < count; i++) {
file_extent *extent = ExtentAt(i);
dprintf("[%ld] extend offset %Ld, disk offset %Ld, length %Ld\n",
i, extent->offset, extent->disk.offset, extent->disk.length);
@@ -144,36 +180,21 @@ file_map::Add(file_io_vec *vecs, size_t vecCount, off_t &lastOffset)
void
file_map::Free()
file_map::Invalidate(off_t offset, off_t size)
{
if (count > CACHED_FILE_EXTENTS)
free(array);
array = NULL;
count = 0;
// TODO: honour offset/size parameters
Free();
}
// #pragma mark -
static file_extent *
find_file_extent(file_map &map, off_t offset, uint32 *_index)
void
file_map::Free()
{
// TODO: do binary search
if (count > CACHED_FILE_EXTENTS)
free(indirect.array);
for (uint32 index = 0; index < map.count; index++) {
file_extent *extent = map[index];
if (extent->offset <= offset
&& extent->offset + extent->disk.length > offset) {
if (_index)
*_index = index;
return extent;
}
}
return NULL;
indirect.array = NULL;
count = 0;
}
@@ -219,10 +240,11 @@ file_map_set_size(void *_map, off_t size)
if (_map == NULL)
return;
// TODO: honour offset/size parameters
file_map *map = (file_map *)_map;
// if (size < map->size)
map->Free();
if (size < map->size)
map->Invalidate(size, map->size - size);
map->size = size;
}
@@ -233,9 +255,8 @@ file_map_invalidate(void *_map, off_t offset, off_t size)
if (_map == NULL)
return;
// TODO: honour offset/size parameters
file_map *map = (file_map *)_map;
map->Free();
map->Invalidate(offset, size);
}
@@ -298,7 +319,7 @@ file_map_translate(void *_map, off_t offset, size_t size, file_io_vec *vecs,
// translate it for the requested access.
uint32 index;
file_extent *fileExtent = find_file_extent(map, offset, &index);
file_extent *fileExtent = map.FindExtent(offset, &index);
if (fileExtent == NULL) {
// access outside file bounds? But that's not our problem
*_count = 0;