diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mailnews/db/mork/morkTable.cpp | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/mailnews/db/mork/morkTable.cpp')
-rw-r--r-- | comm/mailnews/db/mork/morkTable.cpp | 1415 |
1 files changed, 1415 insertions, 0 deletions
diff --git a/comm/mailnews/db/mork/morkTable.cpp b/comm/mailnews/db/mork/morkTable.cpp new file mode 100644 index 0000000000..ee27ff1328 --- /dev/null +++ b/comm/mailnews/db/mork/morkTable.cpp @@ -0,0 +1,1415 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _MDB_ +# include "mdb.h" +#endif + +#ifndef _MORK_ +# include "mork.h" +#endif + +#ifndef _MORKNODE_ +# include "morkNode.h" +#endif + +#ifndef _MORKMAP_ +# include "morkMap.h" +#endif + +#ifndef _MORKENV_ +# include "morkEnv.h" +#endif + +#ifndef _MORKTABLE_ +# include "morkTable.h" +#endif + +#ifndef _MORKSTORE_ +# include "morkStore.h" +#endif + +#ifndef _MORKROWSPACE_ +# include "morkRowSpace.h" +#endif + +#ifndef _MORKARRAY_ +# include "morkArray.h" +#endif + +#ifndef _MORKROW_ +# include "morkRow.h" +#endif + +#ifndef _MORKTABLEROWCURSOR_ +# include "morkTableRowCursor.h" +#endif + +#ifndef _MORKROWOBJECT_ +# include "morkRowObject.h" +#endif + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +// ````` ````` ````` ````` ````` +// { ===== begin morkNode interface ===== + +/*public virtual*/ void morkTable::CloseMorkNode( + morkEnv* ev) /*i*/ // CloseTable() only if open +{ + if (this->IsOpenNode()) { + morkObject::CloseMorkNode(ev); // give base class a chance. + this->MarkClosing(); + this->CloseTable(ev); + this->MarkShut(); + } +} + +/*public virtual*/ +morkTable::~morkTable() /*i*/ // assert CloseTable() executed earlier +{ + CloseMorkNode(mMorkEnv); + MORK_ASSERT(this->IsShutNode()); + MORK_ASSERT(mTable_Store == 0); + MORK_ASSERT(mTable_RowSpace == 0); +} + +/*public non-poly*/ +morkTable::morkTable( + morkEnv* ev, /*i*/ + const morkUsage& inUsage, nsIMdbHeap* ioHeap, morkStore* ioStore, + nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace, + const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying + mork_tid inTid, mork_kind inKind, mork_bool inMustBeUnique) + : morkObject(ev, inUsage, ioHeap, (mork_color)inTid, (morkHandle*)0), + mTable_Store(0), + mTable_RowSpace(0), + mTable_MetaRow(0) + + , + mTable_RowMap(0) + // , mTable_RowMap(ev, morkUsage::kMember, (nsIMdbHeap*) 0, ioSlotHeap, + // morkTable_kStartRowMapSlotCount) + , + mTable_RowArray(ev, morkUsage::kMember, (nsIMdbHeap*)0, + morkTable_kStartRowArraySize, ioSlotHeap) + + , + mTable_ChangeList(), + mTable_ChangesCount(0), + mTable_ChangesMax(3) // any very small number greater than zero + + , + mTable_Kind(inKind) + + , + mTable_Flags(0), + mTable_Priority(morkPriority_kLo) // NOT high priority + , + mTable_GcUses(0), + mTable_Pad(0) { + this->mLink_Next = 0; + this->mLink_Prev = 0; + + if (ev->Good()) { + if (ioStore && ioSlotHeap && ioRowSpace) { + if (inKind) { + if (inMustBeUnique) this->SetTableUnique(); + mTable_Store = ioStore; + mTable_RowSpace = ioRowSpace; + if (inOptionalMetaRowOid) + mTable_MetaRowOid = *inOptionalMetaRowOid; + else { + mTable_MetaRowOid.mOid_Scope = 0; + mTable_MetaRowOid.mOid_Id = morkRow_kMinusOneRid; + } + if (ev->Good()) { + if (this->MaybeDirtySpaceStoreAndTable()) + this->SetTableRewrite(); // everything is dirty + + mNode_Derived = morkDerived_kTable; + } + this->MaybeDirtySpaceStoreAndTable(); // new table might dirty store + } else + ioRowSpace->ZeroKindError(ev); + } else + ev->NilPointerError(); + } +} + +NS_IMPL_ISUPPORTS_INHERITED(morkTable, morkObject, nsIMdbTable) + +/*public non-poly*/ void morkTable::CloseTable( + morkEnv* ev) /*i*/ // called by CloseMorkNode(); +{ + if (this->IsNode()) { + morkRowMap::SlotStrongRowMap((morkRowMap*)0, ev, &mTable_RowMap); + // mTable_RowMap.CloseMorkNode(ev); + mTable_RowArray.CloseMorkNode(ev); + mTable_Store = 0; + mTable_RowSpace = 0; + this->MarkShut(); + } else + this->NonNodeError(ev); +} + +// } ===== end morkNode methods ===== +// ````` ````` ````` ````` ````` + +// { ===== begin nsIMdbCollection methods ===== + +// { ----- begin attribute methods ----- +NS_IMETHODIMP +morkTable::GetSeed(nsIMdbEnv* mev, + mdb_seed* outSeed) // member change count +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + *outSeed = mTable_RowArray.mArray_Seed; + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::GetCount(nsIMdbEnv* mev, + mdb_count* outCount) // member count +{ + NS_ENSURE_ARG_POINTER(outCount); + *outCount = mTable_RowArray.mArray_Fill; + return NS_OK; +} + +NS_IMETHODIMP +morkTable::GetPort(nsIMdbEnv* mev, + nsIMdbPort** acqPort) // collection container +{ + (void)morkEnv::FromMdbEnv(mev); + NS_ENSURE_ARG_POINTER(acqPort); + *acqPort = mTable_Store; + return NS_OK; +} +// } ----- end attribute methods ----- + +// { ----- begin cursor methods ----- +NS_IMETHODIMP +morkTable::GetCursor( // make a cursor starting iter at inMemberPos + nsIMdbEnv* mev, // context + mdb_pos inMemberPos, // zero-based ordinal pos of member in collection + nsIMdbCursor** acqCursor) // acquire new cursor instance +{ + return this->GetTableRowCursor(mev, inMemberPos, + (nsIMdbTableRowCursor**)acqCursor); +} +// } ----- end cursor methods ----- + +// { ----- begin ID methods ----- +NS_IMETHODIMP +morkTable::GetOid(nsIMdbEnv* mev, + mdbOid* outOid) // read object identity +{ + morkEnv* ev = morkEnv::FromMdbEnv(mev); + GetTableOid(ev, outOid); + return NS_OK; +} + +NS_IMETHODIMP +morkTable::BecomeContent(nsIMdbEnv* mev, + const mdbOid* inOid) // exchange content +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; + // remember table->MaybeDirtySpaceStoreAndTable(); +} + +// } ----- end ID methods ----- + +// { ----- begin activity dropping methods ----- +NS_IMETHODIMP +morkTable::DropActivity( // tell collection usage no longer expected + nsIMdbEnv* mev) { + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +// } ----- end activity dropping methods ----- + +// } ===== end nsIMdbCollection methods ===== + +// { ===== begin nsIMdbTable methods ===== + +// { ----- begin attribute methods ----- + +NS_IMETHODIMP +morkTable::SetTablePriority(nsIMdbEnv* mev, mdb_priority inPrio) { + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + if (inPrio > morkPriority_kMax) inPrio = morkPriority_kMax; + + mTable_Priority = inPrio; + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::GetTablePriority(nsIMdbEnv* mev, mdb_priority* outPrio) { + nsresult outErr = NS_OK; + mork_priority prio = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + prio = mTable_Priority; + if (prio > morkPriority_kMax) { + prio = morkPriority_kMax; + mTable_Priority = prio; + } + outErr = ev->AsErr(); + } + if (outPrio) *outPrio = prio; + return outErr; +} + +NS_IMETHODIMP +morkTable::GetTableBeVerbose(nsIMdbEnv* mev, mdb_bool* outBeVerbose) { + NS_ENSURE_ARG_POINTER(outBeVerbose); + *outBeVerbose = IsTableVerbose(); + return NS_OK; +} + +NS_IMETHODIMP +morkTable::SetTableBeVerbose(nsIMdbEnv* mev, mdb_bool inBeVerbose) { + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + if (inBeVerbose) + SetTableVerbose(); + else + ClearTableVerbose(); + + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::GetTableIsUnique(nsIMdbEnv* mev, mdb_bool* outIsUnique) { + NS_ENSURE_ARG_POINTER(outIsUnique); + *outIsUnique = IsTableUnique(); + return NS_OK; +} + +NS_IMETHODIMP +morkTable::GetTableKind(nsIMdbEnv* mev, mdb_kind* outTableKind) { + NS_ENSURE_ARG_POINTER(outTableKind); + *outTableKind = mTable_Kind; + return NS_OK; +} + +NS_IMETHODIMP +morkTable::GetRowScope(nsIMdbEnv* mev, mdb_scope* outRowScope) { + nsresult outErr = NS_OK; + mdb_scope rowScope = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + if (mTable_RowSpace) + rowScope = mTable_RowSpace->SpaceScope(); + else + NilRowSpaceError(ev); + + outErr = ev->AsErr(); + } + if (outRowScope) *outRowScope = rowScope; + return outErr; +} + +NS_IMETHODIMP +morkTable::GetMetaRow( + nsIMdbEnv* mev, + const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying + mdbOid* outOid, // output meta row oid, can be nil to suppress output + nsIMdbRow** acqRow) // acquire table's unique singleton meta row +// The purpose of a meta row is to support the persistent recording of +// meta info about a table as cells put into the distinguished meta row. +// Each table has exactly one meta row, which is not considered a member +// of the collection of rows inside the table. The only way to tell +// whether a row is a meta row is by the fact that it is returned by this +// GetMetaRow() method from some table. Otherwise nothing distinguishes +// a meta row from any other row. A meta row can be used anyplace that +// any other row can be used, and can even be put into other tables (or +// the same table) as a table member, if this is useful for some reason. +// The first attempt to access a table's meta row using GetMetaRow() will +// cause the meta row to be created if it did not already exist. When the +// meta row is created, it will have the row oid that was previously +// requested for this table's meta row; or if no oid was ever explicitly +// specified for this meta row, then a unique oid will be generated in +// the row scope named "metaScope" (so obviously MDB clients should not +// manually allocate any row IDs from that special meta scope namespace). +// The meta row oid can be specified either when the table is created, or +// else the first time that GetMetaRow() is called, by passing a non-nil +// pointer to an oid for parameter inOptionalMetaRowOid. The meta row's +// actual oid is returned in outOid (if this is a non-nil pointer), and +// it will be different from inOptionalMetaRowOid when the meta row was +// already given a different oid earlier. +{ + nsresult outErr = NS_OK; + nsIMdbRow* outRow = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRow* row = GetMetaRow(ev, inOptionalMetaRowOid); + if (row && ev->Good()) { + if (outOid) *outOid = row->mRow_Oid; + + outRow = row->AcquireRowHandle(ev, mTable_Store); + } + outErr = ev->AsErr(); + } + if (acqRow) *acqRow = outRow; + + if (ev->Bad() && outOid) { + outOid->mOid_Scope = 0; + outOid->mOid_Id = morkRow_kMinusOneRid; + } + return outErr; +} + +// } ----- end attribute methods ----- + +// { ----- begin cursor methods ----- +NS_IMETHODIMP +morkTable::GetTableRowCursor( // make a cursor, starting iteration at inRowPos + nsIMdbEnv* mev, // context + mdb_pos inRowPos, // zero-based ordinal position of row in table + nsIMdbTableRowCursor** acqCursor) // acquire new cursor instance +{ + nsresult outErr = NS_OK; + nsIMdbTableRowCursor* outCursor = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkTableRowCursor* cursor = NewTableRowCursor(ev, inRowPos); + if (cursor) { + if (ev->Good()) { + // cursor->mCursor_Seed = (mork_seed) inRowPos; + outCursor = cursor; + outCursor->AddRef(); + } + } + + outErr = ev->AsErr(); + } + if (acqCursor) *acqCursor = outCursor; + return outErr; +} +// } ----- end row position methods ----- + +// { ----- begin row position methods ----- +NS_IMETHODIMP +morkTable::PosToOid( // get row member for a table position + nsIMdbEnv* mev, // context + mdb_pos inRowPos, // zero-based ordinal position of row in table + mdbOid* outOid) // row oid at the specified position +{ + nsresult outErr = NS_OK; + mdbOid roid; + roid.mOid_Scope = 0; + roid.mOid_Id = (mork_id)-1; + + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRow* row = SafeRowAt(ev, inRowPos); + if (row) roid = row->mRow_Oid; + + outErr = ev->AsErr(); + } + if (outOid) *outOid = roid; + return outErr; +} + +NS_IMETHODIMP +morkTable::OidToPos( // test for the table position of a row member + nsIMdbEnv* mev, // context + const mdbOid* inOid, // row to find in table + mdb_pos* outPos) // zero-based ordinal position of row in table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + mork_pos pos = ArrayHasOid(ev, inOid); + if (outPos) *outPos = pos; + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::PosToRow( // get row member for a table position + nsIMdbEnv* mev, // context + mdb_pos inRowPos, // zero-based ordinal position of row in table + nsIMdbRow** acqRow) // acquire row at table position inRowPos +{ + nsresult outErr = NS_OK; + nsIMdbRow* outRow = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRow* row = SafeRowAt(ev, inRowPos); + if (row && mTable_Store) outRow = row->AcquireRowHandle(ev, mTable_Store); + + outErr = ev->AsErr(); + } + if (acqRow) *acqRow = outRow; + return outErr; +} + +NS_IMETHODIMP +morkTable::RowToPos( // test for the table position of a row member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow, // row to find in table + mdb_pos* outPos) // zero-based ordinal position of row in table +{ + nsresult outErr = NS_OK; + mork_pos pos = -1; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRowObject* row = (morkRowObject*)ioRow; + pos = ArrayHasOid(ev, &row->mRowObject_Row->mRow_Oid); + outErr = ev->AsErr(); + } + if (outPos) *outPos = pos; + return outErr; +} + +// Note that HasRow() performs the inverse oid->pos mapping +// } ----- end row position methods ----- + +// { ----- begin oid set methods ----- +NS_IMETHODIMP +morkTable::AddOid( // make sure the row with inOid is a table member + nsIMdbEnv* mev, // context + const mdbOid* inOid) // row to ensure membership in table +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::HasOid( // test for the table position of a row member + nsIMdbEnv* mev, // context + const mdbOid* inOid, // row to find in table + mdb_bool* outHasOid) // whether inOid is a member row +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + if (outHasOid) *outHasOid = MapHasOid(ev, inOid); + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::CutOid( // make sure the row with inOid is not a member + nsIMdbEnv* mev, // context + const mdbOid* inOid) // row to remove from table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + if (inOid && mTable_Store) { + morkRow* row = mTable_Store->GetRow(ev, inOid); + if (row) CutRow(ev, row); + } else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + return outErr; +} +// } ----- end oid set methods ----- + +// { ----- begin row set methods ----- +NS_IMETHODIMP +morkTable::NewRow( // create a new row instance in table + nsIMdbEnv* mev, // context + mdbOid* ioOid, // please use zero (unbound) rowId for db-assigned IDs + nsIMdbRow** acqRow) // create new row +{ + nsresult outErr = NS_OK; + nsIMdbRow* outRow = 0; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + if (ioOid && mTable_Store) { + morkRow* row = 0; + if (ioOid->mOid_Id == morkRow_kMinusOneRid) + row = mTable_Store->NewRow(ev, ioOid->mOid_Scope); + else + row = mTable_Store->NewRowWithOid(ev, ioOid); + + if (row && AddRow(ev, row)) + outRow = row->AcquireRowHandle(ev, mTable_Store); + } else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + if (acqRow) *acqRow = outRow; + return outErr; +} + +NS_IMETHODIMP +morkTable::AddRow( // make sure the row with inOid is a table member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow) // row to ensure membership in table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRowObject* rowObj = (morkRowObject*)ioRow; + morkRow* row = rowObj->mRowObject_Row; + AddRow(ev, row); + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::HasRow( // test for the table position of a row member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow, // row to find in table + mdb_bool* outBool) // zero-based ordinal position of row in table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRowObject* rowObj = (morkRowObject*)ioRow; + morkRow* row = rowObj->mRowObject_Row; + if (outBool) *outBool = MapHasOid(ev, &row->mRow_Oid); + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::CutRow( // make sure the row with inOid is not a member + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow) // row to remove from table +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRowObject* rowObj = (morkRowObject*)ioRow; + morkRow* row = rowObj->mRowObject_Row; + CutRow(ev, row); + outErr = ev->AsErr(); + } + return outErr; +} + +NS_IMETHODIMP +morkTable::CutAllRows( // remove all rows from the table + nsIMdbEnv* mev) // context +{ + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + CutAllRows(ev); + outErr = ev->AsErr(); + } + return outErr; +} +// } ----- end row set methods ----- + +// { ----- begin searching methods ----- +NS_IMETHODIMP +morkTable::FindRowMatches( // search variable number of sorted cols + nsIMdbEnv* mev, // context + const mdbYarn* inPrefix, // content to find as prefix in row's column cell + nsIMdbTableRowCursor** acqCursor) // set of matching rows +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::GetSearchColumns( // query columns used by FindRowMatches() + nsIMdbEnv* mev, // context + mdb_count* outCount, // context + mdbColumnSet* outColSet) // caller supplied space to put columns +// GetSearchColumns() returns the columns actually searched when the +// FindRowMatches() method is called. No more than mColumnSet_Count +// slots of mColumnSet_Columns will be written, since mColumnSet_Count +// indicates how many slots are present in the column array. The +// actual number of search column used by the table is returned in +// the outCount parameter; if this number exceeds mColumnSet_Count, +// then a caller needs a bigger array to read the entire column set. +// The minimum of mColumnSet_Count and outCount is the number slots +// in mColumnSet_Columns that were actually written by this method. +// +// Callers are expected to change this set of columns by calls to +// nsIMdbTable::SearchColumnsHint() or SetSearchSorting(), or both. +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} +// } ----- end searching methods ----- + +// { ----- begin hinting methods ----- +NS_IMETHODIMP +morkTable::SearchColumnsHint( // advise re future expected search cols + nsIMdbEnv* mev, // context + const mdbColumnSet* inColumnSet) // columns likely to be searched +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::SortColumnsHint( // advise re future expected sort columns + nsIMdbEnv* mev, // context + const mdbColumnSet* inColumnSet) // columns for likely sort requests +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::StartBatchChangeHint( // advise before many adds and cuts + nsIMdbEnv* mev, // context + const void* inLabel) // intend unique address to match end call +// If batch starts nest by virtue of nesting calls in the stack, then +// the address of a local variable makes a good batch start label that +// can be used at batch end time, and such addresses remain unique. +{ + // we don't do anything here. + return NS_OK; +} + +NS_IMETHODIMP +morkTable::EndBatchChangeHint( // advise before many adds and cuts + nsIMdbEnv* mev, // context + const void* inLabel) // label matching start label +// Suppose a table is maintaining one or many sort orders for a table, +// so that every row added to the table must be inserted in each sort, +// and every row cut must be removed from each sort. If a db client +// intends to make many such changes before needing any information +// about the order or positions of rows inside a table, then a client +// might tell the table to start batch changes in order to disable +// sorting of rows for the interim. Presumably a table will then do +// a full sort of all rows at need when the batch changes end, or when +// a surprise request occurs for row position during batch changes. +{ + // we don't do anything here. + return NS_OK; +} +// } ----- end hinting methods ----- + +// { ----- begin sorting methods ----- +// sorting: note all rows are assumed sorted by row ID as a secondary +// sort following the primary column sort, when table rows are sorted. + +NS_IMETHODIMP +morkTable::CanSortColumn( // query which column is currently used for sorting + nsIMdbEnv* mev, // context + mdb_column inColumn, // column to query sorting potential + mdb_bool* outCanSort) // whether the column can be sorted +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::GetSorting( // view same table in particular sorting + nsIMdbEnv* mev, // context + mdb_column inColumn, // requested new column for sorting table + nsIMdbSorting** acqSorting) // acquire sorting for column +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::SetSearchSorting( // use this sorting in FindRowMatches() + nsIMdbEnv* mev, // context + mdb_column inColumn, // often same as nsIMdbSorting::GetSortColumn() + nsIMdbSorting* ioSorting) // requested sorting for some column +// SetSearchSorting() attempts to inform the table that ioSorting +// should be used during calls to FindRowMatches() for searching +// the column which is actually sorted by ioSorting. This method +// is most useful in conjunction with nsIMdbSorting::SetCompare(), +// because otherwise a caller would not be able to override the +// comparison ordering method used during searches. Note that some +// database implementations might be unable to use an arbitrarily +// specified sort order, either due to schema or runtime interface +// constraints, in which case ioSorting might not actually be used. +// Presumably ioSorting is an instance that was returned from some +// earlier call to nsIMdbTable::GetSorting(). A caller can also +// use nsIMdbTable::SearchColumnsHint() to specify desired change +// in which columns are sorted and searched by FindRowMatches(). +// +// A caller can pass a nil pointer for ioSorting to request that +// column inColumn no longer be used at all by FindRowMatches(). +// But when ioSorting is non-nil, then inColumn should match the +// column actually sorted by ioSorting; when these do not agree, +// implementations are instructed to give precedence to the column +// specified by ioSorting (so this means callers might just pass +// zero for inColumn when ioSorting is also provided, since then +// inColumn is both redundant and ignored). +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +// } ----- end sorting methods ----- + +// { ----- begin moving methods ----- +// moving a row does nothing unless a table is currently unsorted + +NS_IMETHODIMP +morkTable::MoveOid( // change position of row in unsorted table + nsIMdbEnv* mev, // context + const mdbOid* inOid, // row oid to find in table + mdb_pos inHintFromPos, // suggested hint regarding start position + mdb_pos inToPos, // desired new position for row inOid + mdb_pos* outActualPos) // actual new position of row in table +{ + nsresult outErr = NS_OK; + mdb_pos actualPos = -1; // meaning it was never found in table + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + if (inOid && mTable_Store) { + morkRow* row = mTable_Store->GetRow(ev, inOid); + if (row) actualPos = MoveRow(ev, row, inHintFromPos, inToPos); + } else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + if (outActualPos) *outActualPos = actualPos; + return outErr; +} + +NS_IMETHODIMP +morkTable::MoveRow( // change position of row in unsorted table + nsIMdbEnv* mev, // context + nsIMdbRow* ioRow, // row oid to find in table + mdb_pos inHintFromPos, // suggested hint regarding start position + mdb_pos inToPos, // desired new position for row ioRow + mdb_pos* outActualPos) // actual new position of row in table +{ + mdb_pos actualPos = -1; // meaning it was never found in table + nsresult outErr = NS_OK; + morkEnv* ev = morkEnv::FromMdbEnv(mev); + if (ev) { + morkRowObject* rowObj = (morkRowObject*)ioRow; + morkRow* row = rowObj->mRowObject_Row; + actualPos = MoveRow(ev, row, inHintFromPos, inToPos); + outErr = ev->AsErr(); + } + if (outActualPos) *outActualPos = actualPos; + return outErr; +} +// } ----- end moving methods ----- + +// { ----- begin index methods ----- +NS_IMETHODIMP +morkTable::AddIndex( // create a sorting index for column if possible + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column to sort by index + nsIMdbThumb** acqThumb) // acquire thumb for incremental index building +// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and +// then the index addition will be finished. +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::CutIndex( // stop supporting a specific column index + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column with index to be removed + nsIMdbThumb** acqThumb) // acquire thumb for incremental index destroy +// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and +// then the index removal will be finished. +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::HasIndex( // query for current presence of a column index + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column to investigate + mdb_bool* outHasIndex) // whether column has index for this column +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::EnableIndexOnSort( // create an index for col on first sort + nsIMdbEnv* mev, // context + mdb_column inColumn) // the column to index if ever sorted +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::QueryIndexOnSort( // check whether index on sort is enabled + nsIMdbEnv* mev, // context + mdb_column inColumn, // the column to investigate + mdb_bool* outIndexOnSort) // whether column has index-on-sort enabled +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +morkTable::DisableIndexOnSort( // prevent future index creation on sort + nsIMdbEnv* mev, // context + mdb_column inColumn) // the column to index if ever sorted +{ + NS_ASSERTION(false, "not implemented"); + return NS_ERROR_NOT_IMPLEMENTED; +} +// } ----- end index methods ----- + +// } ===== end nsIMdbTable methods ===== + +// we override these so that we'll use the xpcom add and release ref. +#ifndef _MSC_VER +mork_refs morkTable::AddStrongRef(nsIMdbEnv* ev) { return (mork_refs)AddRef(); } +#endif + +mork_refs morkTable::AddStrongRef(morkEnv* ev) { return (mork_refs)AddRef(); } + +#ifndef _MSC_VER +nsresult morkTable::CutStrongRef(nsIMdbEnv* ev) { return (nsresult)Release(); } +#endif + +mork_refs morkTable::CutStrongRef(morkEnv* ev) { return (mork_refs)Release(); } + +mork_u2 morkTable::AddTableGcUse(morkEnv* ev) { + MORK_USED_1(ev); + if (mTable_GcUses < morkTable_kMaxTableGcUses) // not already maxed out? + ++mTable_GcUses; + + return mTable_GcUses; +} + +mork_u2 morkTable::CutTableGcUse(morkEnv* ev) { + if (mTable_GcUses) // any outstanding uses to cut? + { + if (mTable_GcUses < morkTable_kMaxTableGcUses) // not frozen at max? + --mTable_GcUses; + } else + this->TableGcUsesUnderflowWarning(ev); + + return mTable_GcUses; +} + +// table dirty handling more complex than morkNode::SetNodeDirty() etc. + +void morkTable::SetTableClean(morkEnv* ev) { + if (mTable_ChangeList.HasListMembers()) { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes + } + mTable_ChangesCount = 0; + + mTable_Flags = 0; + this->SetNodeClean(); +} + +// notifications regarding table changes: + +void morkTable::NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos) { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + if (this->IsTableRewrite() || this->HasChangeOverflow()) + this->NoteTableSetAll(ev); + else { + morkTableChange* tableChange = + new (*heap, ev) morkTableChange(ev, ioRow, inPos); + if (tableChange) { + if (ev->Good()) { + mTable_ChangeList.PushTail(tableChange); + ++mTable_ChangesCount; + } else { + tableChange->ZapOldNext(ev, heap); + this->SetTableRewrite(); // just plan to write all table rows + } + } + } +} + +void morkTable::note_row_move(morkEnv* ev, morkRow* ioRow, mork_pos inNewPos) { + if (this->IsTableRewrite() || this->HasChangeOverflow()) + this->NoteTableSetAll(ev); + else { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + morkTableChange* tableChange = + new (*heap, ev) morkTableChange(ev, ioRow, inNewPos); + if (tableChange) { + if (ev->Good()) { + mTable_ChangeList.PushTail(tableChange); + ++mTable_ChangesCount; + } else { + tableChange->ZapOldNext(ev, heap); + this->NoteTableSetAll(ev); + } + } + } +} + +void morkTable::note_row_change(morkEnv* ev, mork_change inChange, + morkRow* ioRow) { + if (this->IsTableRewrite() || this->HasChangeOverflow()) + this->NoteTableSetAll(ev); + else { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + morkTableChange* tableChange = + new (*heap, ev) morkTableChange(ev, inChange, ioRow); + if (tableChange) { + if (ev->Good()) { + mTable_ChangeList.PushTail(tableChange); + ++mTable_ChangesCount; + } else { + tableChange->ZapOldNext(ev, heap); + this->NoteTableSetAll(ev); + } + } + } +} + +void morkTable::NoteTableSetAll(morkEnv* ev) { + if (mTable_ChangeList.HasListMembers()) { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes + } + mTable_ChangesCount = 0; + this->SetTableRewrite(); +} + +/*static*/ void morkTable::TableGcUsesUnderflowWarning(morkEnv* ev) { + ev->NewWarning("mTable_GcUses underflow"); +} + +/*static*/ void morkTable::NonTableTypeError(morkEnv* ev) { + ev->NewError("non morkTable"); +} + +/*static*/ void morkTable::NonTableTypeWarning(morkEnv* ev) { + ev->NewWarning("non morkTable"); +} + +/*static*/ void morkTable::NilRowSpaceError(morkEnv* ev) { + ev->NewError("nil mTable_RowSpace"); +} + +mork_bool morkTable::MaybeDirtySpaceStoreAndTable() { + morkRowSpace* rowSpace = mTable_RowSpace; + if (rowSpace) { + morkStore* store = rowSpace->mSpace_Store; + if (store && store->mStore_CanDirty) { + store->SetStoreDirty(); + rowSpace->mSpace_CanDirty = morkBool_kTrue; + } + + if (rowSpace->mSpace_CanDirty) // first time being dirtied? + { + if (this->IsTableClean()) { + mork_count rowCount = this->GetRowCount(); + mork_count oneThird = rowCount / 4; // one third of rows + if (oneThird > 0x07FFF) // more than half max u2? + oneThird = 0x07FFF; + + mTable_ChangesMax = (mork_u2)oneThird; + } + this->SetTableDirty(); + rowSpace->SetRowSpaceDirty(); + + return morkBool_kTrue; + } + } + return morkBool_kFalse; +} + +morkRow* morkTable::GetMetaRow(morkEnv* ev, + const mdbOid* inOptionalMetaRowOid) { + morkRow* outRow = mTable_MetaRow; + if (!outRow) { + morkStore* store = mTable_Store; + mdbOid* oid = &mTable_MetaRowOid; + if (inOptionalMetaRowOid && !oid->mOid_Scope) *oid = *inOptionalMetaRowOid; + + if (oid->mOid_Scope) // oid already recorded in table? + outRow = store->OidToRow(ev, oid); + else { + outRow = store->NewRow(ev, morkStore_kMetaScope); + if (outRow) // need to record new oid in table? + *oid = outRow->mRow_Oid; + } + mTable_MetaRow = outRow; + if (outRow) // need to note another use of this row? + { + outRow->AddRowGcUse(ev); + + this->SetTableNewMeta(); + if (this->IsTableClean()) // catch dirty status of meta row? + this->MaybeDirtySpaceStoreAndTable(); + } + } + + return outRow; +} + +void morkTable::GetTableOid(morkEnv* ev, mdbOid* outOid) { + morkRowSpace* space = mTable_RowSpace; + if (space) { + outOid->mOid_Scope = space->SpaceScope(); + outOid->mOid_Id = this->TableId(); + } else + this->NilRowSpaceError(ev); +} + +nsIMdbTable* morkTable::AcquireTableHandle(morkEnv* ev) { + AddRef(); + return this; +} + +mork_pos morkTable::ArrayHasOid(morkEnv* ev, const mdbOid* inOid) { + MORK_USED_1(ev); + mork_count count = mTable_RowArray.mArray_Fill; + mork_pos pos = -1; + while (++pos < (mork_pos)count) { + morkRow* row = (morkRow*)mTable_RowArray.At(pos); + MORK_ASSERT(row); + if (row && row->EqualOid(inOid)) { + return pos; + } + } + return -1; +} + +mork_bool morkTable::MapHasOid(morkEnv* ev, const mdbOid* inOid) { + if (mTable_RowMap) + return (mTable_RowMap->GetOid(ev, inOid) != 0); + else + return (ArrayHasOid(ev, inOid) >= 0); +} + +void morkTable::build_row_map(morkEnv* ev) { + morkRowMap* map = mTable_RowMap; + if (!map) { + mork_count count = mTable_RowArray.mArray_Fill + 3; + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + map = new (*heap, ev) morkRowMap(ev, morkUsage::kHeap, heap, heap, count); + if (map) { + if (ev->Good()) { + mTable_RowMap = map; // put strong ref here + count = mTable_RowArray.mArray_Fill; + mork_pos pos = -1; + while (++pos < (mork_pos)count) { + morkRow* row = (morkRow*)mTable_RowArray.At(pos); + if (row && row->IsRow()) + map->AddRow(ev, row); + else + row->NonRowTypeError(ev); + } + } else + map->CutStrongRef(ev); + } + } +} + +morkRow* morkTable::find_member_row(morkEnv* ev, morkRow* ioRow) { + if (mTable_RowMap) + return mTable_RowMap->GetRow(ev, ioRow); + else { + mork_count count = mTable_RowArray.mArray_Fill; + mork_pos pos = -1; + while (++pos < (mork_pos)count) { + morkRow* row = (morkRow*)mTable_RowArray.At(pos); + if (row == ioRow) return row; + } + } + return (morkRow*)0; +} + +mork_pos morkTable::MoveRow( + morkEnv* ev, morkRow* ioRow, // change row position + mork_pos inHintFromPos, // suggested hint regarding start position + mork_pos inToPos) // desired new position for row ioRow +// MoveRow() returns the actual position of ioRow afterwards; this +// position is -1 if and only if ioRow was not found as a member. +{ + mork_pos outPos = -1; // means ioRow was not a table member + mork_bool canDirty = (this->IsTableClean()) + ? this->MaybeDirtySpaceStoreAndTable() + : morkBool_kTrue; + + morkRow** rows = (morkRow**)mTable_RowArray.mArray_Slots; + mork_count count = mTable_RowArray.mArray_Fill; + if (count && rows && ev->Good()) // any members at all? no errors? + { + mork_pos lastPos = count - 1; // index of last row slot + + if (inToPos > lastPos) // beyond last used array slot? + inToPos = lastPos; // put row into last available slot + else if (inToPos < 0) // before first usable slot? + inToPos = 0; // put row in very first slow + + if (inHintFromPos > lastPos) // beyond last used array slot? + inHintFromPos = lastPos; // seek row in last available slot + else if (inHintFromPos < 0) // before first usable slot? + inHintFromPos = 0; // seek row in very first slow + + morkRow** fromSlot = 0; // becomes nonzero of ioRow is ever found + morkRow** rowsEnd = rows + count; // one past last used array slot + + if (inHintFromPos <= 0) // start of table? just scan for row? + { + morkRow** cursor = rows - 1; // before first array slot + while (++cursor < rowsEnd) { + if (*cursor == ioRow) { + fromSlot = cursor; + break; // end while loop + } + } + } else // search near the start position and work outwards + { + morkRow** lo = rows + inHintFromPos; // lowest search point + morkRow** hi = lo; // highest search point starts at lowest point + + // Seek ioRow in spiral widening search below and above inHintFromPos. + // This is faster when inHintFromPos is at all accurate, but is slower + // than a straightforward scan when inHintFromPos is nearly random. + + while (lo >= rows || hi < rowsEnd) // keep searching? + { + if (lo >= rows) // low direction search still feasible? + { + if (*lo == ioRow) // actually found the row? + { + fromSlot = lo; + break; // end while loop + } + --lo; // advance further lower + } + if (hi < rowsEnd) // high direction search still feasible? + { + if (*hi == ioRow) // actually found the row? + { + fromSlot = hi; + break; // end while loop + } + ++hi; // advance further higher + } + } + } + + if (fromSlot) // ioRow was found as a table member? + { + outPos = fromSlot - rows; // actual position where row was found + if (outPos != inToPos) // actually need to move this row? + { + morkRow** toSlot = rows + inToPos; // slot where row must go + + ++mTable_RowArray.mArray_Seed; // we modify the array now: + + if (fromSlot < toSlot) // row is moving upwards? + { + morkRow** up = fromSlot; // leading pointer going upward + while (++up <= toSlot) // have not gone above destination? + { + *fromSlot = *up; // shift down one + fromSlot = up; // shift trailing pointer up + } + } else // ( fromSlot > toSlot ) // row is moving downwards + { + morkRow** down = fromSlot; // leading pointer going downward + while (--down >= toSlot) // have not gone below destination? + { + *fromSlot = *down; // shift up one + fromSlot = down; // shift trailing pointer + } + } + *toSlot = ioRow; + outPos = inToPos; // okay, we actually moved the row here + + if (canDirty) this->note_row_move(ev, ioRow, inToPos); + } + } + } + return outPos; +} + +mork_bool morkTable::AddRow(morkEnv* ev, morkRow* ioRow) { + morkRow* row = this->find_member_row(ev, ioRow); + if (!row && ev->Good()) { + mork_bool canDirty = (this->IsTableClean()) + ? this->MaybeDirtySpaceStoreAndTable() + : morkBool_kTrue; + + mork_pos pos = mTable_RowArray.AppendSlot(ev, ioRow); + if (ev->Good() && pos >= 0) { + ioRow->AddRowGcUse(ev); + if (mTable_RowMap) { + if (mTable_RowMap->AddRow(ev, ioRow)) { + // okay, anything else? + } else + mTable_RowArray.CutSlot(ev, pos); + } else if (mTable_RowArray.mArray_Fill >= morkTable_kMakeRowMapThreshold) + this->build_row_map(ev); + + if (canDirty && ev->Good()) this->NoteTableAddRow(ev, ioRow); + } + } + return ev->Good(); +} + +mork_bool morkTable::CutRow(morkEnv* ev, morkRow* ioRow) { + morkRow* row = this->find_member_row(ev, ioRow); + if (row) { + mork_bool canDirty = (this->IsTableClean()) + ? this->MaybeDirtySpaceStoreAndTable() + : morkBool_kTrue; + + mork_count count = mTable_RowArray.mArray_Fill; + morkRow** rowSlots = (morkRow**)mTable_RowArray.mArray_Slots; + if (rowSlots) // array has vector as expected? + { + mork_pos pos = -1; + morkRow** end = rowSlots + count; + morkRow** slot = rowSlots - 1; // prepare for preincrement: + while (++slot < end) // another slot to check? + { + if (*slot == row) // found the slot containing row? + { + pos = slot - rowSlots; // record absolute position + break; // end while loop + } + } + if (pos >= 0) // need to cut if from the array? + mTable_RowArray.CutSlot(ev, pos); + else + ev->NewWarning("row not found in array"); + } else + mTable_RowArray.NilSlotsAddressError(ev); + + if (mTable_RowMap) mTable_RowMap->CutRow(ev, ioRow); + + if (canDirty) this->NoteTableCutRow(ev, ioRow); + + if (ioRow->CutRowGcUse(ev) == 0) ioRow->OnZeroRowGcUse(ev); + } + return ev->Good(); +} + +mork_bool morkTable::CutAllRows(morkEnv* ev) { + if (this->MaybeDirtySpaceStoreAndTable()) { + this->SetTableRewrite(); // everything is dirty + this->NoteTableSetAll(ev); + } + + if (ev->Good()) { + mTable_RowArray.CutAllSlots(ev); + if (mTable_RowMap) { + morkRowMapIter i(ev, mTable_RowMap); + mork_change* c = 0; + morkRow* r = 0; + + for (c = i.FirstRow(ev, &r); c; c = i.NextRow(ev, &r)) { + if (r) { + if (r->CutRowGcUse(ev) == 0) r->OnZeroRowGcUse(ev); + + i.CutHereRow(ev, (morkRow**)0); + } else + ev->NewWarning("nil row in table map"); + } + } + } + return ev->Good(); +} + +morkTableRowCursor* morkTable::NewTableRowCursor(morkEnv* ev, + mork_pos inRowPos) { + morkTableRowCursor* outCursor = 0; + if (ev->Good()) { + nsIMdbHeap* heap = mTable_Store->mPort_Heap; + morkTableRowCursor* cursor = new (*heap, ev) + morkTableRowCursor(ev, morkUsage::kHeap, heap, this, inRowPos); + if (cursor) { + if (ev->Good()) + outCursor = cursor; + else + cursor->CutStrongRef((nsIMdbEnv*)ev); + } + } + return outCursor; +} + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +morkTableChange::morkTableChange(morkEnv* ev, mork_change inChange, + morkRow* ioRow) + // use this constructor for inChange == morkChange_kAdd or morkChange_kCut + : morkNext(), + mTableChange_Row(ioRow), + mTableChange_Pos(morkTableChange_kNone) { + if (ioRow) { + if (ioRow->IsRow()) { + if (inChange == morkChange_kAdd) + mTableChange_Pos = morkTableChange_kAdd; + else if (inChange == morkChange_kCut) + mTableChange_Pos = morkTableChange_kCut; + else + this->UnknownChangeError(ev); + } else + ioRow->NonRowTypeError(ev); + } else + ev->NilPointerError(); +} + +morkTableChange::morkTableChange(morkEnv* ev, morkRow* ioRow, mork_pos inPos) + // use this constructor when the row is moved + : morkNext(), mTableChange_Row(ioRow), mTableChange_Pos(inPos) { + if (ioRow) { + if (ioRow->IsRow()) { + if (inPos < 0) this->NegativeMovePosError(ev); + } else + ioRow->NonRowTypeError(ev); + } else + ev->NilPointerError(); +} + +void morkTableChange::UnknownChangeError(morkEnv* ev) const +// morkChange_kAdd or morkChange_kCut +{ + ev->NewError("mTableChange_Pos neither kAdd nor kCut"); +} + +void morkTableChange::NegativeMovePosError(morkEnv* ev) const +// move must be non-neg position +{ + ev->NewError("negative mTableChange_Pos for row move"); +} + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +morkTableMap::~morkTableMap() {} + +morkTableMap::morkTableMap(morkEnv* ev, const morkUsage& inUsage, + nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap) +#ifdef MORK_BEAD_OVER_NODE_MAPS + : morkBeadMap(ev, inUsage, ioHeap, ioSlotHeap) +#else /*MORK_BEAD_OVER_NODE_MAPS*/ + : morkNodeMap(ev, inUsage, ioHeap, ioSlotHeap) +#endif /*MORK_BEAD_OVER_NODE_MAPS*/ +{ + if (ev->Good()) mNode_Derived = morkDerived_kTableMap; +} + +// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 |