cid#1607171 Data race condition
[LibreOffice.git] / connectivity / source / inc / dbase / dindexnode.hxx
blobc1db23f76b606dccd187b8e63ea0312821b297c9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #pragma once
21 #include <file/fcode.hxx>
22 #include <connectivity/FValue.hxx>
23 #include <memory>
25 #define NODE_NOTFOUND 0xFFFF
26 #define DINDEX_PAGE_SIZE 512
28 class SvStream;
30 namespace connectivity::dbase
33 class ONDXNode;
34 class ODbaseIndex;
36 // Index Key
38 typedef file::OOperand ONDXKey_BASE;
39 class ONDXKey : public ONDXKey_BASE
41 friend class ONDXNode;
42 sal_uInt32 nRecord; /* Record pointer */
43 ORowSetValue xValue; /* Key values */
45 public:
46 ONDXKey();
47 ONDXKey(ORowSetValue aVal, sal_Int32 eType, sal_uInt32 nRec);
48 ONDXKey(const OUString& aStr, sal_uInt32 nRec);
49 ONDXKey(double aVal, sal_uInt32 nRec);
51 inline ONDXKey(const ONDXKey& rKey);
53 inline ONDXKey& operator= (const ONDXKey& rKey);
54 virtual void setValue(const ORowSetValue& _rVal) override;
56 virtual const ORowSetValue& getValue() const override;
58 sal_uInt32 GetRecord() const { return nRecord; }
59 void setRecord(sal_uInt32 _nRec) { nRecord = _nRec; }
60 void ResetRecord() { nRecord = 0; }
62 bool operator == (const ONDXKey& rKey) const;
63 bool operator != (const ONDXKey& rKey) const;
64 bool operator < (const ONDXKey& rKey) const;
65 bool operator <= (const ONDXKey& rKey) const;
66 bool operator > (const ONDXKey& rKey) const;
68 static bool IsText(sal_Int32 eType);
70 private:
71 int Compare(const ONDXKey& rKey) const;
75 class ONDXPage;
77 // Index Page Pointer
78 // This is ref-count pointer class
79 class ONDXPagePtr
81 friend SvStream& WriteONDXPagePtr(SvStream &rStream, const ONDXPagePtr&);
82 friend SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
84 ONDXPage* mpPage;
85 sal_uInt32 nPagePos; // Position in the index file
87 public:
88 ONDXPagePtr();
89 ONDXPagePtr(ONDXPagePtr&& rObj) noexcept;
90 ONDXPagePtr(ONDXPagePtr const & rRef);
91 ONDXPagePtr(ONDXPage* pRefPage);
92 ~ONDXPagePtr();
93 void Clear();
94 ONDXPagePtr& operator=(ONDXPagePtr const & rRef);
95 ONDXPagePtr& operator=(ONDXPagePtr && rRef);
96 bool Is() const { return mpPage != nullptr; }
98 ONDXPage * operator ->() const { assert(mpPage != nullptr); return mpPage; }
99 operator ONDXPage *() const { return mpPage; }
101 sal_uInt32 GetPagePos() const {return nPagePos;}
102 bool HasPage() const {return nPagePos != 0;}
105 // Index Page
106 // This is a ref-counted class, with re-cycling
107 class ONDXPage
109 friend class ODbaseIndex;
110 friend class ONDXPagePtr;
112 friend SvStream& WriteONDXPage(SvStream &rStream, const ONDXPage&);
113 friend SvStream& operator >> (SvStream &rStream, ONDXPage&);
115 // work around a clang 3.5 optimization bug: if the bNoDelete is *first*
116 // it mis-compiles "if (--nRefCount == 0)" and never deletes any object
117 unsigned int nRefCount : 31;
118 // the only reason this is not bool is because MSVC cannot handle mixed type bitfields
119 unsigned int bNoDelete : 1;
120 sal_uInt32 nPagePos; // Position in the index file
121 bool bModified : 1;
122 sal_uInt16 nCount;
124 ONDXPagePtr aParent, // Parent page
125 aChild; // Pointer to the right child page
126 ODbaseIndex& rIndex;
127 std::unique_ptr<ONDXNode[]>
128 ppNodes; // Array of nodes
130 public:
131 // Node operations
132 sal_uInt16 Count() const {return nCount;}
134 bool Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft = 0);
135 bool Insert(sal_uInt16 nIndex, ONDXNode& rNode);
136 bool Append(ONDXNode& rNode);
137 void Delete(sal_uInt16);
138 void Remove(sal_uInt16);
139 void Release(bool bSave = true);
140 void ReleaseFull();
142 // Split and merge
143 ONDXNode Split(ONDXPage& rPage);
144 void Merge(sal_uInt16 nParentNodePos, const ONDXPagePtr& xPage);
146 // Access operators
147 ONDXNode& operator[] (sal_uInt16 nPos);
148 const ONDXNode& operator[] (sal_uInt16 nPos) const;
150 bool IsRoot() const;
151 bool IsLeaf() const;
152 bool IsModified() const;
153 bool HasParent() const;
155 bool IsFull() const;
157 sal_uInt32 GetPagePos() const {return nPagePos;}
158 ONDXPagePtr& GetChild(ODbaseIndex const * pIndex = nullptr);
160 // Parent does not need to be reloaded
161 const ONDXPagePtr& GetParent() const;
162 ODbaseIndex& GetIndex() {return rIndex;}
163 const ODbaseIndex& GetIndex() const {return rIndex;}
165 // Setting the child, via reference to retain the PagePos
166 void SetChild(const ONDXPagePtr& rCh);
167 void SetParent(const ONDXPagePtr& rPa);
169 sal_uInt16 Search(const ONDXKey& rSearch);
170 sal_uInt16 Search(const ONDXPage* pPage);
171 void SearchAndReplace(const ONDXKey& rSearch, ONDXKey const & rReplace);
173 protected:
174 ONDXPage(ODbaseIndex& rIndex, sal_uInt32 nPos, ONDXPage*);
175 ~ONDXPage();
177 void ReleaseRef();
178 void QueryDelete();
179 void AddNextRef()
181 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" );
182 ++nRefCount;
184 void AddFirstRef()
186 assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" );
187 if( bNoDelete )
188 bNoDelete = 0;
189 ++nRefCount;
192 void SetModified(bool bMod) {bModified = bMod;}
193 void SetPagePos(sal_uInt32 nPage) {nPagePos = nPage;}
195 bool Find(const ONDXKey&); // Descend recursively
196 sal_uInt16 FindPos(const ONDXKey& rKey) const;
198 #if OSL_DEBUG_LEVEL > 1
199 void PrintPage();
200 #endif
203 SvStream& WriteONDXPagePtr(SvStream &rStream, const ONDXPagePtr&);
204 SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
206 inline bool ONDXPage::IsRoot() const {return !aParent.Is();}
207 inline bool ONDXPage::IsLeaf() const {return !aChild.HasPage();}
208 inline bool ONDXPage::IsModified() const {return bModified;}
209 inline bool ONDXPage::HasParent() const {return aParent.Is();}
210 inline const ONDXPagePtr& ONDXPage::GetParent() const {return aParent;}
212 inline void ONDXPage::SetParent(const ONDXPagePtr& rPa = ONDXPagePtr())
214 aParent = rPa;
217 inline void ONDXPage::SetChild(const ONDXPagePtr& rCh = ONDXPagePtr())
219 aChild = rCh;
220 if (aChild.Is())
221 aChild->SetParent(this);
223 SvStream& operator >> (SvStream &rStream, ONDXPage& rPage);
224 SvStream& WriteONDXPage(SvStream &rStream, const ONDXPage& rPage);
227 // Index Node
229 class ONDXNode
231 friend class ONDXPage;
232 ONDXPagePtr aChild; /* Next page reference */
233 ONDXKey aKey;
235 public:
236 ONDXNode(){}
237 ONDXNode(const ONDXKey& rKey)
238 :aKey(rKey) {}
240 // Does the node point to a page?
241 bool HasChild() const {return aChild.HasPage();}
242 // If an index is provided, we may be able to retrieve the page
243 ONDXPagePtr& GetChild(ODbaseIndex* pIndex = nullptr, ONDXPage* = nullptr);
245 const ONDXKey& GetKey() const { return aKey;}
246 ONDXKey& GetKey() { return aKey;}
248 // Setting the child, via reference to retain the PagePos
249 void SetChild(const ONDXPagePtr& rCh = ONDXPagePtr(), ONDXPage* = nullptr);
251 void Write(SvStream &rStream, const ONDXPage& rPage) const;
252 void Read(SvStream &rStream, ODbaseIndex const &);
255 inline ONDXKey::ONDXKey(const ONDXKey& rKey)
256 : ONDXKey_BASE(rKey.getDBType())
257 ,nRecord(rKey.nRecord)
258 ,xValue(rKey.xValue)
262 inline ONDXKey& ONDXKey::operator=(const ONDXKey& rKey)
264 if(&rKey == this)
265 return *this;
267 xValue = rKey.xValue;
268 nRecord = rKey.nRecord;
269 m_eDBType = rKey.getDBType();
270 return *this;
273 inline bool ONDXKey::operator == (const ONDXKey& rKey) const
275 if(&rKey == this)
276 return true;
277 return Compare(rKey) == 0;
279 inline bool ONDXKey::operator != (const ONDXKey& rKey) const
281 return !operator== (rKey);
283 inline bool ONDXKey::operator < (const ONDXKey& rKey) const
285 return Compare(rKey) < 0;
287 inline bool ONDXKey::operator > (const ONDXKey& rKey) const
289 return Compare(rKey) > 0;
291 inline bool ONDXKey::operator <= (const ONDXKey& rKey) const
293 return !operator > (rKey);
296 inline void ONDXNode::SetChild(const ONDXPagePtr& rCh, ONDXPage* pParent)
298 aChild = rCh;
299 if (aChild.Is())
300 aChild->SetParent(pParent);
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */