00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "eyedb_p.h"
00026
00027 namespace eyedb {
00028
00029 static unsigned int COEF = 50;
00030 static unsigned int RESCALE_COEF = 2;
00031 static unsigned int MAX_LINKS_CNT = 16384;
00032
00033 struct ObjCacheLink {
00034 Oid oid;
00035 void *o;
00036 unsigned int tstamp;
00037 unsigned int refcnt;
00038 ObjCacheLink *next;
00039 ObjCacheLink(const Oid &, void *, unsigned int);
00040 };
00041
00042 ObjCacheLink::ObjCacheLink(const Oid &toid, void *to, unsigned int ts)
00043 {
00044 oid = toid;
00045 o = to;
00046 tstamp = ts;
00047 refcnt = 1;
00048 }
00049
00050 ObjCache::ObjCache(unsigned int n)
00051 {
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 key = n - 1;
00063
00064 links_cnt = key + 1;
00065 links = (ObjCacheLink **)malloc(sizeof(ObjCacheLink *) * links_cnt);
00066 memset(links, 0, sizeof(ObjCacheLink *) * links_cnt);
00067 tstamp = 0;
00068 obj_cnt = 0;
00069 rescaling = false;
00070 }
00071
00072 unsigned int ObjCache::getIndex(const Oid &oid)
00073 {
00074 return (oid.getNX() & key);
00075 }
00076
00077 void ObjCache::rescale() {
00078 if (rescaling)
00079 return;
00080
00081 char *p = (char *)sbrk(0);
00082
00083 rescaling = true;
00084 ObjCache *obj_cache = new ObjCache(links_cnt * RESCALE_COEF);
00085
00086 for (unsigned int n = 0; n < links_cnt; n++) {
00087 ObjCacheLink *link = links[n];
00088
00089 while (link) {
00090 ObjCacheLink *next = link->next;
00091 obj_cache->insertObject(link->oid, link->o, link->refcnt);
00092 delete link;
00093 link = next;
00094 }
00095
00096 links[n] = 0;
00097 }
00098
00099 free(links);
00100
00101 key = obj_cache->key;
00102 obj_cache->key = 0;
00103
00104 links_cnt = obj_cache->links_cnt;
00105 obj_cache->links_cnt = 0;
00106
00107 obj_cnt = obj_cache->obj_cnt;
00108 obj_cache->obj_cnt = 0;
00109
00110 links = obj_cache->links;
00111 obj_cache->links = 0;
00112
00113 tstamp = obj_cache->tstamp;
00114 obj_cache->tstamp = 0;
00115
00116 delete obj_cache;
00117 rescaling = false;
00118 }
00119
00120 Bool ObjCache::insertObject(const Oid &oid, void *o, unsigned int _refcnt)
00121 {
00122
00123 if (!_refcnt) {
00124 if (getObject(oid))
00125 return False;
00126 }
00127
00128 if (links_cnt < MAX_LINKS_CNT && obj_cnt > COEF * links_cnt)
00129 rescale();
00130
00131 unsigned int index = getIndex(oid);
00132 ObjCacheLink *ol = new ObjCacheLink(oid, o, ++tstamp);
00133 if (_refcnt)
00134 ol->refcnt = _refcnt;
00135
00136 ObjCacheLink *link = links[index];
00137
00138 ol->next = link;
00139 links[index] = ol;
00140
00141 obj_cnt++;
00142 return True;
00143 }
00144
00145 Bool ObjCache::deleteObject(const Oid &oid, bool force)
00146 {
00147 ObjCacheLink *prev = 0;
00148 ObjCacheLink *link = links[getIndex(oid)];
00149
00150
00151 while (link) {
00152 if (oid.compare(link->oid)) {
00153 assert(link->refcnt > 0);
00154 if (!force) {
00155 if (--link->refcnt > 0) {
00156
00157 return True;
00158 }
00159 }
00160
00161 if (prev)
00162 prev->next = link->next;
00163 else
00164 links[getIndex(oid)] = link->next;
00165
00166 delete link;
00167 obj_cnt--;
00168
00169 return True;
00170 }
00171 prev = link;
00172 link = link->next;
00173 }
00174
00175 return False;
00176 }
00177
00178 void *ObjCache::getObject(const Oid &oid, bool incr)
00179 {
00180 ObjCacheLink *link = links[getIndex(oid)];
00181
00182
00183 while (link) {
00184 if (oid.compare(link->oid)) {
00185
00186 if (incr)
00187 link->refcnt++;
00188 return link->o;
00189 }
00190 link = link->next;
00191 }
00192
00193
00194 return 0;
00195 }
00196
00197 ObjectList *
00198 ObjCache::getObjects()
00199 {
00200 ObjectList *obj_list = new ObjectList();
00201 for (unsigned int n = 0; n < links_cnt; n++) {
00202 ObjCacheLink *link = links[n];
00203 while (link) {
00204 obj_list->insertObjectLast((Object *)link->o);
00205 link = link->next;
00206 }
00207 }
00208
00209 return obj_list;
00210 }
00211
00212 void ObjCache::empty(void)
00213 {
00214 for (unsigned int n = 0; n < links_cnt; n++) {
00215 ObjCacheLink *link = links[n];
00216
00217 while (link) {
00218 ObjCacheLink *next = link->next;
00219 delete link;
00220 link = next;
00221 }
00222
00223 links[n] = 0;
00224 }
00225
00226 obj_cnt = 0;
00227 tstamp = 0;
00228 }
00229
00230 ObjCache::~ObjCache()
00231 {
00232 empty();
00233 free(links);
00234 }
00235 }