1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 ***************************************************************************/
27 FixedSizeAllocator
= 0,
28 VariableSizeAllocator
= 1,
32 //Used to store the meta data information about the variable size data
36 InUse size_
; /**< size of the allocated node */
37 InUse isUsed_
; /**< bit to represent whether this node is under use */
43 * @brief Page Header Info
45 * Database is divided into equal size parts(PAGE_SIZE) called pages. Each page contains page header (PageInfo) to store information related to pages such as whether it is in use, next used page for chunk, etc
47 * If data size is more than PAGE_SIZE then contigous pages are merged and those pages wont have page header info(pageInfo) in them. Only the start page where that data is stored will have header information. This object is stored at the start of each page unless it is a merged page.
53 InUse isUsed_
; /**< specifies whether this page is in use */
54 InUse flags
; /**< stores hasFreeSpace and isDirty flags */
56 Page
*nextPageAfterMerge_
; /**<used only in case of merged pages */
58 Page
*nextPage_
; /**<points to the next page in the same chunk */
62 * @brief set page used flag
64 * @param offset size of chunk in case of fixed size. For size greater than PAGE_SIZE, it will be aligned by PAGE_SIZE. Default value zero
67 void setPageAsUsed(size_t offset
=0);
70 * @brief set page as unused
80 //Iterator for the data
81 //Data is stored in chunks and this class gives
86 size_t allocSize_
; // used if it is a fixed size allocator
89 //current iterating page
92 //Each page is divided into nodes of size allocSize_
93 //This gives the offset of the node in the page
98 //Total number of nodes in the page
99 //It is a constant value for this chunk
100 //and it is cached for performance
106 ChunkIterator() { pageSize
= PAGE_SIZE
; allocSize_
=0; iterPage_
= NULL
; nodeOffset_
=0;
107 chunkID_
= -1; noOfNodes_
=0; }
108 int isLargeSize() { if (noOfNodes_
== 0) return true; else return false; }
110 void* nextElementIntMatch(int value
, int offset
);
111 inline void* nextElementInt() {
113 pageSize
= PAGE_SIZE
;
114 data
= ((char*)iterPage_
) + sizeof(PageInfo
);
115 if ((*(InUse
*)data
) == 1) return data
+ sizeof(InUse
);
118 if(0 == noOfNodes_
) return nextElement();
120 while(data
< iterPageEnd
)
122 if (*((InUse
*)data
)) {
123 return data
+ sizeof(InUse
);
128 while(iterPage_
->nextPage_
!= NULL
)
130 iterPage_
= (PageInfo
*)iterPage_
->nextPage_
;
131 data
= ((char*)iterPage_
) + sizeof(PageInfo
);
132 iterPageEnd
= ((char*)iterPage_
) + pageSize
;
133 while(data
< iterPageEnd
)
135 if (*((InUse
*)data
) == 0) {
136 data
= data
+ allocSize_
;
139 return data
+sizeof(InUse
);
148 class DatabaseManagerImpl
;
154 // used if it is a fixed size allocator
156 AllocType allocType_
;
158 //Current page where the last data allocation was made
161 //Page where data allocation was made for the first time
162 //This is the start of the data
163 //Iterator should start from this page
165 char chunkName
[CHUNK_NAME_LEN
];
170 //sets the size of the allocator
171 //for fixed size allocator
172 void setSize(size_t size
);
174 void setChunkNameForSystemDB(int id
);
175 void setChunkName(char const *name
){strcpy(chunkName
,name
);}
176 char *getChunkName(){return chunkName
;}
178 size_t getSize() { return allocSize_
; }
179 void setChunkID(unsigned int id
) { chunkID_
= id
; }
180 int getChunkID() { return chunkID_
; }
181 void setAllocType(AllocType type
) { allocType_
= type
; }
182 AllocType
getAllocType() { return allocType_
; }
183 Page
* getFirstPage(){ return firstPage_
; }
184 Page
* getCurrentPage(){ return curPage_
; }
185 void setFirstPage(void *fp
) { firstPage_
= fp
;}
186 void setCurPage(void *cp
) { curPage_
= cp
;}
187 PageInfo
* getPageInfo(Database
*db
, void *ptr
);
188 void* tryAllocate(Database
*db
, DbRetVal
*status
, int totalTries
=10);
189 void* allocate(Database
*db
, DbRetVal
*status
);
191 void* allocate(Database
*db
, size_t size
, DbRetVal
*status
);
193 void free(Database
*db
, void* ptr
);
194 ChunkIterator
getIterator();
196 void printMutexInfo() { chunkMutex_
.print(); }
198 long getTotalDataNodes();
199 long getVarTotalDataNodes();
201 int totalDirtyPages();
202 int compact(int procSlot
);
207 int initMutex(int i
=-1);
208 int getChunkMutex(int procSlot
);
209 int releaseChunkMutex(int procSlot
);
212 void* allocateFromFirstPage(Database
*db
, int noOfDataNodes
, DbRetVal
*status
);
213 void* allocateFromNewPage(Database
*db
, DbRetVal
*status
);
216 int createDataBucket(Page
*page
, size_t totalSize
, size_t needSize
, int pslot
);
217 int splitDataBucket(VarSizeInfo
*varInfo
, size_t needSize
, int pslot
, DbRetVal
*status
);
218 void* varSizeFirstFitAllocate(size_t size
, int pslot
, DbRetVal
*status
);
219 void freeForVarSizeAllocator(Database
*db
, void *ptr
, int pslot
);
220 void* allocateForVarLargeSize(PageInfo
*pInfo
, size_t size
, int offset
);
221 void* allocFromNewPageForVarSize(Database
*db
, size_t size
, int pslot
,
223 void* allocateFromCurPageForVarSize(size_t size
, int pslot
, DbRetVal
*status
);
225 void* allocateForLargeDataSize(Database
*db
);
226 void* allocateForLargeDataSize(Database
*db
, size_t size
);
227 void freeForLargeAllocator(void *ptr
, int pslot
);
229 void setPageDirty(Database
*db
, void *ptr
);
230 void setPageDirty(PageInfo
*pInfo
);
233 friend class Database
;
234 friend class DatabaseManagerImpl
;