00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef __HARRAY_H__
00012 #define __HARRAY_H__
00013
00014 #include "fastdb.h"
00015
00016 const size_t dbHArrayPageSize = dbPageSize / sizeof(oid_t);
00017
00018 #ifdef HAS_TEMPLATE_FRIENDS
00019 template<class T>
00020 class dbHArray : public dbAnyReference {
00021 public:
00022 enum {
00023 leafPageSize = dbPageSize / sizeof(T),
00024 maxArraySize = dbHArrayPageSize*dbHArrayPageSize*leafPageSize
00025 };
00026
00027 void create(dbDatabase* db) {
00028 db->beginTransaction(dbDatabase::dbExclusiveLock);
00029 oid = db->allocateObject(dbHArrayPageMarker);
00030 memset(db->get(oid), 0, dbPageSize);
00031 }
00032
00033 T get(size_t i, dbDatabase* db) const {
00034 assert (oid != 0 && i < maxArraySize);
00035 db->beginTransaction(dbDatabase::dbSharedLock);
00036 oid_t* page = (oid_t*)db->get(oid);
00037 oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
00038 if (pageOid == 0) {
00039 return 0;
00040 }
00041 page = (oid_t*)db->get(pageOid);
00042 pageOid = page[i / leafPageSize % dbHArrayPageSize];
00043 if (pageOid == 0) {
00044 return 0;
00045 }
00046 T* leaf = (T*)db->get(pageOid);
00047 return leaf[i % leafPageSize];
00048 }
00049
00050 T& set(size_t i, dbDatabase* db) {
00051 assert (oid != 0 && i < maxArraySize);
00052 db->beginTransaction(dbDatabase::dbExclusiveLock);
00053 oid_t* page = (oid_t*)db->get(oid);
00054 oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
00055 if (pageOid == 0) {
00056 pageOid = db->allocateObject(dbHArrayPageMarker);
00057 page = (oid_t*)db->put(oid);
00058 page[i / (dbHArrayPageSize*leafPageSize)] = pageOid;
00059 page = (oid_t*)db->get(pageOid);
00060 memset(page, 0, dbPageSize);
00061 } else {
00062 page = (oid_t*)db->get(pageOid);
00063 }
00064 oid_t leafPageOid = page[i / leafPageSize % dbHArrayPageSize];
00065 T* leaf;
00066 if (leafPageOid == 0) {
00067 leafPageOid = db->allocateObject(dbHArrayPageMarker);
00068 page = (oid_t*)db->put(pageOid);
00069 page[i / leafPageSize % dbHArrayPageSize] = leafPageOid;
00070 leaf = (T*)db->get(leafPageOid);
00071 memset(leaf, 0, dbPageSize);
00072 } else {
00073 leaf = (T*)db->put(leafPageOid);
00074 }
00075 return leaf[i % leafPageSize];
00076 }
00077
00078 void set(size_t i, T value, dbDatabase* db) {
00079 set(i, db) = value;
00080 }
00081 };
00082 #else
00083 class dbAnyHArray : public dbAnyReference {
00084 public:
00085 void create(dbDatabase* db) {
00086 db->beginTransaction(dbDatabase::dbExclusiveLock);
00087 oid = db->allocateObject(dbHArrayPageMarker);
00088 memset(db->get(oid), 0, dbPageSize);
00089 }
00090
00091 byte* get(size_t i, dbDatabase* db, const size_t maxArraySize, const size_t leafPageSize) const {
00092 assert (oid != 0 && i < maxArraySize);
00093 db->beginTransaction(dbDatabase::dbSharedLock);
00094 oid_t* page = (oid_t*)db->get(oid);
00095 oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
00096 if (pageOid == 0) {
00097 return 0;
00098 }
00099 page = (oid_t*)db->get(pageOid);
00100 pageOid = page[i / leafPageSize % dbHArrayPageSize];
00101 if (pageOid == 0) {
00102 return 0;
00103 }
00104 return db->get(pageOid);
00105 }
00106
00107 byte* set(size_t i, dbDatabase* db, const size_t maxArraySize, const size_t leafPageSize) {
00108 assert (oid != 0 && i < maxArraySize);
00109 db->beginTransaction(dbDatabase::dbExclusiveLock);
00110 oid_t* page = (oid_t*)db->get(oid);
00111 oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
00112 if (pageOid == 0) {
00113 pageOid = db->allocateObject(dbHArrayPageMarker);
00114 page = (oid_t*)db->put(oid);
00115 page[i / (dbHArrayPageSize*leafPageSize)] = pageOid;
00116 page = (oid_t*)db->get(pageOid);
00117 memset(page, 0, dbPageSize);
00118 } else {
00119 page = (oid_t*)db->get(pageOid);
00120 }
00121 oid_t leafPageOid = page[i / leafPageSize % dbHArrayPageSize];
00122 byte* leaf;
00123 if (leafPageOid == 0) {
00124 leafPageOid = db->allocateObject(dbHArrayPageMarker);
00125 page = (oid_t*)db->put(pageOid);
00126 page[i / leafPageSize % dbHArrayPageSize] = leafPageOid;
00127 leaf = db->get(leafPageOid);
00128 memset(leaf, 0, dbPageSize);
00129 } else {
00130 leaf = db->put(leafPageOid);
00131 }
00132 return leaf;
00133 }
00134 };
00135
00136 template<class T>
00137 class dbHArray : public dbAnyHArray {
00138 public:
00139 enum {
00140 leafPageSize = dbPageSize / sizeof(T),
00141 maxArraySize = dbHArrayPageSize*dbHArrayPageSize*leafPageSize
00142 };
00143
00144 void set(size_t i, T value, dbDatabase* db) {
00145 set(i, db) = value;
00146 }
00147 T get(size_t i, dbDatabase* db) const {
00148 return ((T*)dbAnyHArray::get(i, db, maxArraySize, leafPageSize))[i % leafPageSize];
00149 }
00150 T& set(size_t i, dbDatabase* db) {
00151 return ((T*)dbAnyHArray::set(i, db, maxArraySize, leafPageSize))[i % leafPageSize];
00152 }
00153 };
00154 #endif
00155
00156
00157
00158
00159 class dbBitmap : public dbHArray<int4> {
00160 typedef dbHArray<int4> base;
00161 public:
00162 void create(dbDatabase* db) {
00163 base::create(db);
00164 }
00165
00166 bool get(size_t i, dbDatabase* db) const {
00167 return (base::get(i >> 5, db) & (1 << (i & 31))) != 0;
00168 }
00169
00170 void set(size_t i, bool value, dbDatabase* db) {
00171 int4& mask = base::set(i >> 5, db);
00172 if (value) {
00173 mask |= 1 << (i & 31);
00174 } else {
00175 mask &= ~(1 << (i & 31));
00176 }
00177 }
00178 };
00179
00180 #endif
00181