Back to index

lightning-sunbird  0.9+nobinonly
orkinFile.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 _MORKFILE_
00055 #include "morkFile.h"
00056 #endif
00057 
00058 #ifndef _MORKENV_
00059 #include "morkEnv.h"
00060 #endif
00061 
00062 #ifndef _ORKINFILE_
00063 #include "orkinFile.h"
00064 #endif
00065 
00066 #ifndef _MORKFILE_
00067 #include "morkFile.h"
00068 #endif
00069 
00070 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00071 
00072 /* public virtual*/
00073 orkinFile:: ~orkinFile() // morkHandle destructor does everything
00074 {
00075 }
00076 
00077 /*protected non-poly construction*/
00078 orkinFile::orkinFile(morkEnv* ev, // morkUsage is morkUsage_kPool
00079     morkHandleFace* ioFace,    // must not be nil, cookie for this handle
00080     morkFile* ioObject)  // must not be nil, the object for this handle
00081 : morkHandle(ev, ioFace, ioObject, morkMagic_kFile)
00082 {
00083   // do not modify mNode_Derived; leave it equal to morkDerived_kHandle
00084 }
00085 
00086 
00087 /*static */ orkinFile*
00088 orkinFile::MakeFile(morkEnv* ev, morkFile* ioObject)
00089 {
00090   mork_bool isEnv = ev->IsEnv();
00091   MORK_ASSERT(isEnv);
00092   if ( isEnv )
00093   {
00094     morkHandleFace* face = ev->NewHandle(sizeof(orkinFile));
00095     if ( face )
00096       return new(face) orkinFile(ev, face, ioObject);
00097     else
00098       ev->OutOfMemoryError();
00099   }
00100     
00101   return (orkinFile*) 0;
00102 }
00103 
00104 morkEnv*
00105 orkinFile::CanUseFile(nsIMdbEnv* mev,
00106   mork_bool inMutable, mdb_err* outErr) const
00107 {
00108   morkEnv* outEnv = 0;
00109   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00110   if ( ev )
00111   {  
00112     morkFile* self = (morkFile*)
00113       this->GetGoodHandleObject(ev, inMutable, morkMagic_kFile,
00114         /*inClosedOkay*/ morkBool_kFalse);
00115     if ( self )
00116     {
00117       if ( self->IsFile() )
00118         outEnv = ev;
00119       else
00120         self->NonFileTypeError(ev);
00121     }
00122     *outErr = ev->AsErr();
00123   }
00124   MORK_ASSERT(outEnv);
00125   return outEnv;
00126 }
00127 
00128 
00129 // { ===== begin nsIMdbISupports methods =====
00130 NS_IMPL_QUERY_INTERFACE1(orkinFile, nsIMdbFile)
00131 
00132 /*virtual*/ nsrefcnt
00133 orkinFile::AddRef() // add strong ref with no
00134 {
00135   morkEnv* ev = mHandle_Env;
00136   if ( ev && ev->IsEnv() )
00137     return this->Handle_AddStrongRef(ev->AsMdbEnv());
00138   else
00139     return morkEnv_kNonEnvTypeError;
00140 }
00141 
00142 /*virtual*/ nsrefcnt
00143 orkinFile::Release() // cut strong ref
00144 {
00145   morkEnv* ev = mHandle_Env;
00146   if ( ev && ev->IsEnv() )
00147     return this->Handle_CutStrongRef(ev->AsMdbEnv());
00148   else
00149     return morkEnv_kNonEnvTypeError;
00150 }
00151 // } ===== end nsIMdbISupports methods =====
00152 
00153 // { ===== begin nsIMdbObject methods =====
00154 
00155 // { ----- begin attribute methods -----
00156 /*virtual*/ mdb_err
00157 orkinFile::IsFrozenMdbObject(nsIMdbEnv* mev, mdb_bool* outIsReadonly)
00158 {
00159   return this->Handle_IsFrozenMdbObject(mev, outIsReadonly);
00160 }
00161 // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port.
00162 // } ----- end attribute methods -----
00163 
00164 // { ----- begin factory methods -----
00165 /*virtual*/ mdb_err
00166 orkinFile::GetMdbFactory(nsIMdbEnv* mev, nsIMdbFactory** acqFactory)
00167 {
00168   return this->Handle_GetMdbFactory(mev, acqFactory);
00169 } 
00170 // } ----- end factory methods -----
00171 
00172 // { ----- begin ref counting for well-behaved cyclic graphs -----
00173 /*virtual*/ mdb_err
00174 orkinFile::GetWeakRefCount(nsIMdbEnv* mev, // weak refs
00175   mdb_count* outCount)
00176 {
00177   return this->Handle_GetWeakRefCount(mev, outCount);
00178 }  
00179 /*virtual*/ mdb_err
00180 orkinFile::GetStrongRefCount(nsIMdbEnv* mev, // strong refs
00181   mdb_count* outCount)
00182 {
00183   return this->Handle_GetStrongRefCount(mev, outCount);
00184 }
00185 
00186 /*virtual*/ mdb_err
00187 orkinFile::AddWeakRef(nsIMdbEnv* mev)
00188 {
00189   return this->Handle_AddWeakRef(mev);
00190 }
00191 /*virtual*/ mdb_err
00192 orkinFile::AddStrongRef(nsIMdbEnv* mev)
00193 {
00194   return this->Handle_AddStrongRef(mev);
00195 }
00196 
00197 /*virtual*/ mdb_err
00198 orkinFile::CutWeakRef(nsIMdbEnv* mev)
00199 {
00200   return this->Handle_CutWeakRef(mev);
00201 }
00202 /*virtual*/ mdb_err
00203 orkinFile::CutStrongRef(nsIMdbEnv* mev)
00204 {
00205   return this->Handle_CutStrongRef(mev);
00206 }
00207 
00208 /*virtual*/ mdb_err
00209 orkinFile::CloseMdbObject(nsIMdbEnv* mev)
00210 {
00211   return this->Handle_CloseMdbObject(mev);
00212 }
00213 
00214 /*virtual*/ mdb_err
00215 orkinFile::IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen)
00216 {
00217   return this->Handle_IsOpenMdbObject(mev, outOpen);
00218 }
00219 // } ----- end ref counting -----
00220 
00221 // } ===== end nsIMdbObject methods =====
00222 
00223 // { ===== begin nsIMdbFile methods =====
00224 
00225 // { ----- begin pos methods -----
00226 /*virtual*/ mdb_err
00227 orkinFile::Tell(nsIMdbEnv* mev, mdb_pos* outPos)
00228 {
00229   mdb_err outErr = 0;
00230   mdb_pos pos = -1;
00231   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00232   if ( ev )
00233   {
00234     morkFile* file = (morkFile*) mHandle_Object;
00235     pos = file->Tell(ev);
00236     outErr = ev->AsErr();
00237   }
00238   if ( outPos )
00239     *outPos = pos;
00240   return outErr;
00241 }
00242 
00243 /*virtual*/ mdb_err
00244 orkinFile::Seek(nsIMdbEnv* mev, mdb_pos inPos)
00245 {
00246   mdb_err outErr = 0;
00247   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00248   if ( ev )
00249   {
00250     morkFile* file = (morkFile*) mHandle_Object;
00251     file->Seek(ev, inPos);
00252     outErr = ev->AsErr();
00253   }
00254   return outErr;
00255 }
00256 
00257 /*virtual*/ mdb_err
00258 orkinFile::Eof(nsIMdbEnv* mev, mdb_pos* outPos)
00259 {
00260   mdb_err outErr = 0;
00261   mdb_pos pos = -1;
00262   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00263   if ( ev )
00264   {
00265     morkFile* file = (morkFile*) mHandle_Object;
00266     pos = file->Length(ev);
00267     outErr = ev->AsErr();
00268   }
00269   if ( outPos )
00270     *outPos = pos;
00271   return outErr;
00272 }
00273 
00274 // } ----- end pos methods -----
00275 
00276 // { ----- begin read methods -----
00277 /*virtual*/ mdb_err
00278 orkinFile::Read(nsIMdbEnv* mev, void* outBuf, mdb_size inSize,
00279   mdb_size* outActualSize)
00280 {
00281   mdb_err outErr = 0;
00282   mdb_size actualSize = 0;
00283   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00284   if ( ev )
00285   {
00286     morkFile* file = (morkFile*) mHandle_Object;
00287     actualSize = file->Read(ev, outBuf, inSize);
00288     outErr = ev->AsErr();
00289   }
00290   if ( outActualSize )
00291     *outActualSize = actualSize;
00292   return outErr;
00293 }
00294 
00295 /*virtual*/ mdb_err
00296 orkinFile::Get(nsIMdbEnv* mev, void* outBuf, mdb_size inSize,
00297   mdb_pos inPos, mdb_size* outActualSize)
00298 {
00299   mdb_err outErr = 0;
00300   mdb_size actualSize = 0;
00301   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00302   if ( ev )
00303   {
00304     morkFile* file = (morkFile*) mHandle_Object;
00305     file->Seek(ev, inPos);
00306     if ( ev->Good() )
00307       actualSize = file->Read(ev, outBuf, inSize);
00308     outErr = ev->AsErr();
00309   }
00310   if ( outActualSize )
00311     *outActualSize = actualSize;
00312   return outErr;
00313 }
00314 
00315 // } ----- end read methods -----
00316   
00317 // { ----- begin write methods -----
00318 /*virtual*/ mdb_err
00319 orkinFile::Write(nsIMdbEnv* mev, const void* inBuf, mdb_size inSize,
00320   mdb_size* outActualSize)
00321 {
00322   mdb_err outErr = 0;
00323   mdb_size actualSize = 0;
00324   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00325   if ( ev )
00326   {
00327     morkFile* file = (morkFile*) mHandle_Object;
00328     actualSize = file->Write(ev, inBuf, inSize);
00329     outErr = ev->AsErr();
00330   }
00331   if ( outActualSize )
00332     *outActualSize = actualSize;
00333   return outErr;
00334 }
00335 
00336 /*virtual*/ mdb_err
00337 orkinFile::Put(nsIMdbEnv* mev, const void* inBuf, mdb_size inSize,
00338   mdb_pos inPos, mdb_size* outActualSize)
00339 {
00340   mdb_err outErr = 0;
00341   mdb_size actualSize = 0;
00342   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00343   if ( ev )
00344   {
00345     morkFile* file = (morkFile*) mHandle_Object;
00346     file->Seek(ev, inPos);
00347     if ( ev->Good() )
00348       actualSize = file->Write(ev, inBuf, inSize);
00349     outErr = ev->AsErr();
00350   }
00351   if ( outActualSize )
00352     *outActualSize = actualSize;
00353   return outErr;
00354 }
00355 
00356 /*virtual*/ mdb_err
00357 orkinFile::Flush(nsIMdbEnv* mev)
00358 {
00359   mdb_err outErr = 0;
00360   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00361   if ( ev )
00362   {
00363     morkFile* file = (morkFile*) mHandle_Object;
00364     file->Flush(ev);
00365     outErr = ev->AsErr();
00366   }
00367   return outErr;
00368 }
00369 
00370 // } ----- end attribute methods -----
00371   
00372 // { ----- begin path methods -----
00373 /*virtual*/ mdb_err
00374 orkinFile::Path(nsIMdbEnv* mev, mdbYarn* outFilePath)
00375 {
00376   mdb_err outErr = 0;
00377   if ( outFilePath )
00378     outFilePath->mYarn_Fill = 0;
00379   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00380   if ( ev )
00381   {
00382     morkFile* file = (morkFile*) mHandle_Object;
00383     ev->StringToYarn(file->GetFileNameString(), outFilePath);
00384     outErr = ev->AsErr();
00385   }
00386   return outErr;
00387 }
00388 
00389 // } ----- end path methods -----
00390   
00391 // { ----- begin replacement methods -----
00392 
00393 /*virtual*/ mdb_err
00394 orkinFile::Steal(nsIMdbEnv* mev, nsIMdbFile* ioThief)
00395 {
00396   mdb_err outErr = 0;
00397   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00398   if ( ev )
00399   {
00400     if ( ioThief )
00401     {
00402       // orkinFile* thief = (orkinFile*) ioThief; // unsafe cast -- must type check:
00403       // thief->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00404       
00405       morkFile* file = (morkFile*) mHandle_Object;
00406       file->Steal(ev, ioThief);
00407       outErr = ev->AsErr();
00408     }
00409     else
00410       ev->NilPointerError();
00411   }
00412   return outErr;
00413 }
00414 
00415 /*virtual*/ mdb_err
00416 orkinFile::Thief(nsIMdbEnv* mev, nsIMdbFile** acqThief)
00417 {
00418   mdb_err outErr = 0;
00419   nsIMdbFile* outThief = 0;
00420   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00421   if ( ev )
00422   {
00423     morkFile* file = (morkFile*) mHandle_Object;
00424     outThief = file->GetThief();
00425     if ( outThief )
00426       outThief->AddStrongRef(ev->AsMdbEnv());
00427     outErr = ev->AsErr();
00428   }
00429   if ( acqThief )
00430     *acqThief = outThief;
00431   return outErr;
00432 }
00433 
00434 // } ----- end replacement methods -----
00435 
00436 // { ----- begin versioning methods -----
00437 
00438 /*virtual*/ mdb_err
00439 orkinFile::BecomeTrunk(nsIMdbEnv* mev)
00440 // If this file is a file version branch created by calling AcquireBud(),
00441 // BecomeTrunk() causes this file's content to replace the original
00442 // file's content, typically by assuming the original file's identity.
00443 // This default implementation of BecomeTrunk() does nothing, and this
00444 // is appropriate behavior for files which are not branches, and is
00445 // also the right behavior for files returned from AcquireBud() which are
00446 // in fact the original file that has been truncated down to zero length.
00447 {
00448   mdb_err outErr = 0;
00449   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00450   if ( ev )
00451   {
00452     morkFile* file = (morkFile*) mHandle_Object;
00453     file->BecomeTrunk(ev);
00454     outErr = ev->AsErr();
00455   }
00456   return outErr;
00457 }
00458 
00459 /*virtual*/ mdb_err
00460 orkinFile::AcquireBud(nsIMdbEnv* mev, nsIMdbHeap* ioHeap,
00461   nsIMdbFile** acqBud) // acquired file for new version of content
00462 // AcquireBud() starts a new "branch" version of the file, empty of content,
00463 // so that a new version of the file can be written.  This new file
00464 // can later be told to BecomeTrunk() the original file, so the branch
00465 // created by budding the file will replace the original file.  Some
00466 // file subclasses might initially take the unsafe but expedient
00467 // approach of simply truncating this file down to zero length, and
00468 // then returning the same morkFile pointer as this, with an extra
00469 // reference count increment.  Note that the caller of AcquireBud() is
00470 // expected to eventually call CutStrongRef() on the returned file
00471 // in order to release the strong reference.  High quality versions
00472 // of morkFile subclasses will create entirely new files which later
00473 // are renamed to become the old file, so that better transactional
00474 // behavior is exhibited by the file, so crashes protect old files.
00475 // Note that AcquireBud() is an illegal operation on readonly files.
00476 {
00477   mdb_err outErr = 0;
00478   nsIMdbFile* outBud = 0;
00479   morkEnv* ev = this->CanUseFile(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00480   if ( ev )
00481   {
00482     morkFile* file = (morkFile*) mHandle_Object;
00483     morkFile* bud = file->AcquireBud(ev, ioHeap);
00484     if ( bud )
00485     {
00486       outBud = bud->AcquireFileHandle(ev);
00487       bud->CutStrongRef(mev);
00488     }
00489     outErr = ev->AsErr();
00490   }
00491   if ( acqBud )
00492     *acqBud = outBud;
00493   return outErr;
00494 }
00495 // } ----- end versioning methods -----
00496 
00497 // } ===== end nsIMdbFile methods =====
00498 
00499 
00500 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789