1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // CegoBufferPage.cc
4 // -----------------
5 // Cego BufferPage implementation module
6 //
7 // Design and Implementation by Bjoern Lemke
8 //
9 // (C)opyright 2000-2019 Bjoern Lemke
10 //
11 // IMPLEMENTATION MODULE
12 //
13 // Class: CegoBufferPage
14 //
15 // Description: Database page container class
16 //
17 // Status: CLEAN
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20 
21 // LFC INCLUDES
22 #include <lfcbase/Exception.h>
23 
24 // CEGO INCLUDES
25 #include "CegoDefs.h"
26 #include "CegoBufferPage.h"
27 
28 // POSIX INCLUDES
29 #include <string.h>
30 #include <stdlib.h>
31 
32 #define ALLOCDELTA sizeof(int)
33 
34 // to ensure memory alignment, pagehead size is need to be calculated in the
35 // following way ( at least required for SPARC )
36 #define PAGEHEAD (((sizeof(PageHead)-1)/BUPMNG_ALIGNMENT)+1)*BUPMNG_ALIGNMENT
37 
CegoBufferPage()38 CegoBufferPage::CegoBufferPage()
39 {
40     _isFixed = false;
41     _pageId = 0;
42 }
43 
CegoBufferPage(const CegoBufferPage & bp)44 CegoBufferPage::CegoBufferPage(const CegoBufferPage &bp)
45 {
46     _pageId = bp._pageId;
47 
48     _pageSize = bp._pageSize;
49     _pagePtr = bp._pagePtr;
50 
51     _ePtr = bp._ePtr;
52     _blobPtr = bp._blobPtr;
53 
54     _entryLen = bp._entryLen;
55     _entryPos = bp._entryPos;
56 
57     _pageHead = bp._pageHead;
58     _isFixed = bp._isFixed;
59 }
60 
CegoBufferPage(void * pagePtr,int pageSize)61 CegoBufferPage::CegoBufferPage(void* pagePtr, int pageSize)
62 {
63     _pageSize = pageSize;
64     _pagePtr = (char*)pagePtr;
65     _pageHead = (PageHead*)pagePtr;
66     _isFixed = false;
67 }
68 
~CegoBufferPage()69 CegoBufferPage::~CegoBufferPage()
70 {
71 }
72 
setFixed(bool isFixed)73 void CegoBufferPage::setFixed(bool isFixed)
74 {
75     _isFixed = isFixed;
76 }
77 
isFixed() const78 bool CegoBufferPage::isFixed() const
79 {
80     return _isFixed;
81 }
82 
initPage(CegoBufferPage::PageType t)83 void CegoBufferPage::initPage(CegoBufferPage::PageType t)
84 {
85     PageHead ph;
86 
87     ph.pageType = t;
88     ph.nextPageId = 0;
89 
90     memcpy(_pagePtr, &ph, PAGEHEAD);
91 
92     if ( t == TABLE || t == TUPLE )
93     {
94 	int* ePtr = (int*)((long long)_pagePtr + PAGEHEAD);
95 	*ePtr = 0;
96 
97 	int* freePtr = (int*)((long long)_pagePtr + (long)_pageSize);
98 	freePtr--;
99 	*freePtr=0;
100     }
101 }
102 
setPagePtr(char * ptr)103 void CegoBufferPage::setPagePtr(char* ptr)
104 {
105     _pagePtr = ptr;
106 }
107 
setPageHead(PageHead * ptr)108 void CegoBufferPage::setPageHead(PageHead* ptr)
109 {
110     _pageHead = ptr;
111 }
112 
setPageSize(int pageSize)113 void CegoBufferPage::setPageSize(int pageSize)
114 {
115     _pageSize = pageSize;
116 }
117 
setPageId(PageIdType pageId)118 void CegoBufferPage::setPageId(PageIdType pageId)
119 {
120     _pageId = pageId;
121 }
122 
getPageId()123 PageIdType& CegoBufferPage::getPageId()
124 {
125     return _pageId;
126 }
127 
setNextPageId(PageIdType pageId)128 void CegoBufferPage::setNextPageId(PageIdType pageId)
129 {
130     _pageHead->nextPageId = pageId;
131 }
132 
getNextPageId() const133 PageIdType& CegoBufferPage::getNextPageId() const
134 {
135     return _pageHead->nextPageId;
136 }
137 
getNumEntries()138 int CegoBufferPage::getNumEntries()
139 {
140     int numEntries = 0;
141     if ( getFirstEntry() )
142     {
143 	numEntries++;
144 	while ( getNextEntry() )
145 	    numEntries++;
146     }
147     return numEntries;
148 }
149 
setType(CegoBufferPage::PageType t)150 void CegoBufferPage::setType(CegoBufferPage::PageType t)
151 {
152     _pageHead->pageType = t;
153 }
154 
getType() const155 CegoBufferPage::PageType& CegoBufferPage::getType() const
156 {
157     return _pageHead->pageType;
158 }
159 
newEntry(int size)160 void* CegoBufferPage::newEntry(int size)
161 {
162     if ( size % BUPMNG_ALIGNMENT )
163 	size = ( size / BUPMNG_ALIGNMENT + 1) * BUPMNG_ALIGNMENT;
164 
165     int* ePtr;
166 
167     int* freePtr = (int*)((long long)_pagePtr + (long)_pageSize);
168     freePtr--;
169 
170     while (*freePtr != 0 )
171     {
172 	ePtr = (int*)((long long)_pagePtr + *freePtr);
173 	if (*ePtr >=  size && *ePtr <= size + ALLOCDELTA)
174 	{
175 	    int* sPtr = freePtr;
176 
177 	    while (*(sPtr-1) != 0)
178 	    {
179 		sPtr--;
180 	    }
181 	    *freePtr = *sPtr;
182 	    *sPtr = 0;
183 
184 	    ePtr++;
185 	    return ePtr;
186 	}
187 	else if (*ePtr > size + ALLOCDELTA)
188 	{
189 	    int osize = *ePtr;
190 
191 	    *ePtr = size;
192 
193 	    char* tPtr = (char*)ePtr;
194 	    tPtr += size + sizeof(int);
195 
196 	    int* sPtr = (int*)tPtr;
197 	    *sPtr= osize - size - sizeof(int);
198 
199 	    *freePtr = (long long)sPtr - (long long)_pagePtr;
200 
201 	    ePtr++;
202 	    return ePtr;
203 
204 	}
205 
206 	freePtr--;
207     }
208 
209     // no appropriate entry found in freelist,
210     // allocating new space
211 
212     int* fPtr = (int*)((long long)_pagePtr + PAGEHEAD);
213 
214     // cout << "fptr is " << (int)fPtr << endl;
215 
216     while (*(int*)fPtr != 0 )
217     {
218 	fPtr = (int*)((long long)fPtr + *fPtr + sizeof(int));
219     }
220 
221     // check if enough memory in page
222 
223     if ((long long)fPtr + size >= (long long)_pagePtr + _pageSize - ( _pageSize * BUPMNG_MINFREERATIO ) / 100 )
224     {
225 	// not enough space on page
226 	return 0;
227     }
228 
229     *(int*)fPtr = size;
230     char *sPtr = (char*)fPtr;
231     sPtr = sPtr + size + sizeof(int);
232     int* nPtr = (int*)sPtr;
233     *nPtr = 0;
234 
235     fPtr++;
236 
237     return (fPtr);
238 }
239 
freeEntry(void * p)240 void CegoBufferPage::freeEntry(void* p)
241 {
242     int* freePtr = (int*)((long long)_pagePtr + (long)_pageSize);
243     freePtr--;
244 
245     int* setptr[2];
246 
247     setptr[0]=0;
248     setptr[1]=0;
249 
250     int i = 0;
251     int n;
252     int count=0;
253 
254     while ( *freePtr && count < ( _pageSize * BUPMNG_MINFREERATIO) / ( 100 * sizeof(int)))
255     {
256 	// cout << "*FreePtr=" << *freePtr << endl;
257 	// cout << "p pos " << ((int)p - (int)_pagePtr) << endl;
258 	// cout << "p size " << *((int*)p -1) << endl;
259 	// cout << "size of freePtr " << *(int*)(*freePtr + (int)_pagePtr) << endl;
260 
261 	if ( *freePtr == ((long long)p - (long long)_pagePtr) + *((int*)p - 1))
262 	{
263 	    // cout << "right free neighbour detected" << endl;
264 	    setptr[i]=freePtr;
265 	    i++;
266 	}
267 	else if (*freePtr + sizeof(int) + *(int*)(*freePtr + (long long)_pagePtr)  == ((long long)p - (long long)_pagePtr) - sizeof(int))
268 	{
269 	    // cout << "left free neighbour detected" << endl;
270 
271 	    setptr[i]=freePtr;
272 	    n=i;
273 	    i++;
274 	}
275 
276 	freePtr--;
277 	count++;
278     }
279 
280     if (count == ( _pageSize * BUPMNG_MINFREERATIO ) / ( 100 * sizeof(int)))
281     {
282 	throw Exception(EXLOC, "Minfree exceeded");
283     }
284     switch (i)
285     {
286     case 0:
287 
288 	*freePtr = (long long)p - (long long)_pagePtr - sizeof(int);
289 	freePtr--;
290 	*freePtr = 0;
291 	break;
292 
293     case 1:
294     {
295 	int newsize = *((int*)p -1) + *(int*)( *setptr[0] + (long long)_pagePtr) + sizeof(int);
296 
297 	// cout << "Setup newsize with " << newsize << endl;
298 
299 	if (*setptr[0] > (long long)p - (long long)_pagePtr)
300 	{
301 	    *setptr[0] = (long long)p - (long long)_pagePtr - sizeof(int);
302 	    *((int*)p - 1) = newsize;
303 	}
304 	else if (*setptr[0] < (long long)p - (long long)_pagePtr)
305 	{
306 	    *(int*)( *setptr[0] + (long long)_pagePtr) = newsize;
307 	}
308 
309 	break;
310     }
311     case 2:
312     {
313 	int newsize = *((int*)p -1) + *(int*)( *setptr[0] + (long long)_pagePtr) + *(int*)( *setptr[1] + (long long)_pagePtr) + 2 * sizeof(int);
314 
315 	// cout << "Setup newsize with " << newsize << endl;
316 
317 	int* newptr = setptr[n];
318 
319 	if (*setptr[0] > (long long)p)
320 	{
321 	    *setptr[0] = *newptr;
322 	    *(int*)( *setptr[0] + (long long)_pagePtr) = newsize;
323 	    freePtr++;
324 	    *setptr[1] = *freePtr;
325 	}
326 	else
327 	{
328 	    *setptr[1] = *newptr;
329 	    *(int*)( *setptr[1] + (long long)_pagePtr) = newsize;
330 	    freePtr++;
331 	    *setptr[0] = *freePtr;
332 	}
333 
334 	*freePtr = 0;
335 	break;
336     }
337     }
338 }
339 
getFirstEntry()340 void* CegoBufferPage::getFirstEntry()
341 {
342     _ePtr = (char*)((long long)_pagePtr + PAGEHEAD);
343 
344     // cout << "BufferPage First:  _ePtr is  " << (unsigned)_ePtr << endl;
345 
346     _entryPos = 0;
347     return getNextEntry();
348 }
349 
getNextEntry()350 void* CegoBufferPage::getNextEntry()
351 {
352     // cout << "BufferPage:  _ePtr is  " << (unsigned long long)_ePtr << endl;
353     // cout << "->  size is   " << *(int*)_ePtr << endl;
354     // cout << "->  delta to page end is  " << (unsigned long long)_ePtr - (unsigned long long)_pagePtr << endl;
355 
356     // cout << "Next entry .." << endl;
357 
358     while ( *(int*)_ePtr != 0 )
359     {
360 	// checking free list
361 
362 	int* freePtr = (int*)((long long)_pagePtr + (long long)_pageSize);
363 
364 	freePtr--;
365 
366 	bool isFreeEntry = false;
367 
368 	while ( *freePtr != 0 && ! isFreeEntry )
369 	{
370 	    if ( _ePtr == (char*)((long long)_pagePtr + *freePtr))
371 	    {
372 		isFreeEntry = true;
373 	    }
374 	    else
375 	    {
376 		freePtr--;
377 	    }
378 	}
379 
380 	if ( isFreeEntry )
381 	{
382 	    // skipping free entry
383 	    _entryPos = _entryPos + *((int*)_ePtr) + sizeof(int);
384 
385 	    _ePtr = _ePtr + *((int*)_ePtr) + sizeof(int);
386 	}
387 	else
388 	{
389 
390 	    _entryLen = *(int*)_ePtr;
391 
392 	    char* rPtr = _ePtr + sizeof(int);
393 
394 	    _entryPos = _ePtr - _pagePtr + sizeof(int);
395 
396 	    _ePtr = _ePtr + *((int*)_ePtr) + sizeof(int);
397 
398 	    return rPtr;
399     	}
400     }
401     return 0;
402 }
403 
getChunkEntry() const404 char* CegoBufferPage::getChunkEntry() const
405 {
406     return (char*)((long long)_pagePtr + PAGEHEAD);
407 }
408 
getPageSize() const409 int CegoBufferPage::getPageSize() const
410 {
411     return _pageSize;
412 }
413 
getChunkLen() const414 int CegoBufferPage::getChunkLen() const
415 {
416     return _pageSize - PAGEHEAD;
417 }
418 
getEntryLen() const419 int CegoBufferPage::getEntryLen() const
420 {
421     return _entryLen;
422 }
423 
getEntryPos() const424 int CegoBufferPage::getEntryPos() const
425 {
426     return _entryPos;
427 }
428 
getPagePtr() const429 void* CegoBufferPage::getPagePtr() const
430 {
431     return _pagePtr;
432 }
433 
printPage()434 void CegoBufferPage::printPage()
435 {
436     cout << "--- BufferPage ---" << endl;
437     cout << "PageId: " << _pageId << endl;
438     cout << "NextPageId: " << _pageHead->nextPageId << endl;
439     cout << "PageSize: " << _pageSize << endl;
440     cout << "PagePtr: " << (unsigned long long)_pagePtr << endl;
441 
442     int* e = (int*)getFirstEntry();
443     int i=1;
444     if (e)
445     {
446 	e--;
447 
448 	cout << "Entry " << i << " Pos=" << (long long)e - (long long)_pagePtr << " Size=" << *e << endl;
449 	i++;
450 	while ( ( e = (int*)getNextEntry()) != 0  )
451 	{
452 	    e--;
453 	    cout << "Entry " << i << " Pos=" << (long long)e - (long long)_pagePtr << " Size=" << *e << endl;
454 	    i++;
455 	}
456     }
457 
458     int* freePtr = (int*)((long long)_pagePtr + (long)_pageSize);
459     freePtr--;
460 
461     cout << "---------------------------" << endl;
462     cout << "Free entries : " << endl;
463     i=1;
464     while ( *freePtr )
465     {
466 	cout << "Free Entry " << i << " Pos=" << *freePtr << " Size=" << *(int*)(*freePtr + (long long)_pagePtr)<< endl;
467 	i++;
468 	freePtr--;
469     }
470     cout << endl;
471 }
472 
operator =(const CegoBufferPage & bp)473 CegoBufferPage& CegoBufferPage::operator = ( const CegoBufferPage& bp )
474 {
475     _pageId = bp._pageId;
476     _pageSize = bp._pageSize;
477     _pagePtr = bp._pagePtr;
478 
479     _ePtr = bp._ePtr;
480     _blobPtr = bp._blobPtr;
481 
482     _entryLen = bp._entryLen;
483     _entryPos = bp._entryPos;
484 
485     _pageHead = bp._pageHead;
486     _isFixed = bp._isFixed;
487 
488     return (*this);
489 }
490 
operator ==(const CegoBufferPage & bp)491 bool CegoBufferPage::operator == ( const CegoBufferPage& bp)
492 {
493     if ( _pageId == bp._pageId )
494 	return true;
495     return false;
496 }
497 
operator !=(const CegoBufferPage & bp)498 bool CegoBufferPage::operator != ( const CegoBufferPage& bp)
499 {
500     if ( _pageId != bp._pageId )
501 	return true;
502     return false;
503 }
504