diff --git a/db/mork/macbuild/mork.mcp b/db/mork/macbuild/mork.mcp index 3dc832be125b..d0b017c17e03 100644 Binary files a/db/mork/macbuild/mork.mcp and b/db/mork/macbuild/mork.mcp differ diff --git a/db/mork/src/mork.h b/db/mork/src/mork.h index 0b2d8ffc6446..ab2d551f52f9 100644 --- a/db/mork/src/mork.h +++ b/db/mork/src/mork.h @@ -194,6 +194,8 @@ class morkRow; class morkRowCellCursor; class morkRowObject; class morkRowSpace; +class morkSorting; +class morkSortingRowCursor; class morkSpace; class morkSpan; class morkStore; diff --git a/db/mork/src/morkEnv.cpp b/db/mork/src/morkEnv.cpp index 328acb6ee4bb..624a24efff05 100644 --- a/db/mork/src/morkEnv.cpp +++ b/db/mork/src/morkEnv.cpp @@ -67,6 +67,9 @@ morkEnv::~morkEnv() /*i*/ // assert CloseEnv() executed earlier MORK_ASSERT(mEnv_ErrorHook==0); } +/* choose morkBool_kTrue or morkBool_kFalse for kBeVerbose: */ +#define morkEnv_kBeVerbose morkBool_kFalse + /*public non-poly*/ morkEnv::morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap, morkFactory* ioFactory, nsIMdbHeap* ioSlotHeap) @@ -86,7 +89,7 @@ morkEnv::morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap, , mEnv_DoTrace( morkBool_kFalse ) , mEnv_AutoClear( morkAble_kDisabled ) , mEnv_ShouldAbort( morkBool_kFalse ) -, mEnv_BeVerbose( morkBool_kFalse ) +, mEnv_BeVerbose( morkEnv_kBeVerbose ) { MORK_ASSERT(ioSlotHeap && ioFactory ); if ( ioSlotHeap ) @@ -126,7 +129,7 @@ morkEnv::morkEnv(morkEnv* ev, /*i*/ , mEnv_DoTrace( morkBool_kFalse ) , mEnv_AutoClear( morkAble_kDisabled ) , mEnv_ShouldAbort( morkBool_kFalse ) -, mEnv_BeVerbose( morkBool_kFalse ) +, mEnv_BeVerbose( morkEnv_kBeVerbose ) { // $$$ do we need to refcount the inSelfAsMdbEnv nsIMdbEnv?? diff --git a/db/mork/src/morkFile.cpp b/db/mork/src/morkFile.cpp index 095be8417d44..4eed7d5546de 100644 --- a/db/mork/src/morkFile.cpp +++ b/db/mork/src/morkFile.cpp @@ -36,9 +36,13 @@ #include "morkFile.h" #endif -// #ifndef _ORKINFILE_ -// #include "orkinFile.h" -// #endif +#define MORK_CONFIG_USE_ORKINFILE 1 + +#ifdef MORK_CONFIG_USE_ORKINFILE +#ifndef _ORKINFILE_ +#include "orkinFile.h" +#endif +#endif /*MORK_CONFIG_USE_ORKINFILE*/ //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 diff --git a/db/mork/src/morkHandle.cpp b/db/mork/src/morkHandle.cpp index 12854919eb2f..e6b017c5961e 100644 --- a/db/mork/src/morkHandle.cpp +++ b/db/mork/src/morkHandle.cpp @@ -173,19 +173,20 @@ void morkHandle::NewDownHandleError(morkEnv* ev) const } morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev, - mork_bool inMutable, mork_magic inMagicType) const + mork_bool inMutable, mork_magic inMagicType, mork_bool inClosedOkay) const { morkObject* outObject = 0; - if ( this->IsHandle() && this->GoodHandleTag() && this->IsOpenNode() ) + if ( this->IsHandle() && this->GoodHandleTag() && + ( inClosedOkay || this->IsOpenNode() ) ) { if ( !inMagicType || mHandle_Magic == inMagicType ) { morkObject* obj = this->mHandle_Object; - if ( obj ) + if ( obj ) { if ( obj->IsNode() ) { - if ( obj->IsOpenNode() ) + if ( inClosedOkay || obj->IsOpenNode() ) { if ( this->IsMutable() || !inMutable ) outObject = obj; @@ -198,7 +199,7 @@ morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev, else this->NonNodeObjectError(ev); } - else + else if ( !inClosedOkay ) this->NilHandleObjectError(ev); } else @@ -207,27 +208,28 @@ morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev, else this->NewDownHandleError(ev); - MORK_ASSERT(outObject); + MORK_ASSERT(outObject || inClosedOkay); return outObject; } morkEnv* morkHandle::CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable, - mdb_err* outErr) const + mork_bool inClosedOkay, mdb_err* outErr) const { morkEnv* outEnv = 0; morkEnv* ev = morkEnv::FromMdbEnv(mev); if ( ev ) { - morkObject* obj = this->GetGoodHandleObject(ev, inMutable, /*magic*/ 0); + morkObject* obj = this->GetGoodHandleObject(ev, inMutable, + /*magic*/ 0, inClosedOkay); if ( obj ) { outEnv = ev; } *outErr = ev->AsErr(); } - MORK_ASSERT(outEnv); + MORK_ASSERT(outEnv || inClosedOkay); return outEnv; } @@ -238,15 +240,20 @@ morkHandle::CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable, morkHandle::Handle_IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly) { mdb_err outErr = 0; + mdb_bool readOnly = mdbBool_kTrue; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { - MORK_ASSERT(outIsReadonly); - if ( outIsReadonly ) - *outIsReadonly = mHandle_Object->IsFrozen(); + readOnly = mHandle_Object->IsFrozen(); + outErr = ev->AsErr(); } + MORK_ASSERT(outIsReadonly); + if ( outIsReadonly ) + *outIsReadonly = readOnly; + return outErr; } // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port. @@ -257,23 +264,27 @@ morkHandle::Handle_IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly) morkHandle::Handle_GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory) { mdb_err outErr = 0; + nsIMdbFactory* handle = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { morkFactory* factory = ev->mEnv_Factory; if ( factory ) { - nsIMdbFactory* handle = factory->AcquireFactoryHandle(ev); - MORK_ASSERT(acqFactory); - if ( handle && acqFactory ) - *acqFactory = handle; + handle = factory->AcquireFactoryHandle(ev); } else this->NilFactoryError(ev); outErr = ev->AsErr(); } + + MORK_ASSERT(acqFactory); + if ( acqFactory ) + *acqFactory = handle; + return outErr; } // } ----- end factory methods ----- @@ -284,16 +295,19 @@ morkHandle::Handle_GetWeakRefCount(nsIMdbEnv* mev, // weak refs mdb_count* outCount) { mdb_err outErr = 0; + mdb_count count = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { - MORK_ASSERT(outCount); - if ( outCount ) - *outCount = this->WeakRefsOnly(); + count = this->WeakRefsOnly(); outErr = ev->AsErr(); } + MORK_ASSERT(outCount); + if ( outCount ) + *outCount = count; return outErr; } @@ -302,16 +316,19 @@ morkHandle::Handle_GetStrongRefCount(nsIMdbEnv* mev, // strong refs mdb_count* outCount) { mdb_err outErr = 0; + mdb_count count = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { - MORK_ASSERT(outCount); - if ( outCount ) - *outCount = this->StrongRefsOnly(); + count = this->StrongRefsOnly(); outErr = ev->AsErr(); } + MORK_ASSERT(outCount); + if ( outCount ) + *outCount = count; return outErr; } @@ -321,7 +338,8 @@ morkHandle::Handle_AddWeakRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { this->AddWeakRef(ev); @@ -335,7 +353,8 @@ morkHandle::Handle_AddStrongRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kFalse, &outErr); if ( ev ) { this->AddStrongRef(ev); @@ -350,7 +369,8 @@ morkHandle::Handle_CutWeakRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { this->CutWeakRef(ev); @@ -363,7 +383,8 @@ morkHandle::Handle_CutWeakRef(nsIMdbEnv* mev) morkHandle::Handle_CutStrongRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { this->CutStrongRef(ev); @@ -380,7 +401,8 @@ morkHandle::Handle_CloseMdbObject(nsIMdbEnv* mev) if ( this->IsNode() && this->IsOpenNode() ) { - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { morkObject* object = mHandle_Object; diff --git a/db/mork/src/morkHandle.h b/db/mork/src/morkHandle.h index ead587ef9202..f433b17febf6 100644 --- a/db/mork/src/morkHandle.h +++ b/db/mork/src/morkHandle.h @@ -118,12 +118,12 @@ public: // other handle methods void NonOpenObjectError(morkEnv* ev) const; morkObject* GetGoodHandleObject(morkEnv* ev, - mork_bool inMutabl, mork_magic inMagicType) const; + mork_bool inMutable, mork_magic inMagicType, mork_bool inClosedOkay) const; public: // interface supporting mdbObject methods morkEnv* CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable, - mdb_err* outErr) const; + mork_bool inClosedOkay, mdb_err* outErr) const; // { ----- begin mdbObject style methods ----- mdb_err Handle_IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly); diff --git a/db/mork/src/morkNode.cpp b/db/mork/src/morkNode.cpp index 5e59594217d0..b5511f9b6826 100644 --- a/db/mork/src/morkNode.cpp +++ b/db/mork/src/morkNode.cpp @@ -342,6 +342,30 @@ morkNode::CloseNode(morkEnv* ev) // called by CloseMorkNode(); } +extern void // utility method very similar to morkNode::SlotStrongNode(): +nsIMdbCompare_SlotStrongCompare(nsIMdbCompare* self, morkEnv* ev, + nsIMdbCompare** ioSlot) + // If *ioSlot is non-nil, that compare is released by CutStrongRef() and + // then zeroed out. Then if self is non-nil, this is acquired by + // calling AddStrongRef(), and if the return value shows success, + // then self is put into slot *ioSlot. Note self can be nil, so we take + // expression 'nsIMdbCompare_SlotStrongCompare(0, ev, &slot)'. +{ + nsIMdbEnv* menv = ev->AsMdbEnv(); + nsIMdbCompare* compare = *ioSlot; + if ( self != compare ) + { + if ( compare ) + { + *ioSlot = 0; + compare->CutStrongRef(menv); + } + if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) + *ioSlot = self; + } +} + + extern void // utility method very similar to morkNode::SlotStrongNode(): nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot) // If *ioSlot is non-nil, that file is released by CutStrongRef() and @@ -352,13 +376,16 @@ nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot) { nsIMdbEnv* menv = ev->AsMdbEnv(); nsIMdbFile* file = *ioSlot; - if ( file ) + if ( self != file ) { - *ioSlot = 0; - file->CutStrongRef(menv); + if ( file ) + { + *ioSlot = 0; + file->CutStrongRef(menv); + } + if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) + *ioSlot = self; } - if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) - *ioSlot = self; } void // utility method very similar to morkNode::SlotStrongNode(): @@ -371,13 +398,16 @@ nsIMdbHeap_SlotStrongHeap(nsIMdbHeap* self, morkEnv* ev, nsIMdbHeap** ioSlot) { nsIMdbEnv* menv = ev->AsMdbEnv(); nsIMdbHeap* heap = *ioSlot; - if ( heap ) + if ( self != heap ) { - *ioSlot = 0; - heap->CutStrongRef(menv); + if ( heap ) + { + *ioSlot = 0; + heap->CutStrongRef(menv); + } + if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) + *ioSlot = self; } - if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) - *ioSlot = self; } /*public static*/ void diff --git a/db/mork/src/morkNode.h b/db/mork/src/morkNode.h index 7ea5dca89b95..5193fce8a80f 100644 --- a/db/mork/src/morkNode.h +++ b/db/mork/src/morkNode.h @@ -275,7 +275,16 @@ nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot); // then zeroed out. Then if self is non-nil, this is acquired by // calling AddStrongRef(), and if the return value shows success, // then self is put into slot *ioSlot. Note self can be nil, so we take - // expression 'nsIMdbHeap_SlotStrongFile(0, ev, &slot)'. + // expression 'nsIMdbFile_SlotStrongFile(0, ev, &slot)'. + +extern void // utility method very similar to morkNode::SlotStrongNode(): +nsIMdbCompare_SlotStrongCompare(nsIMdbCompare* self, morkEnv* ev, + nsIMdbCompare** ioSlot); + // If *ioSlot is non-nil, that compare is released by CutStrongRef() and + // then zeroed out. Then if self is non-nil, this is acquired by + // calling AddStrongRef(), and if the return value shows success, + // then self is put into slot *ioSlot. Note self can be nil, so we take + // expression 'nsIMdbCompare_SlotStrongCompare(0, ev, &slot)'. //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 diff --git a/db/mork/src/morkStore.cpp b/db/mork/src/morkStore.cpp index 5418e31fce2a..c4cf6a36075b 100644 --- a/db/mork/src/morkStore.cpp +++ b/db/mork/src/morkStore.cpp @@ -56,9 +56,9 @@ #include "morkNodeMap.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _MORKBUILDER_ #include "morkBuilder.h" @@ -246,9 +246,13 @@ morkStore::CloseStore(morkEnv* ev) // called by CloseMorkNode(); { if ( this->IsNode() ) { - morkFile* file = mStore_File; - if ( file && file->IsOpenNode() ) - file->CloseMorkNode(ev); + // morkFile* file = mStore_File; + // if ( file && file->IsOpenNode() ) + // file->CloseMorkNode(ev); + + nsIMdbFile* file = mStore_File; + if ( file ) + file->CloseMdbObject(ev->AsMdbEnv()); morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev, &mStore_OidAtomSpace); @@ -259,7 +263,11 @@ morkStore::CloseStore(morkEnv* ev) // called by CloseMorkNode(); mStore_RowSpaces.CloseMorkNode(ev); mStore_AtomSpaces.CloseMorkNode(ev); morkBuilder::SlotStrongBuilder((morkBuilder*) 0, ev, &mStore_Builder); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); + + // morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, + &mStore_File); + morkStream::SlotStrongStream((morkStream*) 0, ev, &mStore_InStream); morkStream::SlotStrongStream((morkStream*) 0, ev, &mStore_OutStream); @@ -277,10 +285,27 @@ morkStore::CloseStore(morkEnv* ev) // called by CloseMorkNode(); // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` + +mork_bool morkStore::DoPreferLargeOverCompressCommit(morkEnv* ev) + // true when mStore_CanWriteIncremental && store has file large enough +{ + nsIMdbFile* file = mStore_File; + nsIMdbEnv* menv = ev->AsMdbEnv(); + if ( file && mStore_CanWriteIncremental ) + { + mdb_pos fileEof = 0; + file->Eof(ev->AsMdbEnv(), &fileEof); + if ( ev->Good() && fileEof > 128 ) + return morkBool_kTrue; + } + return morkBool_kFalse; +} + mork_percent morkStore::PercentOfStoreWasted(morkEnv* ev) { mork_percent outPercent = 0; - morkFile* file = mStore_File; + nsIMdbFile* file = mStore_File; + nsIMdbEnv* menv = ev->AsMdbEnv(); if ( file ) { @@ -291,7 +316,8 @@ mork_percent morkStore::PercentOfStoreWasted(morkEnv* ev) if ( firstPos < 512 && secondPos > firstPos ) firstPos = secondPos; // better approximation of first commit - mork_pos fileLength = file->Length(ev); // end of file + mork_pos fileLength = 0; + file->Eof(ev->AsMdbEnv(), &fileLength); // end of file if ( ev->Good() && fileLength > firstPos ) { mork_size groupContent = fileLength - firstPos; @@ -501,7 +527,7 @@ morkStream* morkStore::LazyGetInStream(morkEnv* ev) { if ( !mStore_InStream ) { - morkFile* file = mStore_File; + nsIMdbFile* file = mStore_File; if ( file ) { morkStream* stream = new(*mPort_Heap, ev) @@ -523,7 +549,7 @@ morkStream* morkStore::LazyGetOutStream(morkEnv* ev) { if ( !mStore_OutStream ) { - morkFile* file = mStore_File; + nsIMdbFile* file = mStore_File; if ( file ) { morkStream* stream = new(*mPort_Heap, ev) @@ -643,43 +669,38 @@ morkStore::CannotAutoAssignAtomIdentityError(morkEnv* ev) mork_bool morkStore::OpenStoreFile(morkEnv* ev, mork_bool inFrozen, - const char* inFilePath, const mdbOpenPolicy* inOpenPolicy) + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface + const mdbOpenPolicy* inOpenPolicy) { - MORK_USED_1(inOpenPolicy); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); - if ( ev->Good() ) - { - morkFile* file = morkFile::OpenOldFile(ev, mPort_Heap, - inFilePath, inFrozen); - if ( file ) - { - if ( ev->Good() ) - morkFile::SlotStrongFile(file, ev, &mStore_File); - else - file->CutStrongRef(ev); - } - } + MORK_USED_2(inOpenPolicy,inFrozen); + nsIMdbFile_SlotStrongFile(ioFile, ev, &mStore_File); + + // if ( ev->Good() ) + // { + // morkFile* file = morkFile::OpenOldFile(ev, mPort_Heap, + // inFilePath, inFrozen); + // if ( ioFile ) + // { + // if ( ev->Good() ) + // morkFile::SlotStrongFile(file, ev, &mStore_File); + // else + // file->CutStrongRef(ev); + // + // } + // } return ev->Good(); } mork_bool morkStore::CreateStoreFile(morkEnv* ev, - const char* inFilePath, const mdbOpenPolicy* inOpenPolicy) + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface + const mdbOpenPolicy* inOpenPolicy) { MORK_USED_1(inOpenPolicy); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); - if ( ev->Good() ) - { - morkFile* file = morkFile::CreateNewFile(ev, mPort_Heap, - inFilePath); - if ( file ) - { - if ( ev->Good() ) - morkFile::SlotStrongFile(file, ev, &mStore_File); - else - file->CutStrongRef(ev); - } - } + nsIMdbFile_SlotStrongFile(ioFile, ev, &mStore_File); + return ev->Good(); } diff --git a/db/mork/src/morkStore.h b/db/mork/src/morkStore.h index 00529739c579..04f93ab7dff8 100644 --- a/db/mork/src/morkStore.h +++ b/db/mork/src/morkStore.h @@ -155,7 +155,7 @@ public: // state is public because the entire Mork system is private morkAtomSpace* mStore_GroundAtomSpace; // ground atom space for scopes morkAtomSpace* mStore_GroundColumnSpace; // ground column space for scopes - morkFile* mStore_File; // the file containing Mork text + nsIMdbFile* mStore_File; // the file containing Mork text morkStream* mStore_InStream; // stream using file used by the builder morkBuilder* mStore_Builder; // to parse Mork text and build structures @@ -246,6 +246,11 @@ public: // building an atom inside mStore_BookAtom from a char* string // inString. This method is the standard way to stage a string as an // atom for searching or adding new atoms into an atom space hash table. +public: // determining whether incremental writing is a good use of time: + + mork_bool DoPreferLargeOverCompressCommit(morkEnv* ev); + // true when mStore_CanWriteIncremental && store has file large enough + public: // lazy creation of members and nested row or atom spaces morkAtomSpace* LazyGetOidAtomSpace(morkEnv* ev); @@ -304,11 +309,13 @@ public: // other store methods mork_bool OpenStoreFile(morkEnv* ev, // return value equals ev->Good() mork_bool inFrozen, - const char* inFilePath, + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy); mork_bool CreateStoreFile(morkEnv* ev, // return value equals ev->Good() - const char* inFilePath, + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy); morkAtom* CopyAtom(morkEnv* ev, const morkAtom* inAtom); diff --git a/db/mork/src/morkStream.cpp b/db/mork/src/morkStream.cpp index 9f0d869b8f0f..9e65dfca5221 100644 --- a/db/mork/src/morkStream.cpp +++ b/db/mork/src/morkStream.cpp @@ -66,7 +66,7 @@ morkStream::~morkStream() // assert CloseStream() executed earlier /*public non-poly*/ morkStream::morkStream(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, - morkFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen) + nsIMdbFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen) : morkFile(ev, inUsage, ioHeap, ioHeap) , mStream_At( 0 ) , mStream_ReadEnd( 0 ) @@ -89,12 +89,10 @@ morkStream::morkStream(morkEnv* ev, const morkUsage& inUsage, if ( ioContentFile && ioHeap ) { - if ( ioContentFile->FileFrozen() ) // forced to be readonly? - inFrozen = morkBool_kTrue; // override the input value + // if ( ioContentFile->FileFrozen() ) // forced to be readonly? + // inFrozen = morkBool_kTrue; // override the input value - mork_pos fileEnd = ioContentFile->Length(ev); - - morkFile::SlotStrongFile(ioContentFile, ev, &mStream_ContentFile); + nsIMdbFile_SlotStrongFile(ioContentFile, ev, &mStream_ContentFile); if ( ev->Good() ) { mork_u1* buf = 0; @@ -138,7 +136,7 @@ morkStream::CloseStream(morkEnv* ev) // called by CloseMorkNode(); { if ( this->IsNode() ) { - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStream_ContentFile); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mStream_ContentFile); nsIMdbHeap* heap = mFile_SlotHeap; mork_u1* buf = mStream_Buf; mStream_Buf = 0; @@ -401,7 +399,7 @@ morkStream::AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap) { MORK_USED_1(ioHeap); morkFile* outFile = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { // figure out how this interacts with buffering and mStream_WriteEnd: @@ -417,31 +415,35 @@ morkStream::Length(morkEnv* ev) const // eof { mork_pos outPos = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { - mork_pos contentEof = file->Length(ev); - - if ( mStream_WriteEnd ) // this stream supports writing? + mork_pos contentEof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &contentEof); + if ( ev->Good() ) { - // the local buffer might have buffered content past content eof - if ( ev->Good() ) // no error happened during Length() above? + if ( mStream_WriteEnd ) // this stream supports writing? { - mork_u1* at = mStream_At; - mork_u1* buf = mStream_Buf; - if ( at >= buf ) // expected cursor order? + // the local buffer might have buffered content past content eof + if ( ev->Good() ) // no error happened during Length() above? { - mork_pos localContent = mStream_BufPos + (at - buf); - if ( localContent > contentEof ) // buffered past eof? - contentEof = localContent; // return new logical eof + mork_u1* at = mStream_At; + mork_u1* buf = mStream_Buf; + if ( at >= buf ) // expected cursor order? + { + mork_pos localContent = mStream_BufPos + (at - buf); + if ( localContent > contentEof ) // buffered past eof? + contentEof = localContent; // return new logical eof - outPos = contentEof; + outPos = contentEof; + } + else this->NewBadCursorOrderError(ev); } - else this->NewBadCursorOrderError(ev); } + else + outPos = contentEof; // frozen files get length from content file } - else - outPos = contentEof; // frozen files get length from content file } else this->NewFileDownError(ev); @@ -471,7 +473,7 @@ morkStream::Tell(morkEnv* ev) const { mork_pos outPos = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { mork_u1* buf = mStream_Buf; @@ -512,7 +514,7 @@ morkStream::Read(morkEnv* ev, void* outBuf, mork_size inSize) mork_pos outActual = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { mork_u1* end = mStream_ReadEnd; // byte after last buffered byte @@ -558,21 +560,24 @@ morkStream::Read(morkEnv* ev, void* outBuf, mork_size inSize) mStream_At = mStream_ReadEnd = buf; // empty buffer - file->Seek(ev, mStream_BufPos); // set file pos - if ( ev->Good() ) // no seek error? + // file->Seek(ev, mStream_BufPos); // set file pos + // if ( ev->Good() ) // no seek error? + // { + // } + + mork_num actual = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Get(menv, sink, inSize, mStream_BufPos, &actual); + if ( ev->Good() ) // no read error? { - mork_num actual = file->Read(ev, sink, inSize); - if ( ev->Good() ) // no read error? + if ( actual ) { - if ( actual ) - { - outActual += actual; - mStream_BufPos += actual; - mStream_HitEof = morkBool_kFalse; - } - else if ( !outActual ) - mStream_HitEof = morkBool_kTrue; + outActual += actual; + mStream_BufPos += actual; + mStream_HitEof = morkBool_kFalse; } + else if ( !outActual ) + mStream_HitEof = morkBool_kTrue; } } } @@ -596,7 +601,7 @@ morkStream::Seek(morkEnv* ev, mork_pos inPos) { mork_pos outPos = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenOrClosingNode() && this->FileActive() && file ) { mork_u1* at = mStream_At; // current position in buffer @@ -615,7 +620,9 @@ morkStream::Seek(morkEnv* ev, mork_pos inPos) { if ( mStream_BufPos != inPos ) // need to change pos? { - mork_pos eof = file->Length(ev); + mork_pos eof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &eof); if ( ev->Good() ) // no errors getting length? { if ( inPos <= eof ) // acceptable new position? @@ -634,7 +641,9 @@ morkStream::Seek(morkEnv* ev, mork_pos inPos) { if ( at >= buf && at <= readEnd ) // expected cursor order? { - mork_pos eof = file->Length(ev); + mork_pos eof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &eof); if ( ev->Good() ) // no errors getting length? { if ( inPos <= eof ) // acceptable new position? @@ -662,7 +671,7 @@ morkStream::Write(morkEnv* ev, const void* inBuf, mork_size inSize) { mork_num outActual = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenActiveAndMutableFile() && file ) { mork_u1* end = mStream_WriteEnd; // byte after last buffered byte @@ -725,17 +734,18 @@ morkStream::Write(morkEnv* ev, const void* inBuf, mork_size inSize) } else // directly to content file instead { - file->Seek(ev, mStream_BufPos); // set pos - - if ( ev->Good() ) // no seek error? + // file->Seek(ev, mStream_BufPos); // set pos + // if ( ev->Good() ) // no seek error? + // { + // } + + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + file->Put(menv, source, inSize, mStream_BufPos, &actual); + if ( ev->Good() ) // no write error? { - mork_num actual = - file->Write(ev, source, inSize); - if ( ev->Good() ) // no write error? - { - outActual += actual; - mStream_BufPos += actual; - } + outActual += actual; + mStream_BufPos += actual; } } } @@ -759,12 +769,13 @@ morkStream::Write(morkEnv* ev, const void* inBuf, mork_size inSize) /*public virtual*/ void morkStream::Flush(morkEnv* ev) { - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenOrClosingNode() && this->FileActive() && file ) { if ( mStream_Dirty ) this->spill_buf(ev); - file->Flush(ev); + + file->Flush(ev->AsMdbEnv()); } else this->NewFileDownError(ev); } @@ -777,7 +788,7 @@ morkStream::fill_getc(morkEnv* ev) { int c = EOF; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { mork_u1* buf = mStream_Buf; @@ -789,25 +800,28 @@ morkStream::fill_getc(morkEnv* ev) if ( ev->Good() ) // no errors yet? { - file->Seek(ev, mStream_BufPos); // set file pos - if ( ev->Good() ) // no seek error? + // file->Seek(ev, mStream_BufPos); // set file pos + // if ( ev->Good() ) // no seek error? + // { + // } + + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + file->Get(menv, buf, mStream_BufSize, mStream_BufPos, &actual); + if ( ev->Good() ) // no read errors? { - mork_num actual = file->Read(ev, buf, mStream_BufSize); - if ( ev->Good() ) // no read errors? + if ( actual > mStream_BufSize ) // more than asked for?? + actual = mStream_BufSize; + + mStream_At = buf; + mStream_ReadEnd = buf + actual; + if ( actual ) // any bytes actually read? { - if ( actual > mStream_BufSize ) // more than asked for?? - actual = mStream_BufSize; - - mStream_At = buf; - mStream_ReadEnd = buf + actual; - if ( actual ) // any bytes actually read? - { - c = *mStream_At++; // return first byte from buffer - mStream_HitEof = morkBool_kFalse; - } - else - mStream_HitEof = morkBool_kTrue; + c = *mStream_At++; // return first byte from buffer + mStream_HitEof = morkBool_kFalse; } + else + mStream_HitEof = morkBool_kTrue; } } } @@ -827,7 +841,7 @@ morkStream::spill_putc(morkEnv* ev, int c) void morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file { - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenOrClosingNode() && this->FileActive() && file ) { mork_u1* buf = mStream_Buf; @@ -847,16 +861,19 @@ morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file } if ( ev->Good() ) { - file->Seek(ev, mStream_BufPos); + // file->Seek(ev, mStream_BufPos); + // if ( ev->Good() ) + // { + // } + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + + file->Put(menv, buf, count, mStream_BufPos, &actual); if ( ev->Good() ) { - file->Write(ev, buf, count); - if ( ev->Good() ) - { - mStream_BufPos += count; // past bytes written - mStream_At = buf; // reset buffer cursor - mStream_Dirty = morkBool_kFalse; - } + mStream_BufPos += actual; // past bytes written + mStream_At = buf; // reset buffer cursor + mStream_Dirty = morkBool_kFalse; } } } diff --git a/db/mork/src/morkStream.h b/db/mork/src/morkStream.h index 148a8c71a697..22857c4bcec1 100644 --- a/db/mork/src/morkStream.h +++ b/db/mork/src/morkStream.h @@ -83,7 +83,7 @@ protected: // protected morkStream members mork_u1* mStream_ReadEnd; // null or one byte past last readable byte mork_u1* mStream_WriteEnd; // null or mStream_Buf + mStream_BufSize - morkFile* mStream_ContentFile; // where content is read and written + nsIMdbFile* mStream_ContentFile; // where content is read and written mork_u1* mStream_Buf; // dynamically allocated memory to buffer io mork_size mStream_BufSize; // requested buf size (fixed by min and max) @@ -98,7 +98,7 @@ public: // morkNode virtual methods public: // morkStream construction & destruction morkStream(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, - morkFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen); + nsIMdbFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen); void CloseStream(morkEnv* ev); // called by CloseMorkNode(); private: // copying is not allowed @@ -172,7 +172,7 @@ public: // public non-poly morkStream methods void NewCantWriteSourceError(morkEnv* ev) const; void NewPosBeyondEofError(morkEnv* ev) const; - morkFile* GetStreamContentFile() const { return mStream_ContentFile; } + nsIMdbFile* GetStreamContentFile() const { return mStream_ContentFile; } mork_size GetStreamBufferSize() const { return mStream_BufSize; } mork_size PutIndent(morkEnv* ev, mork_count inDepth); diff --git a/db/mork/src/morkTableRowCursor.cpp b/db/mork/src/morkTableRowCursor.cpp index cb8993bc6952..bb2d0acb3e79 100644 --- a/db/mork/src/morkTableRowCursor.cpp +++ b/db/mork/src/morkTableRowCursor.cpp @@ -129,6 +129,13 @@ morkTableRowCursor::NonTableRowCursorTypeError(morkEnv* ev) ev->NewError("non morkTableRowCursor"); } + +orkinTableRowCursor* +morkTableRowCursor::AcquireUniqueRowCursorHandle(morkEnv* ev) +{ + return this->AcquireTableRowCursorHandle(ev); +} + orkinTableRowCursor* morkTableRowCursor::AcquireTableRowCursorHandle(morkEnv* ev) { @@ -154,6 +161,23 @@ morkTableRowCursor::NextRowOid(morkEnv* ev, mdbOid* outOid) return outPos; } +mork_bool +morkTableRowCursor::CanHaveDupRowMembers(morkEnv* ev) +{ + return morkBool_kFalse; // false default is correct +} + +mork_count +morkTableRowCursor::GetMemberCount(morkEnv* ev) +{ + morkTable* table = mTableRowCursor_Table; + if ( table ) + return table->mTable_RowArray.mArray_Fill; + else + return 0; +} + + morkRow* morkTableRowCursor::NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos) { diff --git a/db/mork/src/morkTableRowCursor.h b/db/mork/src/morkTableRowCursor.h index 54c8cf858362..039660ddbb66 100644 --- a/db/mork/src/morkTableRowCursor.h +++ b/db/mork/src/morkTableRowCursor.h @@ -81,12 +81,20 @@ public: // dynamic type identification public: // typing static void NonTableRowCursorTypeError(morkEnv* ev); +public: // handle attachment + orkinTableRowCursor* AcquireTableRowCursorHandle(morkEnv* ev); + +public: // oid only iteration + mdb_pos NextRowOid(morkEnv* ev, mdbOid* outOid); + public: // other table row cursor methods - orkinTableRowCursor* AcquireTableRowCursorHandle(morkEnv* ev); + virtual mork_bool CanHaveDupRowMembers(morkEnv* ev); + virtual mork_count GetMemberCount(morkEnv* ev); + + virtual orkinTableRowCursor* AcquireUniqueRowCursorHandle(morkEnv* ev); - mdb_pos NextRowOid(morkEnv* ev, mdbOid* outOid); - morkRow* NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos); + virtual morkRow* NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos); public: // typesafe refcounting inlines calling inherited morkNode methods static void SlotWeakTableRowCursor(morkTableRowCursor* me, diff --git a/db/mork/src/morkThumb.cpp b/db/mork/src/morkThumb.cpp index b496125ae70e..4a5e7fc5eb76 100644 --- a/db/mork/src/morkThumb.cpp +++ b/db/mork/src/morkThumb.cpp @@ -44,9 +44,9 @@ #include "morkStore.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _MORKWRITER_ #include "morkWriter.h" @@ -60,10 +60,6 @@ #include "morkBuilder.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif - //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` @@ -134,7 +130,7 @@ morkThumb::CloseThumb(morkEnv* ev) // called by CloseMorkNode(); morkBuilder::SlotStrongBuilder((morkBuilder*) 0, ev, &mThumb_Builder); morkWriter::SlotStrongWriter((morkWriter*) 0, ev, &mThumb_Writer); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mThumb_File); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mThumb_File); morkStore::SlotStrongStore((morkStore*) 0, ev, &mThumb_Store); morkPort::SlotStrongPort((morkPort*) 0, ev, &mThumb_SourcePort); this->MarkShut(); @@ -208,10 +204,11 @@ morkThumb::Make_OpenFileStore(morkEnv* ev, nsIMdbHeap* ioHeap, morkThumb* outThumb = 0; if ( ioHeap && ioStore ) { - morkFile* file = ioStore->mStore_File; + nsIMdbFile* file = ioStore->mStore_File; if ( file ) { - mork_pos fileEof = file->Length(ev); + mork_pos fileEof = 0; + file->Eof(ev->AsMdbEnv(), &fileEof); if ( ev->Good() ) { outThumb = new(*ioHeap, ev) @@ -248,7 +245,7 @@ morkThumb::Make_LargeCommit(morkEnv* ev, morkThumb* outThumb = 0; if ( ioHeap && ioStore ) { - morkFile* file = ioStore->mStore_File; + nsIMdbFile* file = ioStore->mStore_File; if ( file ) { outThumb = new(*ioHeap, ev) @@ -266,10 +263,10 @@ morkThumb::Make_LargeCommit(morkEnv* ev, writer->mWriter_NeedDirtyAll = morkBool_kFalse; outThumb->mThumb_DoCollect = morkBool_kFalse; morkStore::SlotStrongStore(ioStore, ev, &outThumb->mThumb_Store); - morkFile::SlotStrongFile(file, ev, &outThumb->mThumb_File); - morkWriter::SlotStrongWriter(writer, ev, &outThumb->mThumb_Writer); - // writer no longer holds on to this. - writer->CutStrongRef(ev); + + nsIMdbFile_SlotStrongFile(file, ev, &outThumb->mThumb_File); + + outThumb->mThumb_Writer = writer; // pass writer ownership to thumb } } } @@ -289,7 +286,7 @@ morkThumb::Make_CompressCommit(morkEnv* ev, morkThumb* outThumb = 0; if ( ioHeap && ioStore ) { - morkFile* file = ioStore->mStore_File; + nsIMdbFile* file = ioStore->mStore_File; if ( file ) { outThumb = new(*ioHeap, ev) @@ -305,7 +302,7 @@ morkThumb::Make_CompressCommit(morkEnv* ev, writer->mWriter_NeedDirtyAll = morkBool_kTrue; outThumb->mThumb_DoCollect = inDoCollect; morkStore::SlotStrongStore(ioStore, ev, &outThumb->mThumb_Store); - morkFile::SlotStrongFile(file, ev, &outThumb->mThumb_File); + nsIMdbFile_SlotStrongFile(file, ev, &outThumb->mThumb_File); morkWriter::SlotStrongWriter(writer, ev, &outThumb->mThumb_Writer); // cope with fact that parsed transaction groups are going away: diff --git a/db/mork/src/morkThumb.h b/db/mork/src/morkThumb.h index 7c651c1fd234..ba2cb5bbb64f 100644 --- a/db/mork/src/morkThumb.h +++ b/db/mork/src/morkThumb.h @@ -82,7 +82,7 @@ public: // state is public because the entire Mork system is private mork_u2 mThumb_Seed; // optional seed for u4 alignment padding morkStore* mThumb_Store; // weak ref to created store - morkFile* mThumb_File; // strong ref to file (store, import, export) + nsIMdbFile* mThumb_File; // strong ref to file (store, import, export) morkWriter* mThumb_Writer; // strong ref to writer (for commit) morkBuilder* mThumb_Builder; // strong ref to builder (for store open) morkPort* mThumb_SourcePort; // strong ref to port for import diff --git a/db/mork/src/morkWriter.cpp b/db/mork/src/morkWriter.cpp index 8c1f612b3e54..f0158342f8be 100644 --- a/db/mork/src/morkWriter.cpp +++ b/db/mork/src/morkWriter.cpp @@ -40,9 +40,9 @@ #include "morkWriter.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _MORKSTREAM_ #include "morkStream.h" @@ -113,7 +113,7 @@ morkWriter::~morkWriter() // assert CloseTable() executed earlier /*public non-poly*/ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, - nsIMdbHeap* ioHeap, morkStore* ioStore, morkFile* ioFile, + nsIMdbHeap* ioHeap, morkStore* ioStore, nsIMdbFile* ioFile, nsIMdbHeap* ioSlotHeap) : morkNode(ev, inUsage, ioHeap) , mWriter_Store( 0 ) @@ -194,7 +194,7 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, if ( ioSlotHeap && ioFile && ioStore ) { morkStore::SlotWeakStore(ioStore, ev, &mWriter_Store); - morkFile::SlotStrongFile(ioFile, ev, &mWriter_File); + nsIMdbFile_SlotStrongFile(ioFile, ev, &mWriter_File); nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mWriter_SlotHeap); if ( ev->Good() ) { @@ -228,7 +228,8 @@ morkWriter::MakeWriterStream(morkEnv* ev) // give writer a suitable stream } else // compress commit { - morkFile* bud = mWriter_File->AcquireBud(ev, heap); + nsIMdbFile* bud = 0; + mWriter_File->AcquireBud(ev->AsMdbEnv(), heap, &bud); if ( bud ) { if ( ev->Good() ) @@ -239,7 +240,7 @@ morkWriter::MakeWriterStream(morkEnv* ev) // give writer a suitable stream morkWriter_kStreamBufSize, frozen); } else - bud->CutStrongRef(ev); + bud->CutStrongRef(ev->AsMdbEnv()); } } @@ -264,8 +265,8 @@ morkWriter::CloseWriter(morkEnv* ev) // called by CloseMorkNode(); if ( this->IsNode() ) { morkStore::SlotWeakStore((morkStore*) 0, ev, &mWriter_Store); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mWriter_File); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mWriter_Bud); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mWriter_File); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mWriter_Bud); morkStream::SlotStrongStream((morkStream*) 0, ev, &mWriter_Stream); nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mWriter_SlotHeap); this->MarkShut(); @@ -1195,12 +1196,12 @@ morkWriter::OnContentDone(morkEnv* ev) } stream->Flush(ev); - morkFile* bud = mWriter_Bud; + nsIMdbFile* bud = mWriter_Bud; if ( bud ) { - bud->Flush(ev); - bud->BecomeTrunk(ev); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mWriter_Bud); + bud->Flush(ev->AsMdbEnv()); + bud->BecomeTrunk(ev->AsMdbEnv()); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mWriter_Bud); } else if ( !mWriter_Incremental ) // should have a bud? this->NilWriterBudError(ev); diff --git a/db/mork/src/morkWriter.h b/db/mork/src/morkWriter.h index c0b590ed8552..ad2a2f914742 100644 --- a/db/mork/src/morkWriter.h +++ b/db/mork/src/morkWriter.h @@ -126,8 +126,8 @@ class morkWriter : public morkNode { // row iterator public: // state is public because the entire Mork system is private morkStore* mWriter_Store; // weak ref to committing store - morkFile* mWriter_File; // strong ref to store's file - morkFile* mWriter_Bud; // strong ref to bud of mWriter_File + nsIMdbFile* mWriter_File; // strong ref to store's file + nsIMdbFile* mWriter_Bud; // strong ref to bud of mWriter_File morkStream* mWriter_Stream; // strong ref to stream on bud file nsIMdbHeap* mWriter_SlotHeap; // strong ref to slot heap @@ -200,7 +200,7 @@ public: // morkNode virtual methods public: // morkWriter construction & destruction morkWriter(morkEnv* ev, const morkUsage& inUsage, - nsIMdbHeap* ioHeap, morkStore* ioStore, morkFile* ioFile, + nsIMdbHeap* ioHeap, morkStore* ioStore, nsIMdbFile* ioFile, nsIMdbHeap* ioSlotHeap); void CloseWriter(morkEnv* ev); // called by CloseMorkNode(); diff --git a/db/mork/src/orkinCell.cpp b/db/mork/src/orkinCell.cpp index 415117c1363a..cb852da53eac 100644 --- a/db/mork/src/orkinCell.cpp +++ b/db/mork/src/orkinCell.cpp @@ -142,7 +142,8 @@ orkinCell::CanUseCell(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkCellObject* cellObj = (morkCellObject*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kCell); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kCell, + /*inClosedOkay*/ morkBool_kFalse); if ( cellObj ) { if ( cellObj->IsCellObject() ) diff --git a/db/mork/src/orkinFactory.cpp b/db/mork/src/orkinFactory.cpp index aa320c39c835..75fd9b35eb7f 100644 --- a/db/mork/src/orkinFactory.cpp +++ b/db/mork/src/orkinFactory.cpp @@ -80,6 +80,14 @@ #include "morkThumb.h" #endif +#ifndef _ORKINHEAP_ +#include "orkinHeap.h" +#endif + +#ifndef _ORKINCOMPARE_ +#include "orkinCompare.h" +#endif + //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 /* public virtual*/ @@ -144,7 +152,8 @@ orkinFactory::CanUseFactory(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkFactory* factory = (morkFactory*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kFactory); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kFactory, + /*inClosedOkay*/ morkBool_kFalse); if ( factory ) { if ( factory->IsFactory() ) @@ -277,7 +286,8 @@ orkinFactory::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen) // { ----- begin file methods ----- /*virtual*/ mdb_err orkinFactory::OpenOldFile(nsIMdbEnv* mev, nsIMdbHeap* ioHeap, - const char* inFilePath, mork_bool inFrozen, nsIMdbFile** acqFile) + const char* inFilePath, + mork_bool inFrozen, nsIMdbFile** acqFile) // Choose some subclass of nsIMdbFile to instantiate, in order to read // (and write if not frozen) the file known by inFilePath. The file // returned should be open and ready for use, and presumably positioned @@ -413,6 +423,26 @@ orkinFactory::MakeHeap(nsIMdbEnv* mev, nsIMdbHeap** acqHeap) } // } ----- end heap methods ----- +// { ----- begin compare methods ----- +/*virtual*/ mdb_err +orkinFactory::MakeCompare(nsIMdbEnv* mev, nsIMdbCompare** acqCompare) +{ + mdb_err outErr = 0; + nsIMdbCompare* outCompare = 0; + morkEnv* ev = this->CanUseFactory(mev, + /*inMutable*/ morkBool_kFalse, &outErr); + if ( ev ) + { + outCompare = new orkinCompare(); + if ( !outCompare ) + ev->OutOfMemoryError(); + } + if ( acqCompare ) + *acqCompare = outCompare; + return outErr; +} +// } ----- end compare methods ----- + // { ----- begin row methods ----- /*virtual*/ mdb_err orkinFactory::MakeRow(nsIMdbEnv* mev, nsIMdbHeap* ioHeap, @@ -440,8 +470,9 @@ orkinFactory::MakeRow(nsIMdbEnv* mev, nsIMdbHeap* ioHeap, /*virtual*/ mdb_err orkinFactory::CanOpenFilePort( nsIMdbEnv* mev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpen, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion) { @@ -455,9 +486,9 @@ orkinFactory::CanOpenFilePort( /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( inFilePath && inFirst512Bytes && outCanOpen ) + if ( ioFile && outCanOpen ) { - canOpenAsPort = this->CanOpenMorkTextFile(ev, inFirst512Bytes); + canOpenAsPort = this->CanOpenMorkTextFile(ev, ioFile); } else ev->NilPointerError(); @@ -475,7 +506,8 @@ orkinFactory::CanOpenFilePort( orkinFactory::OpenFilePort( nsIMdbEnv* mev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for readonly import + // const char* inFilePath, // the file to open for readonly import + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb) { @@ -486,7 +518,7 @@ orkinFactory::OpenFilePort( /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( inFilePath && inOpenPolicy && acqThumb ) + if ( ioFile && inOpenPolicy && acqThumb ) { } else @@ -543,17 +575,39 @@ orkinFactory::ThumbToOpenPort( // redeeming a completed thumb from OpenFilePort( mork_bool orkinFactory::CanOpenMorkTextFile(morkEnv* ev, - const mdbYarn* inFirst512Bytes) + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile) { MORK_USED_1(ev); mork_bool outBool = morkBool_kFalse; mork_size headSize = MORK_STRLEN(morkWriter_kFileHeader); - const mdbYarn* y = inFirst512Bytes; - if ( y && y->mYarn_Buf && y->mYarn_Fill >= headSize ) + + char localBuf[ 256 + 4 ]; // for extra for sloppy safety + mdbYarn localYarn; + mdbYarn* y = &localYarn; + y->mYarn_Buf = localBuf; // space to hold content + y->mYarn_Fill = 0; // no logical content yet + y->mYarn_Size = 256; // physical capacity is 256 bytes + y->mYarn_More = 0; + y->mYarn_Form = 0; + y->mYarn_Grow = 0; + + if ( ioFile ) { - mork_u1* buf = (mork_u1*) y->mYarn_Buf; - outBool = ( MORK_MEMCMP(morkWriter_kFileHeader, buf, headSize) == 0 ); + nsIMdbEnv* menv = ev->AsMdbEnv(); + mdb_size actualSize = 0; + ioFile->Get(menv, y->mYarn_Buf, y->mYarn_Size, /*pos*/ 0, &actualSize); + y->mYarn_Fill = actualSize; + + if ( y->mYarn_Buf && actualSize >= headSize && ev->Good() ) + { + mork_u1* buf = (mork_u1*) y->mYarn_Buf; + outBool = ( MORK_MEMCMP(morkWriter_kFileHeader, buf, headSize) == 0 ); + } } + else + ev->NilPointerError(); + return outBool; } @@ -561,8 +615,9 @@ orkinFactory::CanOpenMorkTextFile(morkEnv* ev, /*virtual*/ mdb_err orkinFactory::CanOpenFileStore( nsIMdbEnv* mev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpenAsStore, // whether OpenFileStore() might succeed mdb_bool* outCanOpenAsPort, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion) @@ -578,10 +633,10 @@ orkinFactory::CanOpenFileStore( /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( inFilePath && inFirst512Bytes && outCanOpenAsStore ) + if ( ioFile && outCanOpenAsStore ) { // right now always say true; later we should look for magic patterns - canOpenAsStore = this->CanOpenMorkTextFile(ev, inFirst512Bytes); + canOpenAsStore = this->CanOpenMorkTextFile(ev, ioFile); canOpenAsPort = canOpenAsStore; } else @@ -602,7 +657,8 @@ orkinFactory::CanOpenFileStore( orkinFactory::OpenFileStore( // open an existing database nsIMdbEnv* mev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for general db usage + // const char* inFilePath, // the file to open for general db usage + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb) { @@ -615,7 +671,7 @@ orkinFactory::OpenFileStore( // open an existing database if ( !ioHeap ) // need to use heap from env? ioHeap = ev->mEnv_Heap; - if ( inFilePath && inOpenPolicy && acqThumb ) + if ( ioFile && inOpenPolicy && acqThumb ) { morkFactory* factory = (morkFactory*) this->mHandle_Object; morkStore* store = new(*ioHeap, ev) @@ -624,7 +680,7 @@ orkinFactory::OpenFileStore( // open an existing database if ( store ) { mork_bool frozen = morkBool_kFalse; // open store mutable access - if ( store->OpenStoreFile(ev, frozen, inFilePath, inOpenPolicy) ) + if ( store->OpenStoreFile(ev, frozen, ioFile, inOpenPolicy) ) { morkThumb* thumb = morkThumb::Make_OpenFileStore(ev, ioHeap, store); if ( thumb ) @@ -691,7 +747,8 @@ orkinFactory::ThumbToOpenStore( // redeem completed thumb from OpenFileStore() orkinFactory::CreateNewFileStore( // create a new db with minimal content nsIMdbEnv* mev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // name of file which should not yet exist + // const char* inFilePath, // name of file which should not yet exist + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbStore** acqStore) { @@ -704,7 +761,7 @@ orkinFactory::CreateNewFileStore( // create a new db with minimal content if ( !ioHeap ) // need to use heap from env? ioHeap = ev->mEnv_Heap; - if ( inFilePath && inOpenPolicy && acqStore && ioHeap ) + if ( ioFile && inOpenPolicy && acqStore && ioHeap ) { morkFactory* factory = (morkFactory*) this->mHandle_Object; morkStore* store = new(*ioHeap, ev) @@ -716,7 +773,7 @@ orkinFactory::CreateNewFileStore( // create a new db with minimal content store->mStore_CanDirty = morkBool_kTrue; store->SetStoreAndAllSpacesCanDirty(ev, morkBool_kTrue); - if ( store->CreateStoreFile(ev, inFilePath, inOpenPolicy) ) + if ( store->CreateStoreFile(ev, ioFile, inOpenPolicy) ) outStore = orkinStore::MakeStore(ev, store); store->CutStrongRef(ev); // always cut ref (handle has its own ref) diff --git a/db/mork/src/orkinFactory.h b/db/mork/src/orkinFactory.h index bea55c67af61..61781d24f4c9 100644 --- a/db/mork/src/orkinFactory.h +++ b/db/mork/src/orkinFactory.h @@ -93,7 +93,9 @@ public: // utilities: morkEnv* GetInternalFactoryEnv(mdb_err* outErr); - mork_bool CanOpenMorkTextFile(morkEnv* ev, const mdbYarn* inFirst512Bytes); + mork_bool CanOpenMorkTextFile(morkEnv* ev, + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile); public: // type identification mork_bool IsOrkinFactory() const @@ -142,7 +144,8 @@ public: // { ----- begin file methods ----- virtual mdb_err OpenOldFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, - const char* inFilePath, mdb_bool inFrozen, nsIMdbFile** acqFile); + const char* inFilePath, + mdb_bool inFrozen, nsIMdbFile** acqFile); // Choose some subclass of nsIMdbFile to instantiate, in order to read // (and write if not frozen) the file known by inFilePath. The file // returned should be open and ready for use, and presumably positioned @@ -151,7 +154,8 @@ public: // other portions or Mork source code don't want to know how it's done. virtual mdb_err CreateNewFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, - const char* inFilePath, nsIMdbFile** acqFile); + const char* inFilePath, + nsIMdbFile** acqFile); // Choose some subclass of nsIMdbFile to instantiate, in order to read // (and write if not frozen) the file known by inFilePath. The file // returned should be created and ready for use, and presumably positioned @@ -169,6 +173,10 @@ public: virtual mdb_err MakeHeap(nsIMdbEnv* ev, nsIMdbHeap** acqHeap); // new heap // } ----- end heap methods ----- + // { ----- begin compare methods ----- + virtual mdb_err MakeCompare(nsIMdbEnv* ev, nsIMdbCompare** acqCompare); // ASCII + // } ----- end compare methods ----- + // { ----- begin row methods ----- virtual mdb_err MakeRow(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, nsIMdbRow** acqRow); // new row // ioHeap can be nil, causing the heap associated with ev to be used @@ -177,15 +185,17 @@ public: // { ----- begin port methods ----- virtual mdb_err CanOpenFilePort( nsIMdbEnv* ev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpen, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion); // informal file format description virtual mdb_err OpenFilePort( nsIMdbEnv* ev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for readonly import + // const char* inFilePath, // the file to open for readonly import + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb); // acquire thumb for incremental port open // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and @@ -200,8 +210,9 @@ public: // { ----- begin store methods ----- virtual mdb_err CanOpenFileStore( nsIMdbEnv* ev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpenAsStore, // whether OpenFileStore() might succeed mdb_bool* outCanOpenAsPort, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion); // informal file format description @@ -209,7 +220,8 @@ public: virtual mdb_err OpenFileStore( // open an existing database nsIMdbEnv* ev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for general db usage + // const char* inFilePath, // the file to open for general db usage + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb); // acquire thumb for incremental store open // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and @@ -224,7 +236,8 @@ public: virtual mdb_err CreateNewFileStore( // create a new db with minimal content nsIMdbEnv* ev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // name of file which should not yet exist + // const char* inFilePath, // name of file which should not yet exist + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbStore** acqStore); // acquire new db store object // } ----- end store methods ----- diff --git a/db/mork/src/orkinHeap.h b/db/mork/src/orkinHeap.h index ba25fbb2fb26..479a2fc15994 100644 --- a/db/mork/src/orkinHeap.h +++ b/db/mork/src/orkinHeap.h @@ -38,8 +38,8 @@ public: virtual ~orkinHeap(); // does nothing private: // copying is not allowed - orkinHeap(const morkHandle& other); - orkinHeap& operator=(const morkHandle& other); + orkinHeap(const orkinHeap& other); + orkinHeap& operator=(const orkinHeap& other); public: diff --git a/db/mork/src/orkinPortTableCursor.cpp b/db/mork/src/orkinPortTableCursor.cpp index bcaba54a8ae3..48a8bc978b5d 100644 --- a/db/mork/src/orkinPortTableCursor.cpp +++ b/db/mork/src/orkinPortTableCursor.cpp @@ -97,7 +97,8 @@ orkinPortTableCursor::CanUsePortTableCursor(nsIMdbEnv* mev, if ( ev ) { morkPortTableCursor* self = (morkPortTableCursor*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kPortTableCursor); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kPortTableCursor, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsPortTableCursor() ) diff --git a/db/mork/src/orkinRow.cpp b/db/mork/src/orkinRow.cpp index e0ccd83afd5a..2f3be117c67e 100644 --- a/db/mork/src/orkinRow.cpp +++ b/db/mork/src/orkinRow.cpp @@ -120,7 +120,8 @@ orkinRow::CanUseRow(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkRowObject* rowObj = (morkRowObject*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kRow); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kRow, + /*inClosedOkay*/ morkBool_kFalse); if ( rowObj ) { if ( rowObj->IsRowObject() ) diff --git a/db/mork/src/orkinRowCellCursor.cpp b/db/mork/src/orkinRowCellCursor.cpp index 465b47c82a50..592c5bb89575 100644 --- a/db/mork/src/orkinRowCellCursor.cpp +++ b/db/mork/src/orkinRowCellCursor.cpp @@ -104,7 +104,8 @@ orkinRowCellCursor::CanUseRowCellCursor(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkRowCellCursor* self = (morkRowCellCursor*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kRowCellCursor); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kRowCellCursor, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsRowCellCursor() ) diff --git a/db/mork/src/orkinStore.cpp b/db/mork/src/orkinStore.cpp index 2bca3563d145..df5f4984943b 100644 --- a/db/mork/src/orkinStore.cpp +++ b/db/mork/src/orkinStore.cpp @@ -68,9 +68,9 @@ #include "morkThumb.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _ORKINTHUMB_ #include "orkinThumb.h" @@ -119,7 +119,8 @@ orkinStore::CanUseStore(nsIMdbEnv* mev, if ( ev ) { morkStore* self = (morkStore*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kStore); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kStore, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsStore() ) @@ -373,7 +374,46 @@ orkinStore::GetPortFilePath( morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + morkStore* store = (morkStore*) mHandle_Object; + nsIMdbFile* file = store->mStore_File; + + if ( file ) + file->Path(mev, outFilePath); + else + store->NilStoreFileError(ev); + + outErr = ev->AsErr(); + } + return outErr; +} + +/*virtual*/ mdb_err +orkinStore::GetPortFile( + nsIMdbEnv* mev, // context + nsIMdbFile** acqFile) // acquire file used by port or store +{ + mdb_err outErr = 0; + if ( acqFile ) + *acqFile = 0; + + morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); + if ( ev ) + { + morkStore* store = (morkStore*) mHandle_Object; + nsIMdbFile* file = store->mStore_File; + + if ( file ) + { + if ( acqFile ) + { + file->AddStrongRef(mev); + if ( ev->Good() ) + *acqFile = file; + } + } + else + store->NilStoreFileError(ev); + outErr = ev->AsErr(); } return outErr; @@ -421,19 +461,25 @@ orkinStore::CanExportToFormat( // can export content in given specific format? /*virtual*/ mdb_err orkinStore::ExportToFormat( // export content in given specific format nsIMdbEnv* mev, // context - const char* inFilePath, // the file to receive exported content + // const char* inFilePath, // the file to receive exported content + nsIMdbFile* ioFile, // destination abstract file interface const char* inFormatVersion, // file format description nsIMdbThumb** acqThumb) // acquire thumb for incremental export // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and // then the export will be finished. { - MORK_USED_2(inFilePath,inFormatVersion); mdb_err outErr = 0; nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + if ( ioFile && inFormatVersion && acqThumb ) + { + ev->StubMethodOnlyError(); + } + else + ev->NilPointerError(); + outErr = ev->AsErr(); } if ( acqThumb ) @@ -995,6 +1041,33 @@ orkinStore::ImportContent( // import content from port *acqThumb = outThumb; return outErr; } + +/*virtual*/ mdb_err +orkinStore::ImportFile( // import content from port + nsIMdbEnv* mev, // context + nsIMdbFile* ioFile, // the file with content to add to store + nsIMdbThumb** acqThumb) // acquire thumb for incremental import +// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and +// then the import will be finished. +{ + nsIMdbThumb* outThumb = 0; + mdb_err outErr = 0; + morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); + if ( ev ) + { + if ( ioFile && acqThumb ) + { + ev->StubMethodOnlyError(); + } + else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + if ( acqThumb ) + *acqThumb = outThumb; + return outErr; +} // } ----- end inport/export methods ----- // { ----- begin hinting methods ----- @@ -1065,8 +1138,8 @@ orkinStore::LargeCommit( // save important changes if at all possible nsIMdbHeap* heap = store->mPort_Heap; morkThumb* thumb = 0; - morkFile* file = store->mStore_File; - if ( file && file->Length(ev) > 128 && store->mStore_CanWriteIncremental ) + // morkFile* file = store->mStore_File; + if ( store->DoPreferLargeOverCompressCommit(ev) ) { thumb = morkThumb::Make_LargeCommit(ev, heap, store); } @@ -1107,8 +1180,7 @@ orkinStore::SessionCommit( // save all changes if large commits delayed nsIMdbHeap* heap = store->mPort_Heap; morkThumb* thumb = 0; - morkFile* file = store->mStore_File; - if ( file && file->Length(ev) > 128 && store->mStore_CanWriteIncremental ) + if ( store->DoPreferLargeOverCompressCommit(ev) ) { thumb = morkThumb::Make_LargeCommit(ev, heap, store); } diff --git a/db/mork/src/orkinStore.h b/db/mork/src/orkinStore.h index 52039c2e3de6..6b2937e9de6d 100644 --- a/db/mork/src/orkinStore.h +++ b/db/mork/src/orkinStore.h @@ -163,6 +163,10 @@ public: // type identification nsIMdbEnv* ev, // context mdbYarn* outFilePath, // name of file holding port content mdbYarn* outFormatVersion); // file format description + + virtual mdb_err GetPortFile( + nsIMdbEnv* ev, // context + nsIMdbFile** acqFile); // acquire file used by port or store // } ----- end filepath methods ----- // { ----- begin export methods ----- @@ -178,7 +182,8 @@ public: // type identification virtual mdb_err ExportToFormat( // export content in given specific format nsIMdbEnv* ev, // context - const char* inFilePath, // the file to receive exported content + // const char* inFilePath, // the file to receive exported content + nsIMdbFile* ioFile, // destination abstract file interface const char* inFormatVersion, // file format description nsIMdbThumb** acqThumb); // acquire thumb for incremental export // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and @@ -424,6 +429,13 @@ public: // type identification nsIMdbThumb** acqThumb); // acquire thumb for incremental import // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and // then the import will be finished. + + virtual mdb_err ImportFile( // import content from port + nsIMdbEnv* ev, // context + nsIMdbFile* ioFile, // the file with content to add to store + nsIMdbThumb** acqThumb); // acquire thumb for incremental import + // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and + // then the import will be finished. // } ----- end inport/export methods ----- // { ----- begin hinting methods ----- diff --git a/db/mork/src/orkinTable.cpp b/db/mork/src/orkinTable.cpp index c9145e6bf9d8..1e56cf3ff5b2 100644 --- a/db/mork/src/orkinTable.cpp +++ b/db/mork/src/orkinTable.cpp @@ -111,7 +111,8 @@ orkinTable::CanUseTable(nsIMdbEnv* mev, if ( ev ) { morkTable* self = (morkTable*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kTable); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kTable, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsTable() ) @@ -557,7 +558,7 @@ orkinTable::GetTableRowCursor( // make a cursor, starting iteration at inRowPos { if ( ev->Good() ) { - cursor->mCursor_Seed = (mork_seed) inRowPos; + // cursor->mCursor_Seed = (mork_seed) inRowPos; outCursor = cursor->AcquireTableRowCursorHandle(ev); } else @@ -845,15 +846,13 @@ orkinTable::CutAllRows( // remove all rows from the table // { ----- begin searching methods ----- /*virtual*/ mdb_err -orkinTable::SearchOneSortedColumn( // search only currently sorted col +orkinTable::FindRowMatches( // search variable number of sorted cols nsIMdbEnv* mev, // context const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbRange* outRange) // range of matching rows + nsIMdbTableRowCursor** acqCursor) // set of matching rows { MORK_USED_1(inPrefix); - mdbRange range; - range.mRange_FirstPos = -1; - range.mRange_LastPos = -1; + nsIMdbTableRowCursor* outCursor = 0; mdb_err outErr = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) @@ -861,23 +860,31 @@ orkinTable::SearchOneSortedColumn( // search only currently sorted col ev->StubMethodOnlyError(); outErr = ev->AsErr(); } - if ( outRange ) - *outRange = range; + if ( acqCursor ) + *acqCursor = outCursor; return outErr; } /*virtual*/ mdb_err -orkinTable::SearchManyColumns( // search variable number of sorted cols +orkinTable::GetSearchColumns( // query columns used by FindRowMatches() nsIMdbEnv* mev, // context - const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbSearch* ioSearch, // columns to search and resulting ranges - nsIMdbThumb** acqThumb) // acquire thumb for incremental search -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then the search will be finished. Until that time, the ioSearch argument -// is assumed referenced and used by the thumb; one should not inspect any -// output results in ioSearch until after the thumb is finished with it. + 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. { - MORK_USED_2(inPrefix,ioSearch); + MORK_USED_1(outColSet); + mdb_count count = 0; mdb_err outErr = 0; nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); @@ -886,8 +893,8 @@ orkinTable::SearchManyColumns( // search variable number of sorted cols ev->StubMethodOnlyError(); outErr = ev->AsErr(); } - if ( acqThumb ) - *acqThumb = outThumb; + if ( outCount ) + *outCount = count; return outErr; } // } ----- end searching methods ----- @@ -975,20 +982,18 @@ orkinTable::EndBatchChangeHint( // advise before many adds and cuts // sort following the primary column sort, when table rows are sorted. /*virtual*/ mdb_err -orkinTable::CanSortColumn( // query which col is currently used for sorting +orkinTable::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 { MORK_USED_1(inColumn); - mdb_bool canSort = morkBool_kFalse; + mdb_bool canSort = mdbBool_kFalse; mdb_err outErr = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( outCanSort ) - *outCanSort = morkBool_kFalse; - + // ev->StubMethodOnlyError(); outErr = ev->AsErr(); } if ( outCanSort ) @@ -997,121 +1002,70 @@ orkinTable::CanSortColumn( // query which col is currently used for sorting } /*virtual*/ mdb_err -orkinTable::NewSortColumn( // change col used for sorting in the table +orkinTable::GetSorting( // view same table in particular sorting nsIMdbEnv* mev, // context mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort + nsIMdbSorting** acqSorting) // acquire sorting for column { MORK_USED_1(inColumn); - mdb_column actualColumn = 0; + nsIMdbSorting* outSorting = 0; mdb_err outErr = 0; - nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { ev->StubMethodOnlyError(); outErr = ev->AsErr(); } - if ( outActualColumn ) - *outActualColumn = actualColumn; - if ( acqThumb ) - *acqThumb = outThumb; - return outErr; -} -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then the sort will be finished. - -/*virtual*/ mdb_err -orkinTable::NewSortColumnWithCompare( // change sort col w/ explicit compare - nsIMdbEnv* mev, // context - nsIMdbCompare* ioCompare, // explicit interface for yarn comparison - mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort -{ - MORK_USED_2(inColumn,ioCompare); - mdb_column actualColumn = 0; - mdb_err outErr = 0; - nsIMdbThumb* outThumb = 0; - morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - if ( outActualColumn ) - *outActualColumn = actualColumn; - if ( acqThumb ) - *acqThumb = outThumb; - return outErr; -} -// Note the table will hold a reference to inCompare if this object is used -// to sort the table. Until the table closes, callers can only force release -// of the compare object by changing the sort (by say, changing to unsorted). -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then the sort will be finished. - -/*virtual*/ mdb_err -orkinTable::GetSortColumn( // query which col is currently sorted - nsIMdbEnv* mev, // context - mdb_column* outColumn) // col the table uses for sorting (or zero) -{ - mdb_err outErr = 0; - mdb_column col = 0; - morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - if ( outColumn ) - *outColumn = col; + if ( acqSorting ) + *acqSorting = outSorting; return outErr; } - /*virtual*/ mdb_err -orkinTable::CloneSortColumn( // view same table with a different sort +orkinTable::SetSearchSorting( // use this sorting in FindRowMatches() nsIMdbEnv* mev, // context - mdb_column inColumn, // requested new column for sorting table - nsIMdbThumb** acqThumb) // acquire thumb for incremental table clone + 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 searchs. 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). { MORK_USED_1(inColumn); mdb_err outErr = 0; - nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + if ( ioSorting ) + { + ev->StubMethodOnlyError(); + } + else + ev->NilPointerError(); + outErr = ev->AsErr(); } - if ( acqThumb ) - *acqThumb = outThumb; - return outErr; -} -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then call nsIMdbTable::ThumbToCloneSortTable() to get the table instance. - -/*virtual*/ mdb_err -orkinTable::ThumbToCloneSortTable( // redeem complete CloneSortColumn() thumb - nsIMdbEnv* mev, // context - nsIMdbThumb* ioThumb, // thumb from CloneSortColumn() with done status - nsIMdbTable** acqTable) // new table instance (or old if sort unchanged) -{ - MORK_USED_1(ioThumb); - mdb_err outErr = 0; - nsIMdbTable* outTable = 0; - morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - if ( acqTable ) - *acqTable = outTable; return outErr; } + // } ----- end sorting methods ----- // { ----- begin moving methods ----- diff --git a/db/mork/src/orkinTable.h b/db/mork/src/orkinTable.h index 970697dec43f..f8da60e90557 100644 --- a/db/mork/src/orkinTable.h +++ b/db/mork/src/orkinTable.h @@ -60,8 +60,8 @@ protected: // construction is protected (use the static Make() method) // void CloseHandle(morkEnv* ev); // don't need to specialize closing private: // copying is not allowed - orkinTable(const morkHandle& other); - orkinTable& operator=(const morkHandle& other); + orkinTable(const orkinTable& other); + orkinTable& operator=(const orkinTable& other); // public: // dynamic type identification // mork_bool IsHandle() const // @@ -273,23 +273,6 @@ public: // type identification nsIMdbEnv* ev); // context // } ----- end row set methods ----- - // { ----- begin searching methods ----- - virtual mdb_err SearchOneSortedColumn( // search only currently sorted col - nsIMdbEnv* ev, // context - const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbRange* outRange); // range of matching rows - - virtual mdb_err SearchManyColumns( // search variable number of sorted cols - nsIMdbEnv* ev, // context - const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbSearch* ioSearch, // columns to search and resulting ranges - nsIMdbThumb** acqThumb); // acquire thumb for incremental search - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then the search will be finished. Until that time, the ioSearch argument - // is assumed referenced and used by the thumb; one should not inspect any - // output results in ioSearch until after the thumb is finished with it. - // } ----- end searching methods ----- - // { ----- begin hinting methods ----- virtual mdb_err SearchColumnsHint( // advise re future expected search cols nsIMdbEnv* ev, // context @@ -319,6 +302,30 @@ public: // type identification // a surprise request occurs for row position during batch changes. // } ----- end hinting methods ----- + // { ----- begin searching methods ----- + virtual mdb_err FindRowMatches( // search variable number of sorted cols + nsIMdbEnv* ev, // context + const mdbYarn* inPrefix, // content to find as prefix in row's column cell + nsIMdbTableRowCursor** acqCursor); // set of matching rows + + virtual mdb_err GetSearchColumns( // query columns used by FindRowMatches() + nsIMdbEnv* ev, // 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. + // } ----- end searching 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. @@ -328,46 +335,38 @@ public: // type identification nsIMdbEnv* ev, // context mdb_column inColumn, // column to query sorting potential mdb_bool* outCanSort); // whether the column can be sorted - - virtual mdb_err - NewSortColumn( // change the column used for sorting in the table - nsIMdbEnv* ev, // context - mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb); // acquire thumb for incremental table resort - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then the sort will be finished. - - virtual mdb_err - NewSortColumnWithCompare( // change sort column with explicit compare - nsIMdbEnv* ev, // context - nsIMdbCompare* ioCompare, // explicit interface for yarn comparison - mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb); // acquire thumb for incremental table resort - // Note the table will hold a reference to inCompare if this object is used - // to sort the table. Until the table closes, callers can only force release - // of the compare object by changing the sort (by say, changing to unsorted). - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then the sort will be finished. - - virtual mdb_err GetSortColumn( // query which col is currently sorted - nsIMdbEnv* ev, // context - mdb_column* outColumn); // col the table uses for sorting (or zero) - - - virtual mdb_err CloneSortColumn( // view same table with a different sort - nsIMdbEnv* ev, // context - mdb_column inColumn, // requested new column for sorting table - nsIMdbThumb** acqThumb); // acquire thumb for incremental table clone - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then call nsIMdbTable::ThumbToCloneSortTable() to get the table instance. - virtual mdb_err - ThumbToCloneSortTable( // redeem complete CloneSortColumn() thumb + virtual mdb_err GetSorting( // view same table in particular sorting nsIMdbEnv* ev, // context - nsIMdbThumb* ioThumb, // thumb from CloneSortColumn() with done status - nsIMdbTable** acqTable); // new table instance (or old if sort unchanged) + mdb_column inColumn, // requested new column for sorting table + nsIMdbSorting** acqSorting); // acquire sorting for column + + virtual mdb_err SetSearchSorting( // use this sorting in FindRowMatches() + nsIMdbEnv* ev, // 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 searchs. 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). // } ----- end sorting methods ----- // { ----- begin moving methods ----- diff --git a/db/mork/src/orkinTableRowCursor.cpp b/db/mork/src/orkinTableRowCursor.cpp index 886c3ac08194..89a7ffa3e02e 100644 --- a/db/mork/src/orkinTableRowCursor.cpp +++ b/db/mork/src/orkinTableRowCursor.cpp @@ -109,7 +109,8 @@ orkinTableRowCursor::CanUseTableRowCursor(nsIMdbEnv* mev, if ( ev ) { morkTableRowCursor* self = (morkTableRowCursor*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kTableRowCursor); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kTableRowCursor, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsTableRowCursor() ) @@ -235,8 +236,7 @@ orkinTableRowCursor::GetCount(nsIMdbEnv* mev, mdb_count* outCount) if ( ev ) { morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; - morkTable* table = cursor->mTableRowCursor_Table; - count = table->mTable_RowArray.mArray_Fill; + count = cursor->GetMemberCount(ev); outErr = ev->AsErr(); } if ( outCount ) @@ -303,7 +303,8 @@ orkinTableRowCursor::SetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool inFail) this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; + cursor->mCursor_DoFailOnSeedOutOfSync = inFail; outErr = ev->AsErr(); } return outErr; @@ -318,7 +319,8 @@ orkinTableRowCursor::GetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool* outFail) this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; + fail = cursor->mCursor_DoFailOnSeedOutOfSync; outErr = ev->AsErr(); } if ( outFail ) @@ -333,20 +335,6 @@ orkinTableRowCursor::GetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool* outFail) // { ===== begin nsIMdbTableRowCursor methods ===== // { ----- begin attribute methods ----- -/*virtual*/ mdb_err -orkinTableRowCursor::SetTable(nsIMdbEnv* mev, nsIMdbTable* ioTable) -{ - MORK_USED_1(ioTable); - mdb_err outErr = 0; - morkEnv* ev = - this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - return outErr; -} /*virtual*/ mdb_err orkinTableRowCursor::GetTable(nsIMdbEnv* mev, nsIMdbTable** acqTable) @@ -428,67 +416,71 @@ orkinTableRowCursor::NextRow( // get row cells from table for cells already in r } // } ----- end row iteration methods ----- -// { ----- begin copy iteration methods ----- + +// { ----- begin duplicate row removal methods ----- /*virtual*/ mdb_err -orkinTableRowCursor::NextRowCopy( // put row cells into sink only when already in sink - nsIMdbEnv* mev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos) +orkinTableRowCursor::CanHaveDupRowMembers(nsIMdbEnv* mev, // cursor might hold dups? + mdb_bool* outCanHaveDups) { - MORK_USED_1(ioSinkRow); - mdbOid oid; - oid.mOid_Scope = 0; - oid.mOid_Id = (mork_id) -1; - mdb_pos rowPos = -1; mdb_err outErr = 0; + mdb_bool canHaveDups = mdbBool_kFalse; + morkEnv* ev = this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( outOid ) - { - ev->StubMethodOnlyError(); - } - else - ev->NilPointerError(); + morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; + canHaveDups = cursor->CanHaveDupRowMembers(ev); outErr = ev->AsErr(); } - if ( outRowPos ) - *outRowPos = rowPos; - if ( outOid ) - *outOid = oid; + if ( outCanHaveDups ) + *outCanHaveDups = canHaveDups; return outErr; } - + /*virtual*/ mdb_err -orkinTableRowCursor::NextRowCopyAll( // put all row cells into sink, adding to sink +orkinTableRowCursor::MakeUniqueCursor( // clone cursor, removing duplicate rows nsIMdbEnv* mev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos) + nsIMdbTableRowCursor** acqCursor) // acquire clone with no dups + // Note that MakeUniqueCursor() is never necessary for a cursor which was + // created by table method nsIMdbTable::GetTableRowCursor(), because a table + // never contains the same row as a member more than once. However, a cursor + // created by table method nsIMdbTable::FindRowMatches() might contain the + // same row more than once, because the same row can generate a hit by more + // than one column with a matching string prefix. Note this method can + // return the very same cursor instance with just an incremented refcount, + // when the original cursor could not contain any duplicate rows (calling + // CanHaveDupRowMembers() shows this case on a false return). Otherwise + // this method returns a different cursor instance. Callers should not use + // this MakeUniqueCursor() method lightly, because it tends to defeat the + // purpose of lazy programming techniques, since it can force creation of + // an explicit row collection in a new cursor's representation, in order to + // inspect the row membership and remove any duplicates; this can have big + // impact if a collection holds tens of thousands of rows or more, when + // the original cursor with dups simply referenced rows indirectly by row + // position ranges, without using an explicit row set representation. + // Callers are encouraged to use nsIMdbCursor::GetCount() to determine + // whether the row collection is very large (tens of thousands), and to + // delay calling MakeUniqueCursor() when possible, until a user interface + // element actually demands the creation of an explicit set representation. { - MORK_USED_1(ioSinkRow); - mdbOid oid; - oid.mOid_Scope = 0; - oid.mOid_Id = (mork_id) -1; - mdb_pos rowPos = -1; mdb_err outErr = 0; + nsIMdbTableRowCursor* outCursor = 0; + morkEnv* ev = this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + if ( this->Handle_AddStrongRef(mev) == 0 ) + outCursor = this; + outErr = ev->AsErr(); } - if ( outRowPos ) - *outRowPos = rowPos; - if ( outOid ) - *outOid = oid; + if ( acqCursor ) + *acqCursor = outCursor; return outErr; -} // nonzero if child, and a row child - -// } ----- end copy iteration methods ----- +} +// } ----- end duplicate row removal methods ----- // } ===== end nsIMdbTableRowCursor methods ===== diff --git a/db/mork/src/orkinTableRowCursor.h b/db/mork/src/orkinTableRowCursor.h index bdbb4a04dad5..e0ee48673b87 100644 --- a/db/mork/src/orkinTableRowCursor.h +++ b/db/mork/src/orkinTableRowCursor.h @@ -150,7 +150,6 @@ public: // type identification // { ===== begin nsIMdbTableRowCursor methods ===== // { ----- begin attribute methods ----- - virtual mdb_err SetTable(nsIMdbEnv* ev, nsIMdbTable* ioTable); // sets pos to -1 virtual mdb_err GetTable(nsIMdbEnv* ev, nsIMdbTable** acqTable); // } ----- end attribute methods ----- @@ -168,19 +167,35 @@ public: // type identification mdb_pos* outRowPos); // zero-based position of the row in table // } ----- end row iteration methods ----- - // { ----- begin copy iteration methods ----- - virtual mdb_err NextRowCopy( // put row cells into sink only when already in sink + // { ----- begin duplicate row removal methods ----- + virtual mdb_err CanHaveDupRowMembers(nsIMdbEnv* ev, // cursor might hold dups? + mdb_bool* outCanHaveDups); + + virtual mdb_err MakeUniqueCursor( // clone cursor, removing duplicate rows nsIMdbEnv* ev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos); // zero-based position of the row in table - - virtual mdb_err NextRowCopyAll( // put all row cells into sink, adding to sink - nsIMdbEnv* ev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos); // zero-based position of the row in table - // } ----- end copy iteration methods ----- + nsIMdbTableRowCursor** acqCursor); // acquire clone with no dups + // Note that MakeUniqueCursor() is never necessary for a cursor which was + // created by table method nsIMdbTable::GetTableRowCursor(), because a table + // never contains the same row as a member more than once. However, a cursor + // created by table method nsIMdbTable::FindRowMatches() might contain the + // same row more than once, because the same row can generate a hit by more + // than one column with a matching string prefix. Note this method can + // return the very same cursor instance with just an incremented refcount, + // when the original cursor could not contain any duplicate rows (calling + // CanHaveDupRowMembers() shows this case on a false return). Otherwise + // this method returns a different cursor instance. Callers should not use + // this MakeUniqueCursor() method lightly, because it tends to defeat the + // purpose of lazy programming techniques, since it can force creation of + // an explicit row collection in a new cursor's representation, in order to + // inspect the row membership and remove any duplicates; this can have big + // impact if a collection holds tens of thousands of rows or more, when + // the original cursor with dups simply referenced rows indirectly by row + // position ranges, without using an explicit row set representation. + // Callers are encouraged to use nsIMdbCursor::GetCount() to determine + // whether the row collection is very large (tens of thousands), and to + // delay calling MakeUniqueCursor() when possible, until a user interface + // element actually demands the creation of an explicit set representation. + // } ----- end duplicate row removal methods ----- // } ===== end nsIMdbTableRowCursor methods ===== }; diff --git a/db/mork/src/orkinThumb.cpp b/db/mork/src/orkinThumb.cpp index 9e0d11d14b14..179d6975271b 100644 --- a/db/mork/src/orkinThumb.cpp +++ b/db/mork/src/orkinThumb.cpp @@ -87,7 +87,8 @@ orkinThumb::CanUseThumb(nsIMdbEnv* mev, if ( ev ) { morkThumb* self = (morkThumb*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kThumb); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kThumb, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsThumb() ) diff --git a/mailnews/db/mork/macbuild/mork.mcp b/mailnews/db/mork/macbuild/mork.mcp index 3dc832be125b..d0b017c17e03 100644 Binary files a/mailnews/db/mork/macbuild/mork.mcp and b/mailnews/db/mork/macbuild/mork.mcp differ diff --git a/mailnews/db/mork/src/mork.h b/mailnews/db/mork/src/mork.h index 0b2d8ffc6446..ab2d551f52f9 100644 --- a/mailnews/db/mork/src/mork.h +++ b/mailnews/db/mork/src/mork.h @@ -194,6 +194,8 @@ class morkRow; class morkRowCellCursor; class morkRowObject; class morkRowSpace; +class morkSorting; +class morkSortingRowCursor; class morkSpace; class morkSpan; class morkStore; diff --git a/mailnews/db/mork/src/morkEnv.cpp b/mailnews/db/mork/src/morkEnv.cpp index 328acb6ee4bb..624a24efff05 100644 --- a/mailnews/db/mork/src/morkEnv.cpp +++ b/mailnews/db/mork/src/morkEnv.cpp @@ -67,6 +67,9 @@ morkEnv::~morkEnv() /*i*/ // assert CloseEnv() executed earlier MORK_ASSERT(mEnv_ErrorHook==0); } +/* choose morkBool_kTrue or morkBool_kFalse for kBeVerbose: */ +#define morkEnv_kBeVerbose morkBool_kFalse + /*public non-poly*/ morkEnv::morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap, morkFactory* ioFactory, nsIMdbHeap* ioSlotHeap) @@ -86,7 +89,7 @@ morkEnv::morkEnv(const morkUsage& inUsage, nsIMdbHeap* ioHeap, , mEnv_DoTrace( morkBool_kFalse ) , mEnv_AutoClear( morkAble_kDisabled ) , mEnv_ShouldAbort( morkBool_kFalse ) -, mEnv_BeVerbose( morkBool_kFalse ) +, mEnv_BeVerbose( morkEnv_kBeVerbose ) { MORK_ASSERT(ioSlotHeap && ioFactory ); if ( ioSlotHeap ) @@ -126,7 +129,7 @@ morkEnv::morkEnv(morkEnv* ev, /*i*/ , mEnv_DoTrace( morkBool_kFalse ) , mEnv_AutoClear( morkAble_kDisabled ) , mEnv_ShouldAbort( morkBool_kFalse ) -, mEnv_BeVerbose( morkBool_kFalse ) +, mEnv_BeVerbose( morkEnv_kBeVerbose ) { // $$$ do we need to refcount the inSelfAsMdbEnv nsIMdbEnv?? diff --git a/mailnews/db/mork/src/morkFile.cpp b/mailnews/db/mork/src/morkFile.cpp index 095be8417d44..4eed7d5546de 100644 --- a/mailnews/db/mork/src/morkFile.cpp +++ b/mailnews/db/mork/src/morkFile.cpp @@ -36,9 +36,13 @@ #include "morkFile.h" #endif -// #ifndef _ORKINFILE_ -// #include "orkinFile.h" -// #endif +#define MORK_CONFIG_USE_ORKINFILE 1 + +#ifdef MORK_CONFIG_USE_ORKINFILE +#ifndef _ORKINFILE_ +#include "orkinFile.h" +#endif +#endif /*MORK_CONFIG_USE_ORKINFILE*/ //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 diff --git a/mailnews/db/mork/src/morkHandle.cpp b/mailnews/db/mork/src/morkHandle.cpp index 12854919eb2f..e6b017c5961e 100644 --- a/mailnews/db/mork/src/morkHandle.cpp +++ b/mailnews/db/mork/src/morkHandle.cpp @@ -173,19 +173,20 @@ void morkHandle::NewDownHandleError(morkEnv* ev) const } morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev, - mork_bool inMutable, mork_magic inMagicType) const + mork_bool inMutable, mork_magic inMagicType, mork_bool inClosedOkay) const { morkObject* outObject = 0; - if ( this->IsHandle() && this->GoodHandleTag() && this->IsOpenNode() ) + if ( this->IsHandle() && this->GoodHandleTag() && + ( inClosedOkay || this->IsOpenNode() ) ) { if ( !inMagicType || mHandle_Magic == inMagicType ) { morkObject* obj = this->mHandle_Object; - if ( obj ) + if ( obj ) { if ( obj->IsNode() ) { - if ( obj->IsOpenNode() ) + if ( inClosedOkay || obj->IsOpenNode() ) { if ( this->IsMutable() || !inMutable ) outObject = obj; @@ -198,7 +199,7 @@ morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev, else this->NonNodeObjectError(ev); } - else + else if ( !inClosedOkay ) this->NilHandleObjectError(ev); } else @@ -207,27 +208,28 @@ morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev, else this->NewDownHandleError(ev); - MORK_ASSERT(outObject); + MORK_ASSERT(outObject || inClosedOkay); return outObject; } morkEnv* morkHandle::CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable, - mdb_err* outErr) const + mork_bool inClosedOkay, mdb_err* outErr) const { morkEnv* outEnv = 0; morkEnv* ev = morkEnv::FromMdbEnv(mev); if ( ev ) { - morkObject* obj = this->GetGoodHandleObject(ev, inMutable, /*magic*/ 0); + morkObject* obj = this->GetGoodHandleObject(ev, inMutable, + /*magic*/ 0, inClosedOkay); if ( obj ) { outEnv = ev; } *outErr = ev->AsErr(); } - MORK_ASSERT(outEnv); + MORK_ASSERT(outEnv || inClosedOkay); return outEnv; } @@ -238,15 +240,20 @@ morkHandle::CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable, morkHandle::Handle_IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly) { mdb_err outErr = 0; + mdb_bool readOnly = mdbBool_kTrue; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { - MORK_ASSERT(outIsReadonly); - if ( outIsReadonly ) - *outIsReadonly = mHandle_Object->IsFrozen(); + readOnly = mHandle_Object->IsFrozen(); + outErr = ev->AsErr(); } + MORK_ASSERT(outIsReadonly); + if ( outIsReadonly ) + *outIsReadonly = readOnly; + return outErr; } // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port. @@ -257,23 +264,27 @@ morkHandle::Handle_IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly) morkHandle::Handle_GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory) { mdb_err outErr = 0; + nsIMdbFactory* handle = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { morkFactory* factory = ev->mEnv_Factory; if ( factory ) { - nsIMdbFactory* handle = factory->AcquireFactoryHandle(ev); - MORK_ASSERT(acqFactory); - if ( handle && acqFactory ) - *acqFactory = handle; + handle = factory->AcquireFactoryHandle(ev); } else this->NilFactoryError(ev); outErr = ev->AsErr(); } + + MORK_ASSERT(acqFactory); + if ( acqFactory ) + *acqFactory = handle; + return outErr; } // } ----- end factory methods ----- @@ -284,16 +295,19 @@ morkHandle::Handle_GetWeakRefCount(nsIMdbEnv* mev, // weak refs mdb_count* outCount) { mdb_err outErr = 0; + mdb_count count = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { - MORK_ASSERT(outCount); - if ( outCount ) - *outCount = this->WeakRefsOnly(); + count = this->WeakRefsOnly(); outErr = ev->AsErr(); } + MORK_ASSERT(outCount); + if ( outCount ) + *outCount = count; return outErr; } @@ -302,16 +316,19 @@ morkHandle::Handle_GetStrongRefCount(nsIMdbEnv* mev, // strong refs mdb_count* outCount) { mdb_err outErr = 0; + mdb_count count = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { - MORK_ASSERT(outCount); - if ( outCount ) - *outCount = this->StrongRefsOnly(); + count = this->StrongRefsOnly(); outErr = ev->AsErr(); } + MORK_ASSERT(outCount); + if ( outCount ) + *outCount = count; return outErr; } @@ -321,7 +338,8 @@ morkHandle::Handle_AddWeakRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { this->AddWeakRef(ev); @@ -335,7 +353,8 @@ morkHandle::Handle_AddStrongRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kFalse, &outErr); if ( ev ) { this->AddStrongRef(ev); @@ -350,7 +369,8 @@ morkHandle::Handle_CutWeakRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { this->CutWeakRef(ev); @@ -363,7 +383,8 @@ morkHandle::Handle_CutWeakRef(nsIMdbEnv* mev) morkHandle::Handle_CutStrongRef(nsIMdbEnv* mev) { mdb_err outErr = 0; - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { this->CutStrongRef(ev); @@ -380,7 +401,8 @@ morkHandle::Handle_CloseMdbObject(nsIMdbEnv* mev) if ( this->IsNode() && this->IsOpenNode() ) { - morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, &outErr); + morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, + /*inClosedOkay*/ morkBool_kTrue, &outErr); if ( ev ) { morkObject* object = mHandle_Object; diff --git a/mailnews/db/mork/src/morkHandle.h b/mailnews/db/mork/src/morkHandle.h index ead587ef9202..f433b17febf6 100644 --- a/mailnews/db/mork/src/morkHandle.h +++ b/mailnews/db/mork/src/morkHandle.h @@ -118,12 +118,12 @@ public: // other handle methods void NonOpenObjectError(morkEnv* ev) const; morkObject* GetGoodHandleObject(morkEnv* ev, - mork_bool inMutabl, mork_magic inMagicType) const; + mork_bool inMutable, mork_magic inMagicType, mork_bool inClosedOkay) const; public: // interface supporting mdbObject methods morkEnv* CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable, - mdb_err* outErr) const; + mork_bool inClosedOkay, mdb_err* outErr) const; // { ----- begin mdbObject style methods ----- mdb_err Handle_IsFrozenMdbObject(nsIMdbEnv* ev, mdb_bool* outIsReadonly); diff --git a/mailnews/db/mork/src/morkNode.cpp b/mailnews/db/mork/src/morkNode.cpp index 5e59594217d0..b5511f9b6826 100644 --- a/mailnews/db/mork/src/morkNode.cpp +++ b/mailnews/db/mork/src/morkNode.cpp @@ -342,6 +342,30 @@ morkNode::CloseNode(morkEnv* ev) // called by CloseMorkNode(); } +extern void // utility method very similar to morkNode::SlotStrongNode(): +nsIMdbCompare_SlotStrongCompare(nsIMdbCompare* self, morkEnv* ev, + nsIMdbCompare** ioSlot) + // If *ioSlot is non-nil, that compare is released by CutStrongRef() and + // then zeroed out. Then if self is non-nil, this is acquired by + // calling AddStrongRef(), and if the return value shows success, + // then self is put into slot *ioSlot. Note self can be nil, so we take + // expression 'nsIMdbCompare_SlotStrongCompare(0, ev, &slot)'. +{ + nsIMdbEnv* menv = ev->AsMdbEnv(); + nsIMdbCompare* compare = *ioSlot; + if ( self != compare ) + { + if ( compare ) + { + *ioSlot = 0; + compare->CutStrongRef(menv); + } + if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) + *ioSlot = self; + } +} + + extern void // utility method very similar to morkNode::SlotStrongNode(): nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot) // If *ioSlot is non-nil, that file is released by CutStrongRef() and @@ -352,13 +376,16 @@ nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot) { nsIMdbEnv* menv = ev->AsMdbEnv(); nsIMdbFile* file = *ioSlot; - if ( file ) + if ( self != file ) { - *ioSlot = 0; - file->CutStrongRef(menv); + if ( file ) + { + *ioSlot = 0; + file->CutStrongRef(menv); + } + if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) + *ioSlot = self; } - if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) - *ioSlot = self; } void // utility method very similar to morkNode::SlotStrongNode(): @@ -371,13 +398,16 @@ nsIMdbHeap_SlotStrongHeap(nsIMdbHeap* self, morkEnv* ev, nsIMdbHeap** ioSlot) { nsIMdbEnv* menv = ev->AsMdbEnv(); nsIMdbHeap* heap = *ioSlot; - if ( heap ) + if ( self != heap ) { - *ioSlot = 0; - heap->CutStrongRef(menv); + if ( heap ) + { + *ioSlot = 0; + heap->CutStrongRef(menv); + } + if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) + *ioSlot = self; } - if ( self && ev->Good() && (self->AddStrongRef(menv)==0) && ev->Good() ) - *ioSlot = self; } /*public static*/ void diff --git a/mailnews/db/mork/src/morkNode.h b/mailnews/db/mork/src/morkNode.h index 7ea5dca89b95..5193fce8a80f 100644 --- a/mailnews/db/mork/src/morkNode.h +++ b/mailnews/db/mork/src/morkNode.h @@ -275,7 +275,16 @@ nsIMdbFile_SlotStrongFile(nsIMdbFile* self, morkEnv* ev, nsIMdbFile** ioSlot); // then zeroed out. Then if self is non-nil, this is acquired by // calling AddStrongRef(), and if the return value shows success, // then self is put into slot *ioSlot. Note self can be nil, so we take - // expression 'nsIMdbHeap_SlotStrongFile(0, ev, &slot)'. + // expression 'nsIMdbFile_SlotStrongFile(0, ev, &slot)'. + +extern void // utility method very similar to morkNode::SlotStrongNode(): +nsIMdbCompare_SlotStrongCompare(nsIMdbCompare* self, morkEnv* ev, + nsIMdbCompare** ioSlot); + // If *ioSlot is non-nil, that compare is released by CutStrongRef() and + // then zeroed out. Then if self is non-nil, this is acquired by + // calling AddStrongRef(), and if the return value shows success, + // then self is put into slot *ioSlot. Note self can be nil, so we take + // expression 'nsIMdbCompare_SlotStrongCompare(0, ev, &slot)'. //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 diff --git a/mailnews/db/mork/src/morkStore.cpp b/mailnews/db/mork/src/morkStore.cpp index 5418e31fce2a..c4cf6a36075b 100644 --- a/mailnews/db/mork/src/morkStore.cpp +++ b/mailnews/db/mork/src/morkStore.cpp @@ -56,9 +56,9 @@ #include "morkNodeMap.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _MORKBUILDER_ #include "morkBuilder.h" @@ -246,9 +246,13 @@ morkStore::CloseStore(morkEnv* ev) // called by CloseMorkNode(); { if ( this->IsNode() ) { - morkFile* file = mStore_File; - if ( file && file->IsOpenNode() ) - file->CloseMorkNode(ev); + // morkFile* file = mStore_File; + // if ( file && file->IsOpenNode() ) + // file->CloseMorkNode(ev); + + nsIMdbFile* file = mStore_File; + if ( file ) + file->CloseMdbObject(ev->AsMdbEnv()); morkAtomSpace::SlotStrongAtomSpace((morkAtomSpace*) 0, ev, &mStore_OidAtomSpace); @@ -259,7 +263,11 @@ morkStore::CloseStore(morkEnv* ev) // called by CloseMorkNode(); mStore_RowSpaces.CloseMorkNode(ev); mStore_AtomSpaces.CloseMorkNode(ev); morkBuilder::SlotStrongBuilder((morkBuilder*) 0, ev, &mStore_Builder); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); + + // morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, + &mStore_File); + morkStream::SlotStrongStream((morkStream*) 0, ev, &mStore_InStream); morkStream::SlotStrongStream((morkStream*) 0, ev, &mStore_OutStream); @@ -277,10 +285,27 @@ morkStore::CloseStore(morkEnv* ev) // called by CloseMorkNode(); // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` + +mork_bool morkStore::DoPreferLargeOverCompressCommit(morkEnv* ev) + // true when mStore_CanWriteIncremental && store has file large enough +{ + nsIMdbFile* file = mStore_File; + nsIMdbEnv* menv = ev->AsMdbEnv(); + if ( file && mStore_CanWriteIncremental ) + { + mdb_pos fileEof = 0; + file->Eof(ev->AsMdbEnv(), &fileEof); + if ( ev->Good() && fileEof > 128 ) + return morkBool_kTrue; + } + return morkBool_kFalse; +} + mork_percent morkStore::PercentOfStoreWasted(morkEnv* ev) { mork_percent outPercent = 0; - morkFile* file = mStore_File; + nsIMdbFile* file = mStore_File; + nsIMdbEnv* menv = ev->AsMdbEnv(); if ( file ) { @@ -291,7 +316,8 @@ mork_percent morkStore::PercentOfStoreWasted(morkEnv* ev) if ( firstPos < 512 && secondPos > firstPos ) firstPos = secondPos; // better approximation of first commit - mork_pos fileLength = file->Length(ev); // end of file + mork_pos fileLength = 0; + file->Eof(ev->AsMdbEnv(), &fileLength); // end of file if ( ev->Good() && fileLength > firstPos ) { mork_size groupContent = fileLength - firstPos; @@ -501,7 +527,7 @@ morkStream* morkStore::LazyGetInStream(morkEnv* ev) { if ( !mStore_InStream ) { - morkFile* file = mStore_File; + nsIMdbFile* file = mStore_File; if ( file ) { morkStream* stream = new(*mPort_Heap, ev) @@ -523,7 +549,7 @@ morkStream* morkStore::LazyGetOutStream(morkEnv* ev) { if ( !mStore_OutStream ) { - morkFile* file = mStore_File; + nsIMdbFile* file = mStore_File; if ( file ) { morkStream* stream = new(*mPort_Heap, ev) @@ -643,43 +669,38 @@ morkStore::CannotAutoAssignAtomIdentityError(morkEnv* ev) mork_bool morkStore::OpenStoreFile(morkEnv* ev, mork_bool inFrozen, - const char* inFilePath, const mdbOpenPolicy* inOpenPolicy) + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface + const mdbOpenPolicy* inOpenPolicy) { - MORK_USED_1(inOpenPolicy); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); - if ( ev->Good() ) - { - morkFile* file = morkFile::OpenOldFile(ev, mPort_Heap, - inFilePath, inFrozen); - if ( file ) - { - if ( ev->Good() ) - morkFile::SlotStrongFile(file, ev, &mStore_File); - else - file->CutStrongRef(ev); - } - } + MORK_USED_2(inOpenPolicy,inFrozen); + nsIMdbFile_SlotStrongFile(ioFile, ev, &mStore_File); + + // if ( ev->Good() ) + // { + // morkFile* file = morkFile::OpenOldFile(ev, mPort_Heap, + // inFilePath, inFrozen); + // if ( ioFile ) + // { + // if ( ev->Good() ) + // morkFile::SlotStrongFile(file, ev, &mStore_File); + // else + // file->CutStrongRef(ev); + // + // } + // } return ev->Good(); } mork_bool morkStore::CreateStoreFile(morkEnv* ev, - const char* inFilePath, const mdbOpenPolicy* inOpenPolicy) + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface + const mdbOpenPolicy* inOpenPolicy) { MORK_USED_1(inOpenPolicy); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStore_File); - if ( ev->Good() ) - { - morkFile* file = morkFile::CreateNewFile(ev, mPort_Heap, - inFilePath); - if ( file ) - { - if ( ev->Good() ) - morkFile::SlotStrongFile(file, ev, &mStore_File); - else - file->CutStrongRef(ev); - } - } + nsIMdbFile_SlotStrongFile(ioFile, ev, &mStore_File); + return ev->Good(); } diff --git a/mailnews/db/mork/src/morkStore.h b/mailnews/db/mork/src/morkStore.h index 00529739c579..04f93ab7dff8 100644 --- a/mailnews/db/mork/src/morkStore.h +++ b/mailnews/db/mork/src/morkStore.h @@ -155,7 +155,7 @@ public: // state is public because the entire Mork system is private morkAtomSpace* mStore_GroundAtomSpace; // ground atom space for scopes morkAtomSpace* mStore_GroundColumnSpace; // ground column space for scopes - morkFile* mStore_File; // the file containing Mork text + nsIMdbFile* mStore_File; // the file containing Mork text morkStream* mStore_InStream; // stream using file used by the builder morkBuilder* mStore_Builder; // to parse Mork text and build structures @@ -246,6 +246,11 @@ public: // building an atom inside mStore_BookAtom from a char* string // inString. This method is the standard way to stage a string as an // atom for searching or adding new atoms into an atom space hash table. +public: // determining whether incremental writing is a good use of time: + + mork_bool DoPreferLargeOverCompressCommit(morkEnv* ev); + // true when mStore_CanWriteIncremental && store has file large enough + public: // lazy creation of members and nested row or atom spaces morkAtomSpace* LazyGetOidAtomSpace(morkEnv* ev); @@ -304,11 +309,13 @@ public: // other store methods mork_bool OpenStoreFile(morkEnv* ev, // return value equals ev->Good() mork_bool inFrozen, - const char* inFilePath, + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy); mork_bool CreateStoreFile(morkEnv* ev, // return value equals ev->Good() - const char* inFilePath, + // const char* inFilePath, + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy); morkAtom* CopyAtom(morkEnv* ev, const morkAtom* inAtom); diff --git a/mailnews/db/mork/src/morkStream.cpp b/mailnews/db/mork/src/morkStream.cpp index 9f0d869b8f0f..9e65dfca5221 100644 --- a/mailnews/db/mork/src/morkStream.cpp +++ b/mailnews/db/mork/src/morkStream.cpp @@ -66,7 +66,7 @@ morkStream::~morkStream() // assert CloseStream() executed earlier /*public non-poly*/ morkStream::morkStream(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, - morkFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen) + nsIMdbFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen) : morkFile(ev, inUsage, ioHeap, ioHeap) , mStream_At( 0 ) , mStream_ReadEnd( 0 ) @@ -89,12 +89,10 @@ morkStream::morkStream(morkEnv* ev, const morkUsage& inUsage, if ( ioContentFile && ioHeap ) { - if ( ioContentFile->FileFrozen() ) // forced to be readonly? - inFrozen = morkBool_kTrue; // override the input value + // if ( ioContentFile->FileFrozen() ) // forced to be readonly? + // inFrozen = morkBool_kTrue; // override the input value - mork_pos fileEnd = ioContentFile->Length(ev); - - morkFile::SlotStrongFile(ioContentFile, ev, &mStream_ContentFile); + nsIMdbFile_SlotStrongFile(ioContentFile, ev, &mStream_ContentFile); if ( ev->Good() ) { mork_u1* buf = 0; @@ -138,7 +136,7 @@ morkStream::CloseStream(morkEnv* ev) // called by CloseMorkNode(); { if ( this->IsNode() ) { - morkFile::SlotStrongFile((morkFile*) 0, ev, &mStream_ContentFile); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mStream_ContentFile); nsIMdbHeap* heap = mFile_SlotHeap; mork_u1* buf = mStream_Buf; mStream_Buf = 0; @@ -401,7 +399,7 @@ morkStream::AcquireBud(morkEnv* ev, nsIMdbHeap* ioHeap) { MORK_USED_1(ioHeap); morkFile* outFile = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { // figure out how this interacts with buffering and mStream_WriteEnd: @@ -417,31 +415,35 @@ morkStream::Length(morkEnv* ev) const // eof { mork_pos outPos = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { - mork_pos contentEof = file->Length(ev); - - if ( mStream_WriteEnd ) // this stream supports writing? + mork_pos contentEof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &contentEof); + if ( ev->Good() ) { - // the local buffer might have buffered content past content eof - if ( ev->Good() ) // no error happened during Length() above? + if ( mStream_WriteEnd ) // this stream supports writing? { - mork_u1* at = mStream_At; - mork_u1* buf = mStream_Buf; - if ( at >= buf ) // expected cursor order? + // the local buffer might have buffered content past content eof + if ( ev->Good() ) // no error happened during Length() above? { - mork_pos localContent = mStream_BufPos + (at - buf); - if ( localContent > contentEof ) // buffered past eof? - contentEof = localContent; // return new logical eof + mork_u1* at = mStream_At; + mork_u1* buf = mStream_Buf; + if ( at >= buf ) // expected cursor order? + { + mork_pos localContent = mStream_BufPos + (at - buf); + if ( localContent > contentEof ) // buffered past eof? + contentEof = localContent; // return new logical eof - outPos = contentEof; + outPos = contentEof; + } + else this->NewBadCursorOrderError(ev); } - else this->NewBadCursorOrderError(ev); } + else + outPos = contentEof; // frozen files get length from content file } - else - outPos = contentEof; // frozen files get length from content file } else this->NewFileDownError(ev); @@ -471,7 +473,7 @@ morkStream::Tell(morkEnv* ev) const { mork_pos outPos = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { mork_u1* buf = mStream_Buf; @@ -512,7 +514,7 @@ morkStream::Read(morkEnv* ev, void* outBuf, mork_size inSize) mork_pos outActual = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { mork_u1* end = mStream_ReadEnd; // byte after last buffered byte @@ -558,21 +560,24 @@ morkStream::Read(morkEnv* ev, void* outBuf, mork_size inSize) mStream_At = mStream_ReadEnd = buf; // empty buffer - file->Seek(ev, mStream_BufPos); // set file pos - if ( ev->Good() ) // no seek error? + // file->Seek(ev, mStream_BufPos); // set file pos + // if ( ev->Good() ) // no seek error? + // { + // } + + mork_num actual = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Get(menv, sink, inSize, mStream_BufPos, &actual); + if ( ev->Good() ) // no read error? { - mork_num actual = file->Read(ev, sink, inSize); - if ( ev->Good() ) // no read error? + if ( actual ) { - if ( actual ) - { - outActual += actual; - mStream_BufPos += actual; - mStream_HitEof = morkBool_kFalse; - } - else if ( !outActual ) - mStream_HitEof = morkBool_kTrue; + outActual += actual; + mStream_BufPos += actual; + mStream_HitEof = morkBool_kFalse; } + else if ( !outActual ) + mStream_HitEof = morkBool_kTrue; } } } @@ -596,7 +601,7 @@ morkStream::Seek(morkEnv* ev, mork_pos inPos) { mork_pos outPos = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenOrClosingNode() && this->FileActive() && file ) { mork_u1* at = mStream_At; // current position in buffer @@ -615,7 +620,9 @@ morkStream::Seek(morkEnv* ev, mork_pos inPos) { if ( mStream_BufPos != inPos ) // need to change pos? { - mork_pos eof = file->Length(ev); + mork_pos eof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &eof); if ( ev->Good() ) // no errors getting length? { if ( inPos <= eof ) // acceptable new position? @@ -634,7 +641,9 @@ morkStream::Seek(morkEnv* ev, mork_pos inPos) { if ( at >= buf && at <= readEnd ) // expected cursor order? { - mork_pos eof = file->Length(ev); + mork_pos eof = 0; + nsIMdbEnv* menv = ev->AsMdbEnv(); + file->Eof(menv, &eof); if ( ev->Good() ) // no errors getting length? { if ( inPos <= eof ) // acceptable new position? @@ -662,7 +671,7 @@ morkStream::Write(morkEnv* ev, const void* inBuf, mork_size inSize) { mork_num outActual = 0; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenActiveAndMutableFile() && file ) { mork_u1* end = mStream_WriteEnd; // byte after last buffered byte @@ -725,17 +734,18 @@ morkStream::Write(morkEnv* ev, const void* inBuf, mork_size inSize) } else // directly to content file instead { - file->Seek(ev, mStream_BufPos); // set pos - - if ( ev->Good() ) // no seek error? + // file->Seek(ev, mStream_BufPos); // set pos + // if ( ev->Good() ) // no seek error? + // { + // } + + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + file->Put(menv, source, inSize, mStream_BufPos, &actual); + if ( ev->Good() ) // no write error? { - mork_num actual = - file->Write(ev, source, inSize); - if ( ev->Good() ) // no write error? - { - outActual += actual; - mStream_BufPos += actual; - } + outActual += actual; + mStream_BufPos += actual; } } } @@ -759,12 +769,13 @@ morkStream::Write(morkEnv* ev, const void* inBuf, mork_size inSize) /*public virtual*/ void morkStream::Flush(morkEnv* ev) { - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenOrClosingNode() && this->FileActive() && file ) { if ( mStream_Dirty ) this->spill_buf(ev); - file->Flush(ev); + + file->Flush(ev->AsMdbEnv()); } else this->NewFileDownError(ev); } @@ -777,7 +788,7 @@ morkStream::fill_getc(morkEnv* ev) { int c = EOF; - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenAndActiveFile() && file ) { mork_u1* buf = mStream_Buf; @@ -789,25 +800,28 @@ morkStream::fill_getc(morkEnv* ev) if ( ev->Good() ) // no errors yet? { - file->Seek(ev, mStream_BufPos); // set file pos - if ( ev->Good() ) // no seek error? + // file->Seek(ev, mStream_BufPos); // set file pos + // if ( ev->Good() ) // no seek error? + // { + // } + + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + file->Get(menv, buf, mStream_BufSize, mStream_BufPos, &actual); + if ( ev->Good() ) // no read errors? { - mork_num actual = file->Read(ev, buf, mStream_BufSize); - if ( ev->Good() ) // no read errors? + if ( actual > mStream_BufSize ) // more than asked for?? + actual = mStream_BufSize; + + mStream_At = buf; + mStream_ReadEnd = buf + actual; + if ( actual ) // any bytes actually read? { - if ( actual > mStream_BufSize ) // more than asked for?? - actual = mStream_BufSize; - - mStream_At = buf; - mStream_ReadEnd = buf + actual; - if ( actual ) // any bytes actually read? - { - c = *mStream_At++; // return first byte from buffer - mStream_HitEof = morkBool_kFalse; - } - else - mStream_HitEof = morkBool_kTrue; + c = *mStream_At++; // return first byte from buffer + mStream_HitEof = morkBool_kFalse; } + else + mStream_HitEof = morkBool_kTrue; } } } @@ -827,7 +841,7 @@ morkStream::spill_putc(morkEnv* ev, int c) void morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file { - morkFile* file = mStream_ContentFile; + nsIMdbFile* file = mStream_ContentFile; if ( this->IsOpenOrClosingNode() && this->FileActive() && file ) { mork_u1* buf = mStream_Buf; @@ -847,16 +861,19 @@ morkStream::spill_buf(morkEnv* ev) // spill/flush from buffer to file } if ( ev->Good() ) { - file->Seek(ev, mStream_BufPos); + // file->Seek(ev, mStream_BufPos); + // if ( ev->Good() ) + // { + // } + nsIMdbEnv* menv = ev->AsMdbEnv(); + mork_num actual = 0; + + file->Put(menv, buf, count, mStream_BufPos, &actual); if ( ev->Good() ) { - file->Write(ev, buf, count); - if ( ev->Good() ) - { - mStream_BufPos += count; // past bytes written - mStream_At = buf; // reset buffer cursor - mStream_Dirty = morkBool_kFalse; - } + mStream_BufPos += actual; // past bytes written + mStream_At = buf; // reset buffer cursor + mStream_Dirty = morkBool_kFalse; } } } diff --git a/mailnews/db/mork/src/morkStream.h b/mailnews/db/mork/src/morkStream.h index 148a8c71a697..22857c4bcec1 100644 --- a/mailnews/db/mork/src/morkStream.h +++ b/mailnews/db/mork/src/morkStream.h @@ -83,7 +83,7 @@ protected: // protected morkStream members mork_u1* mStream_ReadEnd; // null or one byte past last readable byte mork_u1* mStream_WriteEnd; // null or mStream_Buf + mStream_BufSize - morkFile* mStream_ContentFile; // where content is read and written + nsIMdbFile* mStream_ContentFile; // where content is read and written mork_u1* mStream_Buf; // dynamically allocated memory to buffer io mork_size mStream_BufSize; // requested buf size (fixed by min and max) @@ -98,7 +98,7 @@ public: // morkNode virtual methods public: // morkStream construction & destruction morkStream(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, - morkFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen); + nsIMdbFile* ioContentFile, mork_size inBufSize, mork_bool inFrozen); void CloseStream(morkEnv* ev); // called by CloseMorkNode(); private: // copying is not allowed @@ -172,7 +172,7 @@ public: // public non-poly morkStream methods void NewCantWriteSourceError(morkEnv* ev) const; void NewPosBeyondEofError(morkEnv* ev) const; - morkFile* GetStreamContentFile() const { return mStream_ContentFile; } + nsIMdbFile* GetStreamContentFile() const { return mStream_ContentFile; } mork_size GetStreamBufferSize() const { return mStream_BufSize; } mork_size PutIndent(morkEnv* ev, mork_count inDepth); diff --git a/mailnews/db/mork/src/morkTableRowCursor.cpp b/mailnews/db/mork/src/morkTableRowCursor.cpp index cb8993bc6952..bb2d0acb3e79 100644 --- a/mailnews/db/mork/src/morkTableRowCursor.cpp +++ b/mailnews/db/mork/src/morkTableRowCursor.cpp @@ -129,6 +129,13 @@ morkTableRowCursor::NonTableRowCursorTypeError(morkEnv* ev) ev->NewError("non morkTableRowCursor"); } + +orkinTableRowCursor* +morkTableRowCursor::AcquireUniqueRowCursorHandle(morkEnv* ev) +{ + return this->AcquireTableRowCursorHandle(ev); +} + orkinTableRowCursor* morkTableRowCursor::AcquireTableRowCursorHandle(morkEnv* ev) { @@ -154,6 +161,23 @@ morkTableRowCursor::NextRowOid(morkEnv* ev, mdbOid* outOid) return outPos; } +mork_bool +morkTableRowCursor::CanHaveDupRowMembers(morkEnv* ev) +{ + return morkBool_kFalse; // false default is correct +} + +mork_count +morkTableRowCursor::GetMemberCount(morkEnv* ev) +{ + morkTable* table = mTableRowCursor_Table; + if ( table ) + return table->mTable_RowArray.mArray_Fill; + else + return 0; +} + + morkRow* morkTableRowCursor::NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos) { diff --git a/mailnews/db/mork/src/morkTableRowCursor.h b/mailnews/db/mork/src/morkTableRowCursor.h index 54c8cf858362..039660ddbb66 100644 --- a/mailnews/db/mork/src/morkTableRowCursor.h +++ b/mailnews/db/mork/src/morkTableRowCursor.h @@ -81,12 +81,20 @@ public: // dynamic type identification public: // typing static void NonTableRowCursorTypeError(morkEnv* ev); +public: // handle attachment + orkinTableRowCursor* AcquireTableRowCursorHandle(morkEnv* ev); + +public: // oid only iteration + mdb_pos NextRowOid(morkEnv* ev, mdbOid* outOid); + public: // other table row cursor methods - orkinTableRowCursor* AcquireTableRowCursorHandle(morkEnv* ev); + virtual mork_bool CanHaveDupRowMembers(morkEnv* ev); + virtual mork_count GetMemberCount(morkEnv* ev); + + virtual orkinTableRowCursor* AcquireUniqueRowCursorHandle(morkEnv* ev); - mdb_pos NextRowOid(morkEnv* ev, mdbOid* outOid); - morkRow* NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos); + virtual morkRow* NextRow(morkEnv* ev, mdbOid* outOid, mdb_pos* outPos); public: // typesafe refcounting inlines calling inherited morkNode methods static void SlotWeakTableRowCursor(morkTableRowCursor* me, diff --git a/mailnews/db/mork/src/morkThumb.cpp b/mailnews/db/mork/src/morkThumb.cpp index b496125ae70e..4a5e7fc5eb76 100644 --- a/mailnews/db/mork/src/morkThumb.cpp +++ b/mailnews/db/mork/src/morkThumb.cpp @@ -44,9 +44,9 @@ #include "morkStore.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _MORKWRITER_ #include "morkWriter.h" @@ -60,10 +60,6 @@ #include "morkBuilder.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif - //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` @@ -134,7 +130,7 @@ morkThumb::CloseThumb(morkEnv* ev) // called by CloseMorkNode(); morkBuilder::SlotStrongBuilder((morkBuilder*) 0, ev, &mThumb_Builder); morkWriter::SlotStrongWriter((morkWriter*) 0, ev, &mThumb_Writer); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mThumb_File); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mThumb_File); morkStore::SlotStrongStore((morkStore*) 0, ev, &mThumb_Store); morkPort::SlotStrongPort((morkPort*) 0, ev, &mThumb_SourcePort); this->MarkShut(); @@ -208,10 +204,11 @@ morkThumb::Make_OpenFileStore(morkEnv* ev, nsIMdbHeap* ioHeap, morkThumb* outThumb = 0; if ( ioHeap && ioStore ) { - morkFile* file = ioStore->mStore_File; + nsIMdbFile* file = ioStore->mStore_File; if ( file ) { - mork_pos fileEof = file->Length(ev); + mork_pos fileEof = 0; + file->Eof(ev->AsMdbEnv(), &fileEof); if ( ev->Good() ) { outThumb = new(*ioHeap, ev) @@ -248,7 +245,7 @@ morkThumb::Make_LargeCommit(morkEnv* ev, morkThumb* outThumb = 0; if ( ioHeap && ioStore ) { - morkFile* file = ioStore->mStore_File; + nsIMdbFile* file = ioStore->mStore_File; if ( file ) { outThumb = new(*ioHeap, ev) @@ -266,10 +263,10 @@ morkThumb::Make_LargeCommit(morkEnv* ev, writer->mWriter_NeedDirtyAll = morkBool_kFalse; outThumb->mThumb_DoCollect = morkBool_kFalse; morkStore::SlotStrongStore(ioStore, ev, &outThumb->mThumb_Store); - morkFile::SlotStrongFile(file, ev, &outThumb->mThumb_File); - morkWriter::SlotStrongWriter(writer, ev, &outThumb->mThumb_Writer); - // writer no longer holds on to this. - writer->CutStrongRef(ev); + + nsIMdbFile_SlotStrongFile(file, ev, &outThumb->mThumb_File); + + outThumb->mThumb_Writer = writer; // pass writer ownership to thumb } } } @@ -289,7 +286,7 @@ morkThumb::Make_CompressCommit(morkEnv* ev, morkThumb* outThumb = 0; if ( ioHeap && ioStore ) { - morkFile* file = ioStore->mStore_File; + nsIMdbFile* file = ioStore->mStore_File; if ( file ) { outThumb = new(*ioHeap, ev) @@ -305,7 +302,7 @@ morkThumb::Make_CompressCommit(morkEnv* ev, writer->mWriter_NeedDirtyAll = morkBool_kTrue; outThumb->mThumb_DoCollect = inDoCollect; morkStore::SlotStrongStore(ioStore, ev, &outThumb->mThumb_Store); - morkFile::SlotStrongFile(file, ev, &outThumb->mThumb_File); + nsIMdbFile_SlotStrongFile(file, ev, &outThumb->mThumb_File); morkWriter::SlotStrongWriter(writer, ev, &outThumb->mThumb_Writer); // cope with fact that parsed transaction groups are going away: diff --git a/mailnews/db/mork/src/morkThumb.h b/mailnews/db/mork/src/morkThumb.h index 7c651c1fd234..ba2cb5bbb64f 100644 --- a/mailnews/db/mork/src/morkThumb.h +++ b/mailnews/db/mork/src/morkThumb.h @@ -82,7 +82,7 @@ public: // state is public because the entire Mork system is private mork_u2 mThumb_Seed; // optional seed for u4 alignment padding morkStore* mThumb_Store; // weak ref to created store - morkFile* mThumb_File; // strong ref to file (store, import, export) + nsIMdbFile* mThumb_File; // strong ref to file (store, import, export) morkWriter* mThumb_Writer; // strong ref to writer (for commit) morkBuilder* mThumb_Builder; // strong ref to builder (for store open) morkPort* mThumb_SourcePort; // strong ref to port for import diff --git a/mailnews/db/mork/src/morkWriter.cpp b/mailnews/db/mork/src/morkWriter.cpp index 8c1f612b3e54..f0158342f8be 100644 --- a/mailnews/db/mork/src/morkWriter.cpp +++ b/mailnews/db/mork/src/morkWriter.cpp @@ -40,9 +40,9 @@ #include "morkWriter.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _MORKSTREAM_ #include "morkStream.h" @@ -113,7 +113,7 @@ morkWriter::~morkWriter() // assert CloseTable() executed earlier /*public non-poly*/ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, - nsIMdbHeap* ioHeap, morkStore* ioStore, morkFile* ioFile, + nsIMdbHeap* ioHeap, morkStore* ioStore, nsIMdbFile* ioFile, nsIMdbHeap* ioSlotHeap) : morkNode(ev, inUsage, ioHeap) , mWriter_Store( 0 ) @@ -194,7 +194,7 @@ morkWriter::morkWriter(morkEnv* ev, const morkUsage& inUsage, if ( ioSlotHeap && ioFile && ioStore ) { morkStore::SlotWeakStore(ioStore, ev, &mWriter_Store); - morkFile::SlotStrongFile(ioFile, ev, &mWriter_File); + nsIMdbFile_SlotStrongFile(ioFile, ev, &mWriter_File); nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mWriter_SlotHeap); if ( ev->Good() ) { @@ -228,7 +228,8 @@ morkWriter::MakeWriterStream(morkEnv* ev) // give writer a suitable stream } else // compress commit { - morkFile* bud = mWriter_File->AcquireBud(ev, heap); + nsIMdbFile* bud = 0; + mWriter_File->AcquireBud(ev->AsMdbEnv(), heap, &bud); if ( bud ) { if ( ev->Good() ) @@ -239,7 +240,7 @@ morkWriter::MakeWriterStream(morkEnv* ev) // give writer a suitable stream morkWriter_kStreamBufSize, frozen); } else - bud->CutStrongRef(ev); + bud->CutStrongRef(ev->AsMdbEnv()); } } @@ -264,8 +265,8 @@ morkWriter::CloseWriter(morkEnv* ev) // called by CloseMorkNode(); if ( this->IsNode() ) { morkStore::SlotWeakStore((morkStore*) 0, ev, &mWriter_Store); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mWriter_File); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mWriter_Bud); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mWriter_File); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mWriter_Bud); morkStream::SlotStrongStream((morkStream*) 0, ev, &mWriter_Stream); nsIMdbHeap_SlotStrongHeap((nsIMdbHeap*) 0, ev, &mWriter_SlotHeap); this->MarkShut(); @@ -1195,12 +1196,12 @@ morkWriter::OnContentDone(morkEnv* ev) } stream->Flush(ev); - morkFile* bud = mWriter_Bud; + nsIMdbFile* bud = mWriter_Bud; if ( bud ) { - bud->Flush(ev); - bud->BecomeTrunk(ev); - morkFile::SlotStrongFile((morkFile*) 0, ev, &mWriter_Bud); + bud->Flush(ev->AsMdbEnv()); + bud->BecomeTrunk(ev->AsMdbEnv()); + nsIMdbFile_SlotStrongFile((nsIMdbFile*) 0, ev, &mWriter_Bud); } else if ( !mWriter_Incremental ) // should have a bud? this->NilWriterBudError(ev); diff --git a/mailnews/db/mork/src/morkWriter.h b/mailnews/db/mork/src/morkWriter.h index c0b590ed8552..ad2a2f914742 100644 --- a/mailnews/db/mork/src/morkWriter.h +++ b/mailnews/db/mork/src/morkWriter.h @@ -126,8 +126,8 @@ class morkWriter : public morkNode { // row iterator public: // state is public because the entire Mork system is private morkStore* mWriter_Store; // weak ref to committing store - morkFile* mWriter_File; // strong ref to store's file - morkFile* mWriter_Bud; // strong ref to bud of mWriter_File + nsIMdbFile* mWriter_File; // strong ref to store's file + nsIMdbFile* mWriter_Bud; // strong ref to bud of mWriter_File morkStream* mWriter_Stream; // strong ref to stream on bud file nsIMdbHeap* mWriter_SlotHeap; // strong ref to slot heap @@ -200,7 +200,7 @@ public: // morkNode virtual methods public: // morkWriter construction & destruction morkWriter(morkEnv* ev, const morkUsage& inUsage, - nsIMdbHeap* ioHeap, morkStore* ioStore, morkFile* ioFile, + nsIMdbHeap* ioHeap, morkStore* ioStore, nsIMdbFile* ioFile, nsIMdbHeap* ioSlotHeap); void CloseWriter(morkEnv* ev); // called by CloseMorkNode(); diff --git a/mailnews/db/mork/src/orkinCell.cpp b/mailnews/db/mork/src/orkinCell.cpp index 415117c1363a..cb852da53eac 100644 --- a/mailnews/db/mork/src/orkinCell.cpp +++ b/mailnews/db/mork/src/orkinCell.cpp @@ -142,7 +142,8 @@ orkinCell::CanUseCell(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkCellObject* cellObj = (morkCellObject*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kCell); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kCell, + /*inClosedOkay*/ morkBool_kFalse); if ( cellObj ) { if ( cellObj->IsCellObject() ) diff --git a/mailnews/db/mork/src/orkinFactory.cpp b/mailnews/db/mork/src/orkinFactory.cpp index aa320c39c835..75fd9b35eb7f 100644 --- a/mailnews/db/mork/src/orkinFactory.cpp +++ b/mailnews/db/mork/src/orkinFactory.cpp @@ -80,6 +80,14 @@ #include "morkThumb.h" #endif +#ifndef _ORKINHEAP_ +#include "orkinHeap.h" +#endif + +#ifndef _ORKINCOMPARE_ +#include "orkinCompare.h" +#endif + //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 /* public virtual*/ @@ -144,7 +152,8 @@ orkinFactory::CanUseFactory(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkFactory* factory = (morkFactory*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kFactory); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kFactory, + /*inClosedOkay*/ morkBool_kFalse); if ( factory ) { if ( factory->IsFactory() ) @@ -277,7 +286,8 @@ orkinFactory::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen) // { ----- begin file methods ----- /*virtual*/ mdb_err orkinFactory::OpenOldFile(nsIMdbEnv* mev, nsIMdbHeap* ioHeap, - const char* inFilePath, mork_bool inFrozen, nsIMdbFile** acqFile) + const char* inFilePath, + mork_bool inFrozen, nsIMdbFile** acqFile) // Choose some subclass of nsIMdbFile to instantiate, in order to read // (and write if not frozen) the file known by inFilePath. The file // returned should be open and ready for use, and presumably positioned @@ -413,6 +423,26 @@ orkinFactory::MakeHeap(nsIMdbEnv* mev, nsIMdbHeap** acqHeap) } // } ----- end heap methods ----- +// { ----- begin compare methods ----- +/*virtual*/ mdb_err +orkinFactory::MakeCompare(nsIMdbEnv* mev, nsIMdbCompare** acqCompare) +{ + mdb_err outErr = 0; + nsIMdbCompare* outCompare = 0; + morkEnv* ev = this->CanUseFactory(mev, + /*inMutable*/ morkBool_kFalse, &outErr); + if ( ev ) + { + outCompare = new orkinCompare(); + if ( !outCompare ) + ev->OutOfMemoryError(); + } + if ( acqCompare ) + *acqCompare = outCompare; + return outErr; +} +// } ----- end compare methods ----- + // { ----- begin row methods ----- /*virtual*/ mdb_err orkinFactory::MakeRow(nsIMdbEnv* mev, nsIMdbHeap* ioHeap, @@ -440,8 +470,9 @@ orkinFactory::MakeRow(nsIMdbEnv* mev, nsIMdbHeap* ioHeap, /*virtual*/ mdb_err orkinFactory::CanOpenFilePort( nsIMdbEnv* mev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpen, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion) { @@ -455,9 +486,9 @@ orkinFactory::CanOpenFilePort( /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( inFilePath && inFirst512Bytes && outCanOpen ) + if ( ioFile && outCanOpen ) { - canOpenAsPort = this->CanOpenMorkTextFile(ev, inFirst512Bytes); + canOpenAsPort = this->CanOpenMorkTextFile(ev, ioFile); } else ev->NilPointerError(); @@ -475,7 +506,8 @@ orkinFactory::CanOpenFilePort( orkinFactory::OpenFilePort( nsIMdbEnv* mev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for readonly import + // const char* inFilePath, // the file to open for readonly import + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb) { @@ -486,7 +518,7 @@ orkinFactory::OpenFilePort( /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( inFilePath && inOpenPolicy && acqThumb ) + if ( ioFile && inOpenPolicy && acqThumb ) { } else @@ -543,17 +575,39 @@ orkinFactory::ThumbToOpenPort( // redeeming a completed thumb from OpenFilePort( mork_bool orkinFactory::CanOpenMorkTextFile(morkEnv* ev, - const mdbYarn* inFirst512Bytes) + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile) { MORK_USED_1(ev); mork_bool outBool = morkBool_kFalse; mork_size headSize = MORK_STRLEN(morkWriter_kFileHeader); - const mdbYarn* y = inFirst512Bytes; - if ( y && y->mYarn_Buf && y->mYarn_Fill >= headSize ) + + char localBuf[ 256 + 4 ]; // for extra for sloppy safety + mdbYarn localYarn; + mdbYarn* y = &localYarn; + y->mYarn_Buf = localBuf; // space to hold content + y->mYarn_Fill = 0; // no logical content yet + y->mYarn_Size = 256; // physical capacity is 256 bytes + y->mYarn_More = 0; + y->mYarn_Form = 0; + y->mYarn_Grow = 0; + + if ( ioFile ) { - mork_u1* buf = (mork_u1*) y->mYarn_Buf; - outBool = ( MORK_MEMCMP(morkWriter_kFileHeader, buf, headSize) == 0 ); + nsIMdbEnv* menv = ev->AsMdbEnv(); + mdb_size actualSize = 0; + ioFile->Get(menv, y->mYarn_Buf, y->mYarn_Size, /*pos*/ 0, &actualSize); + y->mYarn_Fill = actualSize; + + if ( y->mYarn_Buf && actualSize >= headSize && ev->Good() ) + { + mork_u1* buf = (mork_u1*) y->mYarn_Buf; + outBool = ( MORK_MEMCMP(morkWriter_kFileHeader, buf, headSize) == 0 ); + } } + else + ev->NilPointerError(); + return outBool; } @@ -561,8 +615,9 @@ orkinFactory::CanOpenMorkTextFile(morkEnv* ev, /*virtual*/ mdb_err orkinFactory::CanOpenFileStore( nsIMdbEnv* mev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpenAsStore, // whether OpenFileStore() might succeed mdb_bool* outCanOpenAsPort, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion) @@ -578,10 +633,10 @@ orkinFactory::CanOpenFileStore( /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( inFilePath && inFirst512Bytes && outCanOpenAsStore ) + if ( ioFile && outCanOpenAsStore ) { // right now always say true; later we should look for magic patterns - canOpenAsStore = this->CanOpenMorkTextFile(ev, inFirst512Bytes); + canOpenAsStore = this->CanOpenMorkTextFile(ev, ioFile); canOpenAsPort = canOpenAsStore; } else @@ -602,7 +657,8 @@ orkinFactory::CanOpenFileStore( orkinFactory::OpenFileStore( // open an existing database nsIMdbEnv* mev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for general db usage + // const char* inFilePath, // the file to open for general db usage + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb) { @@ -615,7 +671,7 @@ orkinFactory::OpenFileStore( // open an existing database if ( !ioHeap ) // need to use heap from env? ioHeap = ev->mEnv_Heap; - if ( inFilePath && inOpenPolicy && acqThumb ) + if ( ioFile && inOpenPolicy && acqThumb ) { morkFactory* factory = (morkFactory*) this->mHandle_Object; morkStore* store = new(*ioHeap, ev) @@ -624,7 +680,7 @@ orkinFactory::OpenFileStore( // open an existing database if ( store ) { mork_bool frozen = morkBool_kFalse; // open store mutable access - if ( store->OpenStoreFile(ev, frozen, inFilePath, inOpenPolicy) ) + if ( store->OpenStoreFile(ev, frozen, ioFile, inOpenPolicy) ) { morkThumb* thumb = morkThumb::Make_OpenFileStore(ev, ioHeap, store); if ( thumb ) @@ -691,7 +747,8 @@ orkinFactory::ThumbToOpenStore( // redeem completed thumb from OpenFileStore() orkinFactory::CreateNewFileStore( // create a new db with minimal content nsIMdbEnv* mev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // name of file which should not yet exist + // const char* inFilePath, // name of file which should not yet exist + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbStore** acqStore) { @@ -704,7 +761,7 @@ orkinFactory::CreateNewFileStore( // create a new db with minimal content if ( !ioHeap ) // need to use heap from env? ioHeap = ev->mEnv_Heap; - if ( inFilePath && inOpenPolicy && acqStore && ioHeap ) + if ( ioFile && inOpenPolicy && acqStore && ioHeap ) { morkFactory* factory = (morkFactory*) this->mHandle_Object; morkStore* store = new(*ioHeap, ev) @@ -716,7 +773,7 @@ orkinFactory::CreateNewFileStore( // create a new db with minimal content store->mStore_CanDirty = morkBool_kTrue; store->SetStoreAndAllSpacesCanDirty(ev, morkBool_kTrue); - if ( store->CreateStoreFile(ev, inFilePath, inOpenPolicy) ) + if ( store->CreateStoreFile(ev, ioFile, inOpenPolicy) ) outStore = orkinStore::MakeStore(ev, store); store->CutStrongRef(ev); // always cut ref (handle has its own ref) diff --git a/mailnews/db/mork/src/orkinFactory.h b/mailnews/db/mork/src/orkinFactory.h index bea55c67af61..61781d24f4c9 100644 --- a/mailnews/db/mork/src/orkinFactory.h +++ b/mailnews/db/mork/src/orkinFactory.h @@ -93,7 +93,9 @@ public: // utilities: morkEnv* GetInternalFactoryEnv(mdb_err* outErr); - mork_bool CanOpenMorkTextFile(morkEnv* ev, const mdbYarn* inFirst512Bytes); + mork_bool CanOpenMorkTextFile(morkEnv* ev, + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile); public: // type identification mork_bool IsOrkinFactory() const @@ -142,7 +144,8 @@ public: // { ----- begin file methods ----- virtual mdb_err OpenOldFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, - const char* inFilePath, mdb_bool inFrozen, nsIMdbFile** acqFile); + const char* inFilePath, + mdb_bool inFrozen, nsIMdbFile** acqFile); // Choose some subclass of nsIMdbFile to instantiate, in order to read // (and write if not frozen) the file known by inFilePath. The file // returned should be open and ready for use, and presumably positioned @@ -151,7 +154,8 @@ public: // other portions or Mork source code don't want to know how it's done. virtual mdb_err CreateNewFile(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, - const char* inFilePath, nsIMdbFile** acqFile); + const char* inFilePath, + nsIMdbFile** acqFile); // Choose some subclass of nsIMdbFile to instantiate, in order to read // (and write if not frozen) the file known by inFilePath. The file // returned should be created and ready for use, and presumably positioned @@ -169,6 +173,10 @@ public: virtual mdb_err MakeHeap(nsIMdbEnv* ev, nsIMdbHeap** acqHeap); // new heap // } ----- end heap methods ----- + // { ----- begin compare methods ----- + virtual mdb_err MakeCompare(nsIMdbEnv* ev, nsIMdbCompare** acqCompare); // ASCII + // } ----- end compare methods ----- + // { ----- begin row methods ----- virtual mdb_err MakeRow(nsIMdbEnv* ev, nsIMdbHeap* ioHeap, nsIMdbRow** acqRow); // new row // ioHeap can be nil, causing the heap associated with ev to be used @@ -177,15 +185,17 @@ public: // { ----- begin port methods ----- virtual mdb_err CanOpenFilePort( nsIMdbEnv* ev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpen, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion); // informal file format description virtual mdb_err OpenFilePort( nsIMdbEnv* ev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for readonly import + // const char* inFilePath, // the file to open for readonly import + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb); // acquire thumb for incremental port open // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and @@ -200,8 +210,9 @@ public: // { ----- begin store methods ----- virtual mdb_err CanOpenFileStore( nsIMdbEnv* ev, // context - const char* inFilePath, // the file to investigate - const mdbYarn* inFirst512Bytes, + // const char* inFilePath, // the file to investigate + // const mdbYarn* inFirst512Bytes, + nsIMdbFile* ioFile, // db abstract file interface mdb_bool* outCanOpenAsStore, // whether OpenFileStore() might succeed mdb_bool* outCanOpenAsPort, // whether OpenFilePort() might succeed mdbYarn* outFormatVersion); // informal file format description @@ -209,7 +220,8 @@ public: virtual mdb_err OpenFileStore( // open an existing database nsIMdbEnv* ev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // the file to open for general db usage + // const char* inFilePath, // the file to open for general db usage + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbThumb** acqThumb); // acquire thumb for incremental store open // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and @@ -224,7 +236,8 @@ public: virtual mdb_err CreateNewFileStore( // create a new db with minimal content nsIMdbEnv* ev, // context nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used - const char* inFilePath, // name of file which should not yet exist + // const char* inFilePath, // name of file which should not yet exist + nsIMdbFile* ioFile, // db abstract file interface const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db nsIMdbStore** acqStore); // acquire new db store object // } ----- end store methods ----- diff --git a/mailnews/db/mork/src/orkinHeap.h b/mailnews/db/mork/src/orkinHeap.h index ba25fbb2fb26..479a2fc15994 100644 --- a/mailnews/db/mork/src/orkinHeap.h +++ b/mailnews/db/mork/src/orkinHeap.h @@ -38,8 +38,8 @@ public: virtual ~orkinHeap(); // does nothing private: // copying is not allowed - orkinHeap(const morkHandle& other); - orkinHeap& operator=(const morkHandle& other); + orkinHeap(const orkinHeap& other); + orkinHeap& operator=(const orkinHeap& other); public: diff --git a/mailnews/db/mork/src/orkinPortTableCursor.cpp b/mailnews/db/mork/src/orkinPortTableCursor.cpp index bcaba54a8ae3..48a8bc978b5d 100644 --- a/mailnews/db/mork/src/orkinPortTableCursor.cpp +++ b/mailnews/db/mork/src/orkinPortTableCursor.cpp @@ -97,7 +97,8 @@ orkinPortTableCursor::CanUsePortTableCursor(nsIMdbEnv* mev, if ( ev ) { morkPortTableCursor* self = (morkPortTableCursor*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kPortTableCursor); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kPortTableCursor, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsPortTableCursor() ) diff --git a/mailnews/db/mork/src/orkinRow.cpp b/mailnews/db/mork/src/orkinRow.cpp index e0ccd83afd5a..2f3be117c67e 100644 --- a/mailnews/db/mork/src/orkinRow.cpp +++ b/mailnews/db/mork/src/orkinRow.cpp @@ -120,7 +120,8 @@ orkinRow::CanUseRow(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkRowObject* rowObj = (morkRowObject*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kRow); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kRow, + /*inClosedOkay*/ morkBool_kFalse); if ( rowObj ) { if ( rowObj->IsRowObject() ) diff --git a/mailnews/db/mork/src/orkinRowCellCursor.cpp b/mailnews/db/mork/src/orkinRowCellCursor.cpp index 465b47c82a50..592c5bb89575 100644 --- a/mailnews/db/mork/src/orkinRowCellCursor.cpp +++ b/mailnews/db/mork/src/orkinRowCellCursor.cpp @@ -104,7 +104,8 @@ orkinRowCellCursor::CanUseRowCellCursor(nsIMdbEnv* mev, mork_bool inMutable, if ( ev ) { morkRowCellCursor* self = (morkRowCellCursor*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kRowCellCursor); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kRowCellCursor, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsRowCellCursor() ) diff --git a/mailnews/db/mork/src/orkinStore.cpp b/mailnews/db/mork/src/orkinStore.cpp index 2bca3563d145..df5f4984943b 100644 --- a/mailnews/db/mork/src/orkinStore.cpp +++ b/mailnews/db/mork/src/orkinStore.cpp @@ -68,9 +68,9 @@ #include "morkThumb.h" #endif -#ifndef _MORKFILE_ -#include "morkFile.h" -#endif +// #ifndef _MORKFILE_ +// #include "morkFile.h" +// #endif #ifndef _ORKINTHUMB_ #include "orkinThumb.h" @@ -119,7 +119,8 @@ orkinStore::CanUseStore(nsIMdbEnv* mev, if ( ev ) { morkStore* self = (morkStore*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kStore); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kStore, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsStore() ) @@ -373,7 +374,46 @@ orkinStore::GetPortFilePath( morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + morkStore* store = (morkStore*) mHandle_Object; + nsIMdbFile* file = store->mStore_File; + + if ( file ) + file->Path(mev, outFilePath); + else + store->NilStoreFileError(ev); + + outErr = ev->AsErr(); + } + return outErr; +} + +/*virtual*/ mdb_err +orkinStore::GetPortFile( + nsIMdbEnv* mev, // context + nsIMdbFile** acqFile) // acquire file used by port or store +{ + mdb_err outErr = 0; + if ( acqFile ) + *acqFile = 0; + + morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); + if ( ev ) + { + morkStore* store = (morkStore*) mHandle_Object; + nsIMdbFile* file = store->mStore_File; + + if ( file ) + { + if ( acqFile ) + { + file->AddStrongRef(mev); + if ( ev->Good() ) + *acqFile = file; + } + } + else + store->NilStoreFileError(ev); + outErr = ev->AsErr(); } return outErr; @@ -421,19 +461,25 @@ orkinStore::CanExportToFormat( // can export content in given specific format? /*virtual*/ mdb_err orkinStore::ExportToFormat( // export content in given specific format nsIMdbEnv* mev, // context - const char* inFilePath, // the file to receive exported content + // const char* inFilePath, // the file to receive exported content + nsIMdbFile* ioFile, // destination abstract file interface const char* inFormatVersion, // file format description nsIMdbThumb** acqThumb) // acquire thumb for incremental export // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and // then the export will be finished. { - MORK_USED_2(inFilePath,inFormatVersion); mdb_err outErr = 0; nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + if ( ioFile && inFormatVersion && acqThumb ) + { + ev->StubMethodOnlyError(); + } + else + ev->NilPointerError(); + outErr = ev->AsErr(); } if ( acqThumb ) @@ -995,6 +1041,33 @@ orkinStore::ImportContent( // import content from port *acqThumb = outThumb; return outErr; } + +/*virtual*/ mdb_err +orkinStore::ImportFile( // import content from port + nsIMdbEnv* mev, // context + nsIMdbFile* ioFile, // the file with content to add to store + nsIMdbThumb** acqThumb) // acquire thumb for incremental import +// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and +// then the import will be finished. +{ + nsIMdbThumb* outThumb = 0; + mdb_err outErr = 0; + morkEnv* ev = this->CanUseStore(mev, /*inMutable*/ morkBool_kFalse, &outErr); + if ( ev ) + { + if ( ioFile && acqThumb ) + { + ev->StubMethodOnlyError(); + } + else + ev->NilPointerError(); + + outErr = ev->AsErr(); + } + if ( acqThumb ) + *acqThumb = outThumb; + return outErr; +} // } ----- end inport/export methods ----- // { ----- begin hinting methods ----- @@ -1065,8 +1138,8 @@ orkinStore::LargeCommit( // save important changes if at all possible nsIMdbHeap* heap = store->mPort_Heap; morkThumb* thumb = 0; - morkFile* file = store->mStore_File; - if ( file && file->Length(ev) > 128 && store->mStore_CanWriteIncremental ) + // morkFile* file = store->mStore_File; + if ( store->DoPreferLargeOverCompressCommit(ev) ) { thumb = morkThumb::Make_LargeCommit(ev, heap, store); } @@ -1107,8 +1180,7 @@ orkinStore::SessionCommit( // save all changes if large commits delayed nsIMdbHeap* heap = store->mPort_Heap; morkThumb* thumb = 0; - morkFile* file = store->mStore_File; - if ( file && file->Length(ev) > 128 && store->mStore_CanWriteIncremental ) + if ( store->DoPreferLargeOverCompressCommit(ev) ) { thumb = morkThumb::Make_LargeCommit(ev, heap, store); } diff --git a/mailnews/db/mork/src/orkinStore.h b/mailnews/db/mork/src/orkinStore.h index 52039c2e3de6..6b2937e9de6d 100644 --- a/mailnews/db/mork/src/orkinStore.h +++ b/mailnews/db/mork/src/orkinStore.h @@ -163,6 +163,10 @@ public: // type identification nsIMdbEnv* ev, // context mdbYarn* outFilePath, // name of file holding port content mdbYarn* outFormatVersion); // file format description + + virtual mdb_err GetPortFile( + nsIMdbEnv* ev, // context + nsIMdbFile** acqFile); // acquire file used by port or store // } ----- end filepath methods ----- // { ----- begin export methods ----- @@ -178,7 +182,8 @@ public: // type identification virtual mdb_err ExportToFormat( // export content in given specific format nsIMdbEnv* ev, // context - const char* inFilePath, // the file to receive exported content + // const char* inFilePath, // the file to receive exported content + nsIMdbFile* ioFile, // destination abstract file interface const char* inFormatVersion, // file format description nsIMdbThumb** acqThumb); // acquire thumb for incremental export // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and @@ -424,6 +429,13 @@ public: // type identification nsIMdbThumb** acqThumb); // acquire thumb for incremental import // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and // then the import will be finished. + + virtual mdb_err ImportFile( // import content from port + nsIMdbEnv* ev, // context + nsIMdbFile* ioFile, // the file with content to add to store + nsIMdbThumb** acqThumb); // acquire thumb for incremental import + // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and + // then the import will be finished. // } ----- end inport/export methods ----- // { ----- begin hinting methods ----- diff --git a/mailnews/db/mork/src/orkinTable.cpp b/mailnews/db/mork/src/orkinTable.cpp index c9145e6bf9d8..1e56cf3ff5b2 100644 --- a/mailnews/db/mork/src/orkinTable.cpp +++ b/mailnews/db/mork/src/orkinTable.cpp @@ -111,7 +111,8 @@ orkinTable::CanUseTable(nsIMdbEnv* mev, if ( ev ) { morkTable* self = (morkTable*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kTable); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kTable, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsTable() ) @@ -557,7 +558,7 @@ orkinTable::GetTableRowCursor( // make a cursor, starting iteration at inRowPos { if ( ev->Good() ) { - cursor->mCursor_Seed = (mork_seed) inRowPos; + // cursor->mCursor_Seed = (mork_seed) inRowPos; outCursor = cursor->AcquireTableRowCursorHandle(ev); } else @@ -845,15 +846,13 @@ orkinTable::CutAllRows( // remove all rows from the table // { ----- begin searching methods ----- /*virtual*/ mdb_err -orkinTable::SearchOneSortedColumn( // search only currently sorted col +orkinTable::FindRowMatches( // search variable number of sorted cols nsIMdbEnv* mev, // context const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbRange* outRange) // range of matching rows + nsIMdbTableRowCursor** acqCursor) // set of matching rows { MORK_USED_1(inPrefix); - mdbRange range; - range.mRange_FirstPos = -1; - range.mRange_LastPos = -1; + nsIMdbTableRowCursor* outCursor = 0; mdb_err outErr = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) @@ -861,23 +860,31 @@ orkinTable::SearchOneSortedColumn( // search only currently sorted col ev->StubMethodOnlyError(); outErr = ev->AsErr(); } - if ( outRange ) - *outRange = range; + if ( acqCursor ) + *acqCursor = outCursor; return outErr; } /*virtual*/ mdb_err -orkinTable::SearchManyColumns( // search variable number of sorted cols +orkinTable::GetSearchColumns( // query columns used by FindRowMatches() nsIMdbEnv* mev, // context - const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbSearch* ioSearch, // columns to search and resulting ranges - nsIMdbThumb** acqThumb) // acquire thumb for incremental search -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then the search will be finished. Until that time, the ioSearch argument -// is assumed referenced and used by the thumb; one should not inspect any -// output results in ioSearch until after the thumb is finished with it. + 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. { - MORK_USED_2(inPrefix,ioSearch); + MORK_USED_1(outColSet); + mdb_count count = 0; mdb_err outErr = 0; nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); @@ -886,8 +893,8 @@ orkinTable::SearchManyColumns( // search variable number of sorted cols ev->StubMethodOnlyError(); outErr = ev->AsErr(); } - if ( acqThumb ) - *acqThumb = outThumb; + if ( outCount ) + *outCount = count; return outErr; } // } ----- end searching methods ----- @@ -975,20 +982,18 @@ orkinTable::EndBatchChangeHint( // advise before many adds and cuts // sort following the primary column sort, when table rows are sorted. /*virtual*/ mdb_err -orkinTable::CanSortColumn( // query which col is currently used for sorting +orkinTable::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 { MORK_USED_1(inColumn); - mdb_bool canSort = morkBool_kFalse; + mdb_bool canSort = mdbBool_kFalse; mdb_err outErr = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( outCanSort ) - *outCanSort = morkBool_kFalse; - + // ev->StubMethodOnlyError(); outErr = ev->AsErr(); } if ( outCanSort ) @@ -997,121 +1002,70 @@ orkinTable::CanSortColumn( // query which col is currently used for sorting } /*virtual*/ mdb_err -orkinTable::NewSortColumn( // change col used for sorting in the table +orkinTable::GetSorting( // view same table in particular sorting nsIMdbEnv* mev, // context mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort + nsIMdbSorting** acqSorting) // acquire sorting for column { MORK_USED_1(inColumn); - mdb_column actualColumn = 0; + nsIMdbSorting* outSorting = 0; mdb_err outErr = 0; - nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { ev->StubMethodOnlyError(); outErr = ev->AsErr(); } - if ( outActualColumn ) - *outActualColumn = actualColumn; - if ( acqThumb ) - *acqThumb = outThumb; - return outErr; -} -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then the sort will be finished. - -/*virtual*/ mdb_err -orkinTable::NewSortColumnWithCompare( // change sort col w/ explicit compare - nsIMdbEnv* mev, // context - nsIMdbCompare* ioCompare, // explicit interface for yarn comparison - mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb) // acquire thumb for incremental table resort -{ - MORK_USED_2(inColumn,ioCompare); - mdb_column actualColumn = 0; - mdb_err outErr = 0; - nsIMdbThumb* outThumb = 0; - morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - if ( outActualColumn ) - *outActualColumn = actualColumn; - if ( acqThumb ) - *acqThumb = outThumb; - return outErr; -} -// Note the table will hold a reference to inCompare if this object is used -// to sort the table. Until the table closes, callers can only force release -// of the compare object by changing the sort (by say, changing to unsorted). -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then the sort will be finished. - -/*virtual*/ mdb_err -orkinTable::GetSortColumn( // query which col is currently sorted - nsIMdbEnv* mev, // context - mdb_column* outColumn) // col the table uses for sorting (or zero) -{ - mdb_err outErr = 0; - mdb_column col = 0; - morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - if ( outColumn ) - *outColumn = col; + if ( acqSorting ) + *acqSorting = outSorting; return outErr; } - /*virtual*/ mdb_err -orkinTable::CloneSortColumn( // view same table with a different sort +orkinTable::SetSearchSorting( // use this sorting in FindRowMatches() nsIMdbEnv* mev, // context - mdb_column inColumn, // requested new column for sorting table - nsIMdbThumb** acqThumb) // acquire thumb for incremental table clone + 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 searchs. 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). { MORK_USED_1(inColumn); mdb_err outErr = 0; - nsIMdbThumb* outThumb = 0; morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + if ( ioSorting ) + { + ev->StubMethodOnlyError(); + } + else + ev->NilPointerError(); + outErr = ev->AsErr(); } - if ( acqThumb ) - *acqThumb = outThumb; - return outErr; -} -// Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and -// then call nsIMdbTable::ThumbToCloneSortTable() to get the table instance. - -/*virtual*/ mdb_err -orkinTable::ThumbToCloneSortTable( // redeem complete CloneSortColumn() thumb - nsIMdbEnv* mev, // context - nsIMdbThumb* ioThumb, // thumb from CloneSortColumn() with done status - nsIMdbTable** acqTable) // new table instance (or old if sort unchanged) -{ - MORK_USED_1(ioThumb); - mdb_err outErr = 0; - nsIMdbTable* outTable = 0; - morkEnv* ev = this->CanUseTable(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - if ( acqTable ) - *acqTable = outTable; return outErr; } + // } ----- end sorting methods ----- // { ----- begin moving methods ----- diff --git a/mailnews/db/mork/src/orkinTable.h b/mailnews/db/mork/src/orkinTable.h index 970697dec43f..f8da60e90557 100644 --- a/mailnews/db/mork/src/orkinTable.h +++ b/mailnews/db/mork/src/orkinTable.h @@ -60,8 +60,8 @@ protected: // construction is protected (use the static Make() method) // void CloseHandle(morkEnv* ev); // don't need to specialize closing private: // copying is not allowed - orkinTable(const morkHandle& other); - orkinTable& operator=(const morkHandle& other); + orkinTable(const orkinTable& other); + orkinTable& operator=(const orkinTable& other); // public: // dynamic type identification // mork_bool IsHandle() const // @@ -273,23 +273,6 @@ public: // type identification nsIMdbEnv* ev); // context // } ----- end row set methods ----- - // { ----- begin searching methods ----- - virtual mdb_err SearchOneSortedColumn( // search only currently sorted col - nsIMdbEnv* ev, // context - const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbRange* outRange); // range of matching rows - - virtual mdb_err SearchManyColumns( // search variable number of sorted cols - nsIMdbEnv* ev, // context - const mdbYarn* inPrefix, // content to find as prefix in row's column cell - mdbSearch* ioSearch, // columns to search and resulting ranges - nsIMdbThumb** acqThumb); // acquire thumb for incremental search - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then the search will be finished. Until that time, the ioSearch argument - // is assumed referenced and used by the thumb; one should not inspect any - // output results in ioSearch until after the thumb is finished with it. - // } ----- end searching methods ----- - // { ----- begin hinting methods ----- virtual mdb_err SearchColumnsHint( // advise re future expected search cols nsIMdbEnv* ev, // context @@ -319,6 +302,30 @@ public: // type identification // a surprise request occurs for row position during batch changes. // } ----- end hinting methods ----- + // { ----- begin searching methods ----- + virtual mdb_err FindRowMatches( // search variable number of sorted cols + nsIMdbEnv* ev, // context + const mdbYarn* inPrefix, // content to find as prefix in row's column cell + nsIMdbTableRowCursor** acqCursor); // set of matching rows + + virtual mdb_err GetSearchColumns( // query columns used by FindRowMatches() + nsIMdbEnv* ev, // 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. + // } ----- end searching 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. @@ -328,46 +335,38 @@ public: // type identification nsIMdbEnv* ev, // context mdb_column inColumn, // column to query sorting potential mdb_bool* outCanSort); // whether the column can be sorted - - virtual mdb_err - NewSortColumn( // change the column used for sorting in the table - nsIMdbEnv* ev, // context - mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb); // acquire thumb for incremental table resort - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then the sort will be finished. - - virtual mdb_err - NewSortColumnWithCompare( // change sort column with explicit compare - nsIMdbEnv* ev, // context - nsIMdbCompare* ioCompare, // explicit interface for yarn comparison - mdb_column inColumn, // requested new column for sorting table - mdb_column* outActualColumn, // column actually used for sorting - nsIMdbThumb** acqThumb); // acquire thumb for incremental table resort - // Note the table will hold a reference to inCompare if this object is used - // to sort the table. Until the table closes, callers can only force release - // of the compare object by changing the sort (by say, changing to unsorted). - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then the sort will be finished. - - virtual mdb_err GetSortColumn( // query which col is currently sorted - nsIMdbEnv* ev, // context - mdb_column* outColumn); // col the table uses for sorting (or zero) - - - virtual mdb_err CloneSortColumn( // view same table with a different sort - nsIMdbEnv* ev, // context - mdb_column inColumn, // requested new column for sorting table - nsIMdbThumb** acqThumb); // acquire thumb for incremental table clone - // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and - // then call nsIMdbTable::ThumbToCloneSortTable() to get the table instance. - virtual mdb_err - ThumbToCloneSortTable( // redeem complete CloneSortColumn() thumb + virtual mdb_err GetSorting( // view same table in particular sorting nsIMdbEnv* ev, // context - nsIMdbThumb* ioThumb, // thumb from CloneSortColumn() with done status - nsIMdbTable** acqTable); // new table instance (or old if sort unchanged) + mdb_column inColumn, // requested new column for sorting table + nsIMdbSorting** acqSorting); // acquire sorting for column + + virtual mdb_err SetSearchSorting( // use this sorting in FindRowMatches() + nsIMdbEnv* ev, // 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 searchs. 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). // } ----- end sorting methods ----- // { ----- begin moving methods ----- diff --git a/mailnews/db/mork/src/orkinTableRowCursor.cpp b/mailnews/db/mork/src/orkinTableRowCursor.cpp index 886c3ac08194..89a7ffa3e02e 100644 --- a/mailnews/db/mork/src/orkinTableRowCursor.cpp +++ b/mailnews/db/mork/src/orkinTableRowCursor.cpp @@ -109,7 +109,8 @@ orkinTableRowCursor::CanUseTableRowCursor(nsIMdbEnv* mev, if ( ev ) { morkTableRowCursor* self = (morkTableRowCursor*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kTableRowCursor); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kTableRowCursor, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsTableRowCursor() ) @@ -235,8 +236,7 @@ orkinTableRowCursor::GetCount(nsIMdbEnv* mev, mdb_count* outCount) if ( ev ) { morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; - morkTable* table = cursor->mTableRowCursor_Table; - count = table->mTable_RowArray.mArray_Fill; + count = cursor->GetMemberCount(ev); outErr = ev->AsErr(); } if ( outCount ) @@ -303,7 +303,8 @@ orkinTableRowCursor::SetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool inFail) this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; + cursor->mCursor_DoFailOnSeedOutOfSync = inFail; outErr = ev->AsErr(); } return outErr; @@ -318,7 +319,8 @@ orkinTableRowCursor::GetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool* outFail) this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; + fail = cursor->mCursor_DoFailOnSeedOutOfSync; outErr = ev->AsErr(); } if ( outFail ) @@ -333,20 +335,6 @@ orkinTableRowCursor::GetDoFailOnSeedOutOfSync(nsIMdbEnv* mev, mdb_bool* outFail) // { ===== begin nsIMdbTableRowCursor methods ===== // { ----- begin attribute methods ----- -/*virtual*/ mdb_err -orkinTableRowCursor::SetTable(nsIMdbEnv* mev, nsIMdbTable* ioTable) -{ - MORK_USED_1(ioTable); - mdb_err outErr = 0; - morkEnv* ev = - this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); - if ( ev ) - { - ev->StubMethodOnlyError(); - outErr = ev->AsErr(); - } - return outErr; -} /*virtual*/ mdb_err orkinTableRowCursor::GetTable(nsIMdbEnv* mev, nsIMdbTable** acqTable) @@ -428,67 +416,71 @@ orkinTableRowCursor::NextRow( // get row cells from table for cells already in r } // } ----- end row iteration methods ----- -// { ----- begin copy iteration methods ----- + +// { ----- begin duplicate row removal methods ----- /*virtual*/ mdb_err -orkinTableRowCursor::NextRowCopy( // put row cells into sink only when already in sink - nsIMdbEnv* mev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos) +orkinTableRowCursor::CanHaveDupRowMembers(nsIMdbEnv* mev, // cursor might hold dups? + mdb_bool* outCanHaveDups) { - MORK_USED_1(ioSinkRow); - mdbOid oid; - oid.mOid_Scope = 0; - oid.mOid_Id = (mork_id) -1; - mdb_pos rowPos = -1; mdb_err outErr = 0; + mdb_bool canHaveDups = mdbBool_kFalse; + morkEnv* ev = this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - if ( outOid ) - { - ev->StubMethodOnlyError(); - } - else - ev->NilPointerError(); + morkTableRowCursor* cursor = (morkTableRowCursor*) mHandle_Object; + canHaveDups = cursor->CanHaveDupRowMembers(ev); outErr = ev->AsErr(); } - if ( outRowPos ) - *outRowPos = rowPos; - if ( outOid ) - *outOid = oid; + if ( outCanHaveDups ) + *outCanHaveDups = canHaveDups; return outErr; } - + /*virtual*/ mdb_err -orkinTableRowCursor::NextRowCopyAll( // put all row cells into sink, adding to sink +orkinTableRowCursor::MakeUniqueCursor( // clone cursor, removing duplicate rows nsIMdbEnv* mev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos) + nsIMdbTableRowCursor** acqCursor) // acquire clone with no dups + // Note that MakeUniqueCursor() is never necessary for a cursor which was + // created by table method nsIMdbTable::GetTableRowCursor(), because a table + // never contains the same row as a member more than once. However, a cursor + // created by table method nsIMdbTable::FindRowMatches() might contain the + // same row more than once, because the same row can generate a hit by more + // than one column with a matching string prefix. Note this method can + // return the very same cursor instance with just an incremented refcount, + // when the original cursor could not contain any duplicate rows (calling + // CanHaveDupRowMembers() shows this case on a false return). Otherwise + // this method returns a different cursor instance. Callers should not use + // this MakeUniqueCursor() method lightly, because it tends to defeat the + // purpose of lazy programming techniques, since it can force creation of + // an explicit row collection in a new cursor's representation, in order to + // inspect the row membership and remove any duplicates; this can have big + // impact if a collection holds tens of thousands of rows or more, when + // the original cursor with dups simply referenced rows indirectly by row + // position ranges, without using an explicit row set representation. + // Callers are encouraged to use nsIMdbCursor::GetCount() to determine + // whether the row collection is very large (tens of thousands), and to + // delay calling MakeUniqueCursor() when possible, until a user interface + // element actually demands the creation of an explicit set representation. { - MORK_USED_1(ioSinkRow); - mdbOid oid; - oid.mOid_Scope = 0; - oid.mOid_Id = (mork_id) -1; - mdb_pos rowPos = -1; mdb_err outErr = 0; + nsIMdbTableRowCursor* outCursor = 0; + morkEnv* ev = this->CanUseTableRowCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr); if ( ev ) { - ev->StubMethodOnlyError(); + if ( this->Handle_AddStrongRef(mev) == 0 ) + outCursor = this; + outErr = ev->AsErr(); } - if ( outRowPos ) - *outRowPos = rowPos; - if ( outOid ) - *outOid = oid; + if ( acqCursor ) + *acqCursor = outCursor; return outErr; -} // nonzero if child, and a row child - -// } ----- end copy iteration methods ----- +} +// } ----- end duplicate row removal methods ----- // } ===== end nsIMdbTableRowCursor methods ===== diff --git a/mailnews/db/mork/src/orkinTableRowCursor.h b/mailnews/db/mork/src/orkinTableRowCursor.h index bdbb4a04dad5..e0ee48673b87 100644 --- a/mailnews/db/mork/src/orkinTableRowCursor.h +++ b/mailnews/db/mork/src/orkinTableRowCursor.h @@ -150,7 +150,6 @@ public: // type identification // { ===== begin nsIMdbTableRowCursor methods ===== // { ----- begin attribute methods ----- - virtual mdb_err SetTable(nsIMdbEnv* ev, nsIMdbTable* ioTable); // sets pos to -1 virtual mdb_err GetTable(nsIMdbEnv* ev, nsIMdbTable** acqTable); // } ----- end attribute methods ----- @@ -168,19 +167,35 @@ public: // type identification mdb_pos* outRowPos); // zero-based position of the row in table // } ----- end row iteration methods ----- - // { ----- begin copy iteration methods ----- - virtual mdb_err NextRowCopy( // put row cells into sink only when already in sink + // { ----- begin duplicate row removal methods ----- + virtual mdb_err CanHaveDupRowMembers(nsIMdbEnv* ev, // cursor might hold dups? + mdb_bool* outCanHaveDups); + + virtual mdb_err MakeUniqueCursor( // clone cursor, removing duplicate rows nsIMdbEnv* ev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos); // zero-based position of the row in table - - virtual mdb_err NextRowCopyAll( // put all row cells into sink, adding to sink - nsIMdbEnv* ev, // context - nsIMdbRow* ioSinkRow, // sink for row cells read from next row - mdbOid* outOid, // out row oid - mdb_pos* outRowPos); // zero-based position of the row in table - // } ----- end copy iteration methods ----- + nsIMdbTableRowCursor** acqCursor); // acquire clone with no dups + // Note that MakeUniqueCursor() is never necessary for a cursor which was + // created by table method nsIMdbTable::GetTableRowCursor(), because a table + // never contains the same row as a member more than once. However, a cursor + // created by table method nsIMdbTable::FindRowMatches() might contain the + // same row more than once, because the same row can generate a hit by more + // than one column with a matching string prefix. Note this method can + // return the very same cursor instance with just an incremented refcount, + // when the original cursor could not contain any duplicate rows (calling + // CanHaveDupRowMembers() shows this case on a false return). Otherwise + // this method returns a different cursor instance. Callers should not use + // this MakeUniqueCursor() method lightly, because it tends to defeat the + // purpose of lazy programming techniques, since it can force creation of + // an explicit row collection in a new cursor's representation, in order to + // inspect the row membership and remove any duplicates; this can have big + // impact if a collection holds tens of thousands of rows or more, when + // the original cursor with dups simply referenced rows indirectly by row + // position ranges, without using an explicit row set representation. + // Callers are encouraged to use nsIMdbCursor::GetCount() to determine + // whether the row collection is very large (tens of thousands), and to + // delay calling MakeUniqueCursor() when possible, until a user interface + // element actually demands the creation of an explicit set representation. + // } ----- end duplicate row removal methods ----- // } ===== end nsIMdbTableRowCursor methods ===== }; diff --git a/mailnews/db/mork/src/orkinThumb.cpp b/mailnews/db/mork/src/orkinThumb.cpp index 9e0d11d14b14..179d6975271b 100644 --- a/mailnews/db/mork/src/orkinThumb.cpp +++ b/mailnews/db/mork/src/orkinThumb.cpp @@ -87,7 +87,8 @@ orkinThumb::CanUseThumb(nsIMdbEnv* mev, if ( ev ) { morkThumb* self = (morkThumb*) - this->GetGoodHandleObject(ev, inMutable, morkMagic_kThumb); + this->GetGoodHandleObject(ev, inMutable, morkMagic_kThumb, + /*inClosedOkay*/ morkBool_kFalse); if ( self ) { if ( self->IsThumb() )