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 _MORKBLOB_
19 # include "morkBlob.h"
20 #endif
21
22 #ifndef _MORKMAP_
23 # include "morkMap.h"
24 #endif
25
26 #ifndef _MORKENV_
27 # include "morkEnv.h"
28 #endif
29
30 #ifndef _MORKSTORE_
31 # include "morkStore.h"
32 #endif
33
34 #ifndef _MORKFACTORY_
35 # include "morkFactory.h"
36 #endif
37
38 #ifndef _MORKNODEMAP_
39 # include "morkNodeMap.h"
40 #endif
41
42 #ifndef _MORKROW_
43 # include "morkRow.h"
44 #endif
45
46 #ifndef _MORKTHUMB_
47 # include "morkThumb.h"
48 #endif
49 // #ifndef _MORKFILE_
50 // #include "morkFile.h"
51 // #endif
52
53 #ifndef _MORKBUILDER_
54 # include "morkBuilder.h"
55 #endif
56
57 #ifndef _MORKATOMSPACE_
58 # include "morkAtomSpace.h"
59 #endif
60
61 #ifndef _MORKSTREAM_
62 # include "morkStream.h"
63 #endif
64
65 #ifndef _MORKATOMSPACE_
66 # include "morkAtomSpace.h"
67 #endif
68
69 #ifndef _MORKROWSPACE_
70 # include "morkRowSpace.h"
71 #endif
72
73 #ifndef _MORKPORTTABLECURSOR_
74 # include "morkPortTableCursor.h"
75 #endif
76
77 #ifndef _MORKTABLE_
78 # include "morkTable.h"
79 #endif
80
81 #ifndef _MORKROWMAP_
82 # include "morkRowMap.h"
83 #endif
84
85 #ifndef _MORKPARSER_
86 # include "morkParser.h"
87 #endif
88
89 #include "nsCOMPtr.h"
90
91 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
92
93 // ````` ````` ````` ````` `````
94 // { ===== begin morkNode interface =====
95
96 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
97
98 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
99
100 // ````` ````` ````` ````` `````
101 // { ===== begin morkNode interface =====
102
CloseMorkNode(morkEnv * ev)103 /*public virtual*/ void morkStore::CloseMorkNode(
104 morkEnv* ev) // ClosePort() only if open
105 {
106 if (this->IsOpenNode()) {
107 this->MarkClosing();
108 this->CloseStore(ev);
109 this->MarkShut();
110 }
111 }
112
ClosePort(morkEnv * ev)113 /*public non-poly*/ void morkStore::ClosePort(
114 morkEnv* ev) // called by CloseMorkNode();
115 {
116 if (this->IsNode()) {
117 morkFactory::SlotWeakFactory((morkFactory*)0, ev, &mPort_Factory);
118 nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*)0, ev, &mPort_Heap);
119 this->CloseObject(ev);
120 this->MarkShut();
121 } else
122 this->NonNodeError(ev);
123 }
124
125 /*public virtual*/
~morkStore()126 morkStore::~morkStore() // assert CloseStore() executed earlier
127 {
128 if (IsOpenNode()) CloseMorkNode(mMorkEnv);
129 MORK_ASSERT(this->IsShutNode());
130 MORK_ASSERT(mStore_File == 0);
131 MORK_ASSERT(mStore_InStream == 0);
132 MORK_ASSERT(mStore_OutStream == 0);
133 MORK_ASSERT(mStore_Builder == 0);
134 MORK_ASSERT(mStore_OidAtomSpace == 0);
135 MORK_ASSERT(mStore_GroundAtomSpace == 0);
136 MORK_ASSERT(mStore_GroundColumnSpace == 0);
137 MORK_ASSERT(mStore_RowSpaces.IsShutNode());
138 MORK_ASSERT(mStore_AtomSpaces.IsShutNode());
139 MORK_ASSERT(mStore_Pool.IsShutNode());
140 }
141
142 /*public non-poly*/
morkStore(morkEnv * ev,const morkUsage & inUsage,nsIMdbHeap * ioNodeHeap,morkFactory * inFactory,nsIMdbHeap * ioPortHeap)143 morkStore::morkStore(
144 morkEnv* ev, const morkUsage& inUsage,
145 nsIMdbHeap* ioNodeHeap, // the heap (if any) for this node instance
146 morkFactory* inFactory, // the factory for this
147 nsIMdbHeap* ioPortHeap // the heap to hold all content in the port
148 )
149 : morkObject(ev, inUsage, ioNodeHeap, morkColor_kNone, (morkHandle*)0),
150 mPort_Env(ev),
151 mPort_Factory(0),
152 mPort_Heap(0),
153 mStore_OidAtomSpace(0),
154 mStore_GroundAtomSpace(0),
155 mStore_GroundColumnSpace(0)
156
157 ,
158 mStore_File(0),
159 mStore_InStream(0),
160 mStore_Builder(0),
161 mStore_OutStream(0)
162
163 ,
164 mStore_RowSpaces(ev, morkUsage::kMember, (nsIMdbHeap*)0, ioPortHeap),
165 mStore_AtomSpaces(ev, morkUsage::kMember, (nsIMdbHeap*)0, ioPortHeap),
166 mStore_Zone(ev, morkUsage::kMember, (nsIMdbHeap*)0, ioPortHeap),
167 mStore_Pool(ev, morkUsage::kMember, (nsIMdbHeap*)0, ioPortHeap)
168
169 ,
170 mStore_CommitGroupIdentity(0)
171
172 ,
173 mStore_FirstCommitGroupPos(0),
174 mStore_SecondCommitGroupPos(0)
175
176 // disable auto-assignment of atom IDs until someone knows it is okay:
177 ,
178 mStore_CanAutoAssignAtomIdentity(morkBool_kFalse),
179 mStore_CanDirty(morkBool_kFalse) // not until the store is open
180 ,
181 mStore_CanWriteIncremental(morkBool_kTrue) // always with few exceptions
182 {
183 if (ev->Good()) {
184 if (inFactory && ioPortHeap) {
185 morkFactory::SlotWeakFactory(inFactory, ev, &mPort_Factory);
186 nsIMdbHeap_SlotStrongHeap(ioPortHeap, ev, &mPort_Heap);
187 if (ev->Good()) mNode_Derived = morkDerived_kPort;
188 } else
189 ev->NilPointerError();
190 }
191 if (ev->Good()) {
192 mNode_Derived = morkDerived_kStore;
193 }
194 }
195
NS_IMPL_ISUPPORTS_INHERITED(morkStore,morkObject,nsIMdbStore)196 NS_IMPL_ISUPPORTS_INHERITED(morkStore, morkObject, nsIMdbStore)
197
198 /*public non-poly*/ void morkStore::CloseStore(
199 morkEnv* ev) // called by CloseMorkNode();
200 {
201 if (this->IsNode()) {
202 nsIMdbFile* file = mStore_File;
203 file->AddRef();
204
205 morkFactory::SlotWeakFactory((morkFactory*)0, ev, &mPort_Factory);
206 nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*)0, ev, &mPort_Heap);
207 morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
208 &mStore_OidAtomSpace);
209 morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
210 &mStore_GroundAtomSpace);
211 morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*)0, ev,
212 &mStore_GroundColumnSpace);
213 mStore_RowSpaces.CloseMorkNode(ev);
214 mStore_AtomSpaces.CloseMorkNode(ev);
215 morkBuilder::SlotStrongBuilder((morkBuilder*)0, ev, &mStore_Builder);
216
217 nsIMdbFile_SlotStrongFile((nsIMdbFile*)0, ev, &mStore_File);
218
219 file->Release();
220
221 morkStream::SlotStrongStream((morkStream*)0, ev, &mStore_InStream);
222 morkStream::SlotStrongStream((morkStream*)0, ev, &mStore_OutStream);
223
224 mStore_Pool.CloseMorkNode(ev);
225 mStore_Zone.CloseMorkNode(ev);
226 this->ClosePort(ev);
227 this->MarkShut();
228 } else
229 this->NonNodeError(ev);
230 }
231
232 // } ===== end morkNode methods =====
233 // ````` ````` ````` ````` `````
234
DoPreferLargeOverCompressCommit(morkEnv * ev)235 mork_bool morkStore::DoPreferLargeOverCompressCommit(morkEnv* ev)
236 // true when mStore_CanWriteIncremental && store has file large enough
237 {
238 nsIMdbFile* file = mStore_File;
239 if (file && mStore_CanWriteIncremental) {
240 mdb_pos fileEof = 0;
241 file->Eof(ev->AsMdbEnv(), &fileEof);
242 if (ev->Good() && fileEof > 128) return morkBool_kTrue;
243 }
244 return morkBool_kFalse;
245 }
246
PercentOfStoreWasted(morkEnv * ev)247 mork_percent morkStore::PercentOfStoreWasted(morkEnv* ev) {
248 mork_percent outPercent = 0;
249 nsIMdbFile* file = mStore_File;
250
251 if (file) {
252 mork_pos firstPos = mStore_FirstCommitGroupPos;
253 mork_pos secondPos = mStore_SecondCommitGroupPos;
254 if (firstPos || secondPos) {
255 if (firstPos < 512 && secondPos > firstPos)
256 firstPos = secondPos; // better approximation of first commit
257
258 mork_pos fileLength = 0;
259 file->Eof(ev->AsMdbEnv(), &fileLength); // end of file
260 if (ev->Good() && fileLength > firstPos) {
261 mork_size groupContent = fileLength - firstPos;
262 outPercent = (groupContent * 100) / fileLength;
263 }
264 }
265 } else
266 this->NilStoreFileError(ev);
267
268 return outPercent;
269 }
270
SetStoreAndAllSpacesCanDirty(morkEnv * ev,mork_bool inCanDirty)271 void morkStore::SetStoreAndAllSpacesCanDirty(morkEnv* ev,
272 mork_bool inCanDirty) {
273 mStore_CanDirty = inCanDirty;
274
275 mork_change* c = 0;
276 mork_scope* key = 0; // ignore keys in maps
277
278 if (ev->Good()) {
279 morkAtomSpaceMapIter asi(ev, &mStore_AtomSpaces);
280
281 morkAtomSpace* atomSpace = 0; // old val node in the map
282
283 for (c = asi.FirstAtomSpace(ev, key, &atomSpace); c && ev->Good();
284 c = asi.NextAtomSpace(ev, key, &atomSpace)) {
285 if (atomSpace) {
286 if (atomSpace->IsAtomSpace())
287 atomSpace->mSpace_CanDirty = inCanDirty;
288 else
289 atomSpace->NonAtomSpaceTypeError(ev);
290 } else
291 ev->NilPointerError();
292 }
293 }
294
295 if (ev->Good()) {
296 morkRowSpaceMapIter rsi(ev, &mStore_RowSpaces);
297 morkRowSpace* rowSpace = 0; // old val node in the map
298
299 for (c = rsi.FirstRowSpace(ev, key, &rowSpace); c && ev->Good();
300 c = rsi.NextRowSpace(ev, key, &rowSpace)) {
301 if (rowSpace) {
302 if (rowSpace->IsRowSpace())
303 rowSpace->mSpace_CanDirty = inCanDirty;
304 else
305 rowSpace->NonRowSpaceTypeError(ev);
306 }
307 }
308 }
309 }
310
RenumberAllCollectableContent(morkEnv * ev)311 void morkStore::RenumberAllCollectableContent(morkEnv* ev) {
312 MORK_USED_1(ev);
313 // do nothing currently
314 }
315
AcquireStoreHandle(morkEnv * ev)316 nsIMdbStore* morkStore::AcquireStoreHandle(morkEnv* ev) { return this; }
317
StageAliasAsFarBookAtom(morkEnv * ev,const morkMid * inMid,morkAtomSpace * ioSpace,mork_cscode inForm)318 morkFarBookAtom* morkStore::StageAliasAsFarBookAtom(morkEnv* ev,
319 const morkMid* inMid,
320 morkAtomSpace* ioSpace,
321 mork_cscode inForm) {
322 if (inMid && inMid->mMid_Buf) {
323 const morkBuf* buf = inMid->mMid_Buf;
324 mork_size length = buf->mBuf_Fill;
325 if (length <= morkBookAtom_kMaxBodySize) {
326 mork_aid dummyAid = 1;
327 // mStore_BookAtom.InitMaxBookAtom(ev, *buf,
328 // inForm, ioSpace, dummyAid);
329
330 mStore_FarBookAtom.InitFarBookAtom(ev, *buf, inForm, ioSpace, dummyAid);
331 return &mStore_FarBookAtom;
332 }
333 } else
334 ev->NilPointerError();
335
336 return (morkFarBookAtom*)0;
337 }
338
StageYarnAsFarBookAtom(morkEnv * ev,const mdbYarn * inYarn,morkAtomSpace * ioSpace)339 morkFarBookAtom* morkStore::StageYarnAsFarBookAtom(morkEnv* ev,
340 const mdbYarn* inYarn,
341 morkAtomSpace* ioSpace) {
342 if (inYarn && inYarn->mYarn_Buf) {
343 mork_size length = inYarn->mYarn_Fill;
344 if (length <= morkBookAtom_kMaxBodySize) {
345 morkBuf buf(inYarn->mYarn_Buf, length);
346 mork_aid dummyAid = 1;
347 // mStore_BookAtom.InitMaxBookAtom(ev, buf,
348 // inYarn->mYarn_Form, ioSpace, dummyAid);
349 mStore_FarBookAtom.InitFarBookAtom(ev, buf, inYarn->mYarn_Form, ioSpace,
350 dummyAid);
351 return &mStore_FarBookAtom;
352 }
353 } else
354 ev->NilPointerError();
355
356 return (morkFarBookAtom*)0;
357 }
358
StageStringAsFarBookAtom(morkEnv * ev,const char * inString,mork_cscode inForm,morkAtomSpace * ioSpace)359 morkFarBookAtom* morkStore::StageStringAsFarBookAtom(morkEnv* ev,
360 const char* inString,
361 mork_cscode inForm,
362 morkAtomSpace* ioSpace) {
363 if (inString) {
364 mork_size length = strlen(inString);
365 if (length <= morkBookAtom_kMaxBodySize) {
366 morkBuf buf(inString, length);
367 mork_aid dummyAid = 1;
368 // mStore_BookAtom.InitMaxBookAtom(ev, buf, inForm, ioSpace, dummyAid);
369 mStore_FarBookAtom.InitFarBookAtom(ev, buf, inForm, ioSpace, dummyAid);
370 return &mStore_FarBookAtom;
371 }
372 } else
373 ev->NilPointerError();
374
375 return (morkFarBookAtom*)0;
376 }
377
LazyGetOidAtomSpace(morkEnv * ev)378 morkAtomSpace* morkStore::LazyGetOidAtomSpace(morkEnv* ev) {
379 MORK_USED_1(ev);
380 if (!mStore_OidAtomSpace) {
381 }
382 return mStore_OidAtomSpace;
383 }
384
LazyGetGroundAtomSpace(morkEnv * ev)385 morkAtomSpace* morkStore::LazyGetGroundAtomSpace(morkEnv* ev) {
386 if (!mStore_GroundAtomSpace) {
387 mork_scope atomScope = morkStore_kValueSpaceScope;
388 nsIMdbHeap* heap = mPort_Heap;
389 morkAtomSpace* space = new (*heap, ev)
390 morkAtomSpace(ev, morkUsage::kHeap, atomScope, this, heap, heap);
391
392 if (space) // successful space creation?
393 {
394 this->MaybeDirtyStore();
395
396 mStore_GroundAtomSpace = space; // transfer strong ref to this slot
397 mStore_AtomSpaces.AddAtomSpace(ev, space);
398 }
399 }
400 return mStore_GroundAtomSpace;
401 }
402
LazyGetGroundColumnSpace(morkEnv * ev)403 morkAtomSpace* morkStore::LazyGetGroundColumnSpace(morkEnv* ev) {
404 if (!mStore_GroundColumnSpace) {
405 mork_scope atomScope = morkStore_kGroundColumnSpace;
406 nsIMdbHeap* heap = mPort_Heap;
407 morkAtomSpace* space = new (*heap, ev)
408 morkAtomSpace(ev, morkUsage::kHeap, atomScope, this, heap, heap);
409
410 if (space) // successful space creation?
411 {
412 this->MaybeDirtyStore();
413
414 mStore_GroundColumnSpace = space; // transfer strong ref to this slot
415 mStore_AtomSpaces.AddAtomSpace(ev, space);
416 }
417 }
418 return mStore_GroundColumnSpace;
419 }
420
LazyGetInStream(morkEnv * ev)421 morkStream* morkStore::LazyGetInStream(morkEnv* ev) {
422 if (!mStore_InStream) {
423 nsIMdbFile* file = mStore_File;
424 if (file) {
425 morkStream* stream = new (*mPort_Heap, ev)
426 morkStream(ev, morkUsage::kHeap, mPort_Heap, file,
427 morkStore_kStreamBufSize, /*frozen*/ morkBool_kTrue);
428 if (stream) {
429 this->MaybeDirtyStore();
430 mStore_InStream = stream; // transfer strong ref to this slot
431 }
432 } else
433 this->NilStoreFileError(ev);
434 }
435 return mStore_InStream;
436 }
437
LazyGetOutStream(morkEnv * ev)438 morkStream* morkStore::LazyGetOutStream(morkEnv* ev) {
439 if (!mStore_OutStream) {
440 nsIMdbFile* file = mStore_File;
441 if (file) {
442 morkStream* stream = new (*mPort_Heap, ev)
443 morkStream(ev, morkUsage::kHeap, mPort_Heap, file,
444 morkStore_kStreamBufSize, /*frozen*/ morkBool_kFalse);
445 if (stream) {
446 this->MaybeDirtyStore();
447 mStore_InStream = stream; // transfer strong ref to this slot
448 }
449 } else
450 this->NilStoreFileError(ev);
451 }
452 return mStore_OutStream;
453 }
454
ForgetBuilder(morkEnv * ev)455 void morkStore::ForgetBuilder(morkEnv* ev) {
456 if (mStore_Builder)
457 morkBuilder::SlotStrongBuilder((morkBuilder*)0, ev, &mStore_Builder);
458 if (mStore_InStream)
459 morkStream::SlotStrongStream((morkStream*)0, ev, &mStore_InStream);
460 }
461
LazyGetBuilder(morkEnv * ev)462 morkBuilder* morkStore::LazyGetBuilder(morkEnv* ev) {
463 if (!mStore_Builder) {
464 morkStream* stream = this->LazyGetInStream(ev);
465 if (stream) {
466 nsIMdbHeap* heap = mPort_Heap;
467 morkBuilder* builder = new (*heap, ev)
468 morkBuilder(ev, morkUsage::kHeap, heap, stream,
469 morkBuilder_kDefaultBytesPerParseSegment, heap, this);
470 if (builder) {
471 mStore_Builder = builder; // transfer strong ref to this slot
472 }
473 }
474 }
475 return mStore_Builder;
476 }
477
LazyGetRowSpace(morkEnv * ev,mdb_scope inRowScope)478 morkRowSpace* morkStore::LazyGetRowSpace(morkEnv* ev, mdb_scope inRowScope) {
479 morkRowSpace* outSpace = mStore_RowSpaces.GetRowSpace(ev, inRowScope);
480 if (!outSpace && ev->Good()) // try to make new space?
481 {
482 nsIMdbHeap* heap = mPort_Heap;
483 outSpace = new (*heap, ev)
484 morkRowSpace(ev, morkUsage::kHeap, inRowScope, this, heap, heap);
485
486 if (outSpace) // successful space creation?
487 {
488 this->MaybeDirtyStore();
489
490 // note adding to node map creates its own strong ref...
491 if (mStore_RowSpaces.AddRowSpace(ev, outSpace))
492 outSpace->CutStrongRef(ev); // ...so we can drop our strong ref
493 }
494 }
495 return outSpace;
496 }
497
LazyGetAtomSpace(morkEnv * ev,mdb_scope inAtomScope)498 morkAtomSpace* morkStore::LazyGetAtomSpace(morkEnv* ev, mdb_scope inAtomScope) {
499 morkAtomSpace* outSpace = mStore_AtomSpaces.GetAtomSpace(ev, inAtomScope);
500 if (!outSpace && ev->Good()) // try to make new space?
501 {
502 if (inAtomScope == morkStore_kValueSpaceScope)
503 outSpace = this->LazyGetGroundAtomSpace(ev);
504
505 else if (inAtomScope == morkStore_kGroundColumnSpace)
506 outSpace = this->LazyGetGroundColumnSpace(ev);
507 else {
508 nsIMdbHeap* heap = mPort_Heap;
509 outSpace = new (*heap, ev)
510 morkAtomSpace(ev, morkUsage::kHeap, inAtomScope, this, heap, heap);
511
512 if (outSpace) // successful space creation?
513 {
514 this->MaybeDirtyStore();
515
516 // note adding to node map creates its own strong ref...
517 if (mStore_AtomSpaces.AddAtomSpace(ev, outSpace))
518 outSpace->CutStrongRef(ev); // ...so we can drop our strong ref
519 }
520 }
521 }
522 return outSpace;
523 }
524
NonStoreTypeError(morkEnv * ev)525 /*static*/ void morkStore::NonStoreTypeError(morkEnv* ev) {
526 ev->NewError("non morkStore");
527 }
528
NilStoreFileError(morkEnv * ev)529 /*static*/ void morkStore::NilStoreFileError(morkEnv* ev) {
530 ev->NewError("nil mStore_File");
531 }
532
CannotAutoAssignAtomIdentityError(morkEnv * ev)533 /*static*/ void morkStore::CannotAutoAssignAtomIdentityError(morkEnv* ev) {
534 ev->NewError("false mStore_CanAutoAssignAtomIdentity");
535 }
536
OpenStoreFile(morkEnv * ev,mork_bool inFrozen,nsIMdbFile * ioFile,const mdbOpenPolicy * inOpenPolicy)537 mork_bool morkStore::OpenStoreFile(
538 morkEnv* ev, mork_bool inFrozen,
539 // const char* inFilePath,
540 nsIMdbFile* ioFile, // db abstract file interface
541 const mdbOpenPolicy* inOpenPolicy) {
542 MORK_USED_2(inOpenPolicy, inFrozen);
543 nsIMdbFile_SlotStrongFile(ioFile, ev, &mStore_File);
544
545 // if ( ev->Good() )
546 // {
547 // morkFile* file = morkFile::OpenOldFile(ev, mPort_Heap,
548 // inFilePath, inFrozen);
549 // if ( ioFile )
550 // {
551 // if ( ev->Good() )
552 // morkFile::SlotStrongFile(file, ev, &mStore_File);
553 // else
554 // file->CutStrongRef(ev);
555 //
556 // }
557 // }
558 return ev->Good();
559 }
560
CreateStoreFile(morkEnv * ev,nsIMdbFile * ioFile,const mdbOpenPolicy * inOpenPolicy)561 mork_bool morkStore::CreateStoreFile(
562 morkEnv* ev,
563 // const char* inFilePath,
564 nsIMdbFile* ioFile, // db abstract file interface
565 const mdbOpenPolicy* inOpenPolicy) {
566 MORK_USED_1(inOpenPolicy);
567 nsIMdbFile_SlotStrongFile(ioFile, ev, &mStore_File);
568
569 return ev->Good();
570 }
571
CopyAtom(morkEnv * ev,const morkAtom * inAtom)572 morkAtom* morkStore::CopyAtom(morkEnv* ev, const morkAtom* inAtom)
573 // copy inAtom (from some other store) over to this store
574 {
575 morkAtom* outAtom = 0;
576 if (inAtom) {
577 mdbYarn yarn;
578 if (morkAtom::AliasYarn(inAtom, &yarn))
579 outAtom = this->YarnToAtom(ev, &yarn, true /* create */);
580 }
581 return outAtom;
582 }
583
YarnToAtom(morkEnv * ev,const mdbYarn * inYarn,bool createIfMissing)584 morkAtom* morkStore::YarnToAtom(morkEnv* ev, const mdbYarn* inYarn,
585 bool createIfMissing /* = true */) {
586 morkAtom* outAtom = 0;
587 if (ev->Good()) {
588 morkAtomSpace* groundSpace = this->LazyGetGroundAtomSpace(ev);
589 if (groundSpace) {
590 morkFarBookAtom* keyAtom =
591 this->StageYarnAsFarBookAtom(ev, inYarn, groundSpace);
592
593 if (keyAtom) {
594 morkAtomBodyMap* map = &groundSpace->mAtomSpace_AtomBodies;
595 outAtom = map->GetAtom(ev, keyAtom);
596 if (!outAtom && createIfMissing) {
597 this->MaybeDirtyStore();
598 outAtom = groundSpace->MakeBookAtomCopy(ev, *keyAtom);
599 }
600 } else if (ev->Good()) {
601 morkBuf b(inYarn->mYarn_Buf, inYarn->mYarn_Fill);
602 morkZone* z = &mStore_Zone;
603 outAtom = mStore_Pool.NewAnonAtom(ev, b, inYarn->mYarn_Form, z);
604 }
605 }
606 }
607 return outAtom;
608 }
609
MidToOid(morkEnv * ev,const morkMid & inMid,mdbOid * outOid)610 mork_bool morkStore::MidToOid(morkEnv* ev, const morkMid& inMid,
611 mdbOid* outOid) {
612 *outOid = inMid.mMid_Oid;
613 const morkBuf* buf = inMid.mMid_Buf;
614 if (buf && !outOid->mOid_Scope) {
615 if (buf->mBuf_Fill <= morkBookAtom_kMaxBodySize) {
616 if (buf->mBuf_Fill == 1) {
617 mork_u1* name = (mork_u1*)buf->mBuf_Body;
618 if (name) {
619 outOid->mOid_Scope = (mork_scope)*name;
620 return ev->Good();
621 }
622 }
623 morkAtomSpace* groundSpace = this->LazyGetGroundColumnSpace(ev);
624 if (groundSpace) {
625 mork_cscode form = 0; // default
626 mork_aid aid = 1; // dummy
627 mStore_FarBookAtom.InitFarBookAtom(ev, *buf, form, groundSpace, aid);
628 morkFarBookAtom* keyAtom = &mStore_FarBookAtom;
629 morkAtomBodyMap* map = &groundSpace->mAtomSpace_AtomBodies;
630 morkBookAtom* bookAtom = map->GetAtom(ev, keyAtom);
631 if (bookAtom)
632 outOid->mOid_Scope = bookAtom->mBookAtom_Id;
633 else {
634 this->MaybeDirtyStore();
635 bookAtom = groundSpace->MakeBookAtomCopy(ev, *keyAtom);
636 if (bookAtom) {
637 outOid->mOid_Scope = bookAtom->mBookAtom_Id;
638 bookAtom->MakeCellUseForever(ev);
639 }
640 }
641 }
642 }
643 }
644 return ev->Good();
645 }
646
MidToRow(morkEnv * ev,const morkMid & inMid)647 morkRow* morkStore::MidToRow(morkEnv* ev, const morkMid& inMid) {
648 mdbOid tempOid;
649 this->MidToOid(ev, inMid, &tempOid);
650 return this->OidToRow(ev, &tempOid);
651 }
652
MidToTable(morkEnv * ev,const morkMid & inMid)653 morkTable* morkStore::MidToTable(morkEnv* ev, const morkMid& inMid) {
654 mdbOid tempOid;
655 this->MidToOid(ev, inMid, &tempOid);
656 return this->OidToTable(ev, &tempOid, /*metarow*/ (mdbOid*)0);
657 }
658
MidToYarn(morkEnv * ev,const morkMid & inMid,mdbYarn * outYarn)659 mork_bool morkStore::MidToYarn(morkEnv* ev, const morkMid& inMid,
660 mdbYarn* outYarn) {
661 mdbOid tempOid;
662 this->MidToOid(ev, inMid, &tempOid);
663 return this->OidToYarn(ev, tempOid, outYarn);
664 }
665
OidToYarn(morkEnv * ev,const mdbOid & inOid,mdbYarn * outYarn)666 mork_bool morkStore::OidToYarn(morkEnv* ev, const mdbOid& inOid,
667 mdbYarn* outYarn) {
668 morkBookAtom* atom = 0;
669
670 morkAtomSpace* atomSpace =
671 mStore_AtomSpaces.GetAtomSpace(ev, inOid.mOid_Scope);
672 if (atomSpace) {
673 morkAtomAidMap* map = &atomSpace->mAtomSpace_AtomAids;
674 atom = map->GetAid(ev, (mork_aid)inOid.mOid_Id);
675 }
676 morkAtom::GetYarn(atom, outYarn);
677
678 return ev->Good();
679 }
680
MidToAtom(morkEnv * ev,const morkMid & inMid)681 morkBookAtom* morkStore::MidToAtom(morkEnv* ev, const morkMid& inMid) {
682 morkBookAtom* outAtom = 0;
683 mdbOid oid;
684 if (this->MidToOid(ev, inMid, &oid)) {
685 morkAtomSpace* atomSpace =
686 mStore_AtomSpaces.GetAtomSpace(ev, oid.mOid_Scope);
687 if (atomSpace) {
688 morkAtomAidMap* map = &atomSpace->mAtomSpace_AtomAids;
689 outAtom = map->GetAid(ev, (mork_aid)oid.mOid_Id);
690 }
691 }
692 return outAtom;
693 }
694
SmallTokenToOneByteYarn(morkEnv * ev,mdb_token inToken,mdbYarn * outYarn)695 /*static*/ void morkStore::SmallTokenToOneByteYarn(morkEnv* ev,
696 mdb_token inToken,
697 mdbYarn* outYarn) {
698 MORK_USED_1(ev);
699 if (outYarn->mYarn_Buf && outYarn->mYarn_Size) // any space in yarn at all?
700 {
701 mork_u1* buf = (mork_u1*)outYarn->mYarn_Buf; // for byte arithmetic
702 buf[0] = (mork_u1)inToken; // write the single byte
703 outYarn->mYarn_Fill = 1;
704 outYarn->mYarn_More = 0;
705 } else // just record we could not write the single byte
706 {
707 outYarn->mYarn_More = 1;
708 outYarn->mYarn_Fill = 0;
709 }
710 }
711
TokenToString(morkEnv * ev,mdb_token inToken,mdbYarn * outTokenName)712 void morkStore::TokenToString(morkEnv* ev, mdb_token inToken,
713 mdbYarn* outTokenName) {
714 if (inToken > morkAtomSpace_kMaxSevenBitAid) {
715 morkBookAtom* atom = 0;
716 morkAtomSpace* space = mStore_GroundColumnSpace;
717 if (space) atom = space->mAtomSpace_AtomAids.GetAid(ev, (mork_aid)inToken);
718
719 morkAtom::GetYarn(atom, outTokenName);
720 } else // token is an "immediate" single byte string representation?
721 this->SmallTokenToOneByteYarn(ev, inToken, outTokenName);
722 }
723
724 // void
725 // morkStore::SyncTokenIdChange(morkEnv* ev, const morkBookAtom* inAtom,
726 // const mdbOid* inOid)
727 // {
728 // mork_token mStore_MorkNoneToken; // token for "mork:none" // fill=9
729 // mork_column mStore_CharsetToken; // token for "charset" // fill=7
730 // mork_column mStore_AtomScopeToken; // token for "atomScope" // fill=9
731 // mork_column mStore_RowScopeToken; // token for "rowScope" // fill=8
732 // mork_column mStore_TableScopeToken; // token for "tableScope" // fill=10
733 // mork_column mStore_ColumnScopeToken; // token for "columnScope" // fill=11
734 // mork_kind mStore_TableKindToken; // token for "tableKind" // fill=9
735 // ---------------------ruler-for-token-length-above---123456789012
736 //
737 // if ( inOid->mOid_Scope == morkStore_kColumnSpaceScope &&
738 // inAtom->IsWeeBook() )
739 // {
740 // const mork_u1* body = ((const morkWeeBookAtom*)
741 // inAtom)->mWeeBookAtom_Body; mork_size size = inAtom->mAtom_Size;
742 //
743 // if ( size >= 7 && size <= 11 )
744 // {
745 // if ( size == 9 )
746 // {
747 // if ( *body == 'm' )
748 // {
749 // if ( MORK_MEMCMP(body, "mork:none", 9) == 0 )
750 // mStore_MorkNoneToken = inAtom->mBookAtom_Id;
751 // }
752 // else if ( *body == 'a' )
753 // {
754 // if ( MORK_MEMCMP(body, "atomScope", 9) == 0 )
755 // mStore_AtomScopeToken = inAtom->mBookAtom_Id;
756 // }
757 // else if ( *body == 't' )
758 // {
759 // if ( MORK_MEMCMP(body, "tableKind", 9) == 0 )
760 // mStore_TableKindToken = inAtom->mBookAtom_Id;
761 // }
762 // }
763 // else if ( size == 7 && *body == 'c' )
764 // {
765 // if ( MORK_MEMCMP(body, "charset", 7) == 0 )
766 // mStore_CharsetToken = inAtom->mBookAtom_Id;
767 // }
768 // else if ( size == 8 && *body == 'r' )
769 // {
770 // if ( MORK_MEMCMP(body, "rowScope", 8) == 0 )
771 // mStore_RowScopeToken = inAtom->mBookAtom_Id;
772 // }
773 // else if ( size == 10 && *body == 't' )
774 // {
775 // if ( MORK_MEMCMP(body, "tableScope", 10) == 0 )
776 // mStore_TableScopeToken = inAtom->mBookAtom_Id;
777 // }
778 // else if ( size == 11 && *body == 'c' )
779 // {
780 // if ( MORK_MEMCMP(body, "columnScope", 11) == 0 )
781 // mStore_ColumnScopeToken = inAtom->mBookAtom_Id;
782 // }
783 // }
784 // }
785 // }
786
AddAlias(morkEnv * ev,const morkMid & inMid,mork_cscode inForm)787 morkAtom* morkStore::AddAlias(morkEnv* ev, const morkMid& inMid,
788 mork_cscode inForm) {
789 morkBookAtom* outAtom = 0;
790 if (ev->Good()) {
791 const mdbOid* oid = &inMid.mMid_Oid;
792 morkAtomSpace* atomSpace = this->LazyGetAtomSpace(ev, oid->mOid_Scope);
793 if (atomSpace) {
794 morkFarBookAtom* keyAtom =
795 this->StageAliasAsFarBookAtom(ev, &inMid, atomSpace, inForm);
796 if (keyAtom) {
797 morkAtomAidMap* map = &atomSpace->mAtomSpace_AtomAids;
798 outAtom = map->GetAid(ev, (mork_aid)oid->mOid_Id);
799 if (outAtom) {
800 if (!outAtom->EqualFormAndBody(ev, keyAtom))
801 ev->NewError("duplicate alias ID");
802 } else {
803 this->MaybeDirtyStore();
804 keyAtom->mBookAtom_Id = oid->mOid_Id;
805 outAtom = atomSpace->MakeBookAtomCopyWithAid(ev, *keyAtom,
806 (mork_aid)oid->mOid_Id);
807
808 // if ( outAtom && outAtom->IsWeeBook() )
809 // {
810 // if ( oid->mOid_Scope == morkStore_kColumnSpaceScope )
811 // {
812 // mork_size size = outAtom->mAtom_Size;
813 // if ( size >= 7 && size <= 11 )
814 // this->SyncTokenIdChange(ev, outAtom, oid);
815 // }
816 // }
817 }
818 }
819 }
820 }
821 return outAtom;
822 }
823
824 #define morkStore_kMaxCopyTokenSize 512 /* if larger, cannot be copied */
825
CopyToken(morkEnv * ev,mdb_token inToken,morkStore * inStore)826 mork_token morkStore::CopyToken(morkEnv* ev, mdb_token inToken,
827 morkStore* inStore)
828 // copy inToken from inStore over to this store
829 {
830 mork_token outToken = 0;
831 if (inStore == this) // same store?
832 outToken = inToken; // just return token unchanged
833 else {
834 char yarnBuf[morkStore_kMaxCopyTokenSize];
835 mdbYarn yarn;
836 yarn.mYarn_Buf = yarnBuf;
837 yarn.mYarn_Fill = 0;
838 yarn.mYarn_Size = morkStore_kMaxCopyTokenSize;
839 yarn.mYarn_More = 0;
840 yarn.mYarn_Form = 0;
841 yarn.mYarn_Grow = 0;
842
843 inStore->TokenToString(ev, inToken, &yarn);
844 if (ev->Good()) {
845 morkBuf buf(yarn.mYarn_Buf, yarn.mYarn_Fill);
846 outToken = this->BufToToken(ev, &buf);
847 }
848 }
849 return outToken;
850 }
851
BufToToken(morkEnv * ev,const morkBuf * inBuf)852 mork_token morkStore::BufToToken(morkEnv* ev, const morkBuf* inBuf) {
853 mork_token outToken = 0;
854 if (ev->Good()) {
855 const mork_u1* s = (const mork_u1*)inBuf->mBuf_Body;
856 mork_bool nonAscii = (*s > 0x7F);
857 mork_size length = inBuf->mBuf_Fill;
858 if (nonAscii || length > 1) // more than one byte?
859 {
860 mork_cscode form = 0; // default charset
861 morkAtomSpace* space = this->LazyGetGroundColumnSpace(ev);
862 if (space) {
863 morkFarBookAtom* keyAtom = 0;
864 if (length <= morkBookAtom_kMaxBodySize) {
865 mork_aid aid = 1; // dummy
866 // mStore_BookAtom.InitMaxBookAtom(ev, *inBuf, form, space, aid);
867 mStore_FarBookAtom.InitFarBookAtom(ev, *inBuf, form, space, aid);
868 keyAtom = &mStore_FarBookAtom;
869 }
870 if (keyAtom) {
871 morkAtomBodyMap* map = &space->mAtomSpace_AtomBodies;
872 morkBookAtom* bookAtom = map->GetAtom(ev, keyAtom);
873 if (bookAtom)
874 outToken = bookAtom->mBookAtom_Id;
875 else {
876 this->MaybeDirtyStore();
877 bookAtom = space->MakeBookAtomCopy(ev, *keyAtom);
878 if (bookAtom) {
879 outToken = bookAtom->mBookAtom_Id;
880 bookAtom->MakeCellUseForever(ev);
881 }
882 }
883 }
884 }
885 } else // only a single byte in inTokenName string:
886 outToken = *s;
887 }
888
889 return outToken;
890 }
891
StringToToken(morkEnv * ev,const char * inTokenName)892 mork_token morkStore::StringToToken(morkEnv* ev, const char* inTokenName) {
893 mork_token outToken = 0;
894 if (ev->Good()) {
895 const mork_u1* s = (const mork_u1*)inTokenName;
896 mork_bool nonAscii = (*s > 0x7F);
897 if (nonAscii || (*s && s[1])) // more than one byte?
898 {
899 mork_cscode form = 0; // default charset
900 morkAtomSpace* groundSpace = this->LazyGetGroundColumnSpace(ev);
901 if (groundSpace) {
902 morkFarBookAtom* keyAtom =
903 this->StageStringAsFarBookAtom(ev, inTokenName, form, groundSpace);
904 if (keyAtom) {
905 morkAtomBodyMap* map = &groundSpace->mAtomSpace_AtomBodies;
906 morkBookAtom* bookAtom = map->GetAtom(ev, keyAtom);
907 if (bookAtom)
908 outToken = bookAtom->mBookAtom_Id;
909 else {
910 this->MaybeDirtyStore();
911 bookAtom = groundSpace->MakeBookAtomCopy(ev, *keyAtom);
912 if (bookAtom) {
913 outToken = bookAtom->mBookAtom_Id;
914 bookAtom->MakeCellUseForever(ev);
915 }
916 }
917 }
918 }
919 } else // only a single byte in inTokenName string:
920 outToken = *s;
921 }
922
923 return outToken;
924 }
925
QueryToken(morkEnv * ev,const char * inTokenName)926 mork_token morkStore::QueryToken(morkEnv* ev, const char* inTokenName) {
927 mork_token outToken = 0;
928 if (ev->Good()) {
929 const mork_u1* s = (const mork_u1*)inTokenName;
930 mork_bool nonAscii = (*s > 0x7F);
931 if (nonAscii || (*s && s[1])) // more than one byte?
932 {
933 mork_cscode form = 0; // default charset
934 morkAtomSpace* groundSpace = this->LazyGetGroundColumnSpace(ev);
935 if (groundSpace) {
936 morkFarBookAtom* keyAtom =
937 this->StageStringAsFarBookAtom(ev, inTokenName, form, groundSpace);
938 if (keyAtom) {
939 morkAtomBodyMap* map = &groundSpace->mAtomSpace_AtomBodies;
940 morkBookAtom* bookAtom = map->GetAtom(ev, keyAtom);
941 if (bookAtom) {
942 outToken = bookAtom->mBookAtom_Id;
943 bookAtom->MakeCellUseForever(ev);
944 }
945 }
946 }
947 } else // only a single byte in inTokenName string:
948 outToken = *s;
949 }
950
951 return outToken;
952 }
953
HasTableKind(morkEnv * ev,mdb_scope inRowScope,mdb_kind inTableKind,mdb_count * outTableCount)954 mork_bool morkStore::HasTableKind(morkEnv* ev, mdb_scope inRowScope,
955 mdb_kind inTableKind,
956 mdb_count* outTableCount) {
957 MORK_USED_2(inRowScope, inTableKind);
958 mork_bool outBool = morkBool_kFalse;
959 mdb_count tableCount = 0;
960
961 ev->StubMethodOnlyError();
962
963 if (outTableCount) *outTableCount = tableCount;
964 return outBool;
965 }
966
GetTableKind(morkEnv * ev,mdb_scope inRowScope,mdb_kind inTableKind,mdb_count * outTableCount,mdb_bool * outMustBeUnique)967 morkTable* morkStore::GetTableKind(morkEnv* ev, mdb_scope inRowScope,
968 mdb_kind inTableKind,
969 mdb_count* outTableCount,
970 mdb_bool* outMustBeUnique) {
971 morkTable* outTable = 0;
972 if (ev->Good()) {
973 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inRowScope);
974 if (rowSpace) {
975 outTable = rowSpace->FindTableByKind(ev, inTableKind);
976 if (outTable) {
977 if (outTableCount) *outTableCount = outTable->GetRowCount();
978 if (outMustBeUnique) *outMustBeUnique = outTable->IsTableUnique();
979 }
980 }
981 }
982 return outTable;
983 }
984
FindRow(morkEnv * ev,mdb_scope inScope,mdb_column inColumn,const mdbYarn * inYarn)985 morkRow* morkStore::FindRow(morkEnv* ev, mdb_scope inScope, mdb_column inColumn,
986 const mdbYarn* inYarn) {
987 morkRow* outRow = 0;
988 if (ev->Good()) {
989 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inScope);
990 if (rowSpace) {
991 outRow = rowSpace->FindRow(ev, inColumn, inYarn);
992 }
993 }
994 return outRow;
995 }
996
GetRow(morkEnv * ev,const mdbOid * inOid)997 morkRow* morkStore::GetRow(morkEnv* ev, const mdbOid* inOid) {
998 morkRow* outRow = 0;
999 if (ev->Good()) {
1000 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inOid->mOid_Scope);
1001 if (rowSpace) {
1002 outRow = rowSpace->mRowSpace_Rows.GetOid(ev, inOid);
1003 }
1004 }
1005 return outRow;
1006 }
1007
GetTable(morkEnv * ev,const mdbOid * inOid)1008 morkTable* morkStore::GetTable(morkEnv* ev, const mdbOid* inOid) {
1009 morkTable* outTable = 0;
1010 if (ev->Good()) {
1011 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inOid->mOid_Scope);
1012 if (rowSpace) {
1013 outTable = rowSpace->FindTableByTid(ev, inOid->mOid_Id);
1014 }
1015 }
1016 return outTable;
1017 }
1018
NewTable(morkEnv * ev,mdb_scope inRowScope,mdb_kind inTableKind,mdb_bool inMustBeUnique,const mdbOid * inOptionalMetaRowOid)1019 morkTable* morkStore::NewTable(
1020 morkEnv* ev, mdb_scope inRowScope, mdb_kind inTableKind,
1021 mdb_bool inMustBeUnique,
1022 const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
1023 {
1024 morkTable* outTable = 0;
1025 if (ev->Good()) {
1026 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inRowScope);
1027 if (rowSpace)
1028 outTable = rowSpace->NewTable(ev, inTableKind, inMustBeUnique,
1029 inOptionalMetaRowOid);
1030 }
1031 return outTable;
1032 }
1033
GetPortTableCursor(morkEnv * ev,mdb_scope inRowScope,mdb_kind inTableKind)1034 morkPortTableCursor* morkStore::GetPortTableCursor(morkEnv* ev,
1035 mdb_scope inRowScope,
1036 mdb_kind inTableKind) {
1037 morkPortTableCursor* outCursor = 0;
1038 if (ev->Good()) {
1039 nsIMdbHeap* heap = mPort_Heap;
1040 outCursor = new (*heap, ev) morkPortTableCursor(
1041 ev, morkUsage::kHeap, heap, this, inRowScope, inTableKind, heap);
1042 }
1043 NS_IF_ADDREF(outCursor);
1044 return outCursor;
1045 }
1046
NewRow(morkEnv * ev,mdb_scope inRowScope)1047 morkRow* morkStore::NewRow(morkEnv* ev, mdb_scope inRowScope) {
1048 morkRow* outRow = 0;
1049 if (ev->Good()) {
1050 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inRowScope);
1051 if (rowSpace) outRow = rowSpace->NewRow(ev);
1052 }
1053 return outRow;
1054 }
1055
NewRowWithOid(morkEnv * ev,const mdbOid * inOid)1056 morkRow* morkStore::NewRowWithOid(morkEnv* ev, const mdbOid* inOid) {
1057 morkRow* outRow = 0;
1058 if (ev->Good()) {
1059 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inOid->mOid_Scope);
1060 if (rowSpace) outRow = rowSpace->NewRowWithOid(ev, inOid);
1061 }
1062 return outRow;
1063 }
1064
OidToRow(morkEnv * ev,const mdbOid * inOid)1065 morkRow* morkStore::OidToRow(morkEnv* ev, const mdbOid* inOid)
1066 // OidToRow() finds old row with oid, or makes new one if not found.
1067 {
1068 morkRow* outRow = 0;
1069 if (ev->Good()) {
1070 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inOid->mOid_Scope);
1071 if (rowSpace) {
1072 outRow = rowSpace->mRowSpace_Rows.GetOid(ev, inOid);
1073 if (!outRow && ev->Good()) outRow = rowSpace->NewRowWithOid(ev, inOid);
1074 }
1075 }
1076 return outRow;
1077 }
1078
OidToTable(morkEnv * ev,const mdbOid * inOid,const mdbOid * inOptionalMetaRowOid)1079 morkTable* morkStore::OidToTable(
1080 morkEnv* ev, const mdbOid* inOid,
1081 const mdbOid* inOptionalMetaRowOid) // can be nil to avoid specifying
1082 // OidToTable() finds old table with oid, or makes new one if not found.
1083 {
1084 morkTable* outTable = 0;
1085 if (ev->Good()) {
1086 morkRowSpace* rowSpace = this->LazyGetRowSpace(ev, inOid->mOid_Scope);
1087 if (rowSpace) {
1088 outTable = rowSpace->mRowSpace_Tables.GetTable(ev, inOid->mOid_Id);
1089 if (!outTable && ev->Good()) {
1090 mork_kind tableKind = morkStore_kNoneToken;
1091 outTable = rowSpace->NewTableWithTid(ev, inOid->mOid_Id, tableKind,
1092 inOptionalMetaRowOid);
1093 }
1094 }
1095 }
1096 return outTable;
1097 }
1098
1099 // { ===== begin nsIMdbObject methods =====
1100
1101 // { ----- begin ref counting for well-behaved cyclic graphs -----
1102 NS_IMETHODIMP
GetWeakRefCount(nsIMdbEnv * mev,mdb_count * outCount)1103 morkStore::GetWeakRefCount(nsIMdbEnv* mev, // weak refs
1104 mdb_count* outCount) {
1105 *outCount = WeakRefsOnly();
1106 return NS_OK;
1107 }
1108 NS_IMETHODIMP
GetStrongRefCount(nsIMdbEnv * mev,mdb_count * outCount)1109 morkStore::GetStrongRefCount(nsIMdbEnv* mev, // strong refs
1110 mdb_count* outCount) {
1111 *outCount = StrongRefsOnly();
1112 return NS_OK;
1113 }
1114 // ### TODO - clean up this cast, if required
1115 NS_IMETHODIMP
AddWeakRef(nsIMdbEnv * mev)1116 morkStore::AddWeakRef(nsIMdbEnv* mev) {
1117 morkEnv* ev = morkEnv::FromMdbEnv(mev);
1118 // XXX Casting mork_refs to nsresult
1119 return static_cast<nsresult>(morkNode::AddWeakRef(ev));
1120 }
1121 #ifndef _MSC_VER
NS_IMETHODIMP_(mork_uses)1122 NS_IMETHODIMP_(mork_uses)
1123 morkStore::AddStrongRef(morkEnv* mev) { return AddRef(); }
1124 #endif
NS_IMETHODIMP_(mork_uses)1125 NS_IMETHODIMP_(mork_uses)
1126 morkStore::AddStrongRef(nsIMdbEnv* mev) { return AddRef(); }
1127 NS_IMETHODIMP
CutWeakRef(nsIMdbEnv * mev)1128 morkStore::CutWeakRef(nsIMdbEnv* mev) {
1129 morkEnv* ev = morkEnv::FromMdbEnv(mev);
1130 // XXX Casting mork_refs to nsresult
1131 return static_cast<nsresult>(morkNode::CutWeakRef(ev));
1132 }
1133 #ifndef _MSC_VER
NS_IMETHODIMP_(mork_uses)1134 NS_IMETHODIMP_(mork_uses)
1135 morkStore::CutStrongRef(morkEnv* mev) { return Release(); }
1136 #endif
1137 NS_IMETHODIMP
CutStrongRef(nsIMdbEnv * mev)1138 morkStore::CutStrongRef(nsIMdbEnv* mev) {
1139 // XXX Casting nsrefcnt to nsresult
1140 return static_cast<nsresult>(Release());
1141 }
1142
1143 NS_IMETHODIMP
CloseMdbObject(nsIMdbEnv * mev)1144 morkStore::CloseMdbObject(nsIMdbEnv* mev) {
1145 morkEnv* ev = morkEnv::FromMdbEnv(mev);
1146 CloseMorkNode(ev);
1147 Release();
1148 return NS_OK;
1149 }
1150
1151 NS_IMETHODIMP
IsOpenMdbObject(nsIMdbEnv * mev,mdb_bool * outOpen)1152 morkStore::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen) {
1153 *outOpen = IsOpenNode();
1154 return NS_OK;
1155 }
1156 // } ----- end ref counting -----
1157
1158 // } ===== end nsIMdbObject methods =====
1159
1160 // { ===== begin nsIMdbPort methods =====
1161
1162 // { ----- begin attribute methods -----
1163 NS_IMETHODIMP
GetIsPortReadonly(nsIMdbEnv * mev,mdb_bool * outBool)1164 morkStore::GetIsPortReadonly(nsIMdbEnv* mev, mdb_bool* outBool) {
1165 nsresult outErr = NS_OK;
1166 mdb_bool isReadOnly = morkBool_kFalse;
1167 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1168 if (ev) {
1169 ev->StubMethodOnlyError();
1170 outErr = ev->AsErr();
1171 }
1172 if (outBool) *outBool = isReadOnly;
1173 return outErr;
1174 }
1175
CanUseStore(nsIMdbEnv * mev,mork_bool inMutable,nsresult * outErr) const1176 morkEnv* morkStore::CanUseStore(nsIMdbEnv* mev, mork_bool inMutable,
1177 nsresult* outErr) const {
1178 morkEnv* outEnv = 0;
1179 morkEnv* ev = morkEnv::FromMdbEnv(mev);
1180 if (ev) {
1181 if (IsStore())
1182 outEnv = ev;
1183 else
1184 NonStoreTypeError(ev);
1185 *outErr = ev->AsErr();
1186 }
1187 MORK_ASSERT(outEnv);
1188 return outEnv;
1189 }
1190
1191 NS_IMETHODIMP
GetIsStore(nsIMdbEnv * mev,mdb_bool * outBool)1192 morkStore::GetIsStore(nsIMdbEnv* mev, mdb_bool* outBool) {
1193 MORK_USED_1(mev);
1194 if (outBool) *outBool = morkBool_kTrue;
1195 return NS_OK;
1196 }
1197
1198 NS_IMETHODIMP
GetIsStoreAndDirty(nsIMdbEnv * mev,mdb_bool * outBool)1199 morkStore::GetIsStoreAndDirty(nsIMdbEnv* mev, mdb_bool* outBool) {
1200 nsresult outErr = NS_OK;
1201 mdb_bool isStoreAndDirty = morkBool_kFalse;
1202 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1203 if (ev) {
1204 ev->StubMethodOnlyError();
1205 outErr = ev->AsErr();
1206 }
1207 if (outBool) *outBool = isStoreAndDirty;
1208 return outErr;
1209 }
1210
1211 NS_IMETHODIMP
GetUsagePolicy(nsIMdbEnv * mev,mdbUsagePolicy * ioUsagePolicy)1212 morkStore::GetUsagePolicy(nsIMdbEnv* mev, mdbUsagePolicy* ioUsagePolicy) {
1213 MORK_USED_1(ioUsagePolicy);
1214 nsresult outErr = NS_OK;
1215 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1216 if (ev) {
1217 ev->StubMethodOnlyError();
1218 outErr = ev->AsErr();
1219 }
1220 return outErr;
1221 }
1222
1223 NS_IMETHODIMP
SetUsagePolicy(nsIMdbEnv * mev,const mdbUsagePolicy * inUsagePolicy)1224 morkStore::SetUsagePolicy(nsIMdbEnv* mev, const mdbUsagePolicy* inUsagePolicy) {
1225 MORK_USED_1(inUsagePolicy);
1226 nsresult outErr = NS_OK;
1227 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1228 if (ev) {
1229 // ev->StubMethodOnlyError(); // okay to do nothing?
1230 outErr = ev->AsErr();
1231 }
1232 return outErr;
1233 }
1234 // } ----- end attribute methods -----
1235
1236 // { ----- begin memory policy methods -----
1237 NS_IMETHODIMP
IdleMemoryPurge(nsIMdbEnv * mev,mdb_size * outEstimatedBytesFreed)1238 morkStore::IdleMemoryPurge( // do memory management already scheduled
1239 nsIMdbEnv* mev, // context
1240 mdb_size* outEstimatedBytesFreed) // approximate bytes actually freed
1241 {
1242 nsresult outErr = NS_OK;
1243 mdb_size estimatedBytesFreed = 0;
1244 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1245 if (ev) {
1246 // ev->StubMethodOnlyError(); // okay to do nothing?
1247 outErr = ev->AsErr();
1248 }
1249 if (outEstimatedBytesFreed) *outEstimatedBytesFreed = estimatedBytesFreed;
1250 return outErr;
1251 }
1252
1253 NS_IMETHODIMP
SessionMemoryPurge(nsIMdbEnv * mev,mdb_size inDesiredBytesFreed,mdb_size * outEstimatedBytesFreed)1254 morkStore::SessionMemoryPurge( // request specific footprint decrease
1255 nsIMdbEnv* mev, // context
1256 mdb_size inDesiredBytesFreed, // approximate number of bytes wanted
1257 mdb_size* outEstimatedBytesFreed) // approximate bytes actually freed
1258 {
1259 MORK_USED_1(inDesiredBytesFreed);
1260 nsresult outErr = NS_OK;
1261 mdb_size estimate = 0;
1262 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1263 if (ev) {
1264 // ev->StubMethodOnlyError(); // okay to do nothing?
1265 outErr = ev->AsErr();
1266 }
1267 if (outEstimatedBytesFreed) *outEstimatedBytesFreed = estimate;
1268 return outErr;
1269 }
1270
1271 NS_IMETHODIMP
PanicMemoryPurge(nsIMdbEnv * mev,mdb_size * outEstimatedBytesFreed)1272 morkStore::PanicMemoryPurge( // desperately free all possible memory
1273 nsIMdbEnv* mev, // context
1274 mdb_size* outEstimatedBytesFreed) // approximate bytes actually freed
1275 {
1276 nsresult outErr = NS_OK;
1277 mdb_size estimate = 0;
1278 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1279 if (ev) {
1280 // ev->StubMethodOnlyError(); // okay to do nothing?
1281 outErr = ev->AsErr();
1282 }
1283 if (outEstimatedBytesFreed) *outEstimatedBytesFreed = estimate;
1284 return outErr;
1285 }
1286 // } ----- end memory policy methods -----
1287
1288 // { ----- begin filepath methods -----
1289 NS_IMETHODIMP
GetPortFilePath(nsIMdbEnv * mev,mdbYarn * outFilePath,mdbYarn * outFormatVersion)1290 morkStore::GetPortFilePath(
1291 nsIMdbEnv* mev, // context
1292 mdbYarn* outFilePath, // name of file holding port content
1293 mdbYarn* outFormatVersion) // file format description
1294 {
1295 nsresult outErr = NS_OK;
1296 if (outFormatVersion) outFormatVersion->mYarn_Fill = 0;
1297 if (outFilePath) outFilePath->mYarn_Fill = 0;
1298 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1299 if (ev) {
1300 if (mStore_File)
1301 mStore_File->Path(mev, outFilePath);
1302 else
1303 NilStoreFileError(ev);
1304
1305 outErr = ev->AsErr();
1306 }
1307 return outErr;
1308 }
1309
1310 NS_IMETHODIMP
GetPortFile(nsIMdbEnv * mev,nsIMdbFile ** acqFile)1311 morkStore::GetPortFile(
1312 nsIMdbEnv* mev, // context
1313 nsIMdbFile** acqFile) // acquire file used by port or store
1314 {
1315 nsresult outErr = NS_OK;
1316 if (acqFile) *acqFile = 0;
1317
1318 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1319 if (ev) {
1320 if (mStore_File) {
1321 if (acqFile) {
1322 mStore_File->AddRef();
1323 if (ev->Good()) *acqFile = mStore_File;
1324 }
1325 } else
1326 NilStoreFileError(ev);
1327
1328 outErr = ev->AsErr();
1329 }
1330 return outErr;
1331 }
1332 // } ----- end filepath methods -----
1333
1334 // { ----- begin export methods -----
1335 NS_IMETHODIMP
BestExportFormat(nsIMdbEnv * mev,mdbYarn * outFormatVersion)1336 morkStore::BestExportFormat( // determine preferred export format
1337 nsIMdbEnv* mev, // context
1338 mdbYarn* outFormatVersion) // file format description
1339 {
1340 nsresult outErr = NS_OK;
1341 if (outFormatVersion) outFormatVersion->mYarn_Fill = 0;
1342 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1343 if (ev) {
1344 ev->StubMethodOnlyError();
1345 outErr = ev->AsErr();
1346 }
1347 return outErr;
1348 }
1349
1350 NS_IMETHODIMP
CanExportToFormat(nsIMdbEnv * mev,const char * inFormatVersion,mdb_bool * outCanExport)1351 morkStore::CanExportToFormat( // can export content in given specific format?
1352 nsIMdbEnv* mev, // context
1353 const char* inFormatVersion, // file format description
1354 mdb_bool* outCanExport) // whether ExportSource() might succeed
1355 {
1356 MORK_USED_1(inFormatVersion);
1357 mdb_bool canExport = morkBool_kFalse;
1358 nsresult outErr = NS_OK;
1359 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1360 if (ev) {
1361 ev->StubMethodOnlyError();
1362 outErr = ev->AsErr();
1363 }
1364 if (outCanExport) *outCanExport = canExport;
1365 return outErr;
1366 }
1367
1368 NS_IMETHODIMP
ExportToFormat(nsIMdbEnv * mev,nsIMdbFile * ioFile,const char * inFormatVersion,nsIMdbThumb ** acqThumb)1369 morkStore::ExportToFormat( // export content in given specific format
1370 nsIMdbEnv* mev, // context
1371 // const char* inFilePath, // the file to receive exported content
1372 nsIMdbFile* ioFile, // destination abstract file interface
1373 const char* inFormatVersion, // file format description
1374 nsIMdbThumb** acqThumb) // acquire thumb for incremental export
1375 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
1376 // then the export will be finished.
1377 {
1378 nsresult outErr = NS_OK;
1379 nsIMdbThumb* outThumb = 0;
1380 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1381 if (ev) {
1382 if (ioFile && inFormatVersion && acqThumb) {
1383 ev->StubMethodOnlyError();
1384 } else
1385 ev->NilPointerError();
1386
1387 outErr = ev->AsErr();
1388 }
1389 if (acqThumb) *acqThumb = outThumb;
1390 return outErr;
1391 }
1392
1393 // } ----- end export methods -----
1394
1395 // { ----- begin token methods -----
1396 NS_IMETHODIMP
TokenToString(nsIMdbEnv * mev,mdb_token inToken,mdbYarn * outTokenName)1397 morkStore::TokenToString( // return a string name for an integer token
1398 nsIMdbEnv* mev, // context
1399 mdb_token inToken, // token for inTokenName inside this port
1400 mdbYarn* outTokenName) // the type of table to access
1401 {
1402 nsresult outErr = NS_OK;
1403 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1404 if (ev) {
1405 TokenToString(ev, inToken, outTokenName);
1406 outErr = ev->AsErr();
1407 }
1408 return outErr;
1409 }
1410
1411 NS_IMETHODIMP
StringToToken(nsIMdbEnv * mev,const char * inTokenName,mdb_token * outToken)1412 morkStore::StringToToken( // return an integer token for scope name
1413 nsIMdbEnv* mev, // context
1414 const char* inTokenName, // Latin1 string to tokenize if possible
1415 mdb_token* outToken) // token for inTokenName inside this port
1416 // String token zero is never used and never supported. If the port
1417 // is a mutable store, then StringToToken() to create a new
1418 // association of inTokenName with a new integer token if possible.
1419 // But a readonly port will return zero for an unknown scope name.
1420 {
1421 nsresult outErr = NS_OK;
1422 mdb_token token = 0;
1423 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1424 if (ev) {
1425 token = StringToToken(ev, inTokenName);
1426 outErr = ev->AsErr();
1427 }
1428 if (outToken) *outToken = token;
1429 return outErr;
1430 }
1431
1432 NS_IMETHODIMP
QueryToken(nsIMdbEnv * mev,const char * inTokenName,mdb_token * outToken)1433 morkStore::QueryToken( // like StringToToken(), but without adding
1434 nsIMdbEnv* mev, // context
1435 const char* inTokenName, // Latin1 string to tokenize if possible
1436 mdb_token* outToken) // token for inTokenName inside this port
1437 // QueryToken() will return a string token if one already exists,
1438 // but unlike StringToToken(), will not assign a new token if not
1439 // already in use.
1440 {
1441 nsresult outErr = NS_OK;
1442 mdb_token token = 0;
1443 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1444 if (ev) {
1445 token = QueryToken(ev, inTokenName);
1446 outErr = ev->AsErr();
1447 }
1448 if (outToken) *outToken = token;
1449 return outErr;
1450 }
1451
1452 // } ----- end token methods -----
1453
1454 // { ----- begin row methods -----
1455 NS_IMETHODIMP
HasRow(nsIMdbEnv * mev,const mdbOid * inOid,mdb_bool * outHasRow)1456 morkStore::HasRow( // contains a row with the specified oid?
1457 nsIMdbEnv* mev, // context
1458 const mdbOid* inOid, // hypothetical row oid
1459 mdb_bool* outHasRow) // whether GetRow() might succeed
1460 {
1461 nsresult outErr = NS_OK;
1462 mdb_bool hasRow = morkBool_kFalse;
1463 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1464 if (ev) {
1465 morkRow* row = GetRow(ev, inOid);
1466 if (row) hasRow = morkBool_kTrue;
1467
1468 outErr = ev->AsErr();
1469 }
1470 if (outHasRow) *outHasRow = hasRow;
1471 return outErr;
1472 }
1473
1474 NS_IMETHODIMP
GetRow(nsIMdbEnv * mev,const mdbOid * inOid,nsIMdbRow ** acqRow)1475 morkStore::GetRow( // access one row with specific oid
1476 nsIMdbEnv* mev, // context
1477 const mdbOid* inOid, // hypothetical row oid
1478 nsIMdbRow** acqRow) // acquire specific row (or null)
1479 {
1480 nsresult outErr = NS_OK;
1481 nsIMdbRow* outRow = 0;
1482 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1483 if (ev) {
1484 morkRow* row = GetRow(ev, inOid);
1485 if (row && ev->Good()) outRow = row->AcquireRowHandle(ev, this);
1486
1487 outErr = ev->AsErr();
1488 }
1489 if (acqRow) *acqRow = outRow;
1490 return outErr;
1491 }
1492
1493 NS_IMETHODIMP
GetRowRefCount(nsIMdbEnv * mev,const mdbOid * inOid,mdb_count * outRefCount)1494 morkStore::GetRowRefCount( // get number of tables that contain a row
1495 nsIMdbEnv* mev, // context
1496 const mdbOid* inOid, // hypothetical row oid
1497 mdb_count* outRefCount) // number of tables containing inRowKey
1498 {
1499 nsresult outErr = NS_OK;
1500 mdb_count count = 0;
1501 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1502 if (ev) {
1503 morkRow* row = GetRow(ev, inOid);
1504 if (row && ev->Good()) count = row->mRow_GcUses;
1505
1506 outErr = ev->AsErr();
1507 }
1508 if (outRefCount) *outRefCount = count;
1509 return outErr;
1510 }
1511
1512 NS_IMETHODIMP
FindRow(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_column inColumn,const mdbYarn * inTargetCellValue,mdbOid * outRowOid,nsIMdbRow ** acqRow)1513 morkStore::FindRow(
1514 nsIMdbEnv* mev, // search for row with matching cell
1515 mdb_scope inRowScope, // row scope for row ids
1516 mdb_column inColumn, // the column to search (and maintain an index)
1517 const mdbYarn* inTargetCellValue, // cell value for which to search
1518 mdbOid* outRowOid, // out row oid on match (or {0,-1} for no match)
1519 nsIMdbRow** acqRow) // acquire matching row (or nil for no match)
1520 // FindRow() searches for one row that has a cell in column inColumn with
1521 // a contained value with the same form (i.e. charset) and is byte-wise
1522 // identical to the blob described by yarn inTargetCellValue. Both content
1523 // and form of the yarn must be an exact match to find a matching row.
1524 //
1525 // (In other words, both a yarn's blob bytes and form are significant. The
1526 // form is not expected to vary in columns used for identity anyway. This
1527 // is intended to make the cost of FindRow() cheaper for MDB implementors,
1528 // since any cell value atomization performed internally must necessarily
1529 // make yarn form significant in order to avoid data loss in atomization.)
1530 //
1531 // FindRow() can lazily create an index on attribute inColumn for all rows
1532 // with that attribute in row space scope inRowScope, so that subsequent
1533 // calls to FindRow() will perform faster. Such an index might or might
1534 // not be persistent (but this seems desirable if it is cheap to do so).
1535 // Note that lazy index creation in readonly DBs is not very feasible.
1536 //
1537 // This FindRow() interface assumes that attribute inColumn is effectively
1538 // an alternative means of unique identification for a row in a rowspace,
1539 // so correct behavior is only guaranteed when no duplicates for this col
1540 // appear in the given set of rows. (If more than one row has the same cell
1541 // value in this column, no more than one will be found; and cutting one of
1542 // two duplicate rows can cause the index to assume no other such row lives
1543 // in the row space, so future calls return nil for negative search results
1544 // even though some duplicate row might still live within the rowspace.)
1545 //
1546 // In other words, the FindRow() implementation is allowed to assume simple
1547 // hash tables mapping unique column keys to associated row values will be
1548 // sufficient, where any duplication is not recorded because only one copy
1549 // of a given key need be remembered. Implementors are not required to sort
1550 // all rows by the specified column.
1551 {
1552 nsresult outErr = NS_OK;
1553 nsIMdbRow* outRow = 0;
1554 mdbOid rowOid;
1555 rowOid.mOid_Scope = 0;
1556 rowOid.mOid_Id = (mdb_id)-1;
1557
1558 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1559 if (ev) {
1560 morkRow* row = FindRow(ev, inRowScope, inColumn, inTargetCellValue);
1561 if (row && ev->Good()) {
1562 rowOid = row->mRow_Oid;
1563 if (acqRow) outRow = row->AcquireRowHandle(ev, this);
1564 }
1565 outErr = ev->AsErr();
1566 }
1567 if (acqRow) *acqRow = outRow;
1568 if (outRowOid) *outRowOid = rowOid;
1569
1570 return outErr;
1571 }
1572
1573 // } ----- end row methods -----
1574
1575 // { ----- begin table methods -----
1576 NS_IMETHODIMP
HasTable(nsIMdbEnv * mev,const mdbOid * inOid,mdb_bool * outHasTable)1577 morkStore::HasTable( // supports a table with the specified oid?
1578 nsIMdbEnv* mev, // context
1579 const mdbOid* inOid, // hypothetical table oid
1580 mdb_bool* outHasTable) // whether GetTable() might succeed
1581 {
1582 nsresult outErr = NS_OK;
1583 mork_bool hasTable = morkBool_kFalse;
1584 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1585 if (ev) {
1586 morkTable* table = GetTable(ev, inOid);
1587 if (table) hasTable = morkBool_kTrue;
1588
1589 outErr = ev->AsErr();
1590 }
1591 if (outHasTable) *outHasTable = hasTable;
1592 return outErr;
1593 }
1594
1595 NS_IMETHODIMP
GetTable(nsIMdbEnv * mev,const mdbOid * inOid,nsIMdbTable ** acqTable)1596 morkStore::GetTable( // access one table with specific oid
1597 nsIMdbEnv* mev, // context
1598 const mdbOid* inOid, // hypothetical table oid
1599 nsIMdbTable** acqTable) // acquire specific table (or null)
1600 {
1601 nsresult outErr = NS_OK;
1602 nsIMdbTable* outTable = 0;
1603 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1604 if (ev) {
1605 morkTable* table = GetTable(ev, inOid);
1606 if (table && ev->Good()) outTable = table->AcquireTableHandle(ev);
1607 outErr = ev->AsErr();
1608 }
1609 if (acqTable) *acqTable = outTable;
1610 return outErr;
1611 }
1612
1613 NS_IMETHODIMP
HasTableKind(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_kind inTableKind,mdb_count * outTableCount,mdb_bool * outSupportsTable)1614 morkStore::HasTableKind( // supports a table of the specified type?
1615 nsIMdbEnv* mev, // context
1616 mdb_scope inRowScope, // rid scope for row ids
1617 mdb_kind inTableKind, // the type of table to access
1618 mdb_count* outTableCount, // current number of such tables
1619 mdb_bool* outSupportsTable) // whether GetTableKind() might succeed
1620 {
1621 nsresult outErr = NS_OK;
1622 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1623 if (ev) {
1624 *outSupportsTable =
1625 HasTableKind(ev, inRowScope, inTableKind, outTableCount);
1626 outErr = ev->AsErr();
1627 }
1628 return outErr;
1629 }
1630
1631 NS_IMETHODIMP
GetTableKind(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_kind inTableKind,mdb_count * outTableCount,mdb_bool * outMustBeUnique,nsIMdbTable ** acqTable)1632 morkStore::GetTableKind( // access one (random) table of specific type
1633 nsIMdbEnv* mev, // context
1634 mdb_scope inRowScope, // row scope for row ids
1635 mdb_kind inTableKind, // the type of table to access
1636 mdb_count* outTableCount, // current number of such tables
1637 mdb_bool* outMustBeUnique, // whether port can hold only one of these
1638 nsIMdbTable** acqTable) // acquire scoped collection of rows
1639 {
1640 nsresult outErr = NS_OK;
1641 nsIMdbTable* outTable = 0;
1642 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1643 if (ev) {
1644 morkTable* table = GetTableKind(ev, inRowScope, inTableKind, outTableCount,
1645 outMustBeUnique);
1646 if (table && ev->Good()) outTable = table->AcquireTableHandle(ev);
1647 outErr = ev->AsErr();
1648 }
1649 if (acqTable) *acqTable = outTable;
1650 return outErr;
1651 }
1652
1653 NS_IMETHODIMP
GetPortTableCursor(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_kind inTableKind,nsIMdbPortTableCursor ** acqCursor)1654 morkStore::GetPortTableCursor( // get cursor for all tables of specific type
1655 nsIMdbEnv* mev, // context
1656 mdb_scope inRowScope, // row scope for row ids
1657 mdb_kind inTableKind, // the type of table to access
1658 nsIMdbPortTableCursor** acqCursor) // all such tables in the port
1659 {
1660 nsresult outErr = NS_OK;
1661 nsIMdbPortTableCursor* outCursor = 0;
1662 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1663 if (ev) {
1664 morkPortTableCursor* cursor =
1665 GetPortTableCursor(ev, inRowScope, inTableKind);
1666 if (cursor && ev->Good()) outCursor = cursor;
1667
1668 outErr = ev->AsErr();
1669 }
1670 if (acqCursor) *acqCursor = outCursor;
1671 return outErr;
1672 }
1673 // } ----- end table methods -----
1674
1675 // { ----- begin commit methods -----
1676
1677 NS_IMETHODIMP
ShouldCompress(nsIMdbEnv * mev,mdb_percent inPercentWaste,mdb_percent * outActualWaste,mdb_bool * outShould)1678 morkStore::ShouldCompress( // store wastes at least inPercentWaste?
1679 nsIMdbEnv* mev, // context
1680 mdb_percent inPercentWaste, // 0..100 percent file size waste threshold
1681 mdb_percent* outActualWaste, // 0..100 percent of file actually wasted
1682 mdb_bool* outShould) // true when about inPercentWaste% is wasted
1683 {
1684 mdb_percent actualWaste = 0;
1685 mdb_bool shouldCompress = morkBool_kFalse;
1686 nsresult outErr = NS_OK;
1687 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1688 if (ev) {
1689 actualWaste = PercentOfStoreWasted(ev);
1690 if (inPercentWaste > 100) inPercentWaste = 100;
1691 shouldCompress = (actualWaste >= inPercentWaste);
1692 outErr = ev->AsErr();
1693 }
1694 if (outActualWaste) *outActualWaste = actualWaste;
1695 if (outShould) *outShould = shouldCompress;
1696 return outErr;
1697 }
1698
1699 // } ===== end nsIMdbPort methods =====
1700
1701 NS_IMETHODIMP
NewTable(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_kind inTableKind,mdb_bool inMustBeUnique,const mdbOid * inOptionalMetaRowOid,nsIMdbTable ** acqTable)1702 morkStore::NewTable( // make one new table of specific type
1703 nsIMdbEnv* mev, // context
1704 mdb_scope inRowScope, // row scope for row ids
1705 mdb_kind inTableKind, // the type of table to access
1706 mdb_bool inMustBeUnique, // whether store can hold only one of these
1707 const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
1708 nsIMdbTable** acqTable) // acquire scoped collection of rows
1709 {
1710 nsresult outErr = NS_OK;
1711 nsIMdbTable* outTable = 0;
1712 morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1713 if (ev) {
1714 morkTable* table = NewTable(ev, inRowScope, inTableKind, inMustBeUnique,
1715 inOptionalMetaRowOid);
1716 if (table && ev->Good()) outTable = table->AcquireTableHandle(ev);
1717 outErr = ev->AsErr();
1718 }
1719 if (acqTable) *acqTable = outTable;
1720 return outErr;
1721 }
1722
1723 NS_IMETHODIMP
NewTableWithOid(nsIMdbEnv * mev,const mdbOid * inOid,mdb_kind inTableKind,mdb_bool inMustBeUnique,const mdbOid * inOptionalMetaRowOid,nsIMdbTable ** acqTable)1724 morkStore::NewTableWithOid( // make one new table of specific type
1725 nsIMdbEnv* mev, // context
1726 const mdbOid* inOid, // caller assigned oid
1727 mdb_kind inTableKind, // the type of table to access
1728 mdb_bool inMustBeUnique, // whether store can hold only one of these
1729 const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
1730 nsIMdbTable** acqTable) // acquire scoped collection of rows
1731 {
1732 nsresult outErr = NS_OK;
1733 nsIMdbTable* outTable = 0;
1734 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1735 if (ev) {
1736 morkTable* table = OidToTable(ev, inOid, inOptionalMetaRowOid);
1737 if (table && ev->Good()) {
1738 table->mTable_Kind = inTableKind;
1739 if (inMustBeUnique) table->SetTableUnique();
1740 outTable = table->AcquireTableHandle(ev);
1741 }
1742 outErr = ev->AsErr();
1743 }
1744 if (acqTable) *acqTable = outTable;
1745 return outErr;
1746 }
1747 // } ----- end table methods -----
1748
1749 // { ----- begin row scope methods -----
1750 NS_IMETHODIMP
RowScopeHasAssignedIds(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_bool * outCallerAssigned,mdb_bool * outStoreAssigned)1751 morkStore::RowScopeHasAssignedIds(
1752 nsIMdbEnv* mev,
1753 mdb_scope inRowScope, // row scope for row ids
1754 mdb_bool* outCallerAssigned, // nonzero if caller assigned specified
1755 mdb_bool* outStoreAssigned) // nonzero if store db assigned specified
1756 {
1757 NS_ASSERTION(false, " not implemented");
1758 return NS_ERROR_NOT_IMPLEMENTED;
1759 }
1760
1761 NS_IMETHODIMP
SetCallerAssignedIds(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_bool * outCallerAssigned,mdb_bool * outStoreAssigned)1762 morkStore::SetCallerAssignedIds(
1763 nsIMdbEnv* mev,
1764 mdb_scope inRowScope, // row scope for row ids
1765 mdb_bool* outCallerAssigned, // nonzero if caller assigned specified
1766 mdb_bool* outStoreAssigned) // nonzero if store db assigned specified
1767 {
1768 NS_ASSERTION(false, " not implemented");
1769 return NS_ERROR_NOT_IMPLEMENTED;
1770 }
1771
1772 NS_IMETHODIMP
SetStoreAssignedIds(nsIMdbEnv * mev,mdb_scope inRowScope,mdb_bool * outCallerAssigned,mdb_bool * outStoreAssigned)1773 morkStore::SetStoreAssignedIds(
1774 nsIMdbEnv* mev,
1775 mdb_scope inRowScope, // row scope for row ids
1776 mdb_bool* outCallerAssigned, // nonzero if caller assigned specified
1777 mdb_bool* outStoreAssigned) // nonzero if store db assigned specified
1778 {
1779 NS_ASSERTION(false, " not implemented");
1780 return NS_ERROR_NOT_IMPLEMENTED;
1781 }
1782 // } ----- end row scope methods -----
1783
1784 // { ----- begin row methods -----
1785 NS_IMETHODIMP
NewRowWithOid(nsIMdbEnv * mev,const mdbOid * inOid,nsIMdbRow ** acqRow)1786 morkStore::NewRowWithOid(nsIMdbEnv* mev, // new row w/ caller assigned oid
1787 const mdbOid* inOid, // caller assigned oid
1788 nsIMdbRow** acqRow) // create new row
1789 {
1790 nsresult outErr = NS_OK;
1791 nsIMdbRow* outRow = 0;
1792 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1793 if (ev) {
1794 morkRow* row = NewRowWithOid(ev, inOid);
1795 if (row && ev->Good()) outRow = row->AcquireRowHandle(ev, this);
1796
1797 outErr = ev->AsErr();
1798 }
1799 if (acqRow) *acqRow = outRow;
1800 return outErr;
1801 }
1802
1803 NS_IMETHODIMP
NewRow(nsIMdbEnv * mev,mdb_scope inRowScope,nsIMdbRow ** acqRow)1804 morkStore::NewRow(nsIMdbEnv* mev, // new row with db assigned oid
1805 mdb_scope inRowScope, // row scope for row ids
1806 nsIMdbRow** acqRow) // create new row
1807 // Note this row must be added to some table or cell child before the
1808 // store is closed in order to make this row persist across sessions.
1809 {
1810 nsresult outErr = NS_OK;
1811 nsIMdbRow* outRow = 0;
1812 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1813 if (ev) {
1814 morkRow* row = NewRow(ev, inRowScope);
1815 if (row && ev->Good()) outRow = row->AcquireRowHandle(ev, this);
1816
1817 outErr = ev->AsErr();
1818 }
1819 if (acqRow) *acqRow = outRow;
1820 return outErr;
1821 }
1822 // } ----- end row methods -----
1823
1824 // { ----- begin import/export methods -----
1825 NS_IMETHODIMP
ImportContent(nsIMdbEnv * mev,mdb_scope inRowScope,nsIMdbPort * ioPort,nsIMdbThumb ** acqThumb)1826 morkStore::ImportContent( // import content from port
1827 nsIMdbEnv* mev, // context
1828 mdb_scope inRowScope, // scope for rows (or zero for all?)
1829 nsIMdbPort* ioPort, // the port with content to add to store
1830 nsIMdbThumb** acqThumb) // acquire thumb for incremental import
1831 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
1832 // then the import will be finished.
1833 {
1834 NS_ASSERTION(false, " not implemented");
1835 return NS_ERROR_NOT_IMPLEMENTED;
1836 }
1837
1838 NS_IMETHODIMP
ImportFile(nsIMdbEnv * mev,nsIMdbFile * ioFile,nsIMdbThumb ** acqThumb)1839 morkStore::ImportFile( // import content from port
1840 nsIMdbEnv* mev, // context
1841 nsIMdbFile* ioFile, // the file with content to add to store
1842 nsIMdbThumb** acqThumb) // acquire thumb for incremental import
1843 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
1844 // then the import will be finished.
1845 {
1846 NS_ASSERTION(false, " not implemented");
1847 return NS_ERROR_NOT_IMPLEMENTED;
1848 }
1849 // } ----- end import/export methods -----
1850
1851 // { ----- begin hinting methods -----
1852 NS_IMETHODIMP
ShareAtomColumnsHint(nsIMdbEnv * mev,mdb_scope inScopeHint,const mdbColumnSet * inColumnSet)1853 morkStore::ShareAtomColumnsHint( // advise re shared col content atomizing
1854 nsIMdbEnv* mev, // context
1855 mdb_scope inScopeHint, // zero, or suggested shared namespace
1856 const mdbColumnSet* inColumnSet) // cols desired tokenized together
1857 {
1858 MORK_USED_2(inColumnSet, inScopeHint);
1859 nsresult outErr = NS_OK;
1860 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1861 if (ev) {
1862 // ev->StubMethodOnlyError(); // okay to do nothing for a hint method
1863 outErr = ev->AsErr();
1864 }
1865 return outErr;
1866 }
1867
1868 NS_IMETHODIMP
AvoidAtomColumnsHint(nsIMdbEnv * mev,const mdbColumnSet * inColumnSet)1869 morkStore::AvoidAtomColumnsHint( // advise col w/ poor atomizing prospects
1870 nsIMdbEnv* mev, // context
1871 const mdbColumnSet* inColumnSet) // cols with poor atomizing prospects
1872 {
1873 MORK_USED_1(inColumnSet);
1874 nsresult outErr = NS_OK;
1875 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1876 if (ev) {
1877 // ev->StubMethodOnlyError(); // okay to do nothing for a hint method
1878 outErr = ev->AsErr();
1879 }
1880 return outErr;
1881 }
1882 // } ----- end hinting methods -----
1883
1884 // { ----- begin commit methods -----
1885 NS_IMETHODIMP
LargeCommit(nsIMdbEnv * mev,nsIMdbThumb ** acqThumb)1886 morkStore::LargeCommit( // save important changes if at all possible
1887 nsIMdbEnv* mev, // context
1888 nsIMdbThumb** acqThumb) // acquire thumb for incremental commit
1889 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
1890 // then the commit will be finished. Note the store is effectively write
1891 // locked until commit is finished or canceled through the thumb instance.
1892 // Until the commit is done, the store will report it has readonly status.
1893 {
1894 nsresult outErr = NS_OK;
1895 nsIMdbThumb* outThumb = 0;
1896 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1897 if (ev) {
1898 morkThumb* thumb = 0;
1899 // morkFile* file = store->mStore_File;
1900 if (DoPreferLargeOverCompressCommit(ev)) {
1901 thumb = morkThumb::Make_LargeCommit(ev, mPort_Heap, this);
1902 } else {
1903 mork_bool doCollect = morkBool_kFalse;
1904 thumb = morkThumb::Make_CompressCommit(ev, mPort_Heap, this, doCollect);
1905 }
1906
1907 if (thumb) {
1908 outThumb = thumb;
1909 thumb->AddRef();
1910 }
1911
1912 outErr = ev->AsErr();
1913 }
1914 if (acqThumb) *acqThumb = outThumb;
1915 return outErr;
1916 }
1917
1918 NS_IMETHODIMP
SessionCommit(nsIMdbEnv * mev,nsIMdbThumb ** acqThumb)1919 morkStore::SessionCommit( // save all changes if large commits delayed
1920 nsIMdbEnv* mev, // context
1921 nsIMdbThumb** acqThumb) // acquire thumb for incremental commit
1922 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
1923 // then the commit will be finished. Note the store is effectively write
1924 // locked until commit is finished or canceled through the thumb instance.
1925 // Until the commit is done, the store will report it has readonly status.
1926 {
1927 nsresult outErr = NS_OK;
1928 nsIMdbThumb* outThumb = 0;
1929 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1930 if (ev) {
1931 morkThumb* thumb = 0;
1932 if (DoPreferLargeOverCompressCommit(ev)) {
1933 thumb = morkThumb::Make_LargeCommit(ev, mPort_Heap, this);
1934 } else {
1935 mork_bool doCollect = morkBool_kFalse;
1936 thumb = morkThumb::Make_CompressCommit(ev, mPort_Heap, this, doCollect);
1937 }
1938
1939 if (thumb) {
1940 outThumb = thumb;
1941 thumb->AddRef();
1942 }
1943 outErr = ev->AsErr();
1944 }
1945 if (acqThumb) *acqThumb = outThumb;
1946 return outErr;
1947 }
1948
1949 NS_IMETHODIMP
CompressCommit(nsIMdbEnv * mev,nsIMdbThumb ** acqThumb)1950 morkStore::CompressCommit( // commit and make db smaller if possible
1951 nsIMdbEnv* mev, // context
1952 nsIMdbThumb** acqThumb) // acquire thumb for incremental commit
1953 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
1954 // then the commit will be finished. Note the store is effectively write
1955 // locked until commit is finished or canceled through the thumb instance.
1956 // Until the commit is done, the store will report it has readonly status.
1957 {
1958 nsresult outErr = NS_OK;
1959 nsIMdbThumb* outThumb = 0;
1960 morkEnv* ev = CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr);
1961 if (ev) {
1962 mork_bool doCollect = morkBool_kFalse;
1963 morkThumb* thumb =
1964 morkThumb::Make_CompressCommit(ev, mPort_Heap, this, doCollect);
1965 if (thumb) {
1966 outThumb = thumb;
1967 thumb->AddRef();
1968 mStore_CanWriteIncremental = morkBool_kTrue;
1969 }
1970
1971 outErr = ev->AsErr();
1972 }
1973 if (acqThumb) *acqThumb = outThumb;
1974 return outErr;
1975 }
1976
1977 // } ----- end commit methods -----
1978
1979 // } ===== end nsIMdbStore methods =====
1980
1981 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
1982