1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef _MORKROWSPACE_
7 #define _MORKROWSPACE_ 1
8 
9 #ifndef _MORK_
10 #  include "mork.h"
11 #endif
12 
13 #ifndef _MORKNODE_
14 #  include "morkNode.h"
15 #endif
16 
17 #ifndef _MORKSPACE_
18 #  include "morkSpace.h"
19 #endif
20 
21 #ifndef _MORKNODEMAP_
22 #  include "morkNodeMap.h"
23 #endif
24 
25 #ifndef _MORKROWMAP_
26 #  include "morkRowMap.h"
27 #endif
28 
29 #ifndef _MORKTABLE_
30 #  include "morkTable.h"
31 #endif
32 
33 #ifndef _MORKARRAY_
34 #  include "morkArray.h"
35 #endif
36 
37 #ifndef _MORKDEQUE_
38 #  include "morkDeque.h"
39 #endif
40 
41 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
42 
43 #define morkDerived_kRowSpace /*i*/ 0x7253 /* ascii 'rS' */
44 
45 #define morkRowSpace_kStartRowMapSlotCount 11
46 
47 #define morkRowSpace_kMaxIndexCount 8   /* no more indexes than this */
48 #define morkRowSpace_kPrimeCacheSize 17 /* should be prime number */
49 
50 class morkAtomRowMap;
51 
52 /*| morkRowSpace:
53 |*/
54 class morkRowSpace : public morkSpace {  //
55 
56   // public: // slots inherited from morkSpace (meant to inform only)
57   // nsIMdbHeap*    mNode_Heap;
58 
59   // mork_base      mNode_Base;     // must equal morkBase_kNode
60   // mork_derived   mNode_Derived;  // depends on specific node subclass
61 
62   // mork_access    mNode_Access;   // kOpen, kClosing, kShut, or kDead
63   // mork_usage     mNode_Usage;    // kHeap, kStack, kMember, kGlobal, kNone
64   // mork_able      mNode_Mutable;  // can this node be modified?
65   // mork_load      mNode_Load;     // is this node clean or dirty?
66 
67   // mork_uses      mNode_Uses;     // refcount for strong refs
68   // mork_refs      mNode_Refs;     // refcount for strong refs + weak refs
69 
70   // morkStore*  mSpace_Store; // weak ref to containing store
71 
72   // mork_bool   mSpace_DoAutoIDs;    // whether db should assign member IDs
73   // mork_bool   mSpace_HaveDoneAutoIDs; // whether actually auto assigned IDs
74   // mork_u1     mSpace_Pad[ 2 ];    // pad to u4 alignment
75 
76  public:  // state is public because the entire Mork system is private
77   nsIMdbHeap* mRowSpace_SlotHeap;
78 
79 #ifdef MORK_ENABLE_PROBE_MAPS
80   morkRowProbeMap mRowSpace_Rows;  // hash table of morkRow instances
81 #else                              /*MORK_ENABLE_PROBE_MAPS*/
82   morkRowMap mRowSpace_Rows;  // hash table of morkRow instances
83 #endif                             /*MORK_ENABLE_PROBE_MAPS*/
84   morkTableMap mRowSpace_Tables;   // all the tables in this row scope
85 
86   mork_tid mRowSpace_NextTableId;  // for auto-assigning table IDs
87   mork_rid mRowSpace_NextRowId;    // for auto-assigning row IDs
88 
89   mork_count mRowSpace_IndexCount;  // if nonzero, row indexes exist
90 
91   // every nonzero slot in IndexCache is a strong ref to a morkAtomRowMap:
92   morkAtomRowMap* mRowSpace_IndexCache[morkRowSpace_kPrimeCacheSize];
93 
94   morkDeque mRowSpace_TablesByPriority[morkPriority_kCount];
95 
96  public:  // more specific dirty methods for row space:
SetRowSpaceDirty()97   void SetRowSpaceDirty() { this->SetNodeDirty(); }
SetRowSpaceClean()98   void SetRowSpaceClean() { this->SetNodeClean(); }
99 
IsRowSpaceClean()100   mork_bool IsRowSpaceClean() const { return this->IsNodeClean(); }
IsRowSpaceDirty()101   mork_bool IsRowSpaceDirty() const { return this->IsNodeDirty(); }
102 
103   // { ===== begin morkNode interface =====
104  public:  // morkNode virtual methods
105   virtual void CloseMorkNode(
106       morkEnv* ev) override;  // CloseRowSpace() only if open
107   virtual ~morkRowSpace();    // assert that CloseRowSpace() executed earlier
108 
109  public:  // morkMap construction & destruction
110   morkRowSpace(morkEnv* ev, const morkUsage& inUsage, mork_scope inScope,
111                morkStore* ioStore, nsIMdbHeap* ioNodeHeap,
112                nsIMdbHeap* ioSlotHeap);
113   void CloseRowSpace(morkEnv* ev);  // called by CloseMorkNode();
114 
115  public:  // dynamic type identification
IsRowSpace()116   mork_bool IsRowSpace() const {
117     return IsNode() && mNode_Derived == morkDerived_kRowSpace;
118   }
119   // } ===== end morkNode methods =====
120 
121  public:  // typing
122   static void NonRowSpaceTypeError(morkEnv* ev);
123   static void ZeroScopeError(morkEnv* ev);
124   static void ZeroKindError(morkEnv* ev);
125   static void ZeroTidError(morkEnv* ev);
126   static void MinusOneRidError(morkEnv* ev);
127 
128   // static void ExpectAutoIdOnlyError(morkEnv* ev);
129   // static void ExpectAutoIdNeverError(morkEnv* ev);
130 
131  public:  // other space methods
132   mork_num CutAllRows(morkEnv* ev, morkPool* ioPool);
133   // CutAllRows() puts all rows and cells back into the pool.
134 
135   morkTable* NewTable(morkEnv* ev, mork_kind inTableKind,
136                       mdb_bool inMustBeUnique,
137                       const mdbOid* inOptionalMetaRowOid);
138 
139   morkTable* NewTableWithTid(morkEnv* ev, mork_tid inTid, mork_kind inTableKind,
140                              const mdbOid* inOptionalMetaRowOid);
141 
142   morkTable* FindTableByKind(morkEnv* ev, mork_kind inTableKind);
FindTableByTid(morkEnv * ev,mork_tid inTid)143   morkTable* FindTableByTid(morkEnv* ev, mork_tid inTid) {
144     return mRowSpace_Tables.GetTable(ev, inTid);
145   }
146 
147   mork_tid MakeNewTableId(morkEnv* ev);
148   mork_rid MakeNewRowId(morkEnv* ev);
149 
150   // morkRow* FindRowByRid(morkEnv* ev, mork_rid inRid)
151   // { return (morkRow*) mRowSpace_Rows.GetRow(ev, inRid); }
152 
153   morkRow* NewRowWithOid(morkEnv* ev, const mdbOid* inOid);
154   morkRow* NewRow(morkEnv* ev);
155 
156   morkRow* FindRow(morkEnv* ev, mork_column inColumn, const mdbYarn* inYarn);
157 
158   morkAtomRowMap* ForceMap(morkEnv* ev, mork_column inColumn);
159   morkAtomRowMap* FindMap(morkEnv* ev, mork_column inColumn);
160 
161  protected:  // internal utilities
162   morkAtomRowMap* make_index(morkEnv* ev, mork_column inColumn);
163 
164  public:  // typesafe refcounting inlines calling inherited morkNode methods
SlotWeakRowSpace(morkRowSpace * me,morkEnv * ev,morkRowSpace ** ioSlot)165   static void SlotWeakRowSpace(morkRowSpace* me, morkEnv* ev,
166                                morkRowSpace** ioSlot) {
167     morkNode::SlotWeakNode((morkNode*)me, ev, (morkNode**)ioSlot);
168   }
169 
SlotStrongRowSpace(morkRowSpace * me,morkEnv * ev,morkRowSpace ** ioSlot)170   static void SlotStrongRowSpace(morkRowSpace* me, morkEnv* ev,
171                                  morkRowSpace** ioSlot) {
172     morkNode::SlotStrongNode((morkNode*)me, ev, (morkNode**)ioSlot);
173   }
174 };
175 
176 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
177 
178 #define morkDerived_kRowSpaceMap /*i*/ 0x725A /* ascii 'rZ' */
179 
180 /*| morkRowSpaceMap: maps mork_scope -> morkRowSpace
181 |*/
182 class morkRowSpaceMap : public morkNodeMap {  // for mapping tokens to tables
183 
184  public:
185   virtual ~morkRowSpaceMap();
186   morkRowSpaceMap(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap,
187                   nsIMdbHeap* ioSlotHeap);
188 
189  public:  // other map methods
AddRowSpace(morkEnv * ev,morkRowSpace * ioRowSpace)190   mork_bool AddRowSpace(morkEnv* ev, morkRowSpace* ioRowSpace) {
191     return this->AddNode(ev, ioRowSpace->SpaceScope(), ioRowSpace);
192   }
193   // the AddRowSpace() boolean return equals ev->Good().
194 
CutRowSpace(morkEnv * ev,mork_scope inScope)195   mork_bool CutRowSpace(morkEnv* ev, mork_scope inScope) {
196     return this->CutNode(ev, inScope);
197   }
198   // The CutRowSpace() boolean return indicates whether removal happened.
199 
GetRowSpace(morkEnv * ev,mork_scope inScope)200   morkRowSpace* GetRowSpace(morkEnv* ev, mork_scope inScope) {
201     return (morkRowSpace*)this->GetNode(ev, inScope);
202   }
203   // Note the returned space does NOT have an increase in refcount for this.
204 
CutAllRowSpaces(morkEnv * ev)205   mork_num CutAllRowSpaces(morkEnv* ev) { return this->CutAllNodes(ev); }
206   // CutAllRowSpaces() releases all the referenced table values.
207 };
208 
209 class morkRowSpaceMapIter : public morkMapIter {  // typesafe wrapper class
210 
211  public:
morkRowSpaceMapIter(morkEnv * ev,morkRowSpaceMap * ioMap)212   morkRowSpaceMapIter(morkEnv* ev, morkRowSpaceMap* ioMap)
213       : morkMapIter(ev, ioMap) {}
214 
morkRowSpaceMapIter()215   morkRowSpaceMapIter() : morkMapIter() {}
InitRowSpaceMapIter(morkEnv * ev,morkRowSpaceMap * ioMap)216   void InitRowSpaceMapIter(morkEnv* ev, morkRowSpaceMap* ioMap) {
217     this->InitMapIter(ev, ioMap);
218   }
219 
FirstRowSpace(morkEnv * ev,mork_scope * outScope,morkRowSpace ** outRowSpace)220   mork_change* FirstRowSpace(morkEnv* ev, mork_scope* outScope,
221                              morkRowSpace** outRowSpace) {
222     return this->First(ev, outScope, outRowSpace);
223   }
224 
NextRowSpace(morkEnv * ev,mork_scope * outScope,morkRowSpace ** outRowSpace)225   mork_change* NextRowSpace(morkEnv* ev, mork_scope* outScope,
226                             morkRowSpace** outRowSpace) {
227     return this->Next(ev, outScope, outRowSpace);
228   }
229 
HereRowSpace(morkEnv * ev,mork_scope * outScope,morkRowSpace ** outRowSpace)230   mork_change* HereRowSpace(morkEnv* ev, mork_scope* outScope,
231                             morkRowSpace** outRowSpace) {
232     return this->Here(ev, outScope, outRowSpace);
233   }
234 
CutHereRowSpace(morkEnv * ev,mork_scope * outScope,morkRowSpace ** outRowSpace)235   mork_change* CutHereRowSpace(morkEnv* ev, mork_scope* outScope,
236                                morkRowSpace** outRowSpace) {
237     return this->CutHere(ev, outScope, outRowSpace);
238   }
239 };
240 
241 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
242 
243 #endif /* _MORKROWSPACE_ */
244