1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_store.hxx" 26 27 #include "lockbyte.hxx" 28 29 #include "sal/types.h" 30 #include "osl/diagnose.h" 31 #include "osl/file.h" 32 #include "osl/process.h" 33 #include "rtl/alloc.h" 34 #include "rtl/ustring.hxx" 35 36 #include "object.hxx" 37 #include "storbase.hxx" 38 39 #ifndef INCLUDED_STRING_H 40 #include <string.h> 41 #define INCLUDED_STRING_H 42 #endif 43 44 using namespace store; 45 46 /*======================================================================== 47 * 48 * ILockBytes (non-virtual interface) implementation. 49 * 50 *======================================================================*/ 51 52 storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) 53 { 54 OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize"); 55 return initialize_Impl (rxAllocator, nPageSize); 56 } 57 58 storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset) 59 { 60 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset"); 61 if (nOffset == STORE_PAGE_NULL) 62 return store_E_CantSeek; 63 64 return readPageAt_Impl (rPage, nOffset); 65 } 66 67 storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset) 68 { 69 // [SECURITY:ValInput] 70 PageData const * pagedata = rPage.get(); 71 OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page"); 72 if (pagedata == 0) 73 return store_E_InvalidParameter; 74 75 sal_uInt32 const offset = pagedata->location(); 76 OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset"); 77 if (nOffset != offset) 78 return store_E_InvalidParameter; 79 80 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset"); 81 if (nOffset == STORE_PAGE_NULL) 82 return store_E_CantSeek; 83 84 return writePageAt_Impl (rPage, nOffset); 85 } 86 87 storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) 88 { 89 // [SECURITY:ValInput] 90 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer); 91 if (!(dst_lo != 0)) 92 return store_E_InvalidParameter; 93 94 sal_uInt8 * dst_hi = dst_lo + nBytes; 95 if (!(dst_lo < dst_hi)) 96 return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None; 97 98 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset"); 99 if (nOffset == STORE_PAGE_NULL) 100 return store_E_CantSeek; 101 102 sal_uInt64 const src_size = nOffset + nBytes; 103 if (src_size > SAL_MAX_UINT32) 104 return store_E_CantSeek; 105 106 return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo)); 107 } 108 109 storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) 110 { 111 // [SECURITY:ValInput] 112 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer); 113 if (!(src_lo != 0)) 114 return store_E_InvalidParameter; 115 116 sal_uInt8 const * src_hi = src_lo + nBytes; 117 if (!(src_lo < src_hi)) 118 return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None; 119 120 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset"); 121 if (nOffset == STORE_PAGE_NULL) 122 return store_E_CantSeek; 123 124 sal_uInt64 const dst_size = nOffset + nBytes; 125 if (dst_size > SAL_MAX_UINT32) 126 return store_E_CantSeek; 127 128 return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo)); 129 } 130 131 storeError ILockBytes::getSize (sal_uInt32 & rnSize) 132 { 133 rnSize = 0; 134 return getSize_Impl (rnSize); 135 } 136 137 storeError ILockBytes::setSize (sal_uInt32 nSize) 138 { 139 return setSize_Impl (nSize); 140 } 141 142 storeError ILockBytes::flush() 143 { 144 return flush_Impl(); 145 } 146 147 /*======================================================================== 148 * 149 * FileLockBytes implementation. 150 * 151 *======================================================================*/ 152 namespace store 153 { 154 155 struct FileHandle 156 { 157 oslFileHandle m_handle; 158 159 FileHandle() : m_handle(0) {} 160 161 bool operator != (FileHandle const & rhs) 162 { 163 return (m_handle != rhs.m_handle); 164 } 165 166 static storeError errorFromNative (oslFileError eErrno) 167 { 168 switch (eErrno) 169 { 170 case osl_File_E_None: 171 return store_E_None; 172 173 case osl_File_E_NOENT: 174 return store_E_NotExists; 175 176 case osl_File_E_ACCES: 177 case osl_File_E_PERM: 178 return store_E_AccessViolation; 179 180 case osl_File_E_AGAIN: 181 case osl_File_E_DEADLK: 182 return store_E_LockingViolation; 183 184 case osl_File_E_BADF: 185 return store_E_InvalidHandle; 186 187 case osl_File_E_INVAL: 188 return store_E_InvalidParameter; 189 190 case osl_File_E_NOMEM: 191 return store_E_OutOfMemory; 192 193 case osl_File_E_NOSPC: 194 return store_E_OutOfSpace; 195 196 case osl_File_E_OVERFLOW: 197 return store_E_CantSeek; 198 199 default: 200 return store_E_Unknown; 201 } 202 } 203 204 static sal_uInt32 modeToNative (storeAccessMode eAccessMode) 205 { 206 sal_uInt32 nFlags = 0; 207 switch (eAccessMode) 208 { 209 case store_AccessCreate: 210 case store_AccessReadCreate: 211 nFlags |= osl_File_OpenFlag_Create; 212 // fall through 213 case store_AccessReadWrite: 214 nFlags |= osl_File_OpenFlag_Write; 215 // fall through 216 case store_AccessReadOnly: 217 nFlags |= osl_File_OpenFlag_Read; 218 break; 219 default: 220 OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode"); 221 } 222 return nFlags; 223 } 224 225 storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode) 226 { 227 // Verify arguments. 228 sal_uInt32 nFlags = modeToNative (eAccessMode); 229 if (!pFilename || !nFlags) 230 return store_E_InvalidParameter; 231 232 // Convert into FileUrl. 233 rtl::OUString aFileUrl; 234 if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None) 235 { 236 // Not system path. Assume file url. 237 rtl_uString_assign (&(aFileUrl.pData), pFilename); 238 } 239 if (aFileUrl.compareToAscii("file://", 7) != 0) 240 { 241 // Not file url. Assume relative path. 242 rtl::OUString aCwdUrl; 243 (void) osl_getProcessWorkingDir (&(aCwdUrl.pData)); 244 245 // Absolute file url. 246 (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData)); 247 } 248 249 // Acquire handle. 250 oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags); 251 if (result == osl_File_E_EXIST) 252 { 253 // Already existing (O_CREAT | O_EXCL). 254 result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write); 255 if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate)) 256 { 257 // Truncate existing file. 258 result = osl_setFileSize (m_handle, 0); 259 } 260 } 261 if (result != osl_File_E_None) 262 return errorFromNative(result); 263 return store_E_None; 264 } 265 266 /** @see FileLockBytes destructor 267 */ 268 static void closeFile (oslFileHandle hFile) 269 { 270 (void) osl_closeFile (hFile); 271 } 272 273 /** @see ResourceHolder<T>::destructor_type 274 */ 275 struct CloseFile 276 { 277 void operator()(FileHandle & rFile) const 278 { 279 // Release handle. 280 closeFile (rFile.m_handle); 281 rFile.m_handle = 0; 282 } 283 }; 284 typedef CloseFile destructor_type; 285 }; 286 287 class FileLockBytes : 288 public store::OStoreObject, 289 public store::ILockBytes 290 { 291 /** Representation. 292 */ 293 oslFileHandle m_hFile; 294 sal_uInt32 m_nSize; 295 rtl::Reference< PageData::Allocator > m_xAllocator; 296 297 storeError initSize_Impl (sal_uInt32 & rnSize); 298 299 /** ILockBytes implementation. 300 */ 301 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize); 302 303 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset); 304 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset); 305 306 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes); 307 virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes); 308 309 virtual storeError getSize_Impl (sal_uInt32 & rnSize); 310 virtual storeError setSize_Impl (sal_uInt32 nSize); 311 312 virtual storeError flush_Impl(); 313 314 /** Not implemented. 315 */ 316 FileLockBytes (FileLockBytes const &); 317 FileLockBytes & operator= (FileLockBytes const &); 318 319 public: 320 /** Construction. 321 */ 322 explicit FileLockBytes (FileHandle & rFile); 323 324 /** Delegate multiple inherited IReference. 325 */ 326 virtual oslInterlockedCount SAL_CALL acquire(); 327 virtual oslInterlockedCount SAL_CALL release(); 328 329 protected: 330 /** Destruction. 331 */ 332 virtual ~FileLockBytes(); 333 }; 334 335 } // namespace store 336 337 FileLockBytes::FileLockBytes (FileHandle & rFile) 338 : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator() 339 { 340 } 341 342 FileLockBytes::~FileLockBytes() 343 { 344 FileHandle::closeFile (m_hFile); 345 } 346 347 oslInterlockedCount SAL_CALL FileLockBytes::acquire() 348 { 349 return OStoreObject::acquire(); 350 } 351 352 oslInterlockedCount SAL_CALL FileLockBytes::release() 353 { 354 return OStoreObject::release(); 355 } 356 357 storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize) 358 { 359 /* osl_getFileSize() uses slow 'fstat(h, &size)', 360 * instead of fast 'size = lseek(h, 0, SEEK_END)'. 361 * so, init size here, and track changes. 362 */ 363 sal_uInt64 uSize = 0; 364 oslFileError result = osl_getFileSize (m_hFile, &uSize); 365 if (result != osl_File_E_None) 366 return FileHandle::errorFromNative(result); 367 if (uSize > SAL_MAX_UINT32) 368 return store_E_CantSeek; 369 370 rnSize = sal::static_int_cast<sal_uInt32>(uSize); 371 return store_E_None; 372 } 373 374 storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) 375 { 376 storeError result = initSize_Impl (m_nSize); 377 if (result != store_E_None) 378 return (result); 379 380 result = PageData::Allocator::createInstance (rxAllocator, nPageSize); 381 if (result != store_E_None) 382 return (result); 383 384 // @see readPageAt_Impl(). 385 m_xAllocator = rxAllocator; 386 return store_E_None; 387 } 388 389 storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) 390 { 391 if (m_xAllocator.is()) 392 { 393 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator); 394 page.swap (rPage); 395 } 396 397 if (!m_xAllocator.is()) 398 return store_E_InvalidAccess; 399 if (!rPage.get()) 400 return store_E_OutOfMemory; 401 402 PageData * pagedata = rPage.get(); 403 return readAt_Impl (nOffset, pagedata, pagedata->size()); 404 } 405 406 storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) 407 { 408 PageData const * pagedata = rPage.get(); 409 OSL_PRECOND(pagedata != 0, "contract violation"); 410 return writeAt_Impl (nOffset, pagedata, pagedata->size()); 411 } 412 413 storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) 414 { 415 sal_uInt64 nDone = 0; 416 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone); 417 if (result != osl_File_E_None) 418 return FileHandle::errorFromNative(result); 419 if (nDone != nBytes) 420 return (nDone != 0) ? store_E_CantRead : store_E_NotExists; 421 return store_E_None; 422 } 423 424 storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) 425 { 426 sal_uInt64 nDone = 0; 427 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone); 428 if (result != osl_File_E_None) 429 return FileHandle::errorFromNative(result); 430 if (nDone != nBytes) 431 return store_E_CantWrite; 432 433 sal_uInt64 const uSize = nOffset + nBytes; 434 OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation"); 435 if (uSize > m_nSize) 436 m_nSize = sal::static_int_cast<sal_uInt32>(uSize); 437 return store_E_None; 438 } 439 440 storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize) 441 { 442 rnSize = m_nSize; 443 return store_E_None; 444 } 445 446 storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize) 447 { 448 oslFileError result = osl_setFileSize (m_hFile, nSize); 449 if (result != osl_File_E_None) 450 return FileHandle::errorFromNative(result); 451 452 m_nSize = nSize; 453 return store_E_None; 454 } 455 456 storeError FileLockBytes::flush_Impl() 457 { 458 oslFileError result = osl_syncFile (m_hFile); 459 if (result != osl_File_E_None) 460 return FileHandle::errorFromNative(result); 461 return store_E_None; 462 } 463 464 /*======================================================================== 465 * 466 * MappedLockBytes implementation. 467 * 468 *======================================================================*/ 469 namespace store 470 { 471 472 struct FileMapping 473 { 474 sal_uInt8 * m_pAddr; 475 sal_uInt32 m_nSize; 476 477 FileMapping() : m_pAddr(0), m_nSize(0) {} 478 479 bool operator != (FileMapping const & rhs) const 480 { 481 return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize)); 482 } 483 484 oslFileError initialize (oslFileHandle hFile) 485 { 486 // Determine mapping size. 487 sal_uInt64 uSize = 0; 488 oslFileError result = osl_getFileSize (hFile, &uSize); 489 if (result != osl_File_E_None) 490 return result; 491 492 // [SECURITY:IntOver] 493 if (uSize > SAL_MAX_UINT32) 494 return osl_File_E_OVERFLOW; 495 m_nSize = sal::static_int_cast<sal_uInt32>(uSize); 496 497 // Acquire mapping. 498 return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess); 499 } 500 501 /** @see MappedLockBytes::destructor. 502 */ 503 static void unmapFile (sal_uInt8 * pAddr, sal_uInt32 nSize) 504 { 505 (void) osl_unmapFile (pAddr, nSize); 506 } 507 508 /** @see ResourceHolder<T>::destructor_type 509 */ 510 struct UnmapFile 511 { 512 void operator ()(FileMapping & rMapping) const 513 { 514 // Release mapping. 515 unmapFile (rMapping.m_pAddr, rMapping.m_nSize); 516 rMapping.m_pAddr = 0, rMapping.m_nSize = 0; 517 } 518 }; 519 typedef UnmapFile destructor_type; 520 }; 521 522 class MappedLockBytes : 523 public store::OStoreObject, 524 public store::PageData::Allocator, 525 public store::ILockBytes 526 { 527 /** Representation. 528 */ 529 sal_uInt8 * m_pData; 530 sal_uInt32 m_nSize; 531 sal_uInt16 m_nPageSize; 532 533 /** PageData::Allocator implementation. 534 */ 535 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize); 536 virtual void deallocate_Impl (void * pPage); 537 538 /** ILockBytes implementation. 539 */ 540 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize); 541 542 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset); 543 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset); 544 545 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes); 546 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes); 547 548 virtual storeError getSize_Impl (sal_uInt32 & rnSize); 549 virtual storeError setSize_Impl (sal_uInt32 nSize); 550 551 virtual storeError flush_Impl(); 552 553 /** Not implemented. 554 */ 555 MappedLockBytes (MappedLockBytes const &); 556 MappedLockBytes & operator= (MappedLockBytes const &); 557 558 public: 559 /** Construction. 560 */ 561 explicit MappedLockBytes (FileMapping & rMapping); 562 563 /** Delegate multiple inherited IReference. 564 */ 565 virtual oslInterlockedCount SAL_CALL acquire(); 566 virtual oslInterlockedCount SAL_CALL release(); 567 568 protected: 569 /* Destruction. 570 */ 571 virtual ~MappedLockBytes(); 572 }; 573 574 } // namespace store 575 576 MappedLockBytes::MappedLockBytes (FileMapping & rMapping) 577 : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0) 578 { 579 } 580 581 MappedLockBytes::~MappedLockBytes() 582 { 583 FileMapping::unmapFile (m_pData, m_nSize); 584 } 585 586 oslInterlockedCount SAL_CALL MappedLockBytes::acquire() 587 { 588 return OStoreObject::acquire(); 589 } 590 591 oslInterlockedCount SAL_CALL MappedLockBytes::release() 592 { 593 return OStoreObject::release(); 594 } 595 596 void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) 597 { 598 OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation"); 599 if ((ppPage != 0) && (pnSize != 0)) 600 *ppPage = 0, *pnSize = m_nPageSize; 601 } 602 603 void MappedLockBytes::deallocate_Impl (void * pPage) 604 { 605 OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation"); 606 (void)pPage; // UNUSED 607 } 608 609 storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) 610 { 611 rxAllocator = this; 612 m_nPageSize = nPageSize; 613 return store_E_None; 614 } 615 616 storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) 617 { 618 sal_uInt8 * src_lo = m_pData + nOffset; 619 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) 620 return store_E_NotExists; 621 622 sal_uInt8 * src_hi = src_lo + m_nPageSize; 623 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) 624 return store_E_CantRead; 625 626 PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this)); 627 page.swap (rPage); 628 629 return store_E_None; 630 } 631 632 storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/) 633 { 634 return store_E_AccessViolation; 635 } 636 637 storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) 638 { 639 sal_uInt8 const * src_lo = m_pData + nOffset; 640 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) 641 return store_E_NotExists; 642 643 sal_uInt8 const * src_hi = src_lo + nBytes; 644 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) 645 return store_E_CantRead; 646 647 memcpy (pBuffer, src_lo, (src_hi - src_lo)); 648 return store_E_None; 649 } 650 651 storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/) 652 { 653 return store_E_AccessViolation; 654 } 655 656 storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize) 657 { 658 rnSize = m_nSize; 659 return store_E_None; 660 } 661 662 storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/) 663 { 664 return store_E_AccessViolation; 665 } 666 667 storeError MappedLockBytes::flush_Impl() 668 { 669 return store_E_None; 670 } 671 672 /*======================================================================== 673 * 674 * MemoryLockBytes implementation. 675 * 676 *======================================================================*/ 677 namespace store 678 { 679 680 class MemoryLockBytes : 681 public store::OStoreObject, 682 public store::ILockBytes 683 { 684 /** Representation. 685 */ 686 sal_uInt8 * m_pData; 687 sal_uInt32 m_nSize; 688 rtl::Reference< PageData::Allocator > m_xAllocator; 689 690 /** ILockBytes implementation. 691 */ 692 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize); 693 694 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset); 695 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset); 696 697 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes); 698 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes); 699 700 virtual storeError getSize_Impl (sal_uInt32 & rnSize); 701 virtual storeError setSize_Impl (sal_uInt32 nSize); 702 703 virtual storeError flush_Impl(); 704 705 /** Not implemented. 706 */ 707 MemoryLockBytes (MemoryLockBytes const &); 708 MemoryLockBytes& operator= (MemoryLockBytes const &); 709 710 public: 711 /** Construction. 712 */ 713 MemoryLockBytes(); 714 715 /** Delegate multiple inherited IReference. 716 */ 717 virtual oslInterlockedCount SAL_CALL acquire(); 718 virtual oslInterlockedCount SAL_CALL release(); 719 720 protected: 721 /** Destruction. 722 */ 723 virtual ~MemoryLockBytes(); 724 }; 725 726 } // namespace store 727 728 MemoryLockBytes::MemoryLockBytes() 729 : m_pData (0), m_nSize (0), m_xAllocator() 730 {} 731 732 MemoryLockBytes::~MemoryLockBytes() 733 { 734 rtl_freeMemory (m_pData); 735 } 736 737 oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void) 738 { 739 return OStoreObject::acquire(); 740 } 741 742 oslInterlockedCount SAL_CALL MemoryLockBytes::release (void) 743 { 744 return OStoreObject::release(); 745 } 746 747 storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) 748 { 749 storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize); 750 if (result == store_E_None) 751 { 752 // @see readPageAt_Impl(). 753 m_xAllocator = rxAllocator; 754 } 755 return result; 756 } 757 758 storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) 759 { 760 if (m_xAllocator.is()) 761 { 762 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator); 763 page.swap (rPage); 764 } 765 766 if (!m_xAllocator.is()) 767 return store_E_InvalidAccess; 768 if (!rPage.get()) 769 return store_E_OutOfMemory; 770 771 PageData * pagedata = rPage.get(); 772 return readAt_Impl (nOffset, pagedata, pagedata->size()); 773 } 774 775 storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) 776 { 777 PageData const * pagedata = rPage.get(); 778 OSL_PRECOND(!(pagedata == 0), "contract violation"); 779 return writeAt_Impl (nOffset, pagedata, pagedata->size()); 780 } 781 782 storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) 783 { 784 sal_uInt8 const * src_lo = m_pData + nOffset; 785 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize)) 786 return store_E_NotExists; 787 788 sal_uInt8 const * src_hi = src_lo + nBytes; 789 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize)) 790 return store_E_CantRead; 791 792 memcpy (pBuffer, src_lo, (src_hi - src_lo)); 793 return store_E_None; 794 } 795 796 storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) 797 { 798 sal_uInt64 const dst_size = nOffset + nBytes; 799 OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation"); 800 if (dst_size > m_nSize) 801 { 802 storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size)); 803 if (eErrCode != store_E_None) 804 return eErrCode; 805 } 806 OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation"); 807 808 sal_uInt8 * dst_lo = m_pData + nOffset; 809 if (dst_lo >= m_pData + m_nSize) 810 return store_E_CantSeek; 811 812 sal_uInt8 * dst_hi = dst_lo + nBytes; 813 if (dst_hi > m_pData + m_nSize) 814 return store_E_CantWrite; 815 816 memcpy (dst_lo, pBuffer, (dst_hi - dst_lo)); 817 return store_E_None; 818 } 819 820 storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize) 821 { 822 rnSize = m_nSize; 823 return store_E_None; 824 } 825 826 storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize) 827 { 828 if (nSize != m_nSize) 829 { 830 sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize)); 831 if (pData != 0) 832 { 833 if (nSize > m_nSize) 834 memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize)); 835 } 836 else 837 { 838 if (nSize != 0) 839 return store_E_OutOfMemory; 840 } 841 m_pData = pData, m_nSize = nSize; 842 } 843 return store_E_None; 844 } 845 846 storeError MemoryLockBytes::flush_Impl() 847 { 848 return store_E_None; 849 } 850 851 /*======================================================================== 852 * 853 * ILockBytes factory implementations. 854 * 855 *======================================================================*/ 856 namespace store 857 { 858 859 template< class T > struct ResourceHolder 860 { 861 typedef typename T::destructor_type destructor_type; 862 863 T m_value; 864 865 explicit ResourceHolder (T const & value = T()) : m_value (value) {} 866 ~ResourceHolder() { reset(); } 867 868 T & get() { return m_value; } 869 T const & get() const { return m_value; } 870 871 void set (T const & value) { m_value = value; } 872 void reset (T const & value = T()) 873 { 874 T tmp (m_value); 875 if (tmp != value) 876 destructor_type()(tmp); 877 set (value); 878 } 879 T release() 880 { 881 T tmp (m_value); 882 set (T()); 883 return tmp; 884 } 885 886 ResourceHolder (ResourceHolder & rhs) 887 { 888 set (rhs.release()); 889 } 890 ResourceHolder & operator= (ResourceHolder & rhs) 891 { 892 reset (rhs.release()); 893 return *this; 894 } 895 }; 896 897 storeError 898 FileLockBytes_createInstance ( 899 rtl::Reference< ILockBytes > & rxLockBytes, 900 rtl_uString * pFilename, 901 storeAccessMode eAccessMode 902 ) 903 { 904 // Acquire file handle. 905 ResourceHolder<FileHandle> xFile; 906 storeError result = xFile.get().initialize (pFilename, eAccessMode); 907 if (result != store_E_None) 908 return (result); 909 910 if (eAccessMode == store_AccessReadOnly) 911 { 912 ResourceHolder<FileMapping> xMapping; 913 if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None) 914 { 915 rxLockBytes = new MappedLockBytes (xMapping.get()); 916 if (!rxLockBytes.is()) 917 return store_E_OutOfMemory; 918 (void) xMapping.release(); 919 } 920 } 921 if (!rxLockBytes.is()) 922 { 923 rxLockBytes = new FileLockBytes (xFile.get()); 924 if (!rxLockBytes.is()) 925 return store_E_OutOfMemory; 926 (void) xFile.release(); 927 } 928 929 return store_E_None; 930 } 931 932 storeError 933 MemoryLockBytes_createInstance ( 934 rtl::Reference< ILockBytes > & rxLockBytes 935 ) 936 { 937 rxLockBytes = new MemoryLockBytes(); 938 if (!rxLockBytes.is()) 939 return store_E_OutOfMemory; 940 941 return store_E_None; 942 } 943 944 } // namespace store 945