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