//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
//-----------------------------------------------------------------------------
//
// Description:
//       CA service class 
//
// Author:  Jie Chen
//
// Revision History:
//   caService.h,v
// Revision 1.8  1998/03/05  18:49:14  chen
// fix a bug on context == 2 on property channels
//
// Revision 1.7  1998/02/18  19:48:27  chen
// fix ca set access error
//
// Revision 1.6  1997/03/03  17:36:33  chen
// add buffering to channel access connection
//
// Revision 1.5  1996/09/10  19:21:16  chen
// change C++ include header
//
// Revision 1.4  1995/10/03  19:57:21  chen
// Add lookup table for attributes from tags
//
// Revision 1.3  1995/07/05  18:34:34  chen
// use default hash function
//
// Revision 1.2  1995/06/30  15:55:17  chen
// remove unnecessary files
//
// Revision 1.1.1.1  1995/06/16  17:14:03  epics
// initial import of cdev
//
// 
#ifndef _CA_SERVICE_H
#define _CA_SERVICE_H

#include <cdevSpec.h>
#include <cdevStrHash.h>
#include <cdevService.h>

#include "caChannel.h"

// epics stuff
#if !defined (_EPICS_3_12)
#define __STDC__
extern "C"{
#endif

#include <cadef.h>
#include <db_access.h>

#if !defined (_EPICS_3_12)
};
#undef __STDC__
#endif

extern "C" CDEVSVCAPI cdevService *newCaService (char *name, cdevSystem* system);

typedef struct _tag_to_attr
{
  int   tag;
  char* attr;
}caTagToAttr; 

class caService: public cdevService
{
 public:
  // constructor
  caService (char *name, cdevSystem &system = cdevSystem::defaultSystem ());

  int getFd (int * &fd, int &numFd);
  // PURPOSE: return channel access network file descriptors
  // REQUIRE: callers provide pointer only and don't free memory
  // PROMISE: numFd will be real number of file descriptors of the 
  //          channel access client. return 0: always

  int flush (void);
  // PURPOSE: flush network requests
  // REQUIRE: nothing
  // PROMISE: return 0: success, return 1: ca error

  int poll (void);
  // PURPOSE: polling method
  // REQUIRE: nothing
  // PROMISE: return 0: success, return 1: ca error

  int pend (int fd = -1);
  // PURPOSE: handle network pending 
  // REQUIRE: nothing
  // PROMISE: return 0: success, return 1: ca error
  int pend (double seconds, int fd = -1);
  // PURPOSE: handle network pending for 'seconds'
  // REQUIRE: nothing
  // PROMISE: return 0: success. return 1: ca error

  int getRequestObject (char *deviceName, char *msg,
			cdevRequestObject * &req);
  // PURPOSE: return a caRequestObject (called from attachPtr function
  //          of cdevRequestObject class)
  // REQUIRE: right pair of deviceName and msg. 
  // PROMISE: a caRequestObject

  int getNameServer (cdevDevice* &ns);
  // PURPOSE: retrieve ca name server in case of missing DDL
  // REQUIRE: nothing
  // PROMISE: a cdevDevice based ca name service

  int channelPtr (char *channelName, caChannel* &ch);
  // PURPOSE: check whether a channel has been created base on channel name
  // REQUIRE: channelName != 0
  // PROMISE: return 0: found a channel. return -1: no

  int addChannel (char *channelName, caChannel* chPtr);
  // PURPOSE: add a new channel to the table in caService
  // REQUIRE: channelName != 0 and chPtr != 0
  // PROMISE: This channle will be inserted only once. return 0: always

  int removeChannel (char *channelName, caChannel* chPtr);
  // PURPOSE: remove a channel from the table in caService
  // REQUIRE: channelName != 0 and chPtr != 0
  // PROMISE: This channle will be removed. return 0: always

  const char* attr (int tag) const;
  // PURPOSE: find a attribute of the ca record corresponding to a tag
  // REQUIRE: tag must be ca default tag, and used by caRequestObject only
  // PROMISE: return an attribute name

  // int tag for channel access
  static int CA_TAG_VALUE, CA_TAG_STATUS, CA_TAG_SEVERITY;
  static int CA_TAG_TIME, CA_TAG_UNITS, CA_TAG_DISPHI, CA_TAG_DISPLO;
  static int CA_TAG_ALRMHI, CA_TAG_ALRMLO, CA_TAG_WRNHI, CA_TAG_WRNLO;
  static int CA_TAG_CTRLHI, CA_TAG_CTRLLO, CA_TAG_RESULT_CODE;
  static int CA_TAG_PRECISION;
  // new tags
  static int CA_TAG_PV, CA_TAG_DFV, CA_TAG_RO;

  const char *className (void) const {return "caService";}

protected:
  // deny direct access to destructor
  ~caService (void);
  // map char tags to int tags
  static void mapCtagToItag (void);

  int handlePending (int fd);
  // keep fd information
  void addReadFd (int fd);
  void removeReadFd (int fd);

  // initialize tag to attribute translation table
  void initTagToAttrTable (void);

  // file descriptor callback routines for Channel access
  // must be static function
  static void fdRegCallback(void *args, int fd, int opend);
  static void exceptionCallback (struct exception_handler_args args);

 private:
  // file descriptors caService associated with
  int *fds_;
  int numFds_;
  // integer tag to attribute translation table
  caTagToAttr tagToAttrTb_[14];
  // default name service for channel access
  cdevDevice *nameSvc_;
  // hash table for channel access connection
  cdevStrHash channelTable_;
};
#endif
