summaryrefslogtreecommitdiffstats
path: root/db/mork/src/morkPool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'db/mork/src/morkPool.cpp')
-rw-r--r--db/mork/src/morkPool.cpp552
1 files changed, 552 insertions, 0 deletions
diff --git a/db/mork/src/morkPool.cpp b/db/mork/src/morkPool.cpp
new file mode 100644
index 000000000..6819b8bd0
--- /dev/null
+++ b/db/mork/src/morkPool.cpp
@@ -0,0 +1,552 @@
+/* -*- 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 _MORKENV_
+#include "morkEnv.h"
+#endif
+
+#ifndef _MORKPOOL_
+#include "morkPool.h"
+#endif
+
+#ifndef _MORKATOM_
+#include "morkAtom.h"
+#endif
+
+#ifndef _MORKHANDLE_
+#include "morkHandle.h"
+#endif
+
+#ifndef _MORKCELL_
+#include "morkCell.h"
+#endif
+
+#ifndef _MORKROW_
+#include "morkRow.h"
+#endif
+
+#ifndef _MORKBLOB_
+#include "morkBlob.h"
+#endif
+
+#ifndef _MORKDEQUE_
+#include "morkDeque.h"
+#endif
+
+#ifndef _MORKZONE_
+#include "morkZone.h"
+#endif
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+
+// ````` ````` ````` ````` `````
+// { ===== begin morkNode interface =====
+
+/*public virtual*/ void
+morkPool::CloseMorkNode(morkEnv* ev) // ClosePool() only if open
+{
+ if ( this->IsOpenNode() )
+ {
+ this->MarkClosing();
+ this->ClosePool(ev);
+ this->MarkShut();
+ }
+}
+
+/*public virtual*/
+morkPool::~morkPool() // assert ClosePool() executed earlier
+{
+ MORK_ASSERT(this->IsShutNode());
+}
+
+/*public non-poly*/
+morkPool::morkPool(const morkUsage& inUsage, nsIMdbHeap* ioHeap,
+ nsIMdbHeap* ioSlotHeap)
+: morkNode(inUsage, ioHeap)
+, mPool_Heap( ioSlotHeap )
+, mPool_UsedFramesCount( 0 )
+, mPool_FreeFramesCount( 0 )
+{
+ // mPool_Heap is NOT refcounted
+ MORK_ASSERT(ioSlotHeap);
+ if ( ioSlotHeap )
+ mNode_Derived = morkDerived_kPool;
+}
+
+/*public non-poly*/
+morkPool::morkPool(morkEnv* ev,
+ const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap)
+: morkNode(ev, inUsage, ioHeap)
+, mPool_Heap( ioSlotHeap )
+, mPool_UsedFramesCount( 0 )
+, mPool_FreeFramesCount( 0 )
+{
+ if ( ioSlotHeap )
+ {
+ // mPool_Heap is NOT refcounted:
+ // nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mPool_Heap);
+ if ( ev->Good() )
+ mNode_Derived = morkDerived_kPool;
+ }
+ else
+ ev->NilPointerError();
+}
+
+/*public non-poly*/ void
+morkPool::ClosePool(morkEnv* ev) // called by CloseMorkNode();
+{
+ if ( this->IsNode() )
+ {
+#ifdef morkZone_CONFIG_ARENA
+#else /*morkZone_CONFIG_ARENA*/
+ //MORK_USED_1(ioZone);
+#endif /*morkZone_CONFIG_ARENA*/
+
+ nsIMdbHeap* heap = mPool_Heap;
+ nsIMdbEnv* mev = ev->AsMdbEnv();
+ morkLink* aLink;
+ morkDeque* d = &mPool_FreeHandleFrames;
+ while ( (aLink = d->RemoveFirst()) != 0 )
+ heap->Free(mev, aLink);
+
+ // if the pool's closed, get rid of the frames in use too.
+ d = &mPool_UsedHandleFrames;
+ while ( (aLink = d->RemoveFirst()) != 0 )
+ heap->Free(mev, aLink);
+
+ this->MarkShut();
+ }
+ else
+ this->NonNodeError(ev);
+}
+
+// } ===== end morkNode methods =====
+// ````` ````` ````` ````` `````
+
+
+// alloc and free individual instances of handles (inside hand frames):
+morkHandleFace*
+morkPool::NewHandle(morkEnv* ev, mork_size inSize, morkZone* ioZone)
+{
+ void* newBlock = 0;
+ if ( inSize <= sizeof(morkHandleFrame) )
+ {
+ morkLink* firstLink = mPool_FreeHandleFrames.RemoveFirst();
+ if ( firstLink )
+ {
+ newBlock = firstLink;
+ if ( mPool_FreeFramesCount )
+ --mPool_FreeFramesCount;
+ else
+ ev->NewWarning("mPool_FreeFramesCount underflow");
+ }
+ else
+ mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkHandleFrame),
+ (void**) &newBlock);
+ }
+ else
+ {
+ ev->NewWarning("inSize > sizeof(morkHandleFrame)");
+ mPool_Heap->Alloc(ev->AsMdbEnv(), inSize, (void**) &newBlock);
+ }
+#ifdef morkZone_CONFIG_ARENA
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+#endif /*morkZone_CONFIG_ARENA*/
+
+ return (morkHandleFace*) newBlock;
+}
+
+void
+morkPool::ZapHandle(morkEnv* ev, morkHandleFace* ioHandle)
+{
+ if ( ioHandle )
+ {
+ morkLink* handleLink = (morkLink*) ioHandle;
+ mPool_FreeHandleFrames.AddLast(handleLink);
+ ++mPool_FreeFramesCount;
+ // lets free all handles to track down leaks
+ // - uncomment out next 3 lines, comment out above 2
+// nsIMdbHeap* heap = mPool_Heap;
+// nsIMdbEnv* mev = ev->AsMdbEnv();
+// heap->Free(mev, handleLink);
+
+ }
+}
+
+
+// alloc and free individual instances of rows:
+morkRow*
+morkPool::NewRow(morkEnv* ev, morkZone* ioZone) // allocate a new row instance
+{
+ morkRow* newRow = 0;
+
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'chip' remembers no size, and so cannot be deallocated:
+ newRow = (morkRow*) ioZone->ZoneNewChip(ev, sizeof(morkRow));
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkRow), (void**) &newRow);
+#endif /*morkZone_CONFIG_ARENA*/
+
+ if ( newRow )
+ MORK_MEMSET(newRow, 0, sizeof(morkRow));
+
+ return newRow;
+}
+
+void
+morkPool::ZapRow(morkEnv* ev, morkRow* ioRow,
+ morkZone* ioZone) // free old row instance
+{
+#ifdef morkZone_CONFIG_ARENA
+ if ( !ioRow )
+ ev->NilPointerWarning(); // a zone 'chip' cannot be freed
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ if ( ioRow )
+ mPool_Heap->Free(ev->AsMdbEnv(), ioRow);
+#endif /*morkZone_CONFIG_ARENA*/
+}
+
+// alloc and free entire vectors of cells (not just one cell at a time)
+morkCell*
+morkPool::NewCells(morkEnv* ev, mork_size inSize,
+ morkZone* ioZone)
+{
+ morkCell* newCells = 0;
+
+ mork_size size = inSize * sizeof(morkCell);
+ if ( size )
+ {
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'run' knows its size, and can indeed be deallocated:
+ newCells = (morkCell*) ioZone->ZoneNewRun(ev, size);
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newCells);
+#endif /*morkZone_CONFIG_ARENA*/
+ }
+
+ // note morkAtom depends on having nil stored in all new mCell_Atom slots:
+ if ( newCells )
+ MORK_MEMSET(newCells, 0, size);
+ return newCells;
+}
+
+void
+morkPool::ZapCells(morkEnv* ev, morkCell* ioVector, mork_size inSize,
+ morkZone* ioZone)
+{
+ MORK_USED_1(inSize);
+
+ if ( ioVector )
+ {
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'run' knows its size, and can indeed be deallocated:
+ ioZone->ZoneZapRun(ev, ioVector);
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Free(ev->AsMdbEnv(), ioVector);
+#endif /*morkZone_CONFIG_ARENA*/
+ }
+}
+
+// resize (grow or trim) cell vectors inside a containing row instance
+mork_bool
+morkPool::AddRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize,
+ morkZone* ioZone)
+{
+ // note strong implementation similarity to morkArray::Grow()
+
+ MORK_USED_1(ioZone);
+#ifdef morkZone_CONFIG_ARENA
+#else /*morkZone_CONFIG_ARENA*/
+#endif /*morkZone_CONFIG_ARENA*/
+
+ mork_fill fill = ioRow->mRow_Length;
+ if ( ev->Good() && fill < inNewSize ) // need more cells?
+ {
+ morkCell* newCells = this->NewCells(ev, inNewSize, ioZone);
+ if ( newCells )
+ {
+ morkCell* c = newCells; // for iterating during copy
+ morkCell* oldCells = ioRow->mRow_Cells;
+ morkCell* end = oldCells + fill; // copy all the old cells
+ while ( oldCells < end )
+ {
+ *c++ = *oldCells++; // bitwise copy each old cell struct
+ }
+ oldCells = ioRow->mRow_Cells;
+ ioRow->mRow_Cells = newCells;
+ ioRow->mRow_Length = (mork_u2) inNewSize;
+ ++ioRow->mRow_Seed;
+
+ if ( oldCells )
+ this->ZapCells(ev, oldCells, fill, ioZone);
+ }
+ }
+ return ( ev->Good() && ioRow->mRow_Length >= inNewSize );
+}
+
+mork_bool
+morkPool::CutRowCells(morkEnv* ev, morkRow* ioRow,
+ mork_size inNewSize,
+ morkZone* ioZone)
+{
+ MORK_USED_1(ioZone);
+#ifdef morkZone_CONFIG_ARENA
+#else /*morkZone_CONFIG_ARENA*/
+#endif /*morkZone_CONFIG_ARENA*/
+
+ mork_fill fill = ioRow->mRow_Length;
+ if ( ev->Good() && fill > inNewSize ) // need fewer cells?
+ {
+ if ( inNewSize ) // want any row cells at all?
+ {
+ morkCell* newCells = this->NewCells(ev, inNewSize, ioZone);
+ if ( newCells )
+ {
+ morkCell* saveNewCells = newCells; // Keep newcell pos
+ morkCell* oldCells = ioRow->mRow_Cells;
+ morkCell* oldEnd = oldCells + fill; // one past all old cells
+ morkCell* newEnd = oldCells + inNewSize; // copy only kept old cells
+ while ( oldCells < newEnd )
+ {
+ *newCells++ = *oldCells++; // bitwise copy each old cell struct
+ }
+ while ( oldCells < oldEnd )
+ {
+ if ( oldCells->mCell_Atom ) // need to unref old cell atom?
+ oldCells->SetAtom(ev, (morkAtom*) 0, this); // unref cell atom
+ ++oldCells;
+ }
+ oldCells = ioRow->mRow_Cells;
+ ioRow->mRow_Cells = saveNewCells;
+ ioRow->mRow_Length = (mork_u2) inNewSize;
+ ++ioRow->mRow_Seed;
+
+ if ( oldCells )
+ this->ZapCells(ev, oldCells, fill, ioZone);
+ }
+ }
+ else // get rid of all row cells
+ {
+ morkCell* oldCells = ioRow->mRow_Cells;
+ ioRow->mRow_Cells = 0;
+ ioRow->mRow_Length = 0;
+ ++ioRow->mRow_Seed;
+
+ if ( oldCells )
+ this->ZapCells(ev, oldCells, fill, ioZone);
+ }
+ }
+ return ( ev->Good() && ioRow->mRow_Length <= inNewSize );
+}
+
+// alloc & free individual instances of atoms (lots of atom subclasses):
+void
+morkPool::ZapAtom(morkEnv* ev, morkAtom* ioAtom,
+ morkZone* ioZone) // any subclass (by kind)
+{
+#ifdef morkZone_CONFIG_ARENA
+ if ( !ioAtom )
+ ev->NilPointerWarning(); // a zone 'chip' cannot be freed
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ if ( ioAtom )
+ mPool_Heap->Free(ev->AsMdbEnv(), ioAtom);
+#endif /*morkZone_CONFIG_ARENA*/
+}
+
+morkOidAtom*
+morkPool::NewRowOidAtom(morkEnv* ev, const mdbOid& inOid,
+ morkZone* ioZone)
+{
+ morkOidAtom* newAtom = 0;
+
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'chip' remembers no size, and so cannot be deallocated:
+ newAtom = (morkOidAtom*) ioZone->ZoneNewChip(ev, sizeof(morkOidAtom));
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom),(void**) &newAtom);
+#endif /*morkZone_CONFIG_ARENA*/
+
+ if ( newAtom )
+ newAtom->InitRowOidAtom(ev, inOid);
+ return newAtom;
+}
+
+morkOidAtom*
+morkPool::NewTableOidAtom(morkEnv* ev, const mdbOid& inOid,
+ morkZone* ioZone)
+{
+ morkOidAtom* newAtom = 0;
+
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'chip' remembers no size, and so cannot be deallocated:
+ newAtom = (morkOidAtom*) ioZone->ZoneNewChip(ev, sizeof(morkOidAtom));
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom), (void**) &newAtom);
+#endif /*morkZone_CONFIG_ARENA*/
+ if ( newAtom )
+ newAtom->InitTableOidAtom(ev, inOid);
+ return newAtom;
+}
+
+morkAtom*
+morkPool::NewAnonAtom(morkEnv* ev, const morkBuf& inBuf,
+ mork_cscode inForm,
+ morkZone* ioZone)
+// if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
+// anon atom will be created, and otherwise a 'big' anon atom.
+{
+ morkAtom* newAtom = 0;
+
+ mork_bool needBig = ( inForm || inBuf.mBuf_Fill > 255 );
+ mork_size size = ( needBig )?
+ morkBigAnonAtom::SizeForFill(inBuf.mBuf_Fill) :
+ morkWeeAnonAtom::SizeForFill(inBuf.mBuf_Fill);
+
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'chip' remembers no size, and so cannot be deallocated:
+ newAtom = (morkAtom*) ioZone->ZoneNewChip(ev, size);
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
+#endif /*morkZone_CONFIG_ARENA*/
+ if ( newAtom )
+ {
+ if ( needBig )
+ ((morkBigAnonAtom*) newAtom)->InitBigAnonAtom(ev, inBuf, inForm);
+ else
+ ((morkWeeAnonAtom*) newAtom)->InitWeeAnonAtom(ev, inBuf);
+ }
+ return newAtom;
+}
+
+morkBookAtom*
+morkPool::NewBookAtom(morkEnv* ev, const morkBuf& inBuf,
+ mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid,
+ morkZone* ioZone)
+// if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
+// book atom will be created, and otherwise a 'big' book atom.
+{
+ morkBookAtom* newAtom = 0;
+
+ mork_bool needBig = ( inForm || inBuf.mBuf_Fill > 255 );
+ mork_size size = ( needBig )?
+ morkBigBookAtom::SizeForFill(inBuf.mBuf_Fill) :
+ morkWeeBookAtom::SizeForFill(inBuf.mBuf_Fill);
+
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'chip' remembers no size, and so cannot be deallocated:
+ newAtom = (morkBookAtom*) ioZone->ZoneNewChip(ev, size);
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
+#endif /*morkZone_CONFIG_ARENA*/
+ if ( newAtom )
+ {
+ if ( needBig )
+ ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
+ inBuf, inForm, ioSpace, inAid);
+ else
+ ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
+ inBuf, ioSpace, inAid);
+ }
+ return newAtom;
+}
+
+morkBookAtom*
+morkPool::NewBookAtomCopy(morkEnv* ev, const morkBigBookAtom& inAtom,
+ morkZone* ioZone)
+ // make the smallest kind of book atom that can hold content in inAtom.
+ // The inAtom parameter is often expected to be a staged book atom in
+ // the store, which was used to search an atom space for existing atoms.
+{
+ morkBookAtom* newAtom = 0;
+
+ mork_cscode form = inAtom.mBigBookAtom_Form;
+ mork_fill fill = inAtom.mBigBookAtom_Size;
+ mork_bool needBig = ( form || fill > 255 );
+ mork_size size = ( needBig )?
+ morkBigBookAtom::SizeForFill(fill) :
+ morkWeeBookAtom::SizeForFill(fill);
+
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'chip' remembers no size, and so cannot be deallocated:
+ newAtom = (morkBookAtom*) ioZone->ZoneNewChip(ev, size);
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
+#endif /*morkZone_CONFIG_ARENA*/
+ if ( newAtom )
+ {
+ morkBuf buf(inAtom.mBigBookAtom_Body, fill);
+ if ( needBig )
+ ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
+ buf, form, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
+ else
+ ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
+ buf, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
+ }
+ return newAtom;
+}
+
+morkBookAtom*
+morkPool::NewFarBookAtomCopy(morkEnv* ev, const morkFarBookAtom& inAtom,
+ morkZone* ioZone)
+ // make the smallest kind of book atom that can hold content in inAtom.
+ // The inAtom parameter is often expected to be a staged book atom in
+ // the store, which was used to search an atom space for existing atoms.
+{
+ morkBookAtom* newAtom = 0;
+
+ mork_cscode form = inAtom.mFarBookAtom_Form;
+ mork_fill fill = inAtom.mFarBookAtom_Size;
+ mork_bool needBig = ( form || fill > 255 );
+ mork_size size = ( needBig )?
+ morkBigBookAtom::SizeForFill(fill) :
+ morkWeeBookAtom::SizeForFill(fill);
+
+#ifdef morkZone_CONFIG_ARENA
+ // a zone 'chip' remembers no size, and so cannot be deallocated:
+ newAtom = (morkBookAtom*) ioZone->ZoneNewChip(ev, size);
+#else /*morkZone_CONFIG_ARENA*/
+ MORK_USED_1(ioZone);
+ mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
+#endif /*morkZone_CONFIG_ARENA*/
+ if ( newAtom )
+ {
+ morkBuf buf(inAtom.mFarBookAtom_Body, fill);
+ if ( needBig )
+ ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
+ buf, form, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
+ else
+ ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
+ buf, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
+ }
+ return newAtom;
+}
+
+
+
+//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+