text: /**********************************************************************
  // @@@ START COPYRIGHT @@@
  //
  // Licensed to the Apache Software Foundation (ASF) under one
  // or more contributor license agreements.  See the NOTICE file
  // distributed with this work for additional information
  // regarding copyright ownership.  The ASF licenses this file
  // to you under the Apache License, Version 2.0 (the
  // "License"); you may not use this file except in compliance
  // with the License.  You may obtain a copy of the License at
  //
  //   http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing,
  // software distributed under the License is distributed on an
  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied.  See the License for the
  // specific language governing permissions and limitations
  // under the License.
  //
  // @@@ END COPYRIGHT @@@
  **********************************************************************/
  #ifndef __EX_UDR_SERVER_H
  #define __EX_UDR_SERVER_H
  
  /* -*-C++-*-
   *****************************************************************************
   *
   * File:         ExUdrServer.h
   * Description:  Client-side process management for UDR servers
   *               
   * Created:      08/16/2000
   * Language:     C++
   *
   *
   *****************************************************************************
   */
  
  #include "ComSmallDefs.h"
  #include "UdrExeIpc.h"
  #include "ExCollections.h"
  #include "NAUserId.h"
  
  // Default nowait depth of 3 is used for connections (except control
  // connection) to UDR Server
  #define DEFAULT_NOWAIT_DEPTH 3
  
  // -----------------------------------------------------------------------
  // Forward class references
  // -----------------------------------------------------------------------
  class UdrControlMsg;
  class UdrClientControlStream;
  class ExUdrTcb;
  class IpcProcessId;
  
  // -----------------------------------------------------------------------
  // Classes defined in this file
  // -----------------------------------------------------------------------
  class ExUdrServer;
  class ExUdrServerManager;
  
  extern NABoolean ProcessIdIsNull(const IpcProcessId &);
  extern void InvalidateProcessId(IpcProcessId &);
  
  // -----------------------------------------------------------------------
  // ExUdrServer
  // -----------------------------------------------------------------------
  class ExUdrServer : public NABasicObject
  {
  public:
    enum ExUdrServerStatus
    {
      EX_UDR_SUCCESS = 0,
      EX_UDR_WARNING,
      EX_UDR_ERROR
    };
  
    enum ExUdrServerState
    {
      EX_UDR_NOT_STARTED = 0,
      EX_UDR_READY,
      EX_UDR_BROKEN
    };
  
    ExUdrServer(IpcEnvironment *env,
                const Int32 &userId,
                const char *options,
                const char *optionDelimiters,
                const char *userName,
                const char *userPassword,
                IpcServerClass *serverClass);
  
    ~ExUdrServer();
  
    void setState(ExUdrServerState state) { state_ = state; }
    ExUdrServerState getState() const { return state_; }
  
    void setDedicated(NABoolean dedicated) { dedicated_ = dedicated; }
    NABoolean isDedicated(void) { return dedicated_;}
    void setInUse(NABoolean inUse) { inUse_ = inUse; }
    NABoolean inUse(void){ return inUse_;}
  
    ExUdrServerStatus start(ComDiagsArea **diags,
                            CollHeap *diagsHeap,
                            Int64 transId,
                            IpcProcessId &newId,
                            NABoolean usesTransactions);
    ExUdrServerStatus stop();
    ExUdrServerStatus kill(ComDiagsArea *diags);
  
    const IpcProcessId getServerProcessId() const { return serverProcessId_; }
  
    const char *getOptions() const { return options_; }
    const char *getOptionDelimiters() const { return optionDelimiters_; }
  
    // Helper function to send down server-side runtime options. Must be
    // called only after successful startup of the server.
    void sendStartupOptions(ComDiagsArea **diags, CollHeap *diagsHeap,
                            Int64 transId);
  
    // Matchmaking logic to determine if this server has the requested
    // attributes
    NABoolean match(const Int32 &userId,
                    const char *options,
                    const char *optionDelimiters) const;
  
    //
    // Functions to quiesce the UDR server
    // - isIOPending() returns TRUE if any replies are outstanding.
    // - completeUdrRequests(TRUE) polls for I/O completion until
    //   isIOPending() returns FALSE. completeUdrRequests(FALSE)
    //   waits for one I/O to complete then returns.
    //
    NABoolean isIOPending(IpcConnection *conn) const;
    void completeUdrRequests(IpcConnection *conn, NABoolean waitForAllIO) const;
  
    IpcConnection *getUdrControlConnection() const;
  
    IpcConnection *getAnIpcConnection() const;
    void releaseConnection(IpcConnection *conn);
  
    IpcEnvironment *myIpcEnv() const { return ipcEnvironment_; }
    CollHeap *myIpcHeap() const;
  
    void incrRefCount() { ++refCount_; }
    void decrRefCount() { --refCount_; }
    void setRefCount(ComUInt32 refCount) { refCount_ = refCount; }
    ComUInt32 getRefCount() const { return refCount_; }
  
    const Int32 &getUserId() const { return userId_; };
  
  #ifdef UDR_DEBUG
    void setTraceFile(FILE *f)
    {
      traceFile_ = f;
    }
  #endif
  
  protected:
  
    inline NABoolean ready() const { return (state_ == EX_UDR_READY); }
  
    ExUdrServerState state_;
    IpcEnvironment *ipcEnvironment_;
    IpcServerClass *udrServerClass_;
    IpcServer *ipcServer_;
    IpcProcessId serverProcessId_;
    ULng32 startAttempts_;
  
    // The user identity for this UDR server
    Int32 userId_;
    char *userName_;
    char *userPassword_;
  
    // Server-side runtime options. Currently the options_ string stores
    // JVM startup options only.
    char *options_;
    char *optionDelimiters_;
  
    // A small summary of how reference count, dedicated and inUse flags
    // are used. Note that there are three layers of maintaining the 
    // usage of mxudr servers. First layer being the top layer.
    // First layer: Server Manager is an instance in CliGlobals. Server
    // manager either creates a new server process or returns a existing
    // server in its pool for reuse. Server manager maintains a single
    // list of servers.
    //
    // Second layer: ContextCli obtains servers from server manager or
    // the first layer on a need basis. ContextCli reuses servers in its
    // pool to service requests from various statements in its scope. 
    // contextCli can request a shared or a dedicated server from server
    // manager. A dedicated server request to server manager will always
    // return a server whose reference count is 1.   
  
    // Note that server manager upon request from other contextCli requests for
    // a shared mode server will not hand over a server from its pool that has
    // been already obtained as dedicated by another contextCli.
    
    // Referece count of server is always incremented by one (by the server
    // manager) when ContextCli obtaines a server from server manager. Once
    // the server is in ContextCli scope, its reference count is not altered 
    // in contextCli scope. Reference count is decremented once contectCli 
    // returns the server back to server manager. Once the server is returned 
    // back to server manager, it is free to be reassined to other contextCli
    // requests as a shared or dedicated server.
  
    // ContextCli uses the list of servers to complete Io or return back servers
    // when under certain scenarios. search for udrServerList_ in contextCli scope.
  
    // Third layer: ex_exe_statement_globals obtains servers from contextcli on 
    // a demand basis. Multiple tcbs in a statment may use a server that is obtained
    // from contextcli in shared mode. For TMUDF tcbs, a dedicated server from
    // contextCli would be obtained in dedicated mode. ex_exe_statement_globals
    // maintains a single pointer to server that is obtained in shared mode and
    // a separate list of pointers to servers that have been obtained in dedicated mode.
    // Ex_exe_statement_global sets the inUse_ flag for dedicated servers so that
    // contextCli does not hand the same dedicated server to other statements.
  
  
  
    // Number of contexts and TCBs using this ExUdrServer object.  A
    // refCount of 0 means no other objects are using this UDR server
    // and it can be returned to the pool of idle servers, or released.
    ComUInt32 refCount_;
  
    // This flag indicates that the server is obtained as dedicated and
    // cannot be shared with other contextCli requests. Usually this flag
    // is set dedicated by contextCli attempting to get this server in dedicated
    // mode, usuually to service a TMUDF client. A dedicated server is 
    // usually used by one client and never shared until it is not in use. 
    // see inUse_ flag.
    NABoolean dedicated_;
  
    // Ex_exe_statement_global sets the inUse_ flag for dedicated servers so that
    // contextCli does not hand the same dedicated server to other statements. 
    // inUse_ flag is reset once a statement is deallocated.
    NABoolean inUse_;
  
  
    // Lists to maintain IPC Connections to the UDR Server process
    NAList<IpcConnection *> *inUseConns_;
    NAList<IpcConnection *> *freeConns_;
  
  #ifdef UDR_DEBUG
    FILE *traceFile_;
  #endif
  
  private:
    ExUdrServer(); // do not implement a default constructor
  
  };
  
  
  // -----------------------------------------------------------------------
  // ExUdrServerManager
  // -----------------------------------------------------------------------
  class ExUdrServerManager : public NABasicObject
  {
  public:
  
    ExUdrServerManager(
      IpcEnvironment *env,
      ComUInt32      maxServersPerGroup = 1);
  
    ~ExUdrServerManager();
  
    // This method provides access to a UDR server with the requested
    // attributes. Successful completion of this method does not
    // guarantee that the process is actually started. Currently the
    // options parameter is for JVM startup options only, and simple
    // string comparision is our test to determine if two option sets
    // are equivalent.
    ExUdrServer *acquireUdrServer(const Int32 &userId,
                                  const char *options,
                                  const char *optionDelimiters,
                                  const char *userName,
                                  const char *userPassword,
                                  NABoolean dedicated = FALSE);
  
    // Decrement the reference count for a given ExUdrServer instance
    void releaseUdrServer(ExUdrServer *udrServer);
  
    // This is the heap that will be used for all dynamic memory
    // allocations
    inline CollHeap *myIpcHeap() const
    {
      return ipcEnvironment_->getHeap();
    }
  
    inline ComUInt32 getMaxServersPerGroup() const
    { return maxServersPerGroup_; }
  
  protected:
  
    // We need an IpcEnvironment pointer to create ExUdrServer objects.
    // That's why we store this here. All ExUdrServer objects share
    // this pointer.
    IpcEnvironment *ipcEnvironment_;
  
    // Server class used to create a server process. This pointer will
    // be copied to all ExUdrServer objects.
    IpcServerClass *udrServerClass_;
  
    // Pool of ExUdrServers
    LIST(ExUdrServer*) serverPool_;
  
    // Maximum number of servers an executor can create with a given set
    // of attributes. Currently this value is set to 1. In the future if
    // we want to manage multiple servers with the same attributes we
    // can set this value higher.
    ComUInt32 maxServersPerGroup_;
  
    // The following boolean helps us decide when it is OK to retain an
    // unused server in the pool for an application that only requires a
    // single server.
    NABoolean okToRetainOneServer_;
  
  #ifdef UDR_DEBUG
    FILE *traceFile_;
  #endif
  
  };
  
  #endif // __EX_UDR_SERVER_H
  
  