summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl/rtl-obj-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libdl/rtl-obj-cache.c')
-rw-r--r--cpukit/libdl/rtl-obj-cache.c87
1 files changed, 70 insertions, 17 deletions
diff --git a/cpukit/libdl/rtl-obj-cache.c b/cpukit/libdl/rtl-obj-cache.c
index 9221765142..a4676cfa0d 100644
--- a/cpukit/libdl/rtl-obj-cache.c
+++ b/cpukit/libdl/rtl-obj-cache.c
@@ -19,12 +19,14 @@
#endif
#include <errno.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <rtems/rtl/rtl-allocator.h>
#include "rtl-obj-cache.h"
#include "rtl-error.h"
+#include "rtl-trace.h"
bool
rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size)
@@ -46,7 +48,10 @@ rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size)
void
rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache)
{
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+ printf ("rtl: cache: %2d: close\n", cache->fd);
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, cache->buffer);
+ cache->buffer = NULL;
cache->fd = -1;
cache->file_size = 0;
cache->level = 0;
@@ -55,8 +60,11 @@ rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache)
void
rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache)
{
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+ printf ("rtl: cache: %2d: flush\n", cache->fd);
cache->fd = -1;
cache->file_size = 0;
+ cache->offset = 0;
cache->level = 0;
}
@@ -69,6 +77,13 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
{
struct stat sb;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+ printf ("rtl: cache: %2d: fd=%d offset=%d length=%d area=[%d,%d] cache=[%d,%d] size=%d\n",
+ fd, cache->fd, (int) offset, (int) *length,
+ (int) offset, (int) offset + *length,
+ (int) cache->offset, (int) cache->offset + cache->level,
+ (int) cache->file_size);
+
if (*length > cache->size)
{
rtems_rtl_set_error (EINVAL, "read size larger than cache size");
@@ -84,8 +99,15 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
return false;
}
+ /*
+ * We sometimes are asked to read strings of a length we do not know.
+ */
if ((offset + *length) > cache->file_size)
+ {
*length = cache->file_size - offset;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+ printf ("rtl: cache: %2d: truncate length=%d\n", fd, (int) *length);
+ }
}
while (true)
@@ -99,12 +121,21 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
if (fd == cache->fd)
{
/*
+ * Do not read past the end of the file.
+ */
+ if ((offset + buffer_read) > cache->file_size)
+ buffer_read = cache->file_size - offset;
+
+ /*
* Is any part of the data in the cache ?
*/
if ((offset >= cache->offset) &&
(offset < (cache->offset + cache->level)))
{
+ size_t size;
+
buffer_offset = offset - cache->offset;
+ size = cache->level - buffer_offset;
/*
* Return the location of the data in the cache.
@@ -114,24 +145,38 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
/*
* Is all the data in the cache or just a part ?
*/
- if (*length <= (cache->level - buffer_offset))
- {
+ if (*length <= size)
return true;
- }
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+ printf ("rtl: cache: %2d: copy-down: buffer_offset=%d size=%d level=%d\n",
+ fd, (int) buffer_offset, (int) size, (int) cache->level);
/*
- * Copy down the data in the buffer and then fill the remaining
- * space with as much data we are able to read.
+ * Copy down the data in the buffer and then fill the remaining space
+ * with as much data we are able to read.
*/
- memmove (cache->buffer,
- cache->buffer + buffer_offset,
- cache->size - buffer_offset);
+ memmove (cache->buffer, cache->buffer + buffer_offset, size);
+
+ cache->offset = offset;
+ cache->level = size;
+ buffer_read = cache->size - cache->level;
+ buffer_offset = size;
- buffer_read = buffer_offset;
- buffer_offset = cache->size - buffer_offset;
+ /*
+ * Do not read past the end of the file.
+ */
+ if ((offset + buffer_offset + buffer_read) > cache->file_size)
+ buffer_read = cache->file_size - (offset + buffer_offset);
}
}
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+ printf ("rtl: cache: %2d: seek: offset=%d buffer_offset=%d read=%d cache=[%d,%d] dist=%d\n",
+ fd, (int) offset + buffer_offset, (int) buffer_offset, (int) buffer_read,
+ (int) offset, (int) offset + buffer_read,
+ (int) (cache->file_size - offset));
+
if (lseek (fd, offset + buffer_offset, SEEK_SET) < 0)
{
rtems_rtl_set_error (errno, "file seek failed");
@@ -143,7 +188,9 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
* returned and if data has been read check if the amount is what we
* want. If not it is an error. A POSIX read can read data in fragments.
*/
- cache->level = buffer_read;
+
+ cache->level = buffer_offset + buffer_read;
+
while (buffer_read)
{
int r = read (fd, cache->buffer + buffer_offset, buffer_read);
@@ -154,6 +201,8 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
}
if ((r == 0) && buffer_read)
{
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_CACHE))
+ printf ("rtl: cache: %2d: read: past end by=%d\n", fd, (int) buffer_read);
cache->level = cache->level - buffer_read;
buffer_read = 0;
}
@@ -164,16 +213,20 @@ rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
}
}
- cache->fd = fd;
cache->offset = offset;
- if (fstat (cache->fd, &sb) < 0)
+ if (cache->fd != fd)
{
- rtems_rtl_set_error (errno, "file stat failed");
- return false;
- }
+ cache->fd = fd;
+
+ if (fstat (cache->fd, &sb) < 0)
+ {
+ rtems_rtl_set_error (errno, "file stat failed");
+ return false;
+ }
- cache->file_size = sb.st_size;
+ cache->file_size = sb.st_size;
+ }
}
return false;