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()38CegoBufferPage::CegoBufferPage() 39 { 40 _isFixed = false; 41 _pageId = 0; 42 } 43 CegoBufferPage(const CegoBufferPage & bp)44CegoBufferPage::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)61CegoBufferPage::CegoBufferPage(void* pagePtr, int pageSize) 62 { 63 _pageSize = pageSize; 64 _pagePtr = (char*)pagePtr; 65 _pageHead = (PageHead*)pagePtr; 66 _isFixed = false; 67 } 68 ~CegoBufferPage()69CegoBufferPage::~CegoBufferPage() 70 { 71 } 72 setFixed(bool isFixed)73void CegoBufferPage::setFixed(bool isFixed) 74 { 75 _isFixed = isFixed; 76 } 77 isFixed() const78bool CegoBufferPage::isFixed() const 79 { 80 return _isFixed; 81 } 82 initPage(CegoBufferPage::PageType t)83void 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)103void CegoBufferPage::setPagePtr(char* ptr) 104 { 105 _pagePtr = ptr; 106 } 107 setPageHead(PageHead * ptr)108void CegoBufferPage::setPageHead(PageHead* ptr) 109 { 110 _pageHead = ptr; 111 } 112 setPageSize(int pageSize)113void CegoBufferPage::setPageSize(int pageSize) 114 { 115 _pageSize = pageSize; 116 } 117 setPageId(PageIdType pageId)118void CegoBufferPage::setPageId(PageIdType pageId) 119 { 120 _pageId = pageId; 121 } 122 getPageId()123PageIdType& CegoBufferPage::getPageId() 124 { 125 return _pageId; 126 } 127 setNextPageId(PageIdType pageId)128void CegoBufferPage::setNextPageId(PageIdType pageId) 129 { 130 _pageHead->nextPageId = pageId; 131 } 132 getNextPageId() const133PageIdType& CegoBufferPage::getNextPageId() const 134 { 135 return _pageHead->nextPageId; 136 } 137 getNumEntries()138int 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)150void CegoBufferPage::setType(CegoBufferPage::PageType t) 151 { 152 _pageHead->pageType = t; 153 } 154 getType() const155CegoBufferPage::PageType& CegoBufferPage::getType() const 156 { 157 return _pageHead->pageType; 158 } 159 newEntry(int size)160void* 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)240void 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()340void* 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()350void* 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() const404char* CegoBufferPage::getChunkEntry() const 405 { 406 return (char*)((long long)_pagePtr + PAGEHEAD); 407 } 408 getPageSize() const409int CegoBufferPage::getPageSize() const 410 { 411 return _pageSize; 412 } 413 getChunkLen() const414int CegoBufferPage::getChunkLen() const 415 { 416 return _pageSize - PAGEHEAD; 417 } 418 getEntryLen() const419int CegoBufferPage::getEntryLen() const 420 { 421 return _entryLen; 422 } 423 getEntryPos() const424int CegoBufferPage::getEntryPos() const 425 { 426 return _entryPos; 427 } 428 getPagePtr() const429void* CegoBufferPage::getPagePtr() const 430 { 431 return _pagePtr; 432 } 433 printPage()434void 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)473CegoBufferPage& 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)491bool CegoBufferPage::operator == ( const CegoBufferPage& bp) 492 { 493 if ( _pageId == bp._pageId ) 494 return true; 495 return false; 496 } 497 operator !=(const CegoBufferPage & bp)498bool CegoBufferPage::operator != ( const CegoBufferPage& bp) 499 { 500 if ( _pageId != bp._pageId ) 501 return true; 502 return false; 503 } 504