* 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:
Vendored
+59
-38
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user