1 //-< HARRAY.H >------------------------------------------------------*--------*
2 // FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *
3 // (Main Memory Database Management System)                          *   /\|  *
4 //                                                                   *  /  \  *
5 //                          Created:     25-Mar-2003  K.A. Knizhnik  * / [] \ *
6 //                          Last update: 25-Mar-2003  K.A. Knizhnik  * GARRET *
7 //-------------------------------------------------------------------*--------*
8 // Hierarchical array
9 //-------------------------------------------------------------------*--------*
10 
11 #ifndef __HARRAY_H__
12 #define __HARRAY_H__
13 
14 BEGIN_FASTDB_NAMESPACE
15 
16 #include "fastdb.h"
17 
18 const size_t dbHArrayPageSize = dbPageSize / sizeof(oid_t);
19 
20 #ifdef HAS_TEMPLATE_FRIENDS
21 template<class T>
22 class dbHArray : public dbAnyReference {
23   public:
24     enum {
25         leafPageSize = dbPageSize / sizeof(T),
26         maxArraySize = dbHArrayPageSize*dbHArrayPageSize*leafPageSize
27     };
28 
create(dbDatabase * db)29     void create(dbDatabase* db) {
30         db->beginTransaction(dbDatabase::dbExclusiveLock);
31         oid = db->allocateObject(dbPageObjectMarker);
32         memset(db->get(oid), 0, dbPageSize);
33     }
34 
get(size_t i,dbDatabase * db)35     T get(size_t i, dbDatabase* db) const {
36         assert (oid != 0 && i < maxArraySize);
37         db->beginTransaction(dbDatabase::dbSharedLock);
38         oid_t* page = (oid_t*)db->get(oid);
39         oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
40         if (pageOid == 0) {
41             return 0;
42         }
43         page = (oid_t*)db->get(pageOid);
44         pageOid = page[i / leafPageSize % dbHArrayPageSize];
45         if (pageOid == 0) {
46             return 0;
47         }
48         T* leaf = (T*)db->get(pageOid);
49         return leaf[i % leafPageSize];
50     }
51 
set(size_t i,dbDatabase * db)52     T& set(size_t i, dbDatabase* db) {
53         assert (oid != 0 && i < maxArraySize);
54         db->beginTransaction(dbDatabase::dbExclusiveLock);
55         oid_t* page = (oid_t*)db->get(oid);
56         oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
57         if (pageOid == 0) {
58             pageOid = db->allocateObject(dbPageObjectMarker);
59             page = (oid_t*)db->put(oid);
60             page[i / (dbHArrayPageSize*leafPageSize)] = pageOid;
61             page = (oid_t*)db->get(pageOid);
62             memset(page, 0, dbPageSize);
63         } else {
64             page = (oid_t*)db->get(pageOid);
65         }
66         oid_t leafPageOid = page[i / leafPageSize % dbHArrayPageSize];
67         T* leaf;
68         if (leafPageOid == 0) {
69             leafPageOid = db->allocateObject(dbPageObjectMarker);
70             page = (oid_t*)db->put(pageOid);
71             page[i / leafPageSize % dbHArrayPageSize] = leafPageOid;
72             leaf = (T*)db->get(leafPageOid);
73             memset(leaf, 0, dbPageSize);
74         } else {
75             leaf = (T*)db->put(leafPageOid);
76         }
77         return leaf[i % leafPageSize];
78     }
79 
set(size_t i,T value,dbDatabase * db)80     void set(size_t i, T value, dbDatabase* db) {
81         set(i, db) = value;
82     }
83 };
84 #else
85 class dbAnyHArray : public dbAnyReference {
86   public:
create(dbDatabase * db)87     void create(dbDatabase* db) {
88         db->beginTransaction(dbDatabase::dbExclusiveLock);
89         oid = db->allocateObject(dbPageObjectMarker);
90         memset(db->get(oid), 0, dbPageSize);
91     }
92 
get(size_t i,dbDatabase * db,const size_t maxArraySize,const size_t leafPageSize)93     byte* get(size_t i, dbDatabase* db, const size_t maxArraySize, const size_t leafPageSize) const {
94         assert (oid != 0 && i < maxArraySize);
95         db->beginTransaction(dbDatabase::dbSharedLock);
96         oid_t* page = (oid_t*)db->get(oid);
97         oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
98         if (pageOid == 0) {
99             return 0;
100         }
101         page = (oid_t*)db->get(pageOid);
102         pageOid = page[i / leafPageSize % dbHArrayPageSize];
103         if (pageOid == 0) {
104             return 0;
105         }
106         return db->get(pageOid);
107     }
108 
set(size_t i,dbDatabase * db,const size_t maxArraySize,const size_t leafPageSize)109     byte* set(size_t i, dbDatabase* db, const size_t maxArraySize, const size_t leafPageSize) {
110         assert (oid != 0 && i < maxArraySize);
111         db->beginTransaction(dbDatabase::dbExclusiveLock);
112         oid_t* page = (oid_t*)db->get(oid);
113         oid_t pageOid = page[i / (dbHArrayPageSize*leafPageSize)];
114         if (pageOid == 0) {
115             pageOid = db->allocateObject(dbPageObjectMarker);
116             page = (oid_t*)db->put(oid);
117             page[i / (dbHArrayPageSize*leafPageSize)] = pageOid;
118             page = (oid_t*)db->get(pageOid);
119             memset(page, 0, dbPageSize);
120         } else {
121             page = (oid_t*)db->get(pageOid);
122         }
123         oid_t leafPageOid = page[i / leafPageSize % dbHArrayPageSize];
124         byte* leaf;
125         if (leafPageOid == 0) {
126             leafPageOid = db->allocateObject(dbPageObjectMarker);
127             page = (oid_t*)db->put(pageOid);
128             page[i / leafPageSize % dbHArrayPageSize] = leafPageOid;
129             leaf = db->get(leafPageOid);
130             memset(leaf, 0, dbPageSize);
131         } else {
132             leaf = db->put(leafPageOid);
133         }
134         return leaf;
135     }
136 };
137 
138 template<class T>
139 class dbHArray : public dbAnyHArray {
140   public:
141     enum {
142         leafPageSize = dbPageSize / sizeof(T),
143         maxArraySize = dbHArrayPageSize*dbHArrayPageSize*leafPageSize
144     };
145 
set(size_t i,T value,dbDatabase * db)146     void set(size_t i, T value, dbDatabase* db) {
147         set(i, db) = value;
148     }
get(size_t i,dbDatabase * db)149     T get(size_t i, dbDatabase* db) const {
150         return ((T*)dbAnyHArray::get(i, db, maxArraySize, leafPageSize))[i % leafPageSize];
151     }
set(size_t i,dbDatabase * db)152     T& set(size_t i, dbDatabase* db) {
153         return ((T*)dbAnyHArray::set(i, db, maxArraySize, leafPageSize))[i % leafPageSize];
154     }
155 };
156 #endif
157 
158 
159 
160 
161 class dbBitmap : public dbHArray<int4> {
162     typedef dbHArray<int4> base;
163   public:
create(dbDatabase * db)164     void create(dbDatabase* db) {
165         base::create(db);
166     }
167 
get(size_t i,dbDatabase * db)168     bool get(size_t i, dbDatabase* db) const {
169         return (base::get(i >> 5, db) & (1 << (i & 31))) != 0;
170     }
171 
set(size_t i,bool value,dbDatabase * db)172     void set(size_t i, bool value, dbDatabase* db) {
173         int4& mask = base::set(i >> 5, db);
174         if (value) {
175             mask |= 1 << (i & 31);
176         } else {
177             mask &= ~(1 << (i & 31));
178         }
179     }
180 };
181 
182 END_FASTDB_NAMESPACE
183 
184 #endif
185 
186