Back to index

lightning-sunbird  0.9+nobinonly
orkinFactory.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef _MDB_
00039 #include "mdb.h"
00040 #endif
00041 
00042 #ifndef _MORK_
00043 #include "mork.h"
00044 #endif
00045 
00046 #ifndef _MORKNODE_
00047 #include "morkNode.h"
00048 #endif
00049 
00050 #ifndef _MORKHANDLE_
00051 #include "morkHandle.h"
00052 #endif
00053 
00054 #ifndef _MORKENV_
00055 #include "morkEnv.h"
00056 #endif
00057 
00058 #ifndef _MORKFACTORY_
00059 #include "morkFactory.h"
00060 #endif
00061 
00062 #ifndef _ORKINFACTORY_
00063 #include "orkinFactory.h"
00064 #endif
00065 
00066 #ifndef _ORKINENV_
00067 #include "orkinEnv.h"
00068 #endif
00069 
00070 #ifndef _MORKROW_
00071 #include "morkRow.h"
00072 #endif
00073 
00074 #ifndef _ORKINROW_
00075 #include "orkinRow.h"
00076 #endif
00077 
00078 #ifndef _MORKFILE_
00079 #include "morkFile.h"
00080 #endif
00081 
00082 #ifndef _MORKWRITER_
00083 #include "morkWriter.h"
00084 #endif
00085 
00086 #ifndef _MORKSTORE_
00087 #include "morkStore.h"
00088 #endif
00089 
00090 #ifndef _ORKINSTORE_
00091 #include "orkinStore.h"
00092 #endif
00093 
00094 #ifndef _ORKINTHUMB_
00095 #include "orkinThumb.h"
00096 #endif
00097 
00098 #ifndef _MORKTHUMB_
00099 #include "morkThumb.h"
00100 #endif
00101 
00102 #ifndef _ORKINHEAP_
00103 #include "orkinHeap.h"
00104 #endif
00105 
00106 #ifndef _ORKINCOMPARE_
00107 #include "orkinCompare.h"
00108 #endif
00109 
00110 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00111 
00112 /* public virtual*/
00113 orkinFactory:: ~orkinFactory() // morkHandle destructor does everything
00114 {
00115 }
00116 
00117 /*protected non-poly construction*/
00118 orkinFactory::orkinFactory(morkEnv* ev, // morkUsage is morkUsage_kPool
00119     morkHandleFace* ioFace,    // must not be nil, cookie for this handle
00120     morkFactory* ioObject)  // must not be nil, object for this handle
00121 : morkHandle(ev, ioFace, ioObject, morkMagic_kFactory)
00122 {
00123   // do not modify mNode_Derived; leave it equal to morkDerived_kHandle
00124 }
00125 
00126 extern "C" nsIMdbFactory* MakeMdbFactory() 
00127 {
00128   return orkinFactory::MakeGlobalFactory();
00129 }
00130 
00131 /*static */ orkinFactory*
00132 orkinFactory::MakeGlobalFactory()
00133 // instantiate objects using almost no context information.
00134 {
00135   morkFactory* factory = new morkFactory(new orkinHeap());
00136   MORK_ASSERT(factory);
00137   if ( factory )
00138     return orkinFactory::MakeFactory(&factory->mFactory_Env, factory);
00139   else
00140     return (orkinFactory*) 0;
00141 }
00142 
00143 /*static */ orkinFactory*
00144 orkinFactory::MakeFactory(morkEnv* ev,  morkFactory* ioObject)
00145 {
00146   mork_bool isEnv = ev->IsEnv();
00147   MORK_ASSERT(isEnv);
00148   if ( isEnv )
00149   {
00150     morkHandleFace* face = ev->NewHandle(sizeof(orkinFactory));
00151     if ( face )
00152     {
00153       orkinFactory* f = new(face) orkinFactory(ev, face, ioObject);
00154       if ( f )
00155         f->mNode_Refs += morkFactory_kWeakRefCountBonus;
00156       return f;
00157     }
00158     else
00159       ev->OutOfMemoryError();
00160   }
00161     
00162   return (orkinFactory*) 0;
00163 }
00164 
00165 morkEnv*
00166 orkinFactory::CanUseFactory(nsIMdbEnv* mev, mork_bool inMutable,
00167   mdb_err* outErr) const
00168 {
00169   morkEnv* outEnv = 0;
00170   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00171   if ( ev )
00172   {
00173     morkFactory* factory = (morkFactory*)
00174       this->GetGoodHandleObject(ev, inMutable, morkMagic_kFactory,
00175         /*inClosedOkay*/ morkBool_kFalse);
00176     if ( factory )
00177     {
00178       if ( factory->IsFactory() )
00179         outEnv = ev;
00180       else
00181         factory->NonFactoryTypeError(ev);
00182     }
00183     *outErr = ev->AsErr();
00184   }
00185   MORK_ASSERT(outEnv);
00186   return outEnv;
00187 }
00188 
00189 morkEnv* orkinFactory::GetInternalFactoryEnv(mdb_err* outErr)
00190 {
00191   morkEnv* outEnv = 0;
00192   morkFactory* f = (morkFactory*) this->mHandle_Object;
00193   if ( f && f->IsNode() && f->IsOpenNode() && f->IsFactory() )
00194   {
00195     morkEnv* fenv = &f->mFactory_Env;
00196     if ( fenv && fenv->IsNode() && fenv->IsOpenNode() && fenv->IsEnv() )
00197     {
00198       fenv->ClearMorkErrorsAndWarnings(); // drop any earlier errors
00199       outEnv = fenv;
00200     }
00201     else
00202       *outErr = morkEnv_kBadFactoryEnvError;
00203   }
00204   else
00205     *outErr = morkEnv_kBadFactoryError;
00206     
00207   return outEnv;
00208 }
00209 
00210 // { ===== begin nsIMdbISupports methods =====
00211 NS_IMPL_QUERY_INTERFACE0(orkinFactory)
00212 
00213 /*virtual*/ nsrefcnt
00214 orkinFactory::AddRef() // add strong ref with no
00215 {
00216   morkEnv* ev = mHandle_Env;
00217   if ( ev && ev->IsEnv() )
00218     return this->Handle_AddStrongRef(ev->AsMdbEnv());
00219   else
00220     return morkEnv_kNonEnvTypeError;
00221 }
00222 
00223 /*virtual*/ nsrefcnt
00224 orkinFactory::Release() // cut strong ref
00225 {
00226   morkEnv* ev = mHandle_Env;
00227   if ( ev && ev->IsEnv() )
00228     return this->Handle_CutStrongRef(ev->AsMdbEnv());
00229   else
00230     return morkEnv_kNonEnvTypeError;
00231 }
00232 // } ===== end nsIMdbObject methods =====
00233 
00234 
00235 // { ===== begin nsIMdbObject methods =====
00236 
00237 // { ----- begin attribute methods -----
00238 /*virtual*/ mdb_err
00239 orkinFactory::IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly)
00240 {
00241   return this->Handle_IsFrozenMdbObject(mev, outIsReadonly);
00242 }
00243 // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
00244 // } ----- end attribute methods -----
00245 
00246 // { ----- begin factory methods -----
00247 /*virtual*/ mdb_err
00248 orkinFactory::GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory)
00249 {
00250   return this->Handle_GetMdbFactory(mev, acqFactory);
00251 } 
00252 // } ----- end factory methods -----
00253 
00254 // { ----- begin ref counting for well-behaved cyclic graphs -----
00255 /*virtual*/ mdb_err
00256 orkinFactory::GetWeakRefCount(nsIMdbEnv* mev, // weak refs
00257   mdb_count* outCount)
00258 {
00259   return this->Handle_GetWeakRefCount(mev, outCount);
00260 }  
00261 /*virtual*/ mdb_err
00262 orkinFactory::GetStrongRefCount(nsIMdbEnv* mev, // strong refs
00263   mdb_count* outCount)
00264 {
00265   return this->Handle_GetStrongRefCount(mev, outCount);
00266 }
00267 
00268 /*virtual*/ mdb_err
00269 orkinFactory::AddWeakRef(nsIMdbEnv* mev)
00270 {
00271   return this->Handle_AddWeakRef(mev);
00272 }
00273 /*virtual*/ mdb_err
00274 orkinFactory::AddStrongRef(nsIMdbEnv* mev)
00275 {
00276   return this->Handle_AddStrongRef(mev);
00277 }
00278 
00279 /*virtual*/ mdb_err
00280 orkinFactory::CutWeakRef(nsIMdbEnv* mev)
00281 {
00282   return this->Handle_CutWeakRef(mev);
00283 }
00284 /*virtual*/ mdb_err
00285 orkinFactory::CutStrongRef(nsIMdbEnv* mev)
00286 {
00287   return this->Handle_CutStrongRef(mev);
00288 }
00289 
00290 /*virtual*/ mdb_err
00291 orkinFactory::CloseMdbObject(nsIMdbEnv* mev)
00292 {
00293   return this->Handle_CloseMdbObject(mev);
00294 }
00295 
00296 /*virtual*/ mdb_err
00297 orkinFactory::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen)
00298 {
00299   return this->Handle_IsOpenMdbObject(mev, outOpen);
00300 }
00301 // } ----- end ref counting -----
00302 
00303 // } ===== end nsIMdbObject methods =====
00304 
00305 // { ===== begin nsIMdbFactory methods =====
00306 
00307 // { ----- begin file methods -----
00308 /*virtual*/ mdb_err
00309 orkinFactory::OpenOldFile(nsIMdbEnv* mev, nsIMdbHeap* ioHeap,
00310   const char* inFilePath,
00311   mork_bool inFrozen, nsIMdbFile** acqFile)
00312   // Choose some subclass of nsIMdbFile to instantiate, in order to read
00313   // (and write if not frozen) the file known by inFilePath.  The file
00314   // returned should be open and ready for use, and presumably positioned
00315   // at the first byte position of the file.  The exact manner in which
00316   // files must be opened is considered a subclass specific detail, and
00317   // other portions or Mork source code don't want to know how it's done.
00318 {
00319   mdb_err outErr = 0;
00320   nsIMdbFile* outFile = 0;
00321   morkEnv* ev = this->CanUseFactory(mev,
00322     /*inMutable*/ morkBool_kFalse, &outErr);
00323   morkFile* file = nsnull;
00324   if ( ev )
00325   {
00326     morkFactory* factory = (morkFactory*) this->mHandle_Object;
00327     if ( !ioHeap )
00328       ioHeap = &factory->mFactory_Heap;
00329       
00330     file = morkFile::OpenOldFile(ev, ioHeap, inFilePath, inFrozen);
00331     NS_IF_ADDREF( file );
00332       
00333     outErr = ev->AsErr();
00334   }
00335   if ( acqFile )
00336     *acqFile = file;
00337     
00338   return outErr;
00339 }
00340 
00341 /*virtual*/ mdb_err
00342 orkinFactory::CreateNewFile(nsIMdbEnv* mev, nsIMdbHeap* ioHeap,
00343   const char* inFilePath, nsIMdbFile** acqFile)
00344   // Choose some subclass of nsIMdbFile to instantiate, in order to read
00345   // (and write if not frozen) the file known by inFilePath.  The file
00346   // returned should be created and ready for use, and presumably positioned
00347   // at the first byte position of the file.  The exact manner in which
00348   // files must be opened is considered a subclass specific detail, and
00349   // other portions or Mork source code don't want to know how it's done.
00350 {
00351   mdb_err outErr = 0;
00352   nsIMdbFile* outFile = 0;
00353   morkEnv* ev = this->CanUseFactory(mev,
00354     /*inMutable*/ morkBool_kFalse, &outErr);
00355   morkFile* file = nsnull;
00356   if ( ev )
00357   {
00358     morkFactory* factory = (morkFactory*) this->mHandle_Object;
00359     if ( !ioHeap )
00360       ioHeap = &factory->mFactory_Heap;
00361       
00362     file = morkFile::CreateNewFile(ev, ioHeap, inFilePath);
00363     if ( file )
00364       NS_ADDREF(file);
00365       
00366     outErr = ev->AsErr();
00367   }
00368   if ( acqFile )
00369     *acqFile = file;
00370     
00371   return outErr;
00372 }
00373 // } ----- end file methods -----
00374 
00375 // { ----- begin env methods -----
00376 /*virtual*/ mdb_err
00377 orkinFactory::MakeEnv(nsIMdbHeap* ioHeap, nsIMdbEnv** acqEnv)
00378 // ioHeap can be nil, causing a MakeHeap() style heap instance to be used
00379 {
00380   mdb_err outErr = 0;
00381   nsIMdbEnv* outEnv = 0;
00382   mork_bool ownsHeap = (ioHeap == 0);
00383   if ( !ioHeap )
00384     ioHeap = new orkinHeap();
00385 
00386   if ( acqEnv && ioHeap )
00387   {
00388     morkEnv* fenv = this->GetInternalFactoryEnv(&outErr);
00389     if ( fenv )
00390     {
00391       morkFactory* factory = (morkFactory*) this->mHandle_Object;
00392       morkEnv* newEnv = new(*ioHeap, fenv)
00393         morkEnv(morkUsage::kHeap, ioHeap, factory, ioHeap);
00394 
00395       if ( newEnv )
00396       {
00397         newEnv->mEnv_OwnsHeap = ownsHeap;
00398         newEnv->mNode_Refs += morkEnv_kWeakRefCountEnvBonus;
00399         NS_ADDREF(newEnv);
00400         newEnv->mEnv_SelfAsMdbEnv = newEnv;
00401         outEnv = newEnv;
00402       }
00403       else
00404         outErr = morkEnv_kOutOfMemoryError;
00405     }
00406     
00407     *acqEnv = outEnv;
00408   }
00409   else
00410     outErr = morkEnv_kNilPointerError;
00411     
00412   return outErr;
00413 }
00414 // } ----- end env methods -----
00415 
00416 // { ----- begin heap methods -----
00417 /*virtual*/ mdb_err
00418 orkinFactory::MakeHeap(nsIMdbEnv* mev, nsIMdbHeap** acqHeap)
00419 {
00420   mdb_err outErr = 0;
00421   nsIMdbHeap* outHeap = 0;
00422   morkEnv* ev = this->CanUseFactory(mev,
00423     /*inMutable*/ morkBool_kFalse, &outErr);
00424   if ( ev )
00425   {
00426     outHeap = new orkinHeap();
00427     if ( !outHeap )
00428       ev->OutOfMemoryError();
00429   }
00430   MORK_ASSERT(acqHeap);
00431   if ( acqHeap )
00432     *acqHeap = outHeap;
00433   return outErr;
00434 }
00435 // } ----- end heap methods -----
00436 
00437 // { ----- begin compare methods -----
00438 /*virtual*/ mdb_err
00439 orkinFactory::MakeCompare(nsIMdbEnv* mev, nsIMdbCompare** acqCompare)
00440 {
00441   mdb_err outErr = 0;
00442   nsIMdbCompare* outCompare = 0;
00443   morkEnv* ev = this->CanUseFactory(mev,
00444     /*inMutable*/ morkBool_kFalse, &outErr);
00445   if ( ev )
00446   {
00447     NS_ASSERTION(PR_FALSE, "not implemented");
00448     outErr = NS_ERROR_NOT_IMPLEMENTED;
00449 //    outCompare = new orkinCompare();
00450     if ( !outCompare )
00451       ev->OutOfMemoryError();
00452   }
00453   if ( acqCompare )
00454     *acqCompare = outCompare;
00455   return outErr;
00456 }
00457 // } ----- end compare methods -----
00458 
00459 // { ----- begin row methods -----
00460 /*virtual*/ mdb_err
00461 orkinFactory::MakeRow(nsIMdbEnv* mev, nsIMdbHeap* ioHeap,
00462   nsIMdbRow** acqRow)
00463 {
00464   MORK_USED_1(ioHeap);
00465   mdb_err outErr = 0;
00466   nsIMdbRow* outRow = 0;
00467   morkEnv* ev = this->CanUseFactory(mev,
00468     /*inMutable*/ morkBool_kFalse, &outErr);
00469   if ( ev )
00470   {
00471     ev->StubMethodOnlyError();
00472     outErr = ev->AsErr();
00473   }
00474   if ( acqRow )
00475     *acqRow = outRow;
00476     
00477   return outErr;
00478 }
00479 // ioHeap can be nil, causing the heap associated with ev to be used
00480 // } ----- end row methods -----
00481 
00482 // { ----- begin port methods -----
00483 /*virtual*/ mdb_err
00484 orkinFactory::CanOpenFilePort(
00485   nsIMdbEnv* mev, // context
00486   // const char* inFilePath, // the file to investigate
00487   // const mdbYarn* inFirst512Bytes,
00488   nsIMdbFile* ioFile, // db abstract file interface
00489   mdb_bool* outCanOpen, // whether OpenFilePort() might succeed
00490   mdbYarn* outFormatVersion)
00491 {
00492   mdb_err outErr = 0;
00493   if ( outFormatVersion )
00494   {
00495     outFormatVersion->mYarn_Fill = 0;
00496   }
00497   mdb_bool canOpenAsPort = morkBool_kFalse;
00498   morkEnv* ev = this->CanUseFactory(mev,
00499     /*inMutable*/ morkBool_kFalse, &outErr);
00500   if ( ev )
00501   {
00502     if ( ioFile && outCanOpen )
00503     {
00504       canOpenAsPort = this->CanOpenMorkTextFile(ev, ioFile);
00505     }
00506     else
00507       ev->NilPointerError();
00508     
00509     outErr = ev->AsErr();
00510   }
00511     
00512   if ( outCanOpen )
00513     *outCanOpen = canOpenAsPort;
00514     
00515   return outErr;
00516 }
00517   
00518 /*virtual*/ mdb_err
00519 orkinFactory::OpenFilePort(
00520   nsIMdbEnv* mev, // context
00521   nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
00522   // const char* inFilePath, // the file to open for readonly import
00523   nsIMdbFile* ioFile, // db abstract file interface
00524   const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
00525   nsIMdbThumb** acqThumb)
00526 {
00527   MORK_USED_1(ioHeap);
00528   mdb_err outErr = 0;
00529   nsIMdbThumb* outThumb = 0;
00530   morkEnv* ev = this->CanUseFactory(mev,
00531     /*inMutable*/ morkBool_kFalse, &outErr);
00532   if ( ev )
00533   {
00534     if ( ioFile && inOpenPolicy && acqThumb )
00535     {
00536     }
00537     else
00538       ev->NilPointerError();
00539     
00540     outErr = ev->AsErr();
00541   }
00542   if ( acqThumb )
00543     *acqThumb = outThumb;
00544   return outErr;
00545 }
00546 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
00547 // then call nsIMdbFactory::ThumbToOpenPort() to get the port instance.
00548 
00549 /*virtual*/ mdb_err
00550 orkinFactory::ThumbToOpenPort( // redeeming a completed thumb from OpenFilePort()
00551   nsIMdbEnv* mev, // context
00552   nsIMdbThumb* ioThumb, // thumb from OpenFilePort() with done status
00553   nsIMdbPort** acqPort)
00554 {
00555   mdb_err outErr = 0;
00556   nsIMdbPort* outPort = 0;
00557   morkEnv* ev = this->CanUseFactory(mev,
00558     /*inMutable*/ morkBool_kFalse, &outErr);
00559   if ( ev )
00560   {
00561     if ( ioThumb && acqPort )
00562     {
00563       morkThumb* thumb = (morkThumb*) ioThumb;
00564       morkStore* store = thumb->ThumbToOpenStore(ev);
00565       if ( store )
00566       {
00567         store->mStore_CanAutoAssignAtomIdentity = morkBool_kTrue;
00568         store->mStore_CanDirty = morkBool_kTrue;
00569         store->SetStoreAndAllSpacesCanDirty(ev, morkBool_kTrue);
00570         
00571         NS_ADDREF(store);
00572         outPort = store;
00573       }
00574     }
00575     else
00576       ev->NilPointerError();
00577     
00578     outErr = ev->AsErr();
00579   }
00580   if ( acqPort )
00581     *acqPort = outPort;
00582   return outErr;
00583 }
00584 // } ----- end port methods -----
00585 
00586 mork_bool
00587 orkinFactory::CanOpenMorkTextFile(morkEnv* ev,
00588   // const mdbYarn* inFirst512Bytes,
00589   nsIMdbFile* ioFile)
00590 {
00591   MORK_USED_1(ev);
00592   mork_bool outBool = morkBool_kFalse;
00593   mork_size headSize = MORK_STRLEN(morkWriter_kFileHeader);
00594   
00595   char localBuf[ 256 + 4 ]; // for extra for sloppy safety
00596   mdbYarn localYarn;
00597   mdbYarn* y = &localYarn;
00598   y->mYarn_Buf = localBuf; // space to hold content
00599   y->mYarn_Fill = 0;       // no logical content yet
00600   y->mYarn_Size = 256;     // physical capacity is 256 bytes
00601   y->mYarn_More = 0;
00602   y->mYarn_Form = 0;
00603   y->mYarn_Grow = 0;
00604   
00605   if ( ioFile )
00606   {
00607     nsIMdbEnv* menv = ev->AsMdbEnv();
00608     mdb_size actualSize = 0;
00609     ioFile->Get(menv, y->mYarn_Buf, y->mYarn_Size, /*pos*/ 0, &actualSize);
00610     y->mYarn_Fill = actualSize;
00611     
00612     if ( y->mYarn_Buf && actualSize >= headSize && ev->Good() )
00613     {
00614       mork_u1* buf = (mork_u1*) y->mYarn_Buf;
00615       outBool = ( MORK_MEMCMP(morkWriter_kFileHeader, buf, headSize) == 0 );
00616     }
00617   }
00618   else
00619     ev->NilPointerError();
00620 
00621   return outBool;
00622 }
00623 
00624 // { ----- begin store methods -----
00625 /*virtual*/ mdb_err
00626 orkinFactory::CanOpenFileStore(
00627   nsIMdbEnv* mev, // context
00628   // const char* inFilePath, // the file to investigate
00629   // const mdbYarn* inFirst512Bytes,
00630   nsIMdbFile* ioFile, // db abstract file interface
00631   mdb_bool* outCanOpenAsStore, // whether OpenFileStore() might succeed
00632   mdb_bool* outCanOpenAsPort, // whether OpenFilePort() might succeed
00633   mdbYarn* outFormatVersion)
00634 {
00635   mdb_bool canOpenAsStore = morkBool_kFalse;
00636   mdb_bool canOpenAsPort = morkBool_kFalse;
00637   if ( outFormatVersion )
00638   {
00639     outFormatVersion->mYarn_Fill = 0;
00640   }
00641   mdb_err outErr = 0;
00642   morkEnv* ev = this->CanUseFactory(mev,
00643     /*inMutable*/ morkBool_kFalse, &outErr);
00644   if ( ev )
00645   {
00646     if ( ioFile && outCanOpenAsStore )
00647     {
00648       // right now always say true; later we should look for magic patterns
00649       canOpenAsStore = this->CanOpenMorkTextFile(ev, ioFile);
00650       canOpenAsPort = canOpenAsStore;
00651     }
00652     else
00653       ev->NilPointerError();
00654     
00655     outErr = ev->AsErr();
00656   }
00657   if ( outCanOpenAsStore )
00658     *outCanOpenAsStore = canOpenAsStore;
00659     
00660   if ( outCanOpenAsPort )
00661     *outCanOpenAsPort = canOpenAsPort;
00662     
00663   return outErr;
00664 }
00665   
00666 /*virtual*/ mdb_err
00667 orkinFactory::OpenFileStore( // open an existing database
00668   nsIMdbEnv* mev, // context
00669   nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
00670   // const char* inFilePath, // the file to open for general db usage
00671   nsIMdbFile* ioFile, // db abstract file interface
00672   const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
00673   nsIMdbThumb** acqThumb)
00674 {
00675   mdb_err outErr = 0;
00676   nsIMdbThumb* outThumb = 0;
00677   morkEnv* ev = this->CanUseFactory(mev,
00678     /*inMutable*/ morkBool_kFalse, &outErr);
00679   if ( ev )
00680   {
00681     if ( !ioHeap ) // need to use heap from env?
00682       ioHeap = ev->mEnv_Heap;
00683     
00684     if ( ioFile && inOpenPolicy && acqThumb )
00685     {
00686       morkFactory* factory = (morkFactory*) this->mHandle_Object;
00687       morkStore* store = new(*ioHeap, ev)
00688         morkStore(ev, morkUsage::kHeap, ioHeap, factory, ioHeap);
00689         
00690       if ( store )
00691       {
00692         mork_bool frozen = morkBool_kFalse; // open store mutable access
00693         if ( store->OpenStoreFile(ev, frozen, ioFile, inOpenPolicy) )
00694         {
00695           morkThumb* thumb = morkThumb::Make_OpenFileStore(ev, ioHeap, store);
00696           if ( thumb )
00697           {
00698             outThumb = thumb;
00699             thumb->AddRef();
00700           }
00701         }
00702 //        store->CutStrongRef(mev); // always cut ref (handle has its own ref)
00703       }
00704     }
00705     else
00706       ev->NilPointerError();
00707     
00708     outErr = ev->AsErr();
00709   }
00710   if ( acqThumb )
00711     *acqThumb = outThumb;
00712   return outErr;
00713 }
00714 // Call nsIMdbThumb::DoMore() until done, or until the thumb is broken, and
00715 // then call nsIMdbFactory::ThumbToOpenStore() to get the store instance.
00716   
00717 /*virtual*/ mdb_err
00718 orkinFactory::ThumbToOpenStore( // redeem completed thumb from OpenFileStore()
00719   nsIMdbEnv* mev, // context
00720   nsIMdbThumb* ioThumb, // thumb from OpenFileStore() with done status
00721   nsIMdbStore** acqStore)
00722 {
00723   mdb_err outErr = 0;
00724   nsIMdbStore* outStore = 0;
00725   morkEnv* ev = this->CanUseFactory(mev,
00726     /*inMutable*/ morkBool_kFalse, &outErr);
00727   if ( ev )
00728   {
00729     if ( ioThumb && acqStore )
00730     {
00731       morkThumb* thumb = (morkThumb*) ioThumb;
00732       morkStore* store = thumb->ThumbToOpenStore(ev);
00733       if ( store )
00734       {
00735         store->mStore_CanAutoAssignAtomIdentity = morkBool_kTrue;
00736         store->mStore_CanDirty = morkBool_kTrue;
00737         store->SetStoreAndAllSpacesCanDirty(ev, morkBool_kTrue);
00738         
00739         outStore = store;
00740         NS_ADDREF(store);
00741       }
00742     }
00743     else
00744       ev->NilPointerError();
00745     
00746     outErr = ev->AsErr();
00747   }
00748   if ( acqStore )
00749     *acqStore = outStore;
00750   return outErr;
00751 }
00752 
00753 /*virtual*/ mdb_err
00754 orkinFactory::CreateNewFileStore( // create a new db with minimal content
00755   nsIMdbEnv* mev, // context
00756   nsIMdbHeap* ioHeap, // can be nil to cause ev's heap attribute to be used
00757   // const char* inFilePath, // name of file which should not yet exist
00758   nsIMdbFile* ioFile, // db abstract file interface
00759   const mdbOpenPolicy* inOpenPolicy, // runtime policies for using db
00760   nsIMdbStore** acqStore)
00761 {
00762   mdb_err outErr = 0;
00763   nsIMdbStore* outStore = 0;
00764   morkEnv* ev = this->CanUseFactory(mev,
00765     /*inMutable*/ morkBool_kFalse, &outErr);
00766   if ( ev )
00767   {
00768     if ( !ioHeap ) // need to use heap from env?
00769       ioHeap = ev->mEnv_Heap;
00770     
00771     if ( ioFile && inOpenPolicy && acqStore && ioHeap )
00772     {
00773       morkFactory* factory = (morkFactory*) this->mHandle_Object;
00774       morkStore* store = new(*ioHeap, ev)
00775         morkStore(ev, morkUsage::kHeap, ioHeap, factory, ioHeap);
00776         
00777       if ( store )
00778       {
00779         store->mStore_CanAutoAssignAtomIdentity = morkBool_kTrue;
00780         store->mStore_CanDirty = morkBool_kTrue;
00781         store->SetStoreAndAllSpacesCanDirty(ev, morkBool_kTrue);
00782 
00783         if ( store->CreateStoreFile(ev, ioFile, inOpenPolicy) )
00784           outStore = store;
00785         NS_ADDREF(store);          
00786       }
00787     }
00788     else
00789       ev->NilPointerError();
00790     
00791     outErr = ev->AsErr();
00792   }
00793   if ( acqStore )
00794     *acqStore = outStore;
00795   return outErr;
00796 }
00797 // } ----- end store methods -----
00798 
00799 // } ===== end nsIMdbFactory methods =====
00800 
00801 
00802 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789