// **********************************************************************
//
// Copyright (c) 1999
// Object Oriented Concepts, Inc.
// Billerica, MA, USA
//
// All Rights Reserved
//
// **********************************************************************

#ifndef OB_GIOP_CLIENT_H
#define OB_GIOP_CLIENT_H

//
// Declare OBGIOPClientWorker as a class
//
class OBGIOPClientWorker;
typedef OBGIOPClientWorker* OBGIOPClientWorker_ptr;
void OBDuplicate(OBGIOPClientWorker_ptr);
void OBRelease(OBGIOPClientWorker_ptr);
typedef OBObjVar< OBGIOPClientWorker > OBGIOPClientWorker_var;

//
// The OBGIOPClient class
//
class OBGIOPClient;
typedef OBGIOPClient* OBGIOPClient_ptr;
void OBDuplicate(OBGIOPClient_ptr);
void OBRelease(OBGIOPClient_ptr);
typedef OBObjVar< OBGIOPClient > OBGIOPClient_var;

class OBGIOPClient : public OBClient
{
    //
    // Hide copy-constructor and asignment operator
    //
    OBGIOPClient(const OBGIOPClient&);
    void operator=(const OBGIOPClient&);

protected:

    //
    // The connector
    //
    OCI_Connector_var connector_;
    
    //
    // The worker
    //
    OBGIOPClientWorker_var worker_;
#ifdef HAVE_JTC
    JTCMutex workerMutex_;
#endif

    //
    // Add message header and request header
    //
    void addHeaders(CORBA_Object_ptr, const char*, CORBA_ULong, bool,
		    OBBuffer&);

    //
    // Get the worker
    //
    OBGIOPClientWorker_ptr getWorker(CORBA_Long);
    
public:

    OBGIOPClient(OCI_Connector_ptr);
    virtual ~OBGIOPClient();

    static inline OBGIOPClient_ptr _duplicate(OBGIOPClient_ptr p)
    { if(p) p -> _OB_incRef(); return p; }
    static inline OBGIOPClient_ptr _nil()
    { return 0; }

    //
    // Destroy the client
    //
    virtual void destroy();

    //
    // Destroy the worker
    //
    void destroyWorker(OBGIOPClientWorker_ptr);

    //
    // Get the OCI Connector
    //
    virtual OCI_Connector_ptr connector();

    //
    // Get the OCI Transport
    //
    virtual OCI_Transport_ptr transport();
    
    //
    // Calculate offset
    //
    virtual CORBA_ULong offset(CORBA_Object_ptr, const char*);

    //
    // Send request and receive response
    // With explicit timeout (throws exception on timeout)
    // With optional retry on communication failure
    //
    virtual CORBA_ULong request(CORBA_Object_ptr, const char*, OBBuffer&,
				bool&, bool&, bool&, CORBA_Long, bool);

    //
    // Send request oneway
    // With implicit zero timeout (does not throw exception on timeout)
    // With optional retry on communication failure
    //
    virtual void oneway(CORBA_Object_ptr, const char*, OBBuffer&, bool);

    //
    // Send request deferred
    // With implicit zero timeout (does not throw exception on timeout)
    // With optional retry on communication failure
    //
    virtual void deferred(CORBA_Object_ptr, const char*, OBBuffer&,
			  CORBA_ULong&, bool);

    //
    // Get repsonse
    // With explicit timeout (throws exception on timeout)
    //
    virtual CORBA_ULong response(CORBA_ULong, OBBuffer&, bool&, bool&, bool&,
				 CORBA_Long);
    
    //
    // Poll response
    // With implicit zero timeout (returns zero on timeout)
    //
    virtual CORBA_ULong poll(CORBA_ULong, OBBuffer&, bool&, bool&, bool&);
};

inline void
CORBA_release(OBGIOPClient_ptr p)
{
    if(p)
	p -> _OB_decRef();
}

inline CORBA_Boolean
CORBA_is_nil(OBGIOPClient_ptr p)
{
    return p == 0;
}

#endif
