static char DataManager_id[] = "$Header: DataManager.cc,v 1.13 98/10/06 11:41:10 oreilly Exp $";

/*
$Log:	DataManager.cc,v $
Revision 1.13  98/10/06  11:41:10  11:41:10  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.12  1998/05/18 19:53:19  oreilly
*** empty log message ***

Revision 1.11  1998/02/26 18:18:09  oreilly
*** empty log message ***

Revision 1.10  1998/02/23 16:33:45  oreilly
*** empty log message ***

Revision 1.9  1997/08/12 15:12:44  oreilly
*** empty log message ***

Revision 1.8  97/03/20  12:24:46  12:24:46  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.7  97/02/24  11:39:51  11:39:51  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.6  97/01/28  09:46:11  09:46:11  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.5  96/10/28  09:10:01  09:10:01  oreilly (Thomas C. O'Reilly)
*** empty log message ***

Revision 1.4  96/07/22  08:46:50  08:46:50  oreilly (Thomas C. O'Reilly)
Added RCS stuff

*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "DataManager.h"
#include "DmErrno.h"
#include "vxUtils.h"

#define dprintf if (debug) fprintf

DmObject::DmObject(const char *name, int arraySize)
{
  _name = strdup(name);
  _handle = NULL;
  _roleFlags = 0;
  _consumePeriod = _providePeriod = NO_PERIOD;
  _arraySize = arraySize;

  if (arraySize <= 0)
  {
    char errorBuf[errorMsgSize];
    sprintf(errorBuf, 
	    "DmObject::DmObject(%s) - Non-positive array size specified",
	    name);

    return;
  }
}


DmObject::DmObject(DM_Item *handle, int arraySize)
{
  // Find name
  DmItemSts status;
  Errno err;
  char buf[errorMsgSize];
  char errorBuf[errorMsgSize];
  if ((err = dm_item_status(handle[0], &status)) != SUCCESS)
  {
    sprintf(buf, "DmObject::DmObject(), item %s - dm_item_status()", 
	    status.is_name);
    
    sprintDmError(err, buf, errorBuf);

    setError(errorBuf);
    return;
  }

  _name = strdup(status.is_name);
  dm_item_status_free(&status);

  _handle = NULL;
  _roleFlags = 0;
  _consumePeriod = _providePeriod = 0;
  _arraySize = arraySize;  

  // Create internal copy of handles using malloc(), etc
  if (createHandle() == -1)
  {
    sprintf(errorBuf, "DmObject::DmObject(), item %s - createHandle() failed",
	    _name);
    return;
  }
}


DmObject::~DmObject()
{
  free(_name);
}


int DmObject::createItem(DM_Type type)
{
  MBool debug = TRUE;
  
  Errno status = dm_create((char *)_name, 1, &_handle, 
			   type, _arraySize,
			   DM_ENDT, 0);

  char errorBuf[errorMsgSize];
  char buf[512];
  sprintf(errorBuf, "createItem(), \"%s\" - ", (const char *)_name);

  switch (status)
  {
    case SUCCESS:
    case EDM_NAME_EXISTS:
    break;
    
    default:
    sprintf(buf, "DmStateObject::DmStateObject(%s)", _name);
    sprintDmError(status, buf, errorBuf);
    setError(errorBuf);
  }
  
  if (error())
  {
    return -1;
  }

  createHandle();

  if (error())
    return -1;

  return 0;
}


int DmObject::createHandle()
{
  char errorBuf[errorMsgSize];
  char *namePtr = (char *)((const char *)_name);
    
  /* Get handle to DM item */
  if ((_handle = dm_lookup(namePtr, 0)) == NO_ITEM)
  {
    sprintf(errorBuf, "createItem(), \"%s\" - dm_lookup() failed", namePtr);
    setError(errorBuf);
  }

  if (error())
    return -1;
  
  return 0;
} 


MBool DmObject::fatalError(Errno err)
{
  if (err != SUCCESS && err != EDM_TOOFAST && err != EDM_PERIOD)
    return TRUE;
  else
    return FALSE;
}


Errno DmObject::startProvide(Period period, ProviderType providerType)
{
  Errno ret;
  if (providerType == MultiProviders)
    ret = dm_start_multiple(_handle);
  else
    ret = dm_start_provider(_handle, period);
  
  if (ret == SUCCESS)
  {
    _providePeriod = period;
    _roleFlags |= DmProvideFlag;
    if (providerType == MultiProviders)
      _roleFlags |= DmMultiProvideFlag;
  }
  if (fatalError(ret))
    return ret;
  else
    return SUCCESS;
}


Errno DmObject::startProvide(ProviderType providerType)
{
  if (_providePeriod == NO_PERIOD)
    return EDM_GENERAL;
  else
    return startProvide(_providePeriod, providerType);
}


Errno DmObject::startConsume(Period period, SEM_ID wakeupSem)
{
  Errno ret;
  if ((ret = dm_start_consumer(_handle, period, wakeupSem)) 
      == SUCCESS || ret == EDM_TOOFAST || ret == EDM_PERIOD)
  {
    _consumePeriod = period;
    _roleFlags |= DmConsumeFlag;
  }
  if (fatalError(ret))
    return ret;
  else 
    return SUCCESS;
}


Errno DmObject::startConsume(SEM_ID wakeupSem)
{
  if (_consumePeriod == NO_PERIOD)
    return EDM_GENERAL;
  else
    return startConsume(_consumePeriod, wakeupSem);
}


Errno DmObject::setConsumePeriod(Period period)
{
  Errno ret;
  if ((ret = dm_set_period(_handle, period)) == SUCCESS ||
      ret == EDM_TOOFAST || ret == EDM_PERIOD)
    _consumePeriod = period;

  if (fatalError(ret))
    return ret;
  else
    return SUCCESS;
}


Errno DmObject::setProvidePeriod(Period period)
{
  _providePeriod = period;
  return SUCCESS;
}


Errno DmObject::stopProvide()
{
  Errno ret;
  if ((ret = dm_stop_provider(_handle)) == SUCCESS)
  {
    _roleFlags &= ~DmProvideFlag;    
    _roleFlags &= ~DmMultiProvideFlag;
  }

  if (fatalError(ret))
    return ret;
  else
    return SUCCESS;
}


Errno DmObject::stopConsume()
{
  Errno ret;
  if ((ret = dm_stop_consumer(_handle)) == SUCCESS)
    _roleFlags &= ~DmConsumeFlag;

  if (fatalError(ret))
    return ret;
  else
    return SUCCESS;
}


inline Errno DmObject::dmWrite(void *data, DM_Size bytes, DM_Time *t)
{
  Errno err;

  if (!t)
  {
    // Time not specified - get it with gettimeofday() 
    DM_Time dmTime;
    gettimeofday(&dmTime, NULL);
    err = dm_write(_handle, data, bytes, &dmTime);
  }
  else
    err = dm_write(_handle, data, bytes, t);

  return err;
}


Errno DmObject::urgentOpen(Period period)
{
  return dm_urgent_open(_handle, period);
}


Errno DmObject::urgentClose()
{
  return dm_urgent_close(_handle);
}



void DmObject::sprintDataType(DM_Type dmType, char *buf)
{
  
  switch (dmType)
  {
    case DM_CHAR:
    strcpy(buf, "DM_CHAR");
    break;
    
    case DM_UCHAR:
    strcpy(buf, "DM_UCHAR");
    break;

    case DM_INT16:
    strcpy(buf, "DM_INT16");
    break;
    
    case DM_NAT16:
    strcpy(buf, "DM_NAT16");
    break;
    
    case DM_INT32:
    strcpy(buf, "DM_INT32");
    break;
    
    case DM_NAT32:
    strcpy(buf, "DM_NAT32");
    break;
    
    case DM_MBOOL:
    strcpy(buf, "DM_MBOOL");
    break;
    
    case DM_FLT32:
    strcpy(buf, "DM_FLT32");
    break;
    
    case DM_FLT64:
    strcpy(buf, "DM_FLT64");
    break;
    
    case DM_PTR:
    strcpy(buf, "DM_PTR");
    break;
    
    case DM_ENUM:
    strcpy(buf, "DM_ENUM");
    break;
    
    case DM_ARRAY:
    strcpy(buf, "DM_ARRAY");
    break;
    
    case DM_STRUCT:
    strcpy(buf, "DM_STRUCT");
    break;
    
    case DM_EMPTY:
    strcpy(buf, "DM_EMPTY");
    break;
    
    default:
    strcpy(buf, "Unknown");
  }
  return;
}


void DmObject::buildName(char itemName[MaxDmNameLen], ...)
{
  MBool debug = FALSE;

  va_list argList;
  
  va_start(argList, itemName);

  char *namePtr = itemName;

  char *component;
  while ((component = va_arg(argList, char *)) != 0) {

    dprintf(stderr, "Adding component %s\n", component);

    // Check that components are separated by '.'
    if (namePtr != itemName && *(namePtr - 1) != '.') {
      *namePtr = '.';
      namePtr++;
    }

    strcpy(namePtr, component);
    namePtr += strlen(component);
  }

  *namePtr = '\0';

  va_end(argList);
  return;
}


void DmObject::buildPrefix(char itemName[MaxDmNameLen], ...)
{
  MBool debug = FALSE;

  va_list argList;
  
  va_start(argList, itemName);

  char *namePtr = itemName;

  char *component;
  while ((component = va_arg(argList, char *)) != 0) {

    dprintf(stderr, "Adding component %s\n", component);

    // Check that components are separated by '.'
    if (namePtr != itemName && *(namePtr - 1) != '.') {
      *namePtr = '.';
      namePtr++;
    }

    strcpy(namePtr, component);
    namePtr += strlen(component);
  }

  if (namePtr != itemName && *(namePtr - 1) != '.') {
    *namePtr = '.';
    namePtr++;
  }

  *namePtr = '\0';

  va_end(argList);
  return;
}



DmInt16Object::DmInt16Object(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_INT16);
}


Errno DmInt16Object::write(Int16 val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(Int16), t);
}


Errno DmInt16Object::write(Int16 *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(Int16) * _arraySize, t);
}


Errno DmInt16Object::read(Int16 *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(Int16) * _arraySize, t);
}


DmNat16Object::DmNat16Object(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_NAT16);
}


Errno DmNat16Object::write(Nat16 val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(Nat16), t);
}


Errno DmNat16Object::write(Nat16 *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(Nat16) * _arraySize, t);
}


Errno DmNat16Object::read(Nat16 *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(Nat16) * _arraySize, t);
}


DmNat32Object::DmNat32Object(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_NAT32);
}


Errno DmNat32Object::write(Nat32 val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(Nat32), t);
}


Errno DmNat32Object::write(Nat32 *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(Nat32) * _arraySize, t);
}


Errno DmNat32Object::read(Nat32 *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(Nat32) * _arraySize, t);
}


DmInt32Object::DmInt32Object(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_INT32);
}


Errno DmInt32Object::write(Int32 val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(Int32), t);
}


Errno DmInt32Object::write(Int32 *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(Int32) * _arraySize, t);
}


Errno DmInt32Object::read(Int32 *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(Int32) * _arraySize, t);
}


DmFlt32Object::DmFlt32Object(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_FLT32);
}


Errno DmFlt32Object::write(Flt32 val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(Flt32), t);
}


Errno DmFlt32Object::write(Flt32 *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(Flt32) * _arraySize, t);
}


Errno DmFlt32Object::read(Flt32 *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(Flt32) * _arraySize, t);
}


DmFlt64Object::DmFlt64Object(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_FLT64);
}


Errno DmFlt64Object::write(Flt64 val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(Flt64), t);
}


Errno DmFlt64Object::write(Flt64 *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(Flt64) * _arraySize, t);
}


Errno DmFlt64Object::read(Flt64 *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(Flt64) * _arraySize, t);
}


DmEnumObject::DmEnumObject(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_ENUM);
}


Errno DmEnumObject::write(Int32 val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(Nat32), t);
}


Errno DmEnumObject::write(Int32 *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(Nat32) * _arraySize, t);
}


Errno DmEnumObject::read(Int32 *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(Nat32) * _arraySize, t);
}


DmBooleanObject::DmBooleanObject(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_MBOOL);
}


Errno DmBooleanObject::write(MBool val, DM_Time *t)
{
  return dmWrite((void *)&val, sizeof(MBool), t);
}


Errno DmBooleanObject::write(MBool *val, DM_Time *t)
{
  return dmWrite((void *)val, sizeof(MBool) * _arraySize, t);
}


Errno DmBooleanObject::read(MBool *val, DM_Time *t)
{
  return dm_read(_handle, (void *)val, sizeof(MBool) * _arraySize, t);
}



DmEmptyObject::DmEmptyObject(const char *name, int arraySize) 
  : DmObject(name, arraySize)
{
  MBool debug = TRUE;
  
  createItem(DM_EMPTY);
}


Errno DmEmptyObject::write(DM_Time *t)
{
  char val;
  
  return dmWrite((void *)&val, 0, t);
}


Errno DmEmptyObject::read(DM_Time *t)
{
  char val;
  return dm_read(_handle, (void *)&val, 0, t);
}


DmStringObject::DmStringObject(const char *name, int maxLength)
  : DmObject(name, 1)
{
  char buf[100];
  char errorBuf[errorMsgSize];

  _maxLength = maxLength;

  Errno status = dm_create((char *)name, 1, &_handle, 
			   DM_CHAR, maxLength,
			   DM_ENDT, 0);

  switch (status)
  {
    case SUCCESS:
    case EDM_NAME_EXISTS:
    break;
    
    default:
    sprintf(buf, "DmStateObject::DmStateObject(%s)", name);
    sprintDmError(status, buf, errorBuf);
    setError(errorBuf);
    return;
  }

  createHandle();
}


Errno DmStringObject::read(char *str, DM_Time *t)
{
  Errno err = dm_read(_handle, (void *)str, _maxLength, t);
  str[_maxLength - 1] = '\0';
  return err;
}


Errno DmStringObject::write(char *str, DM_Time *t)
{
  return dmWrite((void *)str, _maxLength, t);
}







