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