00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "lib/safeclib.h"
00023
00024 #include "backend/file.h"
00025 #include "backend/filehandlecache.h"
00026
00027 NOBUG_DEFINE_FLAG_PARENT (filehandlecache, file_all);
00028
00029
00030
00031 LUMIERA_ERROR_DEFINE (FILEHANDLECACHE_NOHANDLE, "No filehandle available");
00032
00033
00034 LumieraFilehandlecache lumiera_fhcache = NULL;
00035
00036
00037 void
00038 lumiera_filehandlecache_new (int max_entries)
00039 {
00040 REQUIRE (!lumiera_fhcache, "Filehandlecache already initialized");
00041
00042 NOBUG_INIT_FLAG (filehandlecache);
00043 lumiera_fhcache = lumiera_malloc (sizeof (lumiera_filehandlecache));
00044 lumiera_mrucache_init (&lumiera_fhcache->cache, lumiera_filehandle_destroy_node);
00045 lumiera_fhcache->available = max_entries;
00046 lumiera_fhcache->checked_out = 0;
00047 lumiera_mutex_init (&lumiera_fhcache->lock, "filehandlecache", &NOBUG_FLAG (filehandlecache));
00048 }
00049
00050
00051 void
00052 lumiera_filehandlecache_delete (void)
00053 {
00054 if (lumiera_fhcache)
00055 {
00056 REQUIRE (!lumiera_fhcache->checked_out, "Filehandles in use at shutdown");
00057 lumiera_mrucache_destroy (&lumiera_fhcache->cache);
00058 lumiera_mutex_destroy (&lumiera_fhcache->lock, &NOBUG_FLAG (filehandlecache));
00059 lumiera_free (lumiera_fhcache);
00060 lumiera_fhcache = NULL;
00061 }
00062 }
00063
00064
00065 LumieraFilehandle
00066 lumiera_filehandlecache_handle_acquire (LumieraFilehandlecache self, LumieraFiledescriptor desc)
00067 {
00068 TRACE (filehandlecache);
00069 LumieraFilehandle ret = NULL;
00070
00071 LUMIERA_MUTEX_SECTION (filehandlecache, &self->lock)
00072 {
00073 if (self->available <= 0 && self->cache.cached)
00074 {
00075
00076 ret = lumiera_mrucache_pop (&self->cache);
00077 ret = lumiera_filehandle_init (lumiera_mrucache_pop (&self->cache), desc);
00078 if (self->available < 0)
00079
00080 self->available -= self->available + lumiera_mrucache_age (&self->cache, -self->available);
00081 }
00082 else
00083 {
00084
00085 NOTICE (filehandlecache, "overallocating filehandle");
00086 ret = lumiera_filehandle_new (desc);
00087 if (!ret)
00088 LUMIERA_ERROR_SET (filehandlecache, FILEHANDLECACHE_NOHANDLE);
00089 else
00090 --self->available;
00091 }
00092 desc->handle = ret;
00093 ++self->checked_out;
00094 }
00095 return ret;
00096 }
00097
00098
00099 LumieraFilehandle
00100 lumiera_filehandlecache_checkout (LumieraFilehandlecache self, LumieraFilehandle handle)
00101 {
00102 REQUIRE (self);
00103 REQUIRE (handle);
00104
00105 if (!handle->use_cnt)
00106 {
00107
00108 LUMIERA_MUTEX_SECTION (filehandlecache, &self->lock)
00109 {
00110 lumiera_mrucache_checkout (&self->cache, &handle->cachenode);
00111 }
00112 }
00113 ++handle->use_cnt;
00114 ++self->checked_out;
00115
00116 return handle;
00117 }
00118
00119
00120 void
00121 lumiera_filehandlecache_checkin (LumieraFilehandlecache self, LumieraFilehandle handle)
00122 {
00123 REQUIRE (self);
00124 REQUIRE (handle);
00125 REQUIRE (handle->use_cnt);
00126
00127
00128 if (!--handle->use_cnt)
00129 {
00130
00131 LUMIERA_MUTEX_SECTION (filehandlecache, &self->lock)
00132 {
00133 --self->checked_out;
00134 lumiera_mrucache_checkin (&self->cache, &handle->cachenode);
00135 }
00136 }
00137 }
00138