/*! @header FTPersistentSet @abstract Module of FT @availability OS X, GNUstep @copyright 2004, 2005, 2006 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  -------------------------------------------------------------------------
  Modification history

  30.03.06 ola     initial version
  23.08.06 ola     license changed
  -------------------------------------------------------------------------
  
*/ #if !defined(__FTPersistentSetImpl_H) #define __FTPersistentSetImpl_H #include #include #include #include #include #include #include @class _FTPersistentSetChunk; /*! * @class FTPersistentSetImpl * @abstract Utility class which uses a BDB database in order to manage a * set of objects in the database * @description TODO:The currently implemented version works without any caching * althought this might be very helpful here.

* So operations evaluating all entries within a set may require * iteration over all database records thus they are very expensive * at present. Examples of such operations: count, member */ @interface FTPersistentSetImpl : FTObject { @private BDBDatabase *recordNrToObject; /* current chunk to be used for insertion */ _FTPersistentSetChunk *currentInsertionChunk; unsigned maxEntriesPerChunk; NSLock *lock; } - init; - createDBUsingDataFile: (NSString *) aFilename; - openDBUsingDataFile: (NSString *) aFilename; - (void) closeDB; - (void) dealloc; /*! * @method addObject * @abstract Adds a object to the set. This object must implement * NSCoding. * @result self */ - addObject: (id) anObject; /*! * @method chunkAtRecordNumber * @abstract Tries to read a chunk from the specified record. * @param recNr record number to read from * @result related chunk or nil if not existent at the given record number */ - (_FTPersistentSetChunk *) chunkAtRecordNumber: (unsigned) recNr; /*! * @method chunkContainingObject * @param anObject object to look for * @result returns the chunk which contains the specified object or nil if not * existent */ - (_FTPersistentSetChunk *) chunkContainingObject: (id) anObject; /*! * @method chunkIterator * @abstract Note that iterating over chunks is an expensive operation at * present * @result iterator of all chunks */ - (id ) chunkIterator; /*! * @method containsObject * @abstract This is an expensive operation at present * @result YES if the specified object is to be found in the set. */ - (BOOL) containsObject: (id) anObject; /*! * @method count * @abstract Expensive operation used to determine the number of elements * in this set * @description TODO: optimize this operation * @result number of elements in the current set */ - (unsigned) count; /*! * @method dbConfig * @result configuration settings for the underlying database */ - (BDBDatabaseConfig *) dbConfig; /*! * @method iterator * @abstract Returns an iterator over all members of this set. This is an * expensive operation at present * @result iterator over all elements of the set */ - (id ) iterator; /*! * @method newChunk * @abstract Examines new available chunk and sets up corresponding internal * fields appropriately * @result self */ - newChunk; /*! * @method removeObject * @abstract removes the specified object from the set. Operation is ignored * the object could no be found within the set. * @result self */ - removeObject: (id) anObject; /*! * @method validateDBIsOpen * @abstract throws an exception if the database is not opened since this marks * an illegal state */ - (void) validateDBIsOpen; @end /* ----------------------------------------- _FTPersistentSetChunk */ @interface _FTPersistentSetChunk : FTObject { @private BDBDatabase *database; NSMutableArray *objects; unsigned bdb_record_nr; BOOL isModified; BOOL chunkInTransaction; NSLock *lock; } /*! * @method createForDatabase * @abstract Creates a chunk and stores its initial content in the database. * @param aDatabase database to use * @param a_record_nr record number at which to store the chunk * @result created chunk */ + (_FTPersistentSetChunk *) createForDatabase: (BDBDatabase *) aDatabase atRecordNumber: (unsigned) a_record_nr; /*! * @method readFromDatabase * @abstract reads the specified chunk from the database * @param aDatabase database to use * @param a_record_nr record number at which to store the chunk * @result loaded chunk or nil if not existent */ + (_FTPersistentSetChunk *) readFromDatabase: (BDBDatabase *) aDatabase atRecordNumber: (unsigned) record_nr; /*! * @method initForDatabase * @abstract internal method call * @param aDatabase database to use * @param a_record_nr record number to use * @param givenObjects used as the initial set of data for this chunk. * if nil then an empty set will be created and loadedFromDatabase * may only equal NO * @result self */ - initForDatabase: (BDBDatabase *) aDatabase atRecordNumber: (unsigned) a_record_nr usingObjects: (NSArray *) givenObjects; - (void) dealloc; /*! * @method addObject * @abstract adds an object to this chunk. Does *not* store the result in the * database! Call storeChunk for this purpose * @param anObject given object must implement NSCoding * @result self */ - addObject: (id) anObject; /*! * @method count * @result number of objects in this chunk */ - (unsigned) count; /*! * @method containsObject * @result YES if the given object is to be found in the chunk */ - (BOOL) containsObject: (id) anObject; /*! * @method isChunkInTransaction * @result YES if this chunk is already been placed in a transaction */ - (BOOL) isChunkInTransaction; /*! * @method loadChunk * @abstract Loads the chunk from the database * @result self */ - loadChunk; /*! * @method objects * @abstract get all objects stored in this chunk * lresult all objects stored in this chunk */ - (NSArray *) objects; /*! * @method recordNumber * @result number of BDB record used for storing the chunk */ - (unsigned) recordNumber; /*! * @method remove * @abstract removes the chunk from the database */ - (void) remove; /*! * @method removeObject * @abstract removes the specified objects. Operation is ignored if given * object is not to be found in the chunk * @result self */ - removeObject: (id) anObject; /*! * @method setChunkInTransaction * @param itIs set to YES if the chunk is placed within a transaction * @result self */ - setChunkInTransaction: (BOOL) itIs; /*! * @method store * @abstract this method is used to store the content of the chunk into the * database * @result self */ - store; /*! * @method update * @abstract either stores the chunk or deletes it. The latter is done if the * chunk contains no more data. * This method should only called by transaction steps since it directly * writes the content to the database * @result self */ - (void) update; @end /* ----------------------------------------- _FTPersistentSetChunkIterator */ /*! * @class _FTPersistentSetChunkIterator * @abstract Used to iterate over all chunks of a persistent set */ @interface _FTPersistentSetChunkIterator : FTObject { @private unsigned current_rec_number; FTPersistentSetImpl *persistentSet; _FTPersistentSetChunk *fetchedChunk; BOOL fetchedBefore; } - initWithPersistentSet: (FTPersistentSetImpl *) aPersistentSet; - (void) dealloc; - (BOOL) hasNext; - next; - fetchChunk; @end /* ----------------------------------------- _FTPersistentSetIterator */ /*! * @class _FTPersistentSetIterator * @abstract Used to iterate over all elements of a persistent set * @description TODO: Expensive operation at present */ @interface _FTPersistentSetIterator : FTObject { @private id chunkIterator; NSEnumerator *chunkElements; BOOL elementFetched; id nextObject; } - initWithPersistentSet: (FTPersistentSetImpl *) aPersistentSet; - (void) dealloc; /*! * @method fetchNextChunkElements * @abstract fetch enumeration of elements of the next chunk and set up internal * fields appropriately * @result self */ - fetchNextChunkElements; /*! * @nethod currentElement * @abstract Reads the current element of the current enumeration of the current * selected chunk. It stores a reference to this object so that subsequent * calls to this method will return the same object until the flag * elementFetched is set to NO * @result the current object */ - currentElement; /*! * @method hasNext * @result YES if there is an element to return via "next" */ - (BOOL) hasNext; /*! * @method next * @result next element of the current iteration or nil, if not existent. */ - next; @end /* ----------------------------------------- _FTPersistentSetTransactionSetp */ /*! * @class _FTPersistentSetTransactionStep * @abstract Internal method used to perform the database updates */ @interface _FTPersistentSetTransactionStep : FTObject + (void) initialze; /*! * @method addTransactionStepForChunk * @abstract Adds a transaction step to the current transaction in order * to update the given chunk for the given set. Does nothing if there already * exists a transaction for this chunk * @param aChunk chunk to update * @param aSet set the chunk belongs to */ + (void) addTransactionStepForChunk: (_FTPersistentSetChunk *) aChunk forSet: (FTPersistentSetImpl *) aSet; /*! * @method initWithChunk * @param chunk to update * @param aContext underlying transaction context * @result self */ - initWithChunk: (_FTPersistentSetChunk *) chunk forContext: (FTTransactionContext *) aContext; /*! * @method performAction * @abstract Called by the transaction controll in order to run the * transaction * @result return information about the success of this operation */ - (BOOL) performAction: (FTTransactionContext *) transactionContext; /*! * @method undoAction * @abstract removes all modifications previously been done by * {@link #performAction} * @result return YES if done successfully */ - (BOOL) undoAction: (FTTransactionContext *) transactionContext; @end #endif