This commit is contained in:
davidmc%netscape.com 1999-07-20 23:36:08 +00:00
Родитель cd19ad349e
Коммит 4c490446a8
6 изменённых файлов: 345 добавлений и 399 удалений

Просмотреть файл

@ -207,8 +207,11 @@ morkTable::CutTableGcUse(morkEnv* ev)
void morkTable::SetTableClean(morkEnv* ev) void morkTable::SetTableClean(morkEnv* ev)
{ {
nsIMdbHeap* heap = mTable_Store->mPort_Heap; if ( mTable_ChangeList.HasListMembers() )
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes {
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes
}
mTable_ChangesCount = 0; mTable_ChangesCount = 0;
mTable_Flags = 0; mTable_Flags = 0;
@ -242,6 +245,31 @@ void morkTable::NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos)
} }
} }
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, void morkTable::note_row_change(morkEnv* ev, mork_change inChange,
morkRow* ioRow) morkRow* ioRow)
{ {
@ -270,8 +298,11 @@ void morkTable::note_row_change(morkEnv* ev, mork_change inChange,
void morkTable::NoteTableSetAll(morkEnv* ev) void morkTable::NoteTableSetAll(morkEnv* ev)
{ {
nsIMdbHeap* heap = mTable_Store->mPort_Heap; if ( mTable_ChangeList.HasListMembers() )
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes {
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes
}
mTable_ChangesCount = 0; mTable_ChangesCount = 0;
this->SetTableRewrite(); this->SetTableRewrite();
} }
@ -470,6 +501,118 @@ morkRow* morkTable::find_member_row(morkEnv* ev, morkRow* ioRow)
return (morkRow*) 0; 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 mork_bool
morkTable::AddRow(morkEnv* ev, morkRow* ioRow) morkTable::AddRow(morkEnv* ev, morkRow* ioRow)
{ {

Просмотреть файл

@ -209,13 +209,14 @@ public: // noting table changes
void NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos); void NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos);
void note_row_change(morkEnv* ev, mork_change inChange, morkRow* ioRow); void note_row_change(morkEnv* ev, mork_change inChange, morkRow* ioRow);
void note_row_move(morkEnv* ev, morkRow* ioRow, mork_pos inNewPos);
void NoteTableAddRow(morkEnv* ev, morkRow* ioRow) void NoteTableAddRow(morkEnv* ev, morkRow* ioRow)
{ this->note_row_change(ev, morkChange_kAdd, ioRow); } { this->note_row_change(ev, morkChange_kAdd, ioRow); }
void NoteTableCutRow(morkEnv* ev, morkRow* ioRow) void NoteTableCutRow(morkEnv* ev, morkRow* ioRow)
{ this->note_row_change(ev, morkChange_kCut, ioRow); } { this->note_row_change(ev, morkChange_kCut, ioRow); }
protected: // internal row map methods protected: // internal row map methods
morkRow* find_member_row(morkEnv* ev, morkRow* ioRow); morkRow* find_member_row(morkEnv* ev, morkRow* ioRow);
@ -247,6 +248,13 @@ public: // other table methods
mork_bool AddRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good() mork_bool AddRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good() mork_bool CutRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutAllRows(morkEnv* ev); // returns ev->Good() mork_bool CutAllRows(morkEnv* ev); // returns ev->Good()
mork_pos 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.
morkTableRowCursor* NewTableRowCursor(morkEnv* ev, mork_pos inRowPos); morkTableRowCursor* NewTableRowCursor(morkEnv* ev, mork_pos inRowPos);

Просмотреть файл

@ -1122,18 +1122,25 @@ orkinTable::MoveOid( // change position of row in unsorted table
nsIMdbEnv* mev, // context nsIMdbEnv* mev, // context
const mdbOid* inOid, // row oid to find in table const mdbOid* inOid, // row oid to find in table
mdb_pos inHintFromPos, // suggested hint regarding start position mdb_pos inHintFromPos, // suggested hint regarding start position
mdb_pos inToPos, // desired new position for row inRowId mdb_pos inToPos, // desired new position for row inOid
mdb_pos* outActualPos) // actual new position of row in table mdb_pos* outActualPos) // actual new position of row in table
{ {
MORK_USED_3(inHintFromPos,inToPos,inOid);
mdb_err outErr = 0; mdb_err outErr = 0;
mdb_pos actualPos = 0; mdb_pos actualPos = -1; // meaning it was never found in table
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev ) if ( ev )
{ {
// remember table->MaybeDirtySpaceStoreAndTable(); morkTable* table = (morkTable*) mHandle_Object;
morkStore* store = table->mTable_Store;
if ( inOid && store )
{
morkRow* row = store->GetRow(ev, inOid);
if ( row )
actualPos = table->MoveRow(ev, row, inHintFromPos, inToPos);
}
else
ev->NilPointerError();
ev->StubMethodOnlyError();
outErr = ev->AsErr(); outErr = ev->AsErr();
} }
if ( outActualPos ) if ( outActualPos )
@ -1146,18 +1153,21 @@ orkinTable::MoveRow( // change position of row in unsorted table
nsIMdbEnv* mev, // context nsIMdbEnv* mev, // context
nsIMdbRow* ioRow, // row oid to find in table nsIMdbRow* ioRow, // row oid to find in table
mdb_pos inHintFromPos, // suggested hint regarding start position mdb_pos inHintFromPos, // suggested hint regarding start position
mdb_pos inToPos, // desired new position for row inRowId mdb_pos inToPos, // desired new position for row ioRow
mdb_pos* outActualPos) // actual new position of row in table mdb_pos* outActualPos) // actual new position of row in table
{ {
MORK_USED_3(inHintFromPos,inToPos,ioRow); mdb_pos actualPos = -1; // meaning it was never found in table
mdb_pos actualPos = 0;
mdb_err outErr = 0; mdb_err outErr = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev ) if ( ev )
{ {
// remember table->MaybeDirtySpaceStoreAndTable(); morkRow* row = 0;
orkinRow* orow = (orkinRow*) ioRow;
ev->StubMethodOnlyError(); if ( orow->CanUseRow(mev, /*inMutable*/ morkBool_kFalse, &outErr, &row) )
{
morkTable* table = (morkTable*) mHandle_Object;
actualPos = table->MoveRow(ev, row, inHintFromPos, inToPos);
}
outErr = ev->AsErr(); outErr = ev->AsErr();
} }
if ( outActualPos ) if ( outActualPos )

Просмотреть файл

@ -207,8 +207,11 @@ morkTable::CutTableGcUse(morkEnv* ev)
void morkTable::SetTableClean(morkEnv* ev) void morkTable::SetTableClean(morkEnv* ev)
{ {
nsIMdbHeap* heap = mTable_Store->mPort_Heap; if ( mTable_ChangeList.HasListMembers() )
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes {
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes
}
mTable_ChangesCount = 0; mTable_ChangesCount = 0;
mTable_Flags = 0; mTable_Flags = 0;
@ -242,6 +245,31 @@ void morkTable::NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos)
} }
} }
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, void morkTable::note_row_change(morkEnv* ev, mork_change inChange,
morkRow* ioRow) morkRow* ioRow)
{ {
@ -270,8 +298,11 @@ void morkTable::note_row_change(morkEnv* ev, mork_change inChange,
void morkTable::NoteTableSetAll(morkEnv* ev) void morkTable::NoteTableSetAll(morkEnv* ev)
{ {
nsIMdbHeap* heap = mTable_Store->mPort_Heap; if ( mTable_ChangeList.HasListMembers() )
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes {
nsIMdbHeap* heap = mTable_Store->mPort_Heap;
mTable_ChangeList.CutAndZapAllListMembers(ev, heap); // forget changes
}
mTable_ChangesCount = 0; mTable_ChangesCount = 0;
this->SetTableRewrite(); this->SetTableRewrite();
} }
@ -470,6 +501,118 @@ morkRow* morkTable::find_member_row(morkEnv* ev, morkRow* ioRow)
return (morkRow*) 0; 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 mork_bool
morkTable::AddRow(morkEnv* ev, morkRow* ioRow) morkTable::AddRow(morkEnv* ev, morkRow* ioRow)
{ {

Просмотреть файл

@ -1,368 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef _MORKTABLE_
#define _MORKTABLE_ 1
#ifndef _MORK_
#include "mork.h"
#endif
#ifndef _MORKNODE_
#include "morkNode.h"
#endif
#ifndef _MORKDEQUE_
#include "morkDeque.h"
#endif
#ifndef _MORKOBJECT_
#include "morkObject.h"
#endif
#ifndef _MORKARRAY_
#include "morkArray.h"
#endif
#ifndef _MORKROWMAP_
#include "morkRowMap.h"
#endif
#ifndef _MORKNODEMAP_
#include "morkNodeMap.h"
#endif
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
class nsIMdbTable;
#define morkDerived_kTable /*i*/ 0x5462 /* ascii 'Tb' */
/*| kStartRowArraySize: starting physical size of array for mTable_RowArray.
**| We want this number very small, so that a table containing exactly one
**| row member will not pay too significantly in space overhead. But we want
**| a number bigger than one, so there is some space for growth.
|*/
#define morkTable_kStartRowArraySize 3 /* modest starting size for array */
/*| kMakeRowMapThreshold: this is the number of rows in a table which causes
**| a hash table (mTable_RowMap) to be lazily created for faster member row
**| identification, during such operations as cuts and adds. This number must
**| be small enough that linear searches are not bad for member counts less
**| than this; but this number must also be large enough that creating a hash
**| table does not increase the per-row space overhead by a big percentage.
**| For speed, numbers on the order of ten to twenty are all fine; for space,
**| I believe a number as small as ten will have too much space overhead.
|*/
#define morkTable_kMakeRowMapThreshold 17 /* when to build mTable_RowMap */
#define morkTable_kStartRowMapSlotCount 13
#define morkTable_kMaxTableGcUses 0x0FF /* max for 8-bit unsigned int */
#define morkTable_kUniqueBit ((mork_u1) (1 << 0))
#define morkTable_kVerboseBit ((mork_u1) (1 << 1))
#define morkTable_kNotedBit ((mork_u1) (1 << 2)) /* space has change notes */
#define morkTable_kRewriteBit ((mork_u1) (1 << 3)) /* must rewrite all rows */
#define morkTable_kNewMetaBit ((mork_u1) (1 << 4)) /* new table meta row */
class morkTable : public morkObject, public morkLink {
// NOTE the morkLink base is for morkRowSpace::mRowSpace_TablesByPriority
// public: // slots inherited from morkObject (meant to inform only)
// nsIMdbHeap* mNode_Heap;
// mork_base mNode_Base; // must equal morkBase_kNode
// mork_derived mNode_Derived; // depends on specific node subclass
// mork_access mNode_Access; // kOpen, kClosing, kShut, or kDead
// mork_usage mNode_Usage; // kHeap, kStack, kMember, kGlobal, kNone
// mork_able mNode_Mutable; // can this node be modified?
// mork_load mNode_Load; // is this node clean or dirty?
// mork_uses mNode_Uses; // refcount for strong refs
// mork_refs mNode_Refs; // refcount for strong refs + weak refs
// morkHandle* mObject_Handle; // weak ref to handle for this object
public: // state is public because the entire Mork system is private
morkStore* mTable_Store; // weak ref to port
// mTable_RowSpace->mSpace_Scope is row scope
morkRowSpace* mTable_RowSpace; // weak ref to containing space
morkRow* mTable_MetaRow; // table's actual meta row
mdbOid mTable_MetaRowOid; // oid for meta row
morkRowMap* mTable_RowMap; // (strong ref) hash table of all members
morkArray mTable_RowArray; // array of morkRow pointers
morkList mTable_ChangeList; // list of table changes
mork_u2 mTable_ChangesCount; // length of changes list
mork_u2 mTable_ChangesMax; // max list length before rewrite
mork_tid mTable_Id;
mork_kind mTable_Kind;
mork_u1 mTable_Flags; // bit flags
mork_priority mTable_Priority; // 0..9, any other value equals 9
mork_u1 mTable_GcUses; // persistent references from cells
mork_u1 mTable_Pad; // for u4 alignment
public: // flags bit twiddling
void SetTableUnique() { mTable_Flags |= morkTable_kUniqueBit; }
void SetTableVerbose() { mTable_Flags |= morkTable_kVerboseBit; }
void SetTableNoted() { mTable_Flags |= morkTable_kNotedBit; }
void SetTableRewrite() { mTable_Flags |= morkTable_kRewriteBit; }
void SetTableNewMeta() { mTable_Flags |= morkTable_kNewMetaBit; }
void ClearTableUnique() { mTable_Flags &= (mork_u1) ~morkTable_kUniqueBit; }
void ClearTableVerbose() { mTable_Flags &= (mork_u1) ~morkTable_kVerboseBit; }
void ClearTableNoted() { mTable_Flags &= (mork_u1) ~morkTable_kNotedBit; }
void ClearTableRewrite() { mTable_Flags &= (mork_u1) ~morkTable_kRewriteBit; }
void ClearTableNewMeta() { mTable_Flags &= (mork_u1) ~morkTable_kNewMetaBit; }
mork_bool IsTableUnique() const
{ return ( mTable_Flags & morkTable_kUniqueBit ) != 0; }
mork_bool IsTableVerbose() const
{ return ( mTable_Flags & morkTable_kVerboseBit ) != 0; }
mork_bool IsTableNoted() const
{ return ( mTable_Flags & morkTable_kNotedBit ) != 0; }
mork_bool IsTableRewrite() const
{ return ( mTable_Flags & morkTable_kRewriteBit ) != 0; }
mork_bool IsTableNewMeta() const
{ return ( mTable_Flags & morkTable_kNewMetaBit ) != 0; }
public: // table dirty handling more complex than morkNode::SetNodeDirty() etc.
void SetTableDirty() { this->SetNodeDirty(); }
void SetTableClean(morkEnv* ev);
mork_bool IsTableClean() const { return this->IsNodeClean(); }
mork_bool IsTableDirty() const { return this->IsNodeDirty(); }
public: // morkNode memory management operators
void* operator new(size_t inSize, nsIMdbHeap& ioHeap, morkEnv* ev)
{ return morkNode::MakeNew(inSize, ioHeap, ev); }
void operator delete(void* ioAddress)
{ morkNode::OnDeleteAssert(ioAddress); }
// do NOT call delete on morkNode instances. Call ZapOld() instead.
// { ===== begin morkNode interface =====
public: // morkNode virtual methods
virtual void CloseMorkNode(morkEnv* ev); // CloseTable() if open
virtual ~morkTable(); // assert that close executed earlier
public: // morkTable construction & destruction
morkTable(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioNodeHeap, morkStore* ioStore,
nsIMdbHeap* ioSlotHeap, morkRowSpace* ioRowSpace,
const mdbOid* inOptionalMetaRowOid, // can be nil to avoid specifying
mork_tid inTableId,
mork_kind inKind, mork_bool inMustBeUnique);
void CloseTable(morkEnv* ev); // called by CloseMorkNode();
private: // copying is not allowed
morkTable(const morkTable& other);
morkTable& operator=(const morkTable& other);
public: // dynamic type identification
mork_bool IsTable() const
{ return IsNode() && mNode_Derived == morkDerived_kTable; }
// } ===== end morkNode methods =====
public: // errors
static void NonTableTypeError(morkEnv* ev);
static void NonTableTypeWarning(morkEnv* ev);
static void NilRowSpaceError(morkEnv* ev);
public: // warnings
static void TableGcUsesUnderflowWarning(morkEnv* ev);
public: // noting table changes
mork_bool HasChangeOverflow() const
{ return mTable_ChangesCount >= mTable_ChangesMax; }
void NoteTableSetAll(morkEnv* ev);
void NoteTableMoveRow(morkEnv* ev, morkRow* ioRow, mork_pos inPos);
void note_row_change(morkEnv* ev, mork_change inChange, morkRow* ioRow);
void NoteTableAddRow(morkEnv* ev, morkRow* ioRow)
{ this->note_row_change(ev, morkChange_kAdd, ioRow); }
void NoteTableCutRow(morkEnv* ev, morkRow* ioRow)
{ this->note_row_change(ev, morkChange_kCut, ioRow); }
protected: // internal row map methods
morkRow* find_member_row(morkEnv* ev, morkRow* ioRow);
void build_row_map(morkEnv* ev);
public: // other table methods
mork_bool MaybeDirtySpaceStoreAndTable();
morkRow* GetMetaRow(morkEnv* ev, const mdbOid* inOptionalMetaRowOid);
mork_u2 AddTableGcUse(morkEnv* ev);
mork_u2 CutTableGcUse(morkEnv* ev);
// void DirtyAllTableContent(morkEnv* ev);
mork_seed TableSeed() const { return mTable_RowArray.mArray_Seed; }
morkRow* SafeRowAt(morkEnv* ev, mork_pos inPos)
{ return (morkRow*) mTable_RowArray.SafeAt(ev, inPos); }
nsIMdbTable* AcquireTableHandle(morkEnv* ev); // mObject_Handle
mork_count GetRowCount() const { return mTable_RowArray.mArray_Fill; }
void GetTableOid(morkEnv* ev, mdbOid* outOid);
mork_pos ArrayHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool MapHasOid(morkEnv* ev, const mdbOid* inOid);
mork_bool AddRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutRow(morkEnv* ev, morkRow* ioRow); // returns ev->Good()
mork_bool CutAllRows(morkEnv* ev); // returns ev->Good()
morkTableRowCursor* NewTableRowCursor(morkEnv* ev, mork_pos inRowPos);
public: // typesafe refcounting inlines calling inherited morkNode methods
static void SlotWeakTable(morkTable* me,
morkEnv* ev, morkTable** ioSlot)
{ morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
static void SlotStrongTable(morkTable* me,
morkEnv* ev, morkTable** ioSlot)
{ morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
// use negative values for kCut and kAdd, to keep non-neg move pos distinct:
#define morkTableChange_kCut ((mork_pos) -1) /* shows row was cut */
#define morkTableChange_kAdd ((mork_pos) -2) /* shows row was added */
#define morkTableChange_kNone ((mork_pos) -3) /* unknown change */
class morkTableChange : public morkNext {
public: // state is public because the entire Mork system is private
morkRow* mTableChange_Row; // the row in the change
mork_pos mTableChange_Pos; // kAdd, kCut, or non-neg for row move
public:
morkTableChange(morkEnv* ev, mork_change inChange, morkRow* ioRow);
// use this constructor for inChange == morkChange_kAdd or morkChange_kCut
morkTableChange(morkEnv* ev, morkRow* ioRow, mork_pos inPos);
// use this constructor when the row is moved
public:
void UnknownChangeError(morkEnv* ev) const; // morkChange_kAdd or morkChange_kCut
void NegativeMovePosError(morkEnv* ev) const; // move must be non-neg position
public:
mork_bool IsAddRowTableChange() const
{ return ( mTableChange_Pos == morkTableChange_kAdd ); }
mork_bool IsCutRowTableChange() const
{ return ( mTableChange_Pos == morkTableChange_kCut ); }
mork_bool IsMoveRowTableChange() const
{ return ( mTableChange_Pos >= 0 ); }
public:
mork_pos GetMovePos() const { return mTableChange_Pos; }
// GetMovePos() assumes that IsMoveRowTableChange() is true.
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#define morkDerived_kTableMap /*i*/ 0x744D /* ascii 'tM' */
/*| morkTableMap: maps mork_token -> morkTable
|*/
class morkTableMap : public morkNodeMap { // for mapping tokens to tables
public:
virtual ~morkTableMap();
morkTableMap(morkEnv* ev, const morkUsage& inUsage,
nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap);
public: // other map methods
mork_bool AddTable(morkEnv* ev, morkTable* ioTable)
{ return this->AddNode(ev, ioTable->mTable_Id, ioTable); }
// the AddTable() boolean return equals ev->Good().
mork_bool CutTable(morkEnv* ev, mork_tid inTid)
{ return this->CutNode(ev, inTid); }
// The CutTable() boolean return indicates whether removal happened.
morkTable* GetTable(morkEnv* ev, mork_tid inTid)
{ return (morkTable*) this->GetNode(ev, inTid); }
// Note the returned table does NOT have an increase in refcount for this.
mork_num CutAllTables(morkEnv* ev)
{ return this->CutAllNodes(ev); }
// CutAllTables() releases all the referenced table values.
};
class morkTableMapIter: public morkMapIter{ // typesafe wrapper class
public:
morkTableMapIter(morkEnv* ev, morkTableMap* ioMap)
: morkMapIter(ev, ioMap) { }
morkTableMapIter( ) : morkMapIter() { }
void InitTableMapIter(morkEnv* ev, morkTableMap* ioMap)
{ this->InitMapIter(ev, ioMap); }
mork_change*
FirstTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->First(ev, outTid, outTable); }
mork_change*
NextTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->Next(ev, outTid, outTable); }
mork_change*
HereTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->Here(ev, outTid, outTable); }
// cutting while iterating hash map might dirty the parent table:
mork_change*
CutHereTable(morkEnv* ev, mork_tid* outTid, morkTable** outTable)
{ return this->CutHere(ev, outTid, outTable); }
};
//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#endif /* _MORKTABLE_ */

Просмотреть файл

@ -1122,18 +1122,25 @@ orkinTable::MoveOid( // change position of row in unsorted table
nsIMdbEnv* mev, // context nsIMdbEnv* mev, // context
const mdbOid* inOid, // row oid to find in table const mdbOid* inOid, // row oid to find in table
mdb_pos inHintFromPos, // suggested hint regarding start position mdb_pos inHintFromPos, // suggested hint regarding start position
mdb_pos inToPos, // desired new position for row inRowId mdb_pos inToPos, // desired new position for row inOid
mdb_pos* outActualPos) // actual new position of row in table mdb_pos* outActualPos) // actual new position of row in table
{ {
MORK_USED_3(inHintFromPos,inToPos,inOid);
mdb_err outErr = 0; mdb_err outErr = 0;
mdb_pos actualPos = 0; mdb_pos actualPos = -1; // meaning it was never found in table
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev ) if ( ev )
{ {
// remember table->MaybeDirtySpaceStoreAndTable(); morkTable* table = (morkTable*) mHandle_Object;
morkStore* store = table->mTable_Store;
if ( inOid && store )
{
morkRow* row = store->GetRow(ev, inOid);
if ( row )
actualPos = table->MoveRow(ev, row, inHintFromPos, inToPos);
}
else
ev->NilPointerError();
ev->StubMethodOnlyError();
outErr = ev->AsErr(); outErr = ev->AsErr();
} }
if ( outActualPos ) if ( outActualPos )
@ -1146,18 +1153,21 @@ orkinTable::MoveRow( // change position of row in unsorted table
nsIMdbEnv* mev, // context nsIMdbEnv* mev, // context
nsIMdbRow* ioRow, // row oid to find in table nsIMdbRow* ioRow, // row oid to find in table
mdb_pos inHintFromPos, // suggested hint regarding start position mdb_pos inHintFromPos, // suggested hint regarding start position
mdb_pos inToPos, // desired new position for row inRowId mdb_pos inToPos, // desired new position for row ioRow
mdb_pos* outActualPos) // actual new position of row in table mdb_pos* outActualPos) // actual new position of row in table
{ {
MORK_USED_3(inHintFromPos,inToPos,ioRow); mdb_pos actualPos = -1; // meaning it was never found in table
mdb_pos actualPos = 0;
mdb_err outErr = 0; mdb_err outErr = 0;
morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr);
if ( ev ) if ( ev )
{ {
// remember table->MaybeDirtySpaceStoreAndTable(); morkRow* row = 0;
orkinRow* orow = (orkinRow*) ioRow;
ev->StubMethodOnlyError(); if ( orow->CanUseRow(mev, /*inMutable*/ morkBool_kFalse, &outErr, &row) )
{
morkTable* table = (morkTable*) mHandle_Object;
actualPos = table->MoveRow(ev, row, inHintFromPos, inToPos);
}
outErr = ev->AsErr(); outErr = ev->AsErr();
} }
if ( outActualPos ) if ( outActualPos )