1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #pragma once
34 
35 #include <vector>
36 
37 #include "ZException.h"
38 #include "dbCore.h"
39 #include "dbIterator.h"
40 #include "dbVector.h"
41 #include "odb.h"
42 
43 namespace odb {
44 
45 class dbIStream;
46 class dbOStream;
47 
48 class dbTablePage : public dbObjectPage
49 {
50  public:
51   char _objects[1];
52 };
53 
54 template <class T>
55 class dbTable : public dbObjectTable, public dbIterator
56 {
57  public:
58   // PERSISTANT-DATA
59   uint _page_mask;      // bit-mask to get page-offset
60   uint _page_shift;     // number of bits to shift to determine page-no
61   uint _top_idx;        // largest id which has been allocated.
62   uint _bottom_idx;     // smallest id which has been allocated.
63   uint _page_cnt;       // high-water mark of page-table
64   uint _page_tbl_size;  // length of the page table
65   uint _alloc_cnt;      // number of object allocated
66   uint _free_list;      // objects on freelist
67 
68   // NON-PERSISTANT-DATA
69   dbTablePage** _pages;  // page-table
70 
71   void resizePageTbl();
72   void newPage();
73   void pushQ(uint& Q, _dbFreeObject* e);
74   _dbFreeObject* popQ(uint& Q);
75   void unlinkQ(uint& Q, _dbFreeObject* e);
76 
77   dbTable(_dbDatabase* db,
78           dbObject* owner,
79           dbObjectTable* (dbObject::*m)(dbObjectType),
80           dbObjectType type,
81           uint page_size = 128,
82           uint page_shift = 7);
83 
84   // Make a copy of a table.
85   // The copy is identical including the ordering of all free-lists.
86   // dbTable(_dbDatabase * db, dbObject * owner, const dbTable<T> & T );
87   dbTable(_dbDatabase* db, dbObject* owner, const dbTable<T>&);
88 
89   virtual ~dbTable();
90 
91   // returns the number of instances of "T" allocated
size()92   uint size() const { return _alloc_cnt; }
93 
94   // Create a "T", calls T( _dbDatabase * )
95   T* create();
96 
97   // Duplicate a "T", calls T( _dbDatabase *, const T & )
98   T* duplicate(T* t);
99 
100   // Destroy instance of "T", calls destructor
101   void destroy(T*);
102 
103   // clear the table
104   void clear();
105 
page_size()106   uint page_size() const { return _page_mask + 1; }
107 
108   // Get the object of this id
getPtr(dbId<T> id)109   T* getPtr(dbId<T> id) const
110   {
111     uint page = (uint) id >> _page_shift;
112     uint offset = (uint) id & _page_mask;
113 
114     assert(((uint) id != 0) && (page < _page_cnt));
115     T* p = (T*) &(_pages[page]->_objects[offset * sizeof(T)]);
116     assert(p->_oid & DB_ALLOC_BIT);
117     return p;
118   }
119 
validId(dbId<T> id)120   bool validId(dbId<T> id) const
121   {
122     uint page = (uint) id >> _page_shift;
123     uint offset = (uint) id & _page_mask;
124 
125     if (((uint) id != 0) && (page < _page_cnt)) {
126       T* p = (T*) &(_pages[page]->_objects[offset * sizeof(T)]);
127       return (p->_oid & DB_ALLOC_BIT) == DB_ALLOC_BIT;
128     }
129 
130     return false;
131   }
132 
133   //
134   // Get the object of this id
135   // This method is the same as getPtr() but is is
136   // use to get objects on the free-list.
137   //
getFreeObj(dbId<T> id)138   T* getFreeObj(dbId<T> id)
139   {
140     uint page = (uint) id >> _page_shift;
141     uint offset = (uint) id & _page_mask;
142     assert(((uint) id != 0) && (page < _page_cnt));
143     T* p = (T*) &(_pages[page]->_objects[offset * sizeof(T)]);
144     assert((p->_oid & DB_ALLOC_BIT) == 0);
145     return p;
146   }
147 
148   // find the new top_idx...
149   void findTop();
150 
151   // find the new bottom_idx...
152   void findBottom();
153 
154   void readPage(dbIStream& stream, dbTablePage* page);
155   void writePage(dbOStream& stream, const dbTablePage* page) const;
156 
157   bool operator==(const dbTable<T>& table) const;
158   bool operator!=(const dbTable<T>& table) const;
159   void differences(dbDiff& diff, const dbTable<T>& rhs) const;
160   void out(dbDiff& diff, char side) const;
161 
162   // dbIterator interface methods
163   bool reversible();
164   bool orderReversed();
165   void reverse(dbObject* parent);
166   uint sequential();
167   uint size(dbObject* parent);
168   uint begin(dbObject* parent);
169   uint end(dbObject* parent);
170   uint next(uint cur, ...);
171   dbObject* getObject(uint cur, ...);
172   void getObjects(std::vector<T*>& objects);
173 
174  private:
175   void copy_pages(const dbTable<T>&);
176   void copy_page(uint page_id, dbTablePage* page);
177 };
178 
179 template <class T>
180 dbOStream& operator<<(dbOStream& stream, const dbTable<T>& table);
181 
182 template <class T>
183 dbIStream& operator>>(dbIStream& stream, dbTable<T>& table);
184 
185 }  // namespace odb
186