1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef _STGCACHE_HXX
#define _STGCACHE_HXX
#include <osl/endian.h>
#include <rtl/ref.hxx>
#include <tools/solar.h>
#include <tools/stream.hxx>
#include <stgelem.hxx>
#include <boost/noncopyable.hpp>
#include <boost/unordered_map.hpp>
class UCBStorageStream;
class StgPage;
class StgDirEntry;
class StorageBase;
class StgCache
{
typedef boost::unordered_map
<
sal_Int32, rtl::Reference< StgPage >,
boost::hash< sal_Int32 >, std::equal_to< sal_Int32 >
> IndexToStgPage;
typedef std::vector< rtl::Reference< StgPage > > LRUList;
sal_uLong nError; // error code
sal_Int32 nPages; // size of data area in pages
sal_uInt16 nRef; // reference count
IndexToStgPage maDirtyPages; // hash of all dirty pages
int nReplaceIdx; // index into maLRUPages to replace next
LRUList maLRUPages; // list of last few non-dirty pages.
short nPageSize; // page size of the file
UCBStorageStream* pStorageStream; // holds reference to UCB storage stream
void Erase( const rtl::Reference< StgPage >& ); // delete a cache element
rtl::Reference< StgPage > Create( sal_Int32 ); // create a cached page
protected:
SvStream* pStrm; // physical stream
bool bMyStream; // true: delete stream in dtor
bool bFile; // true: file stream
sal_Int32 Page2Pos( sal_Int32 ); // page address --> file position
public:
StgCache();
~StgCache();
void IncRef() { nRef++; }
sal_uInt16 DecRef() { return --nRef; }
void SetPhysPageSize( short );
sal_Int32 GetPhysPages() { return nPages; }
short GetPhysPageSize() { return nPageSize; }
SvStream* GetStrm() { return pStrm; }
void SetStrm( SvStream*, bool );
void SetStrm( UCBStorageStream* );
bool IsWritable() { return ( pStrm && pStrm->IsWritable() ); }
bool Good() { return nError == SVSTREAM_OK; }
bool Bad() { return nError != SVSTREAM_OK; }
sal_uLong GetError() { return nError; }
void MoveError( StorageBase& );
void SetError( sal_uLong );
void ResetError();
bool Open( const OUString& rName, StreamMode );
void Close();
bool Read( sal_Int32 nPage, void* pBuf, sal_Int32 nPages );
bool Write( sal_Int32 nPage, void* pBuf, sal_Int32 nPages );
// two routines for accessing FAT pages
// Assume that the data is a FAT page and get/put FAT data.
void SetToPage ( const rtl::Reference< StgPage > xPage, short nOff, sal_Int32 nVal );
inline sal_Int32 GetFromPage ( const rtl::Reference< StgPage > xPage, short nOff );
void SetDirty ( const rtl::Reference< StgPage > &xPage );
bool SetSize( sal_Int32 nPages );
rtl::Reference< StgPage > Find( sal_Int32 ); // find a cached page
rtl::Reference< StgPage > Get( sal_Int32, bool ); // get a cached page
rtl::Reference< StgPage > Copy( sal_Int32, sal_Int32=STG_FREE ); // copy a page
bool Commit(); // flush all pages
void Clear(); // clear the cache
};
class StgPage : public rtl::IReference, private boost::noncopyable {
sal_uInt32 mnRefCount;
const sal_Int32 mnPage; // page index
sal_uInt8* mpData; // nSize bytes
short mnSize; // size of this page
StgPage( short nData, sal_Int32 nPage );
virtual ~StgPage();
public:
static rtl::Reference< StgPage > Create( short nData, sal_Int32 nPage );
sal_Int32 GetPage() { return mnPage; }
void* GetData() { return mpData; }
short GetSize() { return mnSize; }
public:
virtual oslInterlockedCount SAL_CALL acquire()
{
return ++mnRefCount;
}
virtual oslInterlockedCount SAL_CALL release()
{
if ( --mnRefCount == 0)
{
delete this;
return 0;
}
return mnRefCount;
}
static bool IsPageGreater( const StgPage *pA, const StgPage *pB );
};
inline sal_Int32 StgCache::GetFromPage ( const rtl::Reference< StgPage > xPage, short nOff )
{
if( ( nOff >= (short) ( xPage->GetSize() / sizeof( sal_Int32 ) ) ) || nOff < 0 )
return -1;
sal_Int32 n = ((sal_Int32*) xPage->GetData() )[ nOff ];
#ifdef OSL_BIGENDIAN
return OSL_SWAPDWORD(n);
#else
return n;
#endif
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|