/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */

#ifndef JNH_OBJECT_CACHE_
#define JNH_OBJECT_CACHE_

// Jonah ObjectCache
//
// The Object Cache is the top level of the Jonah objectStore, sitting
// above the QDISAM layer.  It maintains in-memory copies of the active 
// objects within the objectStore.  The server API controls when cached
// objects are destroyed or written back to the QDISAM store; the cache 
// merely follows orders.
//
// The cache provides several services:
//
// i) translation from 32-bit requestIDs to pointers to in-memory copies of
//    objectstore objects.  The value of a requestID is the same as the 
//    key used to retrieve that object's record from the QDISAM layer.
//
//    This funtion requires that the cache provide a fast lookup mechanism
//    to determine whether the designated object is already in memory, and 
//    if so return a pointer to it.  If the object is not in memory, it
//    should be read in from the QDISAM repository and a pointer to it 
//    returned.
//
// ii) The ability to write in-memory objects back to the backing-store.  
//
// iii) The ability to delete in-memory objects.
//
// iv) The ability to associate additional in-memory components with 
//     backing-store objects, which will not be saved back to disk.
//
// All objects that the server code will put in the objectstore will be
// of a single class, derived from asn_object.  The ObjectCache can use
// the read and write member functions of this class to populate an in-memory
// object from its flat on-disk equivalent, and to flatten an object for 
// storage on disk.
//
// Each in-memory object under the control of the objectCache is either locked
// or unlocked.  An unlocked object may be deleted by the objectCache at any 
// time, but is being retained in-memory to speed-up subsequent lookup operations.
// A locked object must be retained in memory until it is explicitly unlocked by
// the objectStore's caller.
//
// Additionally, each in-memory object under the control of the objectCache 
// has an associated <modified> flag.  This flag indicates whether the contents
// of the in-memory object has changed wrt the on-disk representation of the 
// object, and is set when the caller of the object retrieves the object 
// the the getObjectModify() function.  The objectCache uses this flag to determine
// whether the object needs to be re-read from disk when it in unlocked.



#include <asnbase.h>
#include <ObjectStore.h>
#include <ObjectDefs.h>
#include <pkiTask.h>


class TransientPassword : public buffer_t {
public:
  TransientPassword(void) : buffer_t(ASN_SECRET) {};
  bool is_present(void) { return data_len > 0; };
};

class TransientData {
public:
  TransientPassword objPwd;
  TransientPassword importPwd;
  TransientPassword pkcs12Pwd;
  TransientPassword pin;
  PrivateKeyInfo privKey;
  TransientData(void) {
    privKey.set_optional();
  };
};

class EXPORTCLASS CachedObj {
public:
  CachedObj * prev;
  CachedObj * next;
  uint32 key;
  pki_mutex_t mutex;
  bool deleting;
  bool locked;
  bool modified;
  uint32 objClass;
  ObjStoreData obj;
  TransientData transientData;
  CachedObj(void);
  ~CachedObj();
};

class EXPORTCLASS JnhObjectCache  {
private:
  JnhObjectStore * os;
  CachedObj * root;
  pki_mutex_t mutex;
  CachedObj * lookupObject(uint32 key);
  uint32 loadObject(uint32 key);
  uint32 reloadObject(CachedObj * ptr);
  uint32 writeObject(CachedObj * ptr);
  uint32 discardObject(uint32 key, bool lockList);  
  uint32 discardObjectNocheck(uint32 key, bool lockList);  
public:
  JnhObjectCache(int size = 10);
// Create and initialize the objectCache. The <size>
// parameter gives a hint as to the number of active 
// objects that the server will want to maintain.  The default 
// value, 10, is probably typical of end-systems; CAs and RAs
// will probably want to deal with more objects.  This parameter 
// is only a hint, and is expected to be used by the objectCache
// in determining when to reclaim memory occupied by unlocked 
// objects.

  uint32 storeObject(ObjStoreData * objectPtr, uint32 objClass, uint32 * key);
// storeObject saves the provided object in the backing-store,
// and returns the new key.  This is how new objects are placed
// in the objectstore.  The objectstore does not take ownership 
// of the object designated by objectPtr;  A subsequent getObject
// operation using this key will result in a new in-memory object 
// being created.  Therefore the caller should discard the 
// original object after making this call.  If the objectCache
// keeps its own in-memory copy of the object, that copy shall 
// be marked unlocked and unmodified.

  uint32 createObject(uint32 objClass, ObjStoreData ** objectPtr, uint32 * key);
// createObject creates a new object, assigns a objectstore key to it,
// and returns the new key and object, which is marked locked and modified.  
// The objectStore owns the object designated by objectPtr, so the caller
// must not destroy it.  

  uint32 getObject(uint32 key, uint32 * objClass, const ObjStoreData ** objectPtr);  
// getObject retrieves a read-only pointer to the object whose 
// key is <key>.  The object must previously have been locked with
// a call to lockObject()


  uint32 getObjectModify(uint32 key, uint32 * objClass, ObjStoreData ** objectPtr);  
// getObjectModify retrieves a pointer to the object whose key 
// is <key>.  the object must previously have been locked with
// a call to lockObject().  The object's <modified> flag will 
// be set.

  uint32 getTransientData(uint32 key, 
                          TransientData ** transientData);  
// getTransientData retrieves a pointer to the transient data associated
// with the object whose key is <key>.  The object must previously have been 
// locked with a call to lockObject()



  uint32 getObjectFlags(uint32 key, uint32 * objClass);
// getObjectFlags returns the flags associated with the specified
// object.  The object must be locked.

  uint32 setObjectFlags(uint32 key, uint32 objClass);
// setObjectFlags sets the flags associated with the specified
// object.  The object must be locked and marked for modification.

  uint32 lockObject(uint32 key);  
// Lock the specified object.  The object will be read from disk if
// necessary.

  uint32 unlockObject(uint32 key);  
  uint32 discardObject(uint32 key);  
// discard any changes that may have been made to the in-memory
// object.  After either of these calls, the caller must make 
// a getObject call before it may access the object again.  
// The semantics of these calls are identical. The distinction 
// between the two functions is that discardObject indicates 
// that the caller has no subsequent intent to activate the 
// object, while unlockObject indicates that subsequent access
// is likely.  This may affect whether the objectCache implements
// the function simply by deleting the in-memory object, or (if 
// the object's <modified> flag is set) by re-reading its contents 
// from disk, although either implementation will work for either 
// function.  After either call, if the object is retained in memory,
// it will be unlocked and its <modified> flag cleared.  Prior to
// either call, the caller must have invoked getObject or 
// getObjectModify to gain access to the object.
  
  uint32 synchObject(uint32 key);
// synchObject replaces the designated object in the backing-store.
// If the object is not locked, an error should be returned and no 
// action performed.  If the object's <modified> flag is not set, 
// an error should be returned, and no action performed.  On 
// succesful completion, the object's <modified> flag is cleared, 
// and the object is unlocked.
  
  uint32 deleteObject(uint32 key);
// deleteObject deletes the designated object, both from memory and
// from the backing-store.  The object must be locked
// prior to this call, and the state of its <modified> flag is
// not significant.


  ~JnhObjectCache();
// The ObjectCache destructor should destroy all in-memory objects.

  uint32 ListActiveObjects(void (* callback)(uint32 key, 
                                             uint32 objClassSt));
// Run through the database, calling <callback> for every object whose 
// objClass is active

  uint32 ListSurrogateObjects(void (* callback)(uint32 key, 
                                                uint32 objClassSt));
// Run through the database, calling <callback> for every object whose 
// objClass is surrogate

  uint32 ListObjectsByClass(uint32 objClass,
                            void (* callback)(uint32 key, 
                                              uint32 objClassSt));
// Run through the database, calling <callback> for every object
// whose objClass intersects the specified class (masked with ObjClAll)

  uint32 ListObjectsByState(uint32 objClass,
                            void (* callback)(uint32 key, 
                                              uint32 objClassSt));
// Run through the database, calling <callback> for every object
// whose state matches the specified state (masked with ObjStAll)


};




#endif