/*
* Copyright (C) The Community OpenORB Project. All rights reserved.
*
* This software is published under the terms of The OpenORB Community Software
* License version 1.0, a copy of which has been included with this distribution
* in the LICENSE.txt file.
*/

#ifndef _COS_PERSISTENT_STATE_PSDL_
#define _COS_PERSISTENT_STATE_PSDL_

#include <orb.idl>
#include <CosTransactions.idl>

#pragma prefix "omg.org"

module CosPersistentState 
{    
    local interface CatalogBase;
    local interface Connector;
    local interface EndOfAssociationCallback;
    local interface Session;
    local interface SessionPool;
    local interface StorageHomeBase;
    local interface TransactionalSession;

    native StorageObjectBase;
    native StorageObjectFactory;
    native StorageHomeFactory;
    native SessionFactory;
    native SessionPoolFactory;

    exception NotFound {};

    typedef string TypeId;
    typedef CORBA::OctetSeq Pid;
    typedef CORBA::OctetSeq ShortPid;    

    #ifdef _PSDL_
    abstract storagetype StorageObject 
    {
        void destroy_object();
        
        boolean object_exists();

        Pid get_pid();

        ShortPid get_short_pid();

        StorageHomeBase get_storage_home();
    };    
    #endif    

            
    local interface ConnectorRegistry
    {
        Connector find_connector( in string implementation_id ) 
            raises( NotFound );

        void register_connector( in Connector c );

        void unregister_connector( in string implementation_id )
            raises( NotFound );
    };

    enum YieldRef { YIELD_REF };

    enum ForUpdate { FOR_UPDATE };

    typedef short IsolationLevel;

    const IsolationLevel READ_UNCOMMITTED = 0;
    const IsolationLevel READ_COMMITTED = 1;
    const IsolationLevel REPEATABLE_READ = 2;
    const IsolationLevel SERIALIZABLE = 3;

    typedef short TransactionPolicy;
    
    const TransactionPolicy NON_TRANSACTIONAL = 0;
    const TransactionPolicy TRANSACTIONAL = 1;
    
    typedef short AccessMode;
    
    const AccessMode READ_ONLY = 0;
    const AccessMode READ_WRITE = 1;

    struct Parameter 
    {
        string name;
        any val;
    };

    typedef sequence<Parameter> ParameterList;
    typedef sequence<TransactionalSession> TransactionalSessionList;

    //-------------------------------------------------------------
    // Connector
    //-------------------------------------------------------------

    local interface Connector 
    {
        readonly attribute string implementation_id;
        
        Pid get_pid(in StorageObjectBase obj);

        ShortPid get_short_pid(in StorageObjectBase obj);

        Session create_basic_session(in AccessMode access_mode,
                         in TypeId catalog_type_name,
                         in ParameterList additional_parameters );
        
        TransactionalSession create_transactional_session(
                         in AccessMode access_mode,
                         in IsolationLevel default_isolation_level,
                         in EndOfAssociationCallback callback,
                          in TypeId catalog_type_name,
                         in ParameterList additional_parameters );

        SessionPool create_session_pool(
                         in AccessMode access_mode,
                         in TransactionPolicy tx_policy,
                         in TypeId catalog_type_name,
                         in ParameterList additional_parameters );

        TransactionalSession current_session();

        TransactionalSessionList sessions(in CosTransactions::Coordinator transaction);

        StorageObjectFactory register_storage_object_factory(
                          in TypeId storage_type_name,
                          in StorageObjectFactory _factory );

        StorageHomeFactory register_storage_home_factory(
                          in TypeId storage_home_type_name,
                          in StorageHomeFactory _factory );

        SessionFactory register_session_factory(
                          in TypeId catalog_type_name,
                          in SessionFactory _factory );

        SessionPoolFactory register_session_pool_factory(
                          in TypeId catalog_type_name,
                          in SessionPoolFactory _factory );
    };
        
    //-------------------------------------------------------------
    // CatalogBase
    //-------------------------------------------------------------

    local interface CatalogBase 
    {

       /**
        * The read-only attribute <code>access_mode</code> returns the access mode of this catalog.
        * When the access mode is <code>READ_ONLY</code>, the storage object incarnations obtained
        * through storage home instances provided by this catalog are read-only.
        */
        readonly attribute AccessMode access_mode;

       /**
        * The <code>find_storage_home</code> operation can be used to obtain a storage home instance.
        * <code>find_storage_home</code> raises <code>NotFound</code> if it cannot find a storage home that
        * matches the given <code>storage_home_id</code>.
        * The format of the <code>storage_home_id</code> parameter is mostly implementation-defined.
        * In the case of type-specific catalogs (declared in PSDL), the provide declarations
        * define valid <code>storage_home_id</code> parameters. The <code>find_storage_home</code> operation
        * also understands <code>storage_home_id</code> that have the form of a PSDL type id.
        * <code>find_storage_home</code> looks up a PSDL-defined storage home with this type id in
        * the catalog’s default datastore. If the <code>storage_home_id</code> parameter has the form
        * <i>":datastore_name"</i>, where <i>datastore_name</i> is a string, <code>find_storage_home</code> returns
        * a storage home instance for the storage home associated with <code>java.lang.Object</code> (Java)
        * in this datastore.
        */
        StorageHomeBase find_storage_home(in string storage_home_id)
            raises (NotFound);

       /**
        * The <code>find_by_pid</code> operation attempts to locate a storage object
        * with the given PID in the storage homes provided by the target catalog.
        * @return StorageObjectBase an incarnation of this storage object
        * @exception NotFound if it cannot find a storage object with this pid. 
        */
        StorageObjectBase find_by_pid(in Pid the_pid) 
            raises (NotFound);

       /**
        * The <code>flush</code> operation instructs the PSS implementation to write to disk
        * any cached modifications of storage object incarnations managed by this catalog.
        * Often, when an application creates a new storage object or updates a storage object, the
        * modification is not written directly to disk -- the PSS implementation can cache some
        * dirty data.
        */
        void flush();

       /**
        * A PSS implementation can cache data read from the datastore(s). The
        * <code>refresh</code> operation instructs the PSS implementation to refresh any cached storage
        * object incarnations accessed by this catalog. This operation can invalidate any direct
        * reference to a storage object incarnation’s data member.
        */
        void refresh();

       /**
        * The operation <code>free_all</code> instructs the catalog 
        * implementation to set the reference count of all its PSDL storage object instances to 0.
        * In programming languages without garbage collection, such as C++, PSDL storage
        * object instances are reference-counted by the application. Further, when a PSDL
        * storage object A holds a reference to another PSDL storage object B, A’s instance
        * owns a reference count of B’s instance. When PSDL storage objects form a cyclic
        * graph, the corresponding instances own reference count of each other; even if the
        * programmer correctly releases all her reference counts, the cyclic graph will never be
        * completely released.  The <code>free_all</code> operation deals with this problem.
        */
        void free_all();

       /**
        * The operation <code>close</code> terminates the catalog. When closed, the catalog is also flushed.
        * If the catalog is associated with one or more transactions when <code>close</code> is
        * called, these transactions are marked roll-back only.
        */
        void close();
    };
    
    //-------------------------------------------------------------
    // StorageHomeBase
    //-------------------------------------------------------------

    local interface StorageHomeBase 
    {
        StorageObjectBase find_by_short_pid(in ShortPid short_pid)
            raises (NotFound);

        CatalogBase get_catalog();
    };
    
    //-------------------------------------------------------------
    // Session
    //-------------------------------------------------------------

    local interface Session : CatalogBase 
    {};

    //-------------------------------------------------------------
    // TransactionalSession
    //-------------------------------------------------------------

    local interface TransactionalSession : Session 
    {
        readonly attribute IsolationLevel default_isolation_level;

        typedef short AssociationStatus;

        const AssociationStatus NO_ASSOCIATION = 0;
        const AssociationStatus ACTIVE = 1;
        const AssociationStatus SUSPENDED = 2;
        const AssociationStatus ENDING = 3;

        void start(in CosTransactions::Coordinator transaction);

        void suspend(in CosTransactions::Coordinator transaction);

        void end( in CosTransactions::Coordinator transaction,
              in boolean success );

        AssociationStatus get_association_status();

        CosTransactions::Coordinator transaction();
    };
    
    local interface EndOfAssociationCallback 
    {
        void released(in TransactionalSession tsession );
    };

    //-------------------------------------------------------------
    // SessionPool
    //-------------------------------------------------------------

    typedef sequence<Pid> PidList;

    local interface SessionPool : CatalogBase 
    {
        void flush_by_pids(in PidList pids);

        void refresh_by_pids(in PidList pids);

        readonly attribute TransactionPolicy transaction_policy;
    };
};

#endif // _COS_PERSISTENT_STATE_PSDL_
