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 _MDB_
7 #  include "mdb.h"
8 #endif
9 
10 #ifndef _MORK_
11 #  include "mork.h"
12 #endif
13 
14 #ifndef _MORKNODE_
15 #  include "morkNode.h"
16 #endif
17 
18 #ifndef _MORKMAP_
19 #  include "morkMap.h"
20 #endif
21 
22 #ifndef _MORKSPACE_
23 #  include "morkSpace.h"
24 #endif
25 
26 #ifndef _MORKENV_
27 #  include "morkEnv.h"
28 #endif
29 
30 #ifndef _MORKSPACE_
31 #  include "morkSpace.h"
32 #endif
33 
34 #ifndef _MORKATOMSPACE_
35 #  include "morkAtomSpace.h"
36 #endif
37 
38 #ifndef _MORKPOOL_
39 #  include "morkPool.h"
40 #endif
41 
42 #ifndef _MORKSTORE_
43 #  include "morkStore.h"
44 #endif
45 
46 #ifndef _MORKATOM_
47 #  include "morkAtom.h"
48 #endif
49 
50 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
51 
52 // ````` ````` ````` ````` `````
53 // { ===== begin morkNode interface =====
54 
CloseMorkNode(morkEnv * ev)55 /*public virtual*/ void morkAtomSpace::CloseMorkNode(
56     morkEnv* ev)  // CloseAtomSpace() only if open
57 {
58   if (this->IsOpenNode()) {
59     this->MarkClosing();
60     this->CloseAtomSpace(ev);
61     this->MarkShut();
62   }
63 }
64 
65 /*public virtual*/
~morkAtomSpace()66 morkAtomSpace::~morkAtomSpace()  // assert CloseAtomSpace() executed earlier
67 {
68   MORK_ASSERT(mAtomSpace_HighUnderId == 0);
69   MORK_ASSERT(mAtomSpace_HighOverId == 0);
70   MORK_ASSERT(this->IsShutNode());
71   MORK_ASSERT(mAtomSpace_AtomAids.IsShutNode());
72   MORK_ASSERT(mAtomSpace_AtomBodies.IsShutNode());
73 }
74 
75 /*public non-poly*/
morkAtomSpace(morkEnv * ev,const morkUsage & inUsage,mork_scope inScope,morkStore * ioStore,nsIMdbHeap * ioHeap,nsIMdbHeap * ioSlotHeap)76 morkAtomSpace::morkAtomSpace(morkEnv* ev, const morkUsage& inUsage,
77                              mork_scope inScope, morkStore* ioStore,
78                              nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
79     : morkSpace(ev, inUsage, inScope, ioStore, ioHeap, ioSlotHeap),
80       mAtomSpace_HighUnderId(morkAtomSpace_kMinUnderId),
81       mAtomSpace_HighOverId(morkAtomSpace_kMinOverId),
82       mAtomSpace_AtomAids(ev, morkUsage::kMember, (nsIMdbHeap*)0, ioSlotHeap),
83       mAtomSpace_AtomBodies(ev, morkUsage::kMember, (nsIMdbHeap*)0,
84                             ioSlotHeap) {
85   // the morkSpace base constructor handles any dirty propagation
86   if (ev->Good()) mNode_Derived = morkDerived_kAtomSpace;
87 }
88 
CloseAtomSpace(morkEnv * ev)89 /*public non-poly*/ void morkAtomSpace::CloseAtomSpace(
90     morkEnv* ev)  // called by CloseMorkNode();
91 {
92   if (this->IsNode()) {
93     mAtomSpace_AtomBodies.CloseMorkNode(ev);
94     morkStore* store = mSpace_Store;
95     if (store) this->CutAllAtoms(ev, &store->mStore_Pool);
96 
97     mAtomSpace_AtomAids.CloseMorkNode(ev);
98     this->CloseSpace(ev);
99     mAtomSpace_HighUnderId = 0;
100     mAtomSpace_HighOverId = 0;
101     this->MarkShut();
102   } else
103     this->NonNodeError(ev);
104 }
105 
106 // } ===== end morkNode methods =====
107 // ````` ````` ````` ````` `````
108 
NonAtomSpaceTypeError(morkEnv * ev)109 /*static*/ void morkAtomSpace::NonAtomSpaceTypeError(morkEnv* ev) {
110   ev->NewError("non morkAtomSpace");
111 }
112 
CutAllAtoms(morkEnv * ev,morkPool * ioPool)113 mork_num morkAtomSpace::CutAllAtoms(morkEnv* ev, morkPool* ioPool) {
114 #ifdef MORK_ENABLE_ZONE_ARENAS
115   MORK_USED_2(ev, ioPool);
116   return 0;
117 #else /*MORK_ENABLE_ZONE_ARENAS*/
118   if (this->IsAtomSpaceClean()) this->MaybeDirtyStoreAndSpace();
119 
120   mork_num outSlots = mAtomSpace_AtomAids.MapFill();
121   morkBookAtom* a = 0;  // old key atom in the map
122 
123   morkStore* store = mSpace_Store;
124   mork_change* c = 0;
125   morkAtomAidMapIter i(ev, &mAtomSpace_AtomAids);
126   for (c = i.FirstAtom(ev, &a); c; c = i.NextAtom(ev, &a)) {
127     if (a) ioPool->ZapAtom(ev, a, &store->mStore_Zone);
128 
129 #  ifdef MORK_ENABLE_PROBE_MAPS
130       // do not cut anything from the map
131 #  else  /*MORK_ENABLE_PROBE_MAPS*/
132     i.CutHereAtom(ev, /*key*/ (morkBookAtom**)0);
133 #  endif /*MORK_ENABLE_PROBE_MAPS*/
134   }
135 
136   return outSlots;
137 #endif   /*MORK_ENABLE_ZONE_ARENAS*/
138 }
139 
MakeBookAtomCopyWithAid(morkEnv * ev,const morkFarBookAtom & inAtom,mork_aid inAid)140 morkBookAtom* morkAtomSpace::MakeBookAtomCopyWithAid(
141     morkEnv* ev, const morkFarBookAtom& inAtom, mork_aid inAid)
142 // Make copy of inAtom and put it in both maps, using specified ID.
143 {
144   morkBookAtom* outAtom = 0;
145   morkStore* store = mSpace_Store;
146   if (ev->Good() && store) {
147     morkPool* pool = this->GetSpaceStorePool();
148     outAtom = pool->NewFarBookAtomCopy(ev, inAtom, &store->mStore_Zone);
149     if (outAtom) {
150       if (store->mStore_CanDirty) {
151         outAtom->SetAtomDirty();
152         if (this->IsAtomSpaceClean()) this->MaybeDirtyStoreAndSpace();
153       }
154 
155       outAtom->mBookAtom_Id = inAid;
156       outAtom->mBookAtom_Space = this;
157       mAtomSpace_AtomAids.AddAtom(ev, outAtom);
158       mAtomSpace_AtomBodies.AddAtom(ev, outAtom);
159       if (this->SpaceScope() == morkAtomSpace_kColumnScope)
160         outAtom->MakeCellUseForever(ev);
161 
162       if (mAtomSpace_HighUnderId <= inAid) mAtomSpace_HighUnderId = inAid + 1;
163     }
164   }
165   return outAtom;
166 }
167 
MakeBookAtomCopy(morkEnv * ev,const morkFarBookAtom & inAtom)168 morkBookAtom* morkAtomSpace::MakeBookAtomCopy(morkEnv* ev,
169                                               const morkFarBookAtom& inAtom)
170 // make copy of inAtom and put it in both maps, using a new ID as needed.
171 {
172   morkBookAtom* outAtom = 0;
173   morkStore* store = mSpace_Store;
174   if (ev->Good() && store) {
175     if (store->mStore_CanAutoAssignAtomIdentity) {
176       morkPool* pool = this->GetSpaceStorePool();
177       morkBookAtom* atom =
178           pool->NewFarBookAtomCopy(ev, inAtom, &mSpace_Store->mStore_Zone);
179       if (atom) {
180         mork_aid id = this->MakeNewAtomId(ev, atom);
181         if (id) {
182           if (store->mStore_CanDirty) {
183             atom->SetAtomDirty();
184             if (this->IsAtomSpaceClean()) this->MaybeDirtyStoreAndSpace();
185           }
186 
187           outAtom = atom;
188           atom->mBookAtom_Space = this;
189           mAtomSpace_AtomAids.AddAtom(ev, atom);
190           mAtomSpace_AtomBodies.AddAtom(ev, atom);
191           if (this->SpaceScope() == morkAtomSpace_kColumnScope)
192             outAtom->MakeCellUseForever(ev);
193         } else
194           pool->ZapAtom(ev, atom, &mSpace_Store->mStore_Zone);
195       }
196     } else
197       mSpace_Store->CannotAutoAssignAtomIdentityError(ev);
198   }
199   return outAtom;
200 }
201 
MakeNewAtomId(morkEnv * ev,morkBookAtom * ioAtom)202 mork_aid morkAtomSpace::MakeNewAtomId(morkEnv* ev, morkBookAtom* ioAtom) {
203   mork_aid outAid = 0;
204   mork_tid id = mAtomSpace_HighUnderId;
205   mork_num count = 8;  // try up to eight times
206 
207   while (!outAid && count)  // still trying to find an unused table ID?
208   {
209     --count;
210     ioAtom->mBookAtom_Id = id;
211     if (!mAtomSpace_AtomAids.GetAtom(ev, ioAtom))
212       outAid = id;
213     else {
214       MORK_ASSERT(morkBool_kFalse);  // alert developer about ID problems
215       ++id;
216     }
217   }
218 
219   mAtomSpace_HighUnderId = id + 1;
220   return outAid;
221 }
222 
223 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
224 
~morkAtomSpaceMap()225 morkAtomSpaceMap::~morkAtomSpaceMap() {}
226 
morkAtomSpaceMap(morkEnv * ev,const morkUsage & inUsage,nsIMdbHeap * ioHeap,nsIMdbHeap * ioSlotHeap)227 morkAtomSpaceMap::morkAtomSpaceMap(morkEnv* ev, const morkUsage& inUsage,
228                                    nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
229     : morkNodeMap(ev, inUsage, ioHeap, ioSlotHeap) {
230   if (ev->Good()) mNode_Derived = morkDerived_kAtomSpaceMap;
231 }
232 
233 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
234