* 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. * Distributed under the terms of the MIT License.
*/ */
@@ -39,18 +39,25 @@ struct file_extent {
file_io_vec disk; file_io_vec disk;
}; };
struct file_extent_array {
file_extent *array;
size_t max_count;
};
struct file_map { struct file_map {
file_map(off_t size); file_map(off_t size);
~file_map(); ~file_map();
file_extent *operator[](uint32 index); file_extent *operator[](uint32 index);
file_extent *ExtentAt(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); status_t Add(file_io_vec *vecs, size_t vecCount, off_t &lastOffset);
void Invalidate(off_t offset, off_t size);
void Free(); void Free();
union { union {
file_extent direct[CACHED_FILE_EXTENTS]; file_extent direct[CACHED_FILE_EXTENTS];
file_extent *array; file_extent_array indirect;
}; };
size_t count; size_t count;
struct vnode *vnode; struct vnode *vnode;
@@ -60,7 +67,7 @@ struct file_map {
file_map::file_map(off_t _size) file_map::file_map(off_t _size)
{ {
array = NULL; indirect.array = NULL;
count = 0; count = 0;
size = _size; size = _size;
} }
@@ -86,16 +93,45 @@ file_map::ExtentAt(uint32 index)
return NULL; return NULL;
if (count > CACHED_FILE_EXTENTS) if (count > CACHED_FILE_EXTENTS)
return &array[index]; return &indirect.array[index];
return &direct[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 status_t
file_map::Add(file_io_vec *vecs, size_t vecCount, off_t &lastOffset) 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; 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, // TODO: once we can invalidate only parts of the file map,
// we might need to copy the previously cached file extends // we might need to copy the previously cached file extends
// from the direct range // from the direct range
file_extent *newMap = (file_extent *)realloc(array, file_extent *newMap = (file_extent *)realloc(indirect.array,
(count + vecCount) * sizeof(file_extent)); (count + vecCount) * sizeof(file_extent));
if (newMap == NULL) if (newMap == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
array = newMap; indirect.array = newMap;
if (count != 0) { if (count != 0) {
file_extent *extent = ExtentAt(count - 1); 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 #ifdef TRACE_FILE_MAP
for (uint32 i = 0; i < count; i++) { for (uint32 i = start; i < count; i++) {
file_extent *extent = ExtentAt(i); file_extent *extent = ExtentAt(i);
dprintf("[%ld] extend offset %Ld, disk offset %Ld, length %Ld\n", dprintf("[%ld] extend offset %Ld, disk offset %Ld, length %Ld\n",
i, extent->offset, extent->disk.offset, extent->disk.length); 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 void
file_map::Free() file_map::Invalidate(off_t offset, off_t size)
{ {
if (count > CACHED_FILE_EXTENTS) // TODO: honour offset/size parameters
free(array); Free();
array = NULL;
count = 0;
} }
// #pragma mark - void
file_map::Free()
static file_extent *
find_file_extent(file_map &map, off_t offset, uint32 *_index)
{ {
// TODO: do binary search if (count > CACHED_FILE_EXTENTS)
free(indirect.array);
for (uint32 index = 0; index < map.count; index++) { indirect.array = NULL;
file_extent *extent = map[index]; count = 0;
if (extent->offset <= offset
&& extent->offset + extent->disk.length > offset) {
if (_index)
*_index = index;
return extent;
}
}
return NULL;
} }
@@ -219,10 +240,11 @@ file_map_set_size(void *_map, off_t size)
if (_map == NULL) if (_map == NULL)
return; return;
// TODO: honour offset/size parameters
file_map *map = (file_map *)_map; 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; map->size = size;
} }
@@ -233,9 +255,8 @@ file_map_invalidate(void *_map, off_t offset, off_t size)
if (_map == NULL) if (_map == NULL)
return; return;
// TODO: honour offset/size parameters
file_map *map = (file_map *)_map; 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. // translate it for the requested access.
uint32 index; uint32 index;
file_extent *fileExtent = find_file_extent(map, offset, &index); file_extent *fileExtent = map.FindExtent(offset, &index);
if (fileExtent == NULL) { if (fileExtent == NULL) {
// access outside file bounds? But that's not our problem // access outside file bounds? But that's not our problem
*_count = 0; *_count = 0;