Back to index

lightning-sunbird  0.9+nobinonly
morkPortTableCursor.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 _MORKENV_
00051 #include "morkEnv.h"
00052 #endif
00053 
00054 #ifndef _MORKCURSOR_
00055 #include "morkCursor.h"
00056 #endif
00057 
00058 #ifndef _MORKPORTTABLECURSOR_
00059 #include "morkPortTableCursor.h"
00060 #endif
00061 
00062 #ifndef _MORKSTORE_
00063 #include "morkStore.h"
00064 #endif
00065 
00066 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00067 
00068 // ````` ````` ````` ````` ````` 
00069 // { ===== begin morkNode interface =====
00070 
00071 /*public virtual*/ void
00072 morkPortTableCursor::CloseMorkNode(morkEnv* ev) // ClosePortTableCursor() only if open
00073 {
00074   if ( this->IsOpenNode() )
00075   {
00076     this->MarkClosing();
00077     this->ClosePortTableCursor(ev);
00078     this->MarkShut();
00079   }
00080 }
00081 
00082 /*public virtual*/
00083 morkPortTableCursor::~morkPortTableCursor() // ClosePortTableCursor() executed earlier
00084 {
00085   CloseMorkNode(mMorkEnv);
00086 }
00087 
00088 /*public non-poly*/
00089 morkPortTableCursor::morkPortTableCursor(morkEnv* ev,
00090   const morkUsage& inUsage,
00091   nsIMdbHeap* ioHeap, morkStore* ioStore, mdb_scope inRowScope,
00092   mdb_kind inTableKind, nsIMdbHeap* ioSlotHeap)
00093 : morkCursor(ev, inUsage, ioHeap)
00094 , mPortTableCursor_Store( 0 )
00095 , mPortTableCursor_RowScope( (mdb_scope) -1 ) // we want != inRowScope
00096 , mPortTableCursor_TableKind( (mdb_kind) -1 ) // we want != inTableKind
00097 , mPortTableCursor_LastTable ( 0 ) // not refcounted
00098 , mPortTableCursor_RowSpace( 0 ) // strong ref to row space
00099 , mPortTableCursor_TablesDidEnd( morkBool_kFalse )
00100 , mPortTableCursor_SpacesDidEnd( morkBool_kFalse )
00101 {
00102   if ( ev->Good() )
00103   {
00104     if ( ioStore && ioSlotHeap )
00105     {
00106       mCursor_Pos = -1;
00107       mCursor_Seed = 0; // let the iterator do it's own seed handling
00108       morkStore::SlotWeakStore(ioStore, ev, &mPortTableCursor_Store);
00109 
00110       if ( this->SetRowScope(ev, inRowScope) )
00111         this->SetTableKind(ev, inTableKind);
00112         
00113       if ( ev->Good() )
00114         mNode_Derived = morkDerived_kPortTableCursor;
00115     }
00116     else
00117       ev->NilPointerError();
00118   }
00119 }
00120 
00121 NS_IMPL_ISUPPORTS_INHERITED1(morkPortTableCursor, morkCursor, nsIMdbPortTableCursor)
00122 
00123 morkEnv*
00124 morkPortTableCursor::CanUsePortTableCursor(nsIMdbEnv* mev,
00125   mork_bool inMutable, mdb_err* outErr) const
00126 {
00127   morkEnv* outEnv = 0;
00128   morkEnv* ev = morkEnv::FromMdbEnv(mev);
00129   if ( ev )
00130   {
00131     if ( IsPortTableCursor() )
00132       outEnv = ev;
00133     else
00134       NonPortTableCursorTypeError(ev);
00135     *outErr = ev->AsErr();
00136   }
00137   MORK_ASSERT(outEnv);
00138   return outEnv;
00139 }
00140 
00141 
00142 /*public non-poly*/ void
00143 morkPortTableCursor::ClosePortTableCursor(morkEnv* ev) 
00144 {
00145   if ( this )
00146   {
00147     if ( this->IsNode() )
00148     {
00149       mCursor_Pos = -1;
00150       mCursor_Seed = 0;
00151       mPortTableCursor_LastTable = 0;
00152       morkStore::SlotWeakStore((morkStore*) 0, ev, &mPortTableCursor_Store);
00153       morkRowSpace::SlotStrongRowSpace((morkRowSpace*) 0, ev,
00154         &mPortTableCursor_RowSpace);
00155       this->CloseCursor(ev);
00156       this->MarkShut();
00157     }
00158     else
00159       this->NonNodeError(ev);
00160   }
00161   else
00162     ev->NilPointerError();
00163 }
00164 
00165 // } ===== end morkNode methods =====
00166 // ````` ````` ````` ````` ````` 
00167 
00168 /*static*/ void
00169 morkPortTableCursor::NilCursorStoreError(morkEnv* ev)
00170 {
00171   ev->NewError("nil mPortTableCursor_Store");
00172 }
00173 
00174 /*static*/ void
00175 morkPortTableCursor::NonPortTableCursorTypeError(morkEnv* ev)
00176 {
00177   ev->NewError("non morkPortTableCursor");
00178 }
00179 
00180 mork_bool 
00181 morkPortTableCursor::SetRowScope(morkEnv* ev, mork_scope inRowScope)
00182 {
00183   mPortTableCursor_RowScope = inRowScope;
00184   mPortTableCursor_LastTable = 0; // restart iteration of space
00185   
00186   mPortTableCursor_TableIter.CloseMapIter(ev);
00187   mPortTableCursor_TablesDidEnd = morkBool_kTrue;
00188   mPortTableCursor_SpacesDidEnd = morkBool_kTrue;
00189   
00190   morkStore* store = mPortTableCursor_Store;
00191   if ( store )
00192   {
00193     morkRowSpace* space = mPortTableCursor_RowSpace;
00194 
00195     if ( inRowScope ) // intend to cover a specific scope only?
00196     {
00197       space = store->LazyGetRowSpace(ev, inRowScope);
00198       morkRowSpace::SlotStrongRowSpace(space, ev, 
00199        &mPortTableCursor_RowSpace);
00200        
00201       // We want mPortTableCursor_SpacesDidEnd == morkBool_kTrue
00202       // to show this is the only space to be covered.
00203     }
00204     else // prepare space map iter to cover all space scopes
00205     {
00206       morkRowSpaceMapIter* rsi = &mPortTableCursor_SpaceIter;
00207       rsi->InitRowSpaceMapIter(ev, &store->mStore_RowSpaces);
00208       
00209       space = 0;
00210       (void) rsi->FirstRowSpace(ev, (mork_scope*) 0, &space);
00211       morkRowSpace::SlotStrongRowSpace(space, ev,
00212         &mPortTableCursor_RowSpace);
00213         
00214       if ( space ) // found first space in store
00215         mPortTableCursor_SpacesDidEnd = morkBool_kFalse;
00216     }
00217 
00218     this->init_space_tables_map(ev);
00219   }
00220   else
00221     this->NilCursorStoreError(ev);
00222     
00223   return ev->Good();
00224 }
00225 
00226 void
00227 morkPortTableCursor::init_space_tables_map(morkEnv* ev)
00228 {
00229   morkRowSpace* space = mPortTableCursor_RowSpace;
00230   if ( space && ev->Good() )
00231   {
00232     morkTableMapIter* ti = &mPortTableCursor_TableIter;
00233     ti->InitTableMapIter(ev, &space->mRowSpace_Tables);
00234     if ( ev->Good() )
00235       mPortTableCursor_TablesDidEnd = morkBool_kFalse;
00236   }
00237 }
00238 
00239 
00240 mork_bool
00241 morkPortTableCursor::SetTableKind(morkEnv* ev, mork_kind inTableKind)
00242 {
00243   mPortTableCursor_TableKind = inTableKind;
00244   mPortTableCursor_LastTable = 0; // restart iteration of space
00245 
00246   mPortTableCursor_TablesDidEnd = morkBool_kTrue;
00247 
00248   morkRowSpace* space = mPortTableCursor_RowSpace;
00249   if ( !space && mPortTableCursor_RowScope == 0 )
00250   {
00251     this->SetRowScope(ev, 0);
00252     space = mPortTableCursor_RowSpace;
00253   }
00254   this->init_space_tables_map(ev);
00255   
00256   return ev->Good();
00257 }
00258 
00259 morkRowSpace*
00260 morkPortTableCursor::NextSpace(morkEnv* ev)
00261 {
00262   morkRowSpace* outSpace = 0;
00263   mPortTableCursor_LastTable = 0;
00264   mPortTableCursor_SpacesDidEnd = morkBool_kTrue;
00265   mPortTableCursor_TablesDidEnd = morkBool_kTrue;
00266 
00267   if ( !mPortTableCursor_RowScope ) // not just one scope?
00268   {
00269     morkStore* store = mPortTableCursor_Store;
00270     if ( store )
00271     {
00272       morkRowSpaceMapIter* rsi = &mPortTableCursor_SpaceIter;
00273 
00274       (void) rsi->NextRowSpace(ev, (mork_scope*) 0, &outSpace);
00275       morkRowSpace::SlotStrongRowSpace(outSpace, ev,
00276         &mPortTableCursor_RowSpace);
00277         
00278       if ( outSpace ) // found next space in store
00279       {
00280         mPortTableCursor_SpacesDidEnd = morkBool_kFalse;
00281         
00282         this->init_space_tables_map(ev);
00283 
00284         if ( ev->Bad() )
00285           outSpace = 0;
00286       }
00287     }
00288     else
00289       this->NilCursorStoreError(ev);
00290   }
00291     
00292   return outSpace;
00293 }
00294 
00295 morkTable *
00296 morkPortTableCursor::NextTable(morkEnv* ev)
00297 {
00298   mork_kind kind = mPortTableCursor_TableKind;
00299   
00300   do // until spaces end, or until we find a table in a space
00301   { 
00302     morkRowSpace* space = mPortTableCursor_RowSpace;
00303     if ( mPortTableCursor_TablesDidEnd ) // current space exhausted?
00304       space = this->NextSpace(ev); // go on to the next space
00305       
00306     if ( space ) // have a space remaining that might hold tables?
00307     {
00308 #ifdef MORK_BEAD_OVER_NODE_MAPS
00309       morkTableMapIter* ti = &mPortTableCursor_TableIter;
00310       morkTable* table = ( mPortTableCursor_LastTable )?
00311         ti->NextTable(ev) : ti->FirstTable(ev);
00312 
00313       for ( ; table && ev->Good(); table = ti->NextTable(ev) )
00314       
00315 #else /*MORK_BEAD_OVER_NODE_MAPS*/
00316       mork_tid* key = 0; // ignore keys in table map
00317       morkTable* table = 0; // old value table in the map
00318       morkTableMapIter* ti = &mPortTableCursor_TableIter;
00319       mork_change* c = ( mPortTableCursor_LastTable )?
00320         ti->NextTable(ev, key, &table) : ti->FirstTable(ev, key, &table);
00321 
00322       for ( ; c && ev->Good(); c = ti->NextTable(ev, key, &table) )
00323 #endif /*MORK_BEAD_OVER_NODE_MAPS*/
00324       {
00325         if ( table && table->IsTable() )
00326         {
00327           if ( !kind || kind == table->mTable_Kind )
00328           {
00329             mPortTableCursor_LastTable = table; // ti->NextTable() hence
00330             return table;
00331           }
00332         }
00333         else
00334           table->NonTableTypeWarning(ev);
00335       }
00336       mPortTableCursor_TablesDidEnd = morkBool_kTrue; // space is done
00337       mPortTableCursor_LastTable = 0; // make sure next space starts fresh
00338     }
00339   
00340   } while ( ev->Good() && !mPortTableCursor_SpacesDidEnd );
00341 
00342   return (morkTable*) 0;
00343 }
00344 
00345 
00346 // { ----- begin table iteration methods -----
00347 
00348 // { ===== begin nsIMdbPortTableCursor methods =====
00349 
00350 // { ----- begin attribute methods -----
00351 NS_IMETHODIMP
00352 morkPortTableCursor::SetPort(nsIMdbEnv* mev, nsIMdbPort* ioPort)
00353 {
00354   NS_ASSERTION(PR_FALSE,"not implemented");
00355   return NS_ERROR_NOT_IMPLEMENTED;
00356 }
00357 
00358 NS_IMETHODIMP
00359 morkPortTableCursor::GetPort(nsIMdbEnv* mev, nsIMdbPort** acqPort)
00360 {
00361   mdb_err outErr = 0;
00362   nsIMdbPort* outPort = 0;
00363   morkEnv* ev =
00364     this->CanUsePortTableCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00365   if ( ev )
00366   {
00367     if ( mPortTableCursor_Store )
00368       outPort = mPortTableCursor_Store->AcquireStoreHandle(ev);
00369     outErr = ev->AsErr();
00370   }
00371   if ( acqPort )
00372     *acqPort = outPort;
00373   return outErr;
00374 }
00375 
00376 NS_IMETHODIMP
00377 morkPortTableCursor::SetRowScope(nsIMdbEnv* mev, // sets pos to -1
00378   mdb_scope inRowScope)
00379 {
00380   mdb_err outErr = 0;
00381   morkEnv* ev =
00382     this->CanUsePortTableCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00383   if ( ev )
00384   {
00385     mCursor_Pos = -1;
00386     
00387     SetRowScope(ev, inRowScope);
00388     outErr = ev->AsErr();
00389   }
00390   return outErr;
00391 }
00392 
00393 NS_IMETHODIMP
00394 morkPortTableCursor::GetRowScope(nsIMdbEnv* mev, mdb_scope* outRowScope)
00395 {
00396   mdb_err outErr = 0;
00397   mdb_scope rowScope = 0;
00398   morkEnv* ev =
00399     this->CanUsePortTableCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00400   if ( ev )
00401   {
00402     rowScope = mPortTableCursor_RowScope;
00403     outErr = ev->AsErr();
00404   }
00405   *outRowScope = rowScope;
00406   return outErr;
00407 }
00408 // setting row scope to zero iterates over all row scopes in port
00409   
00410 NS_IMETHODIMP
00411 morkPortTableCursor::SetTableKind(nsIMdbEnv* mev, // sets pos to -1
00412   mdb_kind inTableKind)
00413 {
00414   mdb_err outErr = 0;
00415   morkEnv* ev =
00416     this->CanUsePortTableCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00417   if ( ev )
00418   {
00419     mCursor_Pos = -1;
00420     
00421     SetTableKind(ev, inTableKind);
00422     outErr = ev->AsErr();
00423   }
00424   return outErr;
00425 }
00426 
00427 NS_IMETHODIMP
00428 morkPortTableCursor::GetTableKind(nsIMdbEnv* mev, mdb_kind* outTableKind)
00429 // setting table kind to zero iterates over all table kinds in row scope
00430 {
00431   mdb_err outErr = 0;
00432   mdb_kind tableKind = 0;
00433   morkEnv* ev =
00434     this->CanUsePortTableCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00435   if ( ev )
00436   {
00437     tableKind = mPortTableCursor_TableKind;
00438     outErr = ev->AsErr();
00439   }
00440   *outTableKind = tableKind;
00441   return outErr;
00442 }
00443 // } ----- end attribute methods -----
00444 
00445 // { ----- begin table iteration methods -----
00446 NS_IMETHODIMP
00447 morkPortTableCursor::NextTable( // get table at next position in the db
00448   nsIMdbEnv* mev, // context
00449   nsIMdbTable** acqTable)
00450 {
00451   mdb_err outErr = 0;
00452   nsIMdbTable* outTable = 0;
00453   morkEnv* ev =
00454     CanUsePortTableCursor(mev, /*inMutable*/ morkBool_kFalse, &outErr);
00455   if ( ev )
00456   {
00457     morkTable* table = NextTable(ev);
00458     if ( table && ev->Good() )
00459       outTable = table->AcquireTableHandle(ev);
00460         
00461     outErr = ev->AsErr();
00462   }
00463   if ( acqTable )
00464     *acqTable = outTable;
00465   return outErr;
00466 }
00467 
00468 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789