Package tcg.scada.da

Source Code of tcg.scada.da.DataPointServer

package tcg.scada.da;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import org.omg.CORBA.LongHolder;

import tcg.common.CorbaManager;
import tcg.common.DatabaseManager;
import tcg.common.LoggerManager;
import tcg.scada.cos.CosBooleanSeqHolder;
import tcg.scada.cos.CosDpErrorEnum;
import tcg.scada.cos.CosDpErrorSeqHolder;
import tcg.scada.cos.CosDpQualityEnum;
import tcg.scada.cos.CosDpServerException;
import tcg.scada.cos.CosDpServerExceptionCodeEnum;
import tcg.scada.cos.CosDpValueSeqHolder;
import tcg.scada.cos.CosDpValueStruct;
import tcg.scada.cos.CosDpValueTypeEnum;
import tcg.scada.cos.CosDpValueUnion;
import tcg.scada.cos.CosEquipmentStateSeqHolder;
import tcg.scada.cos.CosEquipmentStateStruct;
import tcg.scada.cos.CosHandleSeqHolder;
import tcg.scada.cos.CosStringSeqHolder;
import tcg.scada.cos.CosSubscriptionItemSeqHolder;
import tcg.scada.cos.CosSubscriptionItemStruct;
import tcg.scada.cos.ICosDataPointClient;
import tcg.scada.cos.ICosDataPointServerPOA;
import tcg.syscontrol.ManagedProcess;
import tcg.syscontrol.cos.CosOperationModeEnum;
import tcg.syscontrol.cos.CosPollException;
import tcg.syscontrol.cos.CosPollNotInModeException;
import tcg.syscontrol.cos.CosProcessStatusEnum;
import tcg.syscontrol.cos.CosProcessTypeEnum;
import tcg.syscontrol.cos.STR_DATAPOINT_SERVER;

public class DataPointServer extends ICosDataPointServerPOA implements
    IDataStore
{
  protected static Logger logger_ = LoggerManager
      .getLogger(DataPointServer.class.toString());

  private static final String SUBSYSTEM_TABLE = "SCADA_DA_SUBSYSTEM";
  private static final String DATAPOINT_TABLE = "SCADA_DATAPOINT";
  private static final String DATAPOINT_LASTKNOWN_TABLE = "SCADA_DATAPOINT_LASTKNOWN";
  private static final String EQUIPMENT_TABLE = "SCADA_EQUIPMENT";
  private static final String EQUIPMENT_LASTKNOWN_TABLE = "SCADA_EQUIPMENT_LASTKNOWN";

  private DataPointList datapoints_ = new DataPointList();
  private DataPointList calculatedDataPoints_ = new DataPointList();
  private EquipmentList equipments_ = new EquipmentList();

  // list of subsystem
  private HashMap<Integer, ISubsystem> subsystems_ = new HashMap<Integer, ISubsystem>();

  // list of subscriptions
  private HashMap<Integer, SubscriptionGroup> subscriptions_ = new HashMap<Integer, SubscriptionGroup>();

  private int locationId_ = 0;

  private CosProcessStatusEnum state_ = CosProcessStatusEnum.StatUnstarted;
  private ManagedProcess parent_ = null;
  // private ICosProcessManager procManager_ = null;

  private String serverKey_ = "";
  private int corbaPort_ = 0;
  private long pid_ = 0;
  // private int managerPort_ = 0;
  private boolean hasManager_ = true;

  // private Properties props_ = null;

  // peer name and port number if we are running stand-alone without process
  // manager
  private String peerName_ = "";
  private int peerPort_ = 0;

  @SuppressWarnings("unused")
  private long updateTimestamp_ = 0;

  // prepared statements to update last known value
  private PreparedStatement stmtDataPoint_ = null;
  private PreparedStatement stmtEquipment_ = null;

  /**
   * Constructor
   *
   * @param agent
   *            - the managed process (event agent)
   */
  public DataPointServer(ManagedProcess agent, int locationId)
  {
    parent_ = agent;
    locationId_ = locationId;
    // workingDir_ = agent.getWorkingDirectory();
    corbaPort_ = agent.getCorbaPort();
    pid_ = agent.cosGetProcessId();
    hasManager_ = agent.isManagedAgent();
    // managerPort_ = agent.getProcessManagerPort();
    // props_ = agent.getRuntimeProperties();
    peerName_ = agent.getPeerName();
    peerPort_ = agent.getPeerPort();
    // server key to register with process manager
    serverKey_ = STR_DATAPOINT_SERVER.value + "-" + locationId;
  }

  /*
   * (non-Javadoc)
   *
   * @see tcg.scada.da.IDataStore#getDataPoint(java.lang.String)
   */
  public IDataPoint getDataPoint(String name)
  {
    return datapoints_.getByName(name);
  }

  /*
   * (non-Javadoc)
   *
   * @see tcg.scada.da.IDataStore#getDataPoint(int)
   */
  public IDataPoint getDataPoint(int keyId)
  {
    return datapoints_.getByKeyId(keyId);
  }

  /*
   * (non-Javadoc)
   *
   * @see tcg.scada.da.IDataStore#getEquipment(java.lang.String)
   */
  public IEquipment getEquipment(String name)
  {
    return equipments_.getByName(name);
  }

  /*
   * (non-Javadoc)
   *
   * @see tcg.scada.da.IDataStore#getEquipment(int)
   */
  public IEquipment getEquipment(int keyId)
  {
    return equipments_.getByKeyId(keyId);
  }

  /**
   * Notify the datapoint server when the datapoint has changed. Called by the
   * datapoint.
   *
   * @param datapoint
   *            - the datapoint that has changed
   */
  protected void onDataPointChange(DataPoint datapoint)
  {
    // validation
    if (datapoint == null)
      return;

    // update subscription list in all subscription group
    Iterator<SubscriptionGroup> it = subscriptions_.values().iterator();
    SubscriptionGroup subgroup = null;
    while (it.hasNext())
    {
      subgroup = it.next();
      if (subgroup != null)
      {
        subgroup.notifyDataPointChange(datapoint);
      }
    }

    // update datapoint last known value in database
    update_datapoint_lastknown(datapoint);

    // TODO: update peer dpserver (if any)
  }

  /**
   * Notify the datapoint server when the datapoint source
   * value/timestamp/quality has changed. Similar to onDataPointSource() but
   * here we do not update the datapoint last known. Called by the datapoint.
   *
   * @param datapoint
   *            - the datapoint that has changed
   */
  protected void onDataPointSourceChange(DataPoint datapoint)
  {
    // validation
    if (datapoint == null)
      return;

    // update subscription list in all subscription group
    Iterator<SubscriptionGroup> it = subscriptions_.values().iterator();
    SubscriptionGroup subgroup = null;
    while (it.hasNext())
    {
      subgroup = it.next();
      if (subgroup != null)
      {
        subgroup.notifyDataPointSourceChange(datapoint);
      }
    }

    // TODO: update peer dpserver (if any)
  }

  /**
   * Notify the datapoint server when the equipment has changed. Called by the
   * equipment.
   *
   * @param equipment
   *            - the equipment that has changed
   */
  protected void onEquipmentChange(Equipment equipment)
  {
    // update equipment last known value in database
    update_equipment_lastknown(equipment);

    // TODO: update peer dpserver (if any)
  }

  public boolean initialize()
  {
    state_ = CosProcessStatusEnum.StatStartup;

    // initialize the corba manager. if it is already initialize, this does
    // nothing
    if (!CorbaManager.initialize(corbaPort_))
    {
      logger_.error("Can not initialize Corba Manager");
      state_ = CosProcessStatusEnum.StatUnstarted;
      return false;
    }

    // activate servant with this corba manager
    logger_.debug("Activating corba servant...");
    if (!CorbaManager.activate(this, serverKey_))
    {
      logger_.error("Can not activate servant datapoint store.");
      state_ = CosProcessStatusEnum.StatUnstarted;
      return false;
    }

    if (hasManager_)
    {
      if (!CorbaManager.registerCorbaServer(serverKey_, this._this()))
      {
        logger_.error("Can not register with Process Manager!");
        state_ = CosProcessStatusEnum.StatUnstarted;
        return false;
      }
    }
    else
    {
      // make sure reference to process manager is null. just in case
      // somebody mess around with it.
      // procManager_ = null;
    }

    // database access. critical section
    Connection conn = DatabaseManager.getConnection();
    if (conn == null)
    {
      logger_.error("Can not get connection to database!");
      state_ = CosProcessStatusEnum.StatUnstarted;
      return false;
    }

    String query = "";
    Statement stmt = null;
    ResultSet rs = null;

    // get the list of subsystems from database
    try
    {
      query = "select KEYID, NAME, PROTOCOL_TYPE, STATUS_POLLING_RATE, MULTIPLE_SOCKET, "
          + "PRIMARY_IPADDR, PRIMARY_PORT, PRIMARY_PORT_RANGE, PRIMARY_DEVICEID, "
          + "STANDBY_IPADDR, STANDBY_PORT, STANDBY_PORT_RANGE, STANDBY_DEVICEID, "
          + "SWC_CONN_TIMEOUT, SWC_SOCK_TIMEOUT, SWC_IDLE_TIMEOUT "
          + "from "
          + SUBSYSTEM_TABLE
          + " "
          + "where LOCATION_ID="
          + locationId_;
      logger_.debug("Query: " + query);

      stmt = conn.createStatement();
      rs = stmt.executeQuery(query);

      String tmpStr = "";
      while (rs.next())
      {
        SubsystemConfig config = new SubsystemConfig();
        config.keyId = rs.getInt(1);
        config.name = rs.getString(2);
        config.type = ESubsystemType.valueOf(rs.getString(3));
        if (config.type == null)
        {
          config.type = ESubsystemType.SUBSYSTEM_MODBUS;
        }
        config.statusPollingRate = rs.getInt(4);
        tmpStr = rs.getString(5);
        if (tmpStr != null && tmpStr.compareToIgnoreCase("Y") == 0)
        {
          config.isMultipleSocket = true;
        }
        else
        {
          config.isMultipleSocket = false;
        }
        // primary host
        config.primaryHost.hostname = rs.getString(6);
        config.primaryHost.startPort = rs.getInt(7);
        config.primaryHost.portRange = rs.getShort(8);
        config.primaryHost.deviceId = rs.getShort(9);
        // standby host
        config.standbyHost.hostname = rs.getString(10);
        if (config.standbyHost.hostname != null
            && config.standbyHost.hostname.length() > 0)
        {
          config.standbyHost.startPort = rs.getInt(11);
          if (config.standbyHost.startPort <= 0)
          {
            config.standbyHost.startPort = config.primaryHost.startPort;
          }
          config.standbyHost.portRange = rs.getShort(12);
          if (config.standbyHost.portRange <= 0)
          {
            config.standbyHost.portRange = config.primaryHost.portRange;
          }
          config.standbyHost.deviceId = rs.getShort(13);
          if (config.standbyHost.deviceId < 0) // 0 is a valid device
          // id!
          {
            config.standbyHost.deviceId = config.primaryHost.deviceId;
          }
        }
        // timeout setting
        config.timeout.connTimeoutMillis = rs.getInt(14);
        if (config.timeout.connTimeoutMillis <= 0)
        {
          config.timeout.connTimeoutMillis = SubsystemConfig.DEF_CONN_TIMEOUT_MILLIS;
        }
        config.timeout.sockTimeoutMillis = rs.getInt(15);
        if (config.timeout.sockTimeoutMillis <= 0)
        {
          config.timeout.sockTimeoutMillis = SubsystemConfig.DEF_SOCK_TIMEOUT_MILLIS;
        }
        config.timeout.idleTimeoutMillis = rs.getInt(16);
        if (config.timeout.idleTimeoutMillis <= 0)
        {
          config.timeout.idleTimeoutMillis = SubsystemConfig.DEF_IDLE_TIMEOUT_MILLIS;
        }
        // create the subsystem
        ISubsystem subsystem = null;
        if (config.type == ESubsystemType.SUBSYSTEM_MODBUS)
        {
          subsystem = new tcg.scada.da.modbus.ModbusSubsystem(config);
        }
        else if (config.type == ESubsystemType.SUBSYSTEM_IEC104)
        {
          subsystem = new tcg.scada.da.iec.IecSubsystem(config);
        }
        // add to the list of subsystem
        subsystems_.put(config.keyId, subsystem);
      }

      rs.close();
      stmt.close();
    }
    catch (SQLException sqle)
    {
      logger_.error("Can not get list of subsystems. Exception: "
          + sqle.toString());
      state_ = CosProcessStatusEnum.StatUnstarted;
      // clean up
      try
      {
        rs.close();
        stmt.close();
      }
      catch (Exception ex)
      {
      }
      // return database connection
      DatabaseManager.returnConnection(sqle.getErrorCode());
      return false;
    }

    // return database connection
    DatabaseManager.returnConnection(0);

    // for each configured subsystem, build the list of equipments and
    // datapoints
    Iterator<ISubsystem> it = subsystems_.values().iterator();
    while (it.hasNext())
    {
      // precautions
      if (it.next() == null)
      {
        continue;
      }
      // build list of equipments
      if (!build_equipment_list(it.next()))
      {
        logger_.warn("Can not build list of equipment for subsystem "
            + it.next().getName());
      }
      // build list of datapoints
      if (!build_datapoint_list(it.next()))
      {
        logger_.warn("Can not build list of datapoint for subsystem "
            + it.next().getName());
      }
    }

    // initialize all calculated points. this will parse the given
    // expression
    IDataPoint dp = null;
    for (int i = 0; i < calculatedDataPoints_.size(); i++)
    {
      dp = calculatedDataPoints_.get(i);
      if (dp != null)
      {
        dp.evaluate();
      }
    }

    state_ = CosProcessStatusEnum.StatStarted;
    return true;
  }

  /**
   * Start CONTROL mode. It is called when we are going to control mode.
   */
  protected boolean startControl()
  {
    // start all subsystems
    Iterator<ISubsystem> it = subsystems_.values().iterator();
    ISubsystem subsystem = null;
    while (it.hasNext())
    {
      subsystem = it.next();
      if (subsystem != null)
      {
        logger_.info("Starting subsystem " + subsystem.getName()
            + " to CONTROL mode.");
        subsystem.startControl();
      }
    }

    // update operation mode
    if (hasManager_)
    {
      if (!CorbaManager.updateCorbaServerOperationMode(serverKey_,
          CosOperationModeEnum.OperControl))
      {
        logger_.warn("Can not update operation mode of " + serverKey_
            + " to RUNNING CONTROL");
      }
    }

    return true;
  }

  /**
   * Stop CONTROL mode. It is called when we are leaving control mode.
   */
  protected boolean stopControl()
  {
    // stop all subsystems
    Iterator<ISubsystem> it = subsystems_.values().iterator();
    ISubsystem subsystem = null;
    while (it.hasNext())
    {
      subsystem = it.next();
      if (subsystem != null)
      {
        logger_.info("Stopping subsystem " + subsystem.getName()
            + " from CONTROL mode.");
        subsystem.stopControl();
      }
    }

    // update operation mode
    if (hasManager_)
    {
      if (!CorbaManager.updateCorbaServerOperationMode(serverKey_,
          CosOperationModeEnum.OperNotApplicable))
      {
        logger_.warn("Can not update operation mode of " + serverKey_
            + " to NOT APPLICABLE");
      }
    }

    return true;
  }

  /**
   * Start MONITOR mode. It is called when we are going to monitor mode. In
   * MONITOR mode, we just idle happily.
   */
  protected boolean startMonitor()
  {
    // TODO: subscribe for datapoint change in active dpserver
    // NOTE: subsription will not tell the flag status of datapoint
    // (inhibit/override/etc)!

    // start all subsystems in monitor mode
    Iterator<ISubsystem> it = subsystems_.values().iterator();
    ISubsystem subsystem = null;
    while (it.hasNext())
    {
      subsystem = it.next();
      if (subsystem != null)
      {
        logger_.info("Starting subsystem " + subsystem.getName()
            + " to MONITOR mode.");
        subsystem.startMonitor();
      }
    }

    // update operation mode
    if (hasManager_)
    {
      if (!CorbaManager.updateCorbaServerOperationMode(serverKey_,
          CosOperationModeEnum.OperMonitor))
      {
        logger_.warn("Can not update operation mode of " + serverKey_
            + " to RUNNING MONITOR");
      }
    }

    return true;
  }

  /**
   * Stop MONITOR mode. It is called when we are leaving monitor mode.
   */
  protected boolean stopMonitor()
  {
    // TODO: stop subscription to active dpserver (if it still exist)

    // stop all subsystems from monitor mode
    Iterator<ISubsystem> it = subsystems_.values().iterator();
    ISubsystem subsystem = null;
    while (it.hasNext())
    {
      subsystem = it.next();
      if (subsystem != null)
      {
        logger_.info("Stopping subsystem " + subsystem.getName()
            + " from MONITOR mode.");
        subsystem.stopMonitor();
      }
    }

    // update operation mode
    if (hasManager_)
    {
      if (!CorbaManager.updateCorbaServerOperationMode(serverKey_,
          CosOperationModeEnum.OperNotApplicable))
      {
        logger_.warn("Can not update operation mode of " + serverKey_
            + " to NOT APPLICABLE");
      }
    }

    return true;
  }

  /*
   * (non-Javadoc)
   *
   * @see tcg.scada.da.IDataStore#getDataPointList()
   */
  public final DataPointList getDataPointList()
  {
    return datapoints_;
  }

  /*
   * (non-Javadoc)
   *
   * @see tcg.scada.da.IDataStore#getEquipmentList()
   */
  public final EquipmentList getEquipmentList()
  {
    return equipments_;
  }

  private boolean build_equipment_list(ISubsystem subsystem)
  {
    // database access. critical section
    Connection conn = DatabaseManager.getConnection();
    if (conn == null)
    {
      logger_.error("Can not get connection to database!");
      return false;
    }

    String query = "";
    Statement stmt = null;
    ResultSet rs = null;

    // get the list of equipments from database
    try
    {
      query = "select A.KEYID, A.NAME, B.NOTE, B.HAS_TAG, B.HAS_PTW "
          + "from " + EQUIPMENT_TABLE + " A left outer join "
          + EQUIPMENT_LASTKNOWN_TABLE + " B " + "on A.KEYID=B.KEYID "
          + "where LOCATION_ID=" + locationId_ + " and SUBSYSTEM_ID="
          + subsystem.getKeyId() + " and " + "ASSET_NAME IS NOT NULL";
      logger_.debug("Query: " + query);

      stmt = conn.createStatement();
      rs = stmt.executeQuery(query);

      String str = "";
      while (rs.next())
      {
        // add logging context to equipment name
        NDC.push(rs.getString(2));
        // create the equipment
        Equipment eqpt = new Equipment();
        // eqpt.locationId = locationId_;
        eqpt.subsystem = subsystem;
        eqpt.keyId = rs.getInt(1);
        eqpt.name = rs.getString(2);
        // note
        str = rs.getString(3);
        if (str != null && str.length() > 0)
        {
          eqpt.setNote(str);
        }
        // tag
        str = rs.getString(4);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          eqpt.setTag();
        }
        else
        {
          eqpt.removeTag();
        }
        // permit to work
        str = rs.getString(5);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          eqpt.setPermitToWork();
        }
        else
        {
          eqpt.removePermitToWork();
        }
        // add to the list of equipment
        equipments_.add(eqpt);
        eqpt.setDataStore(this);
        // remove logging context
        NDC.pop();
      }

      rs.close();
      stmt.close();
    }
    catch (SQLException sqle)
    {
      logger_.error("Can not get list of equipments. Exception: "
          + sqle.toString());
      // clean up
      try
      {
        rs.close();
        stmt.close();
      }
      catch (Exception ex)
      {
      }
      // return database connection
      DatabaseManager.returnConnection(sqle.getErrorCode());
      return false;
    }

    // return database connection
    DatabaseManager.returnConnection(0);

    return true;
  }

  private boolean build_datapoint_list(ISubsystem subsystem)
  {
    // database access. critical section
    Connection conn = DatabaseManager.getConnection();
    if (conn == null)
    {
      logger_.error("Can not get connection to database!");
      return false;
    }

    String query = "";
    Statement stmt = null;
    ResultSet rs = null;

    // get the list of datapoints from database. set the initial state with
    // the last known value from database
    try
    {
      query = "select A.DATATYPE, A.KEYID, A.NAME, A.DPTYPE, A.WORD_ADDRESS, "
          + "A.BIT_ADDRESS, A.EQUIPMENT_ID, A.IS_EQPT_DATAPOINT, A.EXPRESSION, A.LCC_EXPRESSION, "
          + "A.RCC_EXPRESSION, B.IS_INHIBIT, B.IS_OVERRIDE, B.IS_ALARM_INHIBIT, B.IS_ALARM_NOTACK, "
          + "B.IS_ALARM_NOTNORM, B.SOURCE_VALUE, B.OUTPUT_VALUE "
          + "from "
          + DATAPOINT_TABLE
          + " A left outer join "
          + DATAPOINT_LASTKNOWN_TABLE
          + " B "
          + "on A.KEYID=B.KEYID "
          + "where A.LOCATION_ID="
          + locationId_
          + " and A.SUBSYSTEM_ID=" + subsystem.getKeyId();
      logger_.debug("Query: " + query);

      stmt = conn.createStatement();
      rs = stmt.executeQuery(query);

      int eqptId = 0;
      boolean isEqptDatapoint = false;

      boolean isInhibit, isOverride, isAlarmInhibit, isAlarmNotAck, isAlarmNotNorm;
      CosDpValueUnion sourceValue = null;
      CosDpValueUnion outputValue = null;

      String str = "";
      while (rs.next())
      {
        // add logging context
        NDC.push(rs.getString(3));
        // create the datapoint
        CosDpValueTypeEnum dataType = DataPoint
            .convString2CosDpValueTypeEnum(rs.getString(1));
        EDataPointType type = EDataPointType.from_string(rs
            .getString(4));
        // validation
        if (type == null || dataType == null)
        {
          logger_.warn("Invalid type (" + rs.getString(4)
              + ") or datatype (" + rs.getString(1) + ")");
          // remove logging context
          NDC.pop();
          continue;
        }
        DataPoint dp = DataPointFactory.createDataPoint(type, dataType);
        dp.subsystem = subsystem;
        // set other datapoint parameters
        dp.keyId = rs.getInt(2);
        dp.name = rs.getString(3);
        dp.address = rs.getInt(5);
        dp.bitAddress = rs.getShort(6);
        eqptId = rs.getInt(7);
        str = rs.getString(8);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          isEqptDatapoint = true;
        }
        else
        {
          isEqptDatapoint = false;
        }
        if (dp.getType() == EDataPointType.TYPE_CALCULATED)
        {
          str = rs.getString(9);
          if (str != null && str.length() > 0)
          {
            try
            {
              // because at this point the dplist is not
              // initialized completely
              // we can not properly initialize the calculated
              // expression.
              // must do it in later stage. for now, just store
              // the expression string
              dp.expression = str;
              // dp.setExpression(str);
            }
            catch (Exception ex)
            {
              logger_
                  .warn("Can not set expression for datapoint "
                      + dp.name
                      + ". Expression: "
                      + str
                      + ". Exception: " + ex.toString());
            }
          }
        }
        if (dp.getType() == EDataPointType.TYPE_OUTPUT)
        {
          str = rs.getString(10);
          if (str != null && str.length() > 0)
          {
            try
            {
              // because at this point the dplist is not
              // initialized completely
              // we can not properly initialize the LCC
              // expression.
              // must do it in later stage. for now, just store
              // the expression string
              dp.lccExpression = str;
              // dp.setLaunchCondition(str);
            }
            catch (Exception ex)
            {
              logger_
                  .warn("Can not set launching condition for datapoint "
                      + dp.name
                      + ". Expression: "
                      + str
                      + ". Exception: " + ex.toString());
            }
          }
          str = rs.getString(11);
          if (str != null && str.length() > 0)
          {
            try
            {
              // because at this point the dplist is not
              // initialized completely
              // we can not properly initialize the RCC
              // expression.
              // must do it in later stage. for now, just store
              // the expression string
              dp.rccExpression = str;
              // dp.setReturnCondition(str);
            }
            catch (Exception ex)
            {
              logger_
                  .warn("Can not set return condition for datapoint "
                      + dp.name
                      + ". Expression: "
                      + str
                      + ". Exception: " + ex.toString());
            }
          }
        }
        // last known value
        str = rs.getString(12);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          isInhibit = true;
        }
        else
        {
          isInhibit = false;
        }
        str = rs.getString(13);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          isOverride = true;
        }
        else
        {
          isOverride = false;
        }
        str = rs.getString(14);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          isAlarmInhibit = true;
        }
        else
        {
          isAlarmInhibit = false;
        }
        str = rs.getString(15);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          isAlarmNotAck = true;
        }
        else
        {
          isAlarmNotAck = false;
        }
        str = rs.getString(16);
        if (str != null && str.compareToIgnoreCase("Y") == 0)
        {
          isAlarmNotNorm = true;
        }
        else
        {
          isAlarmNotNorm = false;
        }
        // set the initial state
        dp._setInitialState(isInhibit, isOverride, isAlarmInhibit,
            isAlarmNotAck, isAlarmNotNorm);
        // source value
        str = rs.getString(17);
        if (str != null && str.length() > 0)
        {
          sourceValue = DataPoint.convString2CosDpValueUnion(dp
              .getInternalDataType(), str);
        }
        else
        {
          sourceValue = null;
        }
        // output value
        str = rs.getString(18);
        if (str != null && str.length() > 0)
        {
          outputValue = DataPoint.convString2CosDpValueUnion(dp
              .getInternalDataType(), str);
        }
        else
        {
          outputValue = null;
        }
        // set the initial value
        dp._setInitialValue(sourceValue, outputValue);
        // get the equipment parent of this datapoint
        // NOTE: this must be done after the datapoint states are
        // initialized with the last known values
        // to ensure that the equipment state are updated accordingly.
        Equipment eqpt = equipments_.getByKeyId(eqptId);
        if (eqpt != null)
        {
          // if it is an equipment datapoint, update the equipment
          if (isEqptDatapoint)
          {
            eqpt.datapoint = dp;
          }
          else
          {
            // else, add into the list of equipment's child
            // datapoints
            dp.setEquipment(eqpt);
            eqpt.addDataPoint(dp);
          }
        }
        // add into the list of datapoint
        datapoints_.add(dp);
        dp.setDataStore(this);
        // if it is calculated point, add into another optimization list
        if (dp.getType() == EDataPointType.TYPE_CALCULATED)
        {
          calculatedDataPoints_.add(dp);
        }
        // add into the list of subsystem' child datapoints
        subsystem.addDataPoint(dp);
        // remove logging context
        NDC.pop();
      }

      rs.close();
      stmt.close();
    }
    catch (SQLException sqle)
    {
      logger_.error("Can not get list of datapoints. Exception: "
          + sqle.toString());
      // clean up
      try
      {
        rs.close();
        stmt.close();
      }
      catch (Exception ex)
      {
      }
      // return database connection
      DatabaseManager.returnConnection(sqle.getErrorCode());
      return false;
    }

    // return database connection
    DatabaseManager.returnConnection(0);

    return true;
  }

  private String generate_subscription_name()
  {
    return UUID.randomUUID().toString();
  }

  private boolean is_closed_statement(Statement stmt)
  {
    try
    {
      return stmt.isClosed();
    }
    catch (SQLException sqle)
    {
      logger_.warn("Can not check SQL statement status. SQLException: "
          + sqle.toString());
      return false;
    }
  }

  private void update_datapoint_lastknown(DataPoint datapoint)
  {
    // reinitialize the prepared statement if necessary
    if (stmtDataPoint_ == null || is_closed_statement(stmtDataPoint_))
    {
      // re-initialize the prepared statement
      Connection conn = DatabaseManager.getConnection();
      if (conn == null)
      {
        logger_.error("Can not get connection to database.");
      }
      else
      {
        int errorCode = 0;
        try
        {
          String query = "update "
              + DATAPOINT_LASTKNOWN_TABLE
              + " set IS_INHIBIT=?, IS_OVERRIDE=?, IS_ALARM_INHIBIT=?, IS_ALARM_NOTACK=?, IS_ALARM_NOTNORM=?, "
              + " SOURCE_VALUE=?, OUTPUT_VALUE=?"
              + " where KEYID=?";
          logger_.debug("Query: " + query);

          stmtDataPoint_ = conn.prepareStatement(query);
        }
        catch (SQLException sqle)
        {
          logger_
              .error("Can not create prepare statement for datapoint update. SQLException: "
                  + sqle.toString());
          errorCode = sqle.getErrorCode();
          try
          {
            stmtDataPoint_.close();
          }
          catch (SQLException sqle2)
          {
            // ignore
          }
          stmtDataPoint_ = null;
        }
        // return the connection
        DatabaseManager.returnConnection(errorCode);
      }
    }

    // update datapoint last known value
    try
    {
      stmtDataPoint_.setString(1, datapoint.isInhibit() ? "Y" : "N");
      stmtDataPoint_.setString(2, datapoint.isOverride() ? "Y" : "N");
      stmtDataPoint_.setString(3, datapoint.isAlarmInhibit() ? "Y" : "N");
      stmtDataPoint_.setString(4, datapoint.isAlarmAcknowledged() ? "N"
          : "Y");
      stmtDataPoint_.setString(5, datapoint.isAlarmNormalized() ? "N"
          : "Y");
      stmtDataPoint_.setString(6, datapoint._getStringifiedSourceValue());
      stmtDataPoint_.setString(7, datapoint._getStringifiedValue());
      stmtDataPoint_.setInt(8, datapoint.keyId);
      // flush
      int counter = stmtDataPoint_.executeUpdate();
      if (counter == 0)
      {
        logger_.debug("Last known entry for datapoint "
            + datapoint.name
            + " does not exist yet. Creating one...");
        // entry does not exist yet. create one
        Connection conn = DatabaseManager.getConnection();
        if (conn == null)
        {
          logger_.error("Can not get connection to database.");
        }
        else
        {
          int errorCode = 0;
          PreparedStatement stmt = null;

          try
          {
            String query = "insert into "
                + DATAPOINT_LASTKNOWN_TABLE
                + "(KEYID,IS_INHIBIT, IS_OVERRIDE, IS_ALARM_INHIBIT, IS_ALARM_NOTACK, "
                + "IS_ALARM_NOTNORM, SOURCE_VALUE, OUTPUT_VALUE) "
                + "values(?,?,?,?,?,?,?,?)";
            logger_.debug("Query: " + query);

            stmt = conn.prepareStatement(query);
            stmt.setInt(1, datapoint.keyId);
            stmt.setString(2, datapoint.isInhibit() ? "Y" : "N");
            stmt.setString(3, datapoint.isOverride() ? "Y" : "N");
            stmt.setString(4, datapoint.isAlarmInhibit() ? "Y"
                : "N");
            stmt.setString(5, datapoint.isAlarmAcknowledged() ? "N"
                : "Y");
            stmt.setString(6, datapoint.isAlarmNormalized() ? "N"
                : "Y");
            stmt.setString(7, datapoint
                ._getStringifiedSourceValue());
            stmt.setString(8, datapoint._getStringifiedValue());
            // flush
            stmt.executeUpdate();
          }
          catch (SQLException sqle)
          {
            logger_
                .error("Can not insert last known value for datapoint "
                    + datapoint.name
                    + ". Exception: "
                    + sqle.toString());
            errorCode = sqle.getErrorCode();
          }
          finally
          {
            // close the statement
            try
            {
              if (stmt != null)
                stmt.close();
            }
            catch (SQLException sqle)
            {
              // ignore
            }
          }

          // return the connection
          DatabaseManager.returnConnection(errorCode);
        } // if (conn == null) - else
      } // if (counter == 0)
    }
    catch (SQLException sqle)
    {
      logger_.error("Can not update last known value for datapoint "
          + datapoint.name + ". Exception: " + sqle.toString());
      // just reset the prepared statement
      stmtDataPoint_ = null;
    }
  }

  private void update_equipment_lastknown(Equipment equipment)
  {
    // reinitialize the prepared statement if necessary
    if (stmtEquipment_ == null || is_closed_statement(stmtEquipment_))
    {
      // re-initialize the prepared statement
      Connection conn = DatabaseManager.getConnection();
      if (conn == null)
      {
        logger_.error("Can not get connection to database.");
      }
      else
      {
        int errorCode = 0;
        try
        {
          String query = "update "
              + EQUIPMENT_LASTKNOWN_TABLE
              + " set HAS_TAG=?, HAS_PTW=?, NOTES=? where KEYID=?";
          logger_.debug("Query: " + query);

          stmtEquipment_ = conn.prepareStatement(query);
        }
        catch (SQLException sqle)
        {
          logger_
              .error("Can not create prepare statement for equipment update. SQLException: "
                  + sqle.toString());
          errorCode = sqle.getErrorCode();
          try
          {
            stmtEquipment_.close();
          }
          catch (SQLException sqle2)
          {
            // ignore
          }
          stmtEquipment_ = null;
        }
        // return the connection
        DatabaseManager.returnConnection(errorCode);
      }
    }

    // update equipment last known value
    try
    {
      stmtEquipment_.setString(1, equipment.hasTag() ? "Y" : "N");
      stmtEquipment_
          .setString(2, equipment.hasPermitToWork() ? "Y" : "N");
      stmtEquipment_.setString(3, equipment.getNote());
      stmtEquipment_.setInt(4, equipment.keyId);
      // flush
      int counter = stmtEquipment_.executeUpdate();
      if (counter == 0)
      {
        logger_.debug("Last known entry for equipment "
            + equipment.name
            + " does not exist yet. Creating one...");
        // entry does not exist yet. create one
        Connection conn = DatabaseManager.getConnection();
        if (conn == null)
        {
          logger_.error("Can not get connection to database.");
        }
        else
        {
          int errorCode = 0;
          PreparedStatement stmt = null;

          try
          {
            String query = "insert into "
                + EQUIPMENT_LASTKNOWN_TABLE
                + "(KEYID, HAS_TAG, HAS_PTW, NOTES) "
                + "values(?,?,?,?)";
            logger_.debug("Query: " + query);

            stmt = conn.prepareStatement(query);
            stmt.setInt(1, equipment.keyId);
            stmt.setString(2, equipment.hasTag() ? "Y" : "N");
            stmt.setString(3, equipment.hasPermitToWork() ? "Y"
                : "N");
            stmt.setString(4, equipment.getNote());
            // flush
            stmt.executeUpdate();
          }
          catch (SQLException sqle)
          {
            logger_
                .error("Can not insert last known value for equipment "
                    + equipment.name
                    + ". Exception: "
                    + sqle.toString());
            errorCode = sqle.getErrorCode();
          }
          finally
          {
            // close the statement
            try
            {
              if (stmt != null)
                stmt.close();
            }
            catch (SQLException sqle)
            {
              // ignore
            }
          }

          // return the connection
          DatabaseManager.returnConnection(errorCode);
        } // if (conn == null) - else
      } // if (counter == 0)
    }
    catch (SQLException sqle)
    {
      logger_.error("Can not update last known value for equipment "
          + equipment.name + ". Exception: " + sqle.toString());
      // just reset the prepared statement
      stmtEquipment_ = null;
    }
  }

  @SuppressWarnings("unused")
  private synchronized int evaluate_calculated_points()
  {
    int counter = 0;
    CalculatedDataPoint dp = null;

    // reset the evaluated flag. this prevent multiple evaluation
    for (int idx = 0; idx < calculatedDataPoints_.size(); idx++)
    {
      dp = (CalculatedDataPoint) calculatedDataPoints_.get(idx);
      // reset the calculated flag
      if (dp != null)
      {
        dp.hasBeenEvaluated = false;
      }
    }

    // calculate each datapoint one by one
    for (int idx = 0; idx < calculatedDataPoints_.size(); idx++)
    {
      dp = (CalculatedDataPoint) calculatedDataPoints_.get(idx);
      // this should never happen, but in case there are some stupid
      // mistakes
      if (dp == null)
        continue;

      // calculate the value
      if (dp.evaluate() > 0)
      {
        counter++;
      }

      dp.hasBeenEvaluated = true;
    }

    // update the timestamp
    if (counter > 0)
    {
      // update the global update timestamp. always use the latest for
      // update timestamp
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemKeyId(String[] items, CosHandleSeqHolder keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    keyIds.value = new int[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        keyIds.value[i] = 0;
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }
      // found one
      keyIds.value[i] = dp.getKeyId();
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetItemValue(int[] keyIds,
      CosDpValueStruct[] values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    // precaution
    int arrLen = (keyIds.length > values.length) ? keyIds.length
        : values.length;
    errors.value = new CosDpErrorEnum[arrLen];

    IDataPoint dp = null;
    int counter = 0, status = 0;
    for (int i = 0; i < arrLen; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not set the value of an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // can not set the value of modbus point. use setoverride to do it.
      if (dp.getType() == EDataPointType.TYPE_REAL)
      {
        errors.value[i] = CosDpErrorEnum.ErrModbusPoint;
        continue;
      }

      // setting overrided or inhibited data points is not allowed
      // anyway, it is unlikely that non-modbus datapoint to be inhibitted
      // or overriden.
      if (dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsOverride;
        continue;
      }
      else if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // update the data points. do some datatype translation for
      // flexibility
      status = dp.setValue(values[i].value);
      if (status == 0)
      {
        errors.value[i] = CosDpErrorEnum.ErrAlreadyTheValue;
        continue;
      }
      else if (status < 0)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidValue;
        continue;
      }

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemValue2(String[] items,
      CosDpValueStruct[] values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    // precaution
    int arrLen = (items.length > values.length) ? items.length
        : values.length;
    errors.value = new CosDpErrorEnum[arrLen];

    IDataPoint dp = null;
    int counter = 0, status = 0;
    for (int i = 0; i < arrLen; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not set the value of an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // can not set the value of modbus point. use setoverride to do it.
      if (dp.getType() == EDataPointType.TYPE_REAL)
      {
        errors.value[i] = CosDpErrorEnum.ErrModbusPoint;
        continue;
      }

      // setting overrided or inhibited data points is not allowed
      // anyway, it is unlikely that non-modbus datapoint to be inhibitted
      // or overriden.
      if (dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsOverride;
        continue;
      }
      else if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // update the data points. do some datatype translation for
      // flexibility
      status = dp.setValue(values[i].value);
      if (status == 0)
      {
        errors.value[i] = CosDpErrorEnum.ErrAlreadyTheValue;
        continue;
      }
      else if (status < 0)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidValue;
        continue;
      }

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemValue(int[] keyIds, CosDpValueSeqHolder values,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    values.value = new CosDpValueStruct[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // can not get the value of an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // change the quality if override or inhibit flag is set
      if (dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityOverride;
      }
      else if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityInhibit;
      }
      else
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = dp.getQuality();
      }

      // success
      counter++;
    }

    return counter;
  }

  public int cosGetItemValue2(String[] items, CosDpValueSeqHolder values,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    values.value = new CosDpValueStruct[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // can not get the value of an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // change the quality if override or inhibit flag is set
      if (dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityOverride;
      }
      else if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityInhibit;
      }
      else
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = dp.getQuality();
      }

      // success
      counter++;
    }

    return counter;
  }

  public int cosGetItemSourceValue(int[] keyIds, CosDpValueSeqHolder values,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    values.value = new CosDpValueStruct[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // can not get the value of an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // change the quality if override or inhibit flag is set
      if (dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getSourceValue();
        values.value[i].timestamp = dp.getSourceTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityOverride;
      }
      else if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getSourceValue();
        values.value[i].timestamp = dp.getSourceTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityInhibit;
      }
      else
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value
        values.value[i].value = dp.getSourceValue();
        values.value[i].timestamp = dp.getSourceTimestamp();
        values.value[i].quality = dp.getQuality();
      }

      // success
      counter++;
    }

    return counter;
  }

  public int cosGetItemSourceValue2(String[] items,
      CosDpValueSeqHolder values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    values.value = new CosDpValueStruct[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // can not get the value of an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // change the quality if override or inhibit flag is set
      if (dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getSourceValue();
        values.value[i].timestamp = dp.getSourceTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityOverride;
      }
      else if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getSourceValue();
        values.value[i].timestamp = dp.getSourceTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityInhibit;
      }
      else
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value
        values.value[i].value = dp.getSourceValue();
        values.value[i].timestamp = dp.getSourceTimestamp();
        values.value[i].quality = dp.getQuality();
      }

      // success
      counter++;
    }

    return counter;
  }

  public int cosGetUpdatedItemValue(int[] keyIds, LongHolder timestamp,
      CosDpValueSeqHolder values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    long curtime = Calendar.getInstance().getTimeInMillis();
    long lasttime = timestamp.value;

    // return variable
    values.value = new CosDpValueStruct[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    // special case when no updates has happened. (due to error? or
    // stopped?)
    // Note: since now the datapoint can be updated directly, this is not
    // valid anymore!
    // if (lasttime >= updateTimestamp_)
    // {
    // for (int i=0; i < keyIds.length; i++)
    // {
    // errors.value[i] = CosDpErrorEnum.ErrNoUpdate;
    // //default value
    // values.value[i].value.longValue(0);
    // values.value[i].quality = CosDpQualityEnum.QualityBad;
    // values.value[i].timestamp = 0;
    // }
    // timestamp.value = curtime;
    // return 0;
    // }

    // check the datapoint one by one
    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // can not get the value of an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // only get the latest value if timestamp is later then the
      // reference/param timestamp
      if (lasttime >= dp.getUpdateTimestamp())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoUpdate;
        // default value
        values.value[i].value.longValue(0);
        values.value[i].quality = CosDpQualityEnum.QualityBad;
        values.value[i].timestamp = 0;
        continue;
      }

      // get the datapoint value
      if (dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityOverride;
      }
      else if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityInhibit;
      }
      else
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        // get the actual value
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = dp.getQuality();
      }

      // success
      counter++;
    }

    // update the client timestamp. always use the earliest timestamp
    timestamp.value = curtime;

    logger_.debug("No of updated datapoints: " + counter);
    return counter;
  }

  public int cosGetAllItems(CosStringSeqHolder items,
      CosHandleSeqHolder keyIds) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    int arrLen = datapoints_.size();
    items.value = new String[arrLen];
    keyIds.value = new int[arrLen];

    IDataPoint dp = null;
    for (int i = 0; i < arrLen; i++)
    {
      dp = datapoints_.get(i);
      if (dp == null)
      {
        // invalid dp, somehow!
        items.value[i] = "";
        keyIds.value[i] = 0;
      }
      else
      {
        // actual dp
        items.value[i] = dp.getName();
        keyIds.value[i] = dp.getKeyId();
      }
    }

    return arrLen;
  }

  public int cosGetAllUpdatedItemValue(LongHolder timestamp,
      CosHandleSeqHolder keyIds, CosDpValueSeqHolder values)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    long curtime = Calendar.getInstance().getTimeInMillis();
    long lasttime = timestamp.value;

    // special case when no updates has happened. (due to error? or
    // stopped?)
    // Note: since now the datapoint can be updated directly, this is not
    // valid anymore!
    // if (lasttime >= updateTimestamp_)
    // {
    // timestamp.value = curtime;
    // return 0;
    // }

    // temporary array for return value
    ArrayList<IDataPoint> updatedList = new ArrayList<IDataPoint>();

    IDataPoint dp = null;

    // check all datapoints one by one
    for (int i = 0; i < datapoints_.size(); i++)
    {
      dp = datapoints_.get(i);
      if (dp == null)
      {
        // invalid datapoint, somehow!
        continue;
      }

      // can not get the value of output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        continue;
      }

      // only get the latest value if timestamp is later then the
      // reference/param timestamp
      if (lasttime > dp.getUpdateTimestamp())
      {
        continue;
      }

      // add into the update list
      updatedList.add(dp);
    }

    // build the return value
    int arrLen = updatedList.size();
    keyIds.value = new int[arrLen];
    values.value = new CosDpValueStruct[arrLen];

    for (int i = 0; i < arrLen; i++)
    {
      dp = updatedList.get(i);
      // add the datapoint to the return parameter
      keyIds.value[i] = dp.getKeyId();
      // datapoint value
      if (dp.isOverride())
      {
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityOverride;
      }
      else if (dp.isInhibit())
      {
        // get the actual value but change the quality to override
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = CosDpQualityEnum.QualityInhibit;
      }
      else
      {
        // get the actual value
        values.value[i].value = dp.getValue();
        values.value[i].timestamp = dp.getTimestamp();
        values.value[i].quality = dp.getQuality();
      }
    }

    // update client timestamp. always use the earliest timestamp
    timestamp.value = curtime;

    logger_.debug("No of updated points: " + arrLen);
    return arrLen;
  }

  public synchronized int cosSetItemOverrideValue(int[] keyIds,
      CosDpValueStruct[] values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    // precaution
    int arrLen = (keyIds.length > values.length) ? keyIds.length
        : values.length;
    errors.value = new CosDpErrorEnum[arrLen];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < arrLen; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not override an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // TODO: should put the override and inhibit logic into the
      // datapoint itself

      // make override and inhibit an exclusive set
      // NOTE: another alternative design is to have override to imply
      // inhibit
      if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      if (!dp.setOverride(values[i].value))
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidValue;
        continue;
      }

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemOverrideValue2(String[] items,
      CosDpValueStruct[] values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    // precaution
    int arrLen = (items.length > values.length) ? items.length
        : values.length;
    errors.value = new CosDpErrorEnum[arrLen];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < arrLen; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not override an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // TODO: should put the override and inhibit logic into the
      // datapoint itself

      // make override and inhibit an exclusive set
      // NOTE: another alternative design is to have override to imply
      // inhibit
      if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      if (!dp.setOverride(values[i].value))
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidValue;
        continue;
      }

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemOverrideStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        status.value[i] = false;
        continue;
      }

      // can not override an output point. so just set to default
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        status.value[i] = false;
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // get override flag
      status.value[i] = dp.isOverride();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetItemOverrideStatus2(String[] items,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        // default value
        status.value[i] = false;
        continue;
      }

      // can not override an output point. so just set to default
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        status.value[i] = false;
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // get override flag
      status.value[i] = dp.isOverride();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveItemOverride(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not override an output point. consider it a success.
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // if it is not in override, ignore. but do not raise error
      // this is mostly to avoid unnecessary database update!
      if (!dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the override flag
      dp.removeOverride();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosRemoveItemOverride2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not override an output point. consider it a success.
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // if it is not in override, ignore. but do not raise error
      // this is mostly to avoid unnecessary database update!
      if (!dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the override flag
      dp.removeOverride();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemInhibit(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // TODO: should put the override and inhibit logic into the
      // datapoint itself

      // can not inhibit an output point
      // now, allow inhibitting control point. but it would be a control
      // inhibit

      // prevent scan inhibit of an already overridden datapoint.
      // make override and inhibit mutually exclusive states
      if (dp.getType() != EDataPointType.TYPE_OUTPUT && dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsOverride;
        continue;
      }

      // if it is already inhibit, ignore. but do not raise error
      // this is mostly to avoid unnecessary database update!
      if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the inhibit flag
      dp.setInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemInhibit2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // TODO: should put the override and inhibit logic into the
      // datapoint itself

      // can not inhibit an output point
      // now, allow inhibitting control point. but it would be a control
      // inhibit

      // prevent scan inhibit of an already overridden datapoint.
      // make override and inhibit mutually exclusive states
      if (dp.getType() != EDataPointType.TYPE_OUTPUT && dp.isOverride())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsOverride;
        continue;
      }

      // if it is already inhibit, ignore. but do not raise error
      // this is mostly to avoid unnecessary database update!
      if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the inhibit flag
      dp.setInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemInhibitStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        status.value[i] = false;
        continue;
      }

      // can not inhibit an output point.
      // now, allow inhibiting control point. but it would be a control
      // inhibit

      // get inhibit flag
      status.value[i] = dp.isInhibit();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetItemInhibitStatus2(String[] items,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        // default value
        status.value[i] = false;
        continue;
      }

      // can not inhibit an output point.
      // now, allow inhibiting control point. but it would be a control
      // inhibit

      // get inhibit flag
      status.value[i] = dp.isInhibit();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveItemInhibit(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not override an output point
      // now, allow inhibitting control point. but it would be a control
      // inhibit

      // if it is not in inhibit, ignore. but do not raise error
      // this is mostly to avoid unnecessary database update!
      if (!dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the inhibit flag
      dp.removeInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosRemoveItemInhibit2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not override an output point
      // now, allow inhibitting control point. but it would be a control
      // inhibit

      // if it is not in inhibit, ignore. but do not raise error
      // this is mostly to avoid unnecessary database update!
      if (!dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the inhibit flag
      dp.removeInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetControlItem(int[] keyIds,
      CosDpValueStruct[] values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // only can set control output datapoint
      if (dp.getType() != EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrNotOutputPoint;
        continue;
      }

      // if it is control inhibit, ignore
      if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // must have underlying subsystem
      if (dp.getSubsystem() == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidSubsystem;
        continue;
      }

      // check for launching condition
      try
      {
        if (!dp.checkLaunchCondition())
        {
          errors.value[i] = CosDpErrorEnum.ErrLaunchCondition;
          continue;
        }
      }
      catch (Exception ex)
      {
        logger_.warn("Can not evaluate launch condition for datapoint "
            + dp.getName() + ". Exception: " + ex.toString());
        errors.value[i] = CosDpErrorEnum.ErrLaunchCondition;
        continue;
      }

      // send to underlying subsystem
      boolean status = false;
      if (dp.getInternalDataType() == CosDpValueTypeEnum.TypeBoolean)
      {
        // already check for subsystem == null above
        status = dp.getSubsystem().setControl(dp,
            values[i].value.boolValue());
      }
      else if (dp.getInternalDataType() == CosDpValueTypeEnum.TypeNumber)
      {
        status = dp.getSubsystem().setControl(dp,
            values[i].value.longValue());
      }
      else
      {
        // can only send either pulse control or integer control
        errors.value[i] = CosDpErrorEnum.ErrInvalidDataType;
        continue;
      }

      // check the status
      if (!status)
      {
        errors.value[i] = CosDpErrorEnum.ErrSubsystemError;
        continue;
      }

      // store the value for historical purpose
      dp.setValue(values[i].value);

      // successful
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetControlItem2(String[] items,
      CosDpValueStruct[] values, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // only can set control output datapoint
      if (dp.getType() != EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrNotOutputPoint;
        continue;
      }

      // if it is control inhibit, ignore
      if (dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // must have underlying subsystem
      if (dp.getSubsystem() == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidSubsystem;
        continue;
      }

      // check for launching condition
      try
      {
        if (!dp.checkLaunchCondition())
        {
          errors.value[i] = CosDpErrorEnum.ErrLaunchCondition;
          continue;
        }
      }
      catch (Exception ex)
      {
        logger_.warn("Can not evaluate launch condition for datapoint "
            + dp.getName() + ". Exception: " + ex.toString());
        errors.value[i] = CosDpErrorEnum.ErrLaunchCondition;
        continue;
      }

      // send to underlying subsystem
      boolean status = false;
      if (dp.getInternalDataType() == CosDpValueTypeEnum.TypeBoolean)
      {
        // already check for subsystem == null above
        status = dp.getSubsystem().setControl(dp,
            values[i].value.boolValue());
      }
      else if (dp.getInternalDataType() == CosDpValueTypeEnum.TypeBoolean)
      {
        // already check for subsystem == null above
        status = dp.getSubsystem().setControl(dp,
            values[i].value.longValue());
      }
      else
      {
        // can only send either pulse control or integer control
        errors.value[i] = CosDpErrorEnum.ErrInvalidDataType;
        continue;
      }

      // check the status
      if (!status)
      {
        errors.value[i] = CosDpErrorEnum.ErrSubsystemError;
        continue;
      }

      // store the value for historical purpose
      dp.setValue(values[i].value);

      // successful
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemReturnConditionStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        status.value[i] = false;
        continue;
      }

      // check the return condition
      try
      {
        status.value[i] = dp.checkReturnCondition();
      }
      catch (Exception ex)
      {
        logger_
            .warn("Can not get return condition value for datapoint "
                + dp.getName()
                + ". Exception: "
                + ex.toString());
        status.value[i] = false;
      }

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetItemReturnConditionStatus2(String[] items,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        // default value
        status.value[i] = false;
        continue;
      }

      // check the return condition
      try
      {
        status.value[i] = dp.checkReturnCondition();
      }
      catch (Exception ex)
      {
        logger_
            .warn("Can not get return condition value for datapoint "
                + dp.getName()
                + ". Exception: "
                + ex.toString());
        status.value[i] = false;
      }

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmState(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // TODO: consider checking current state to prevent unnecessary
      // database access

      dp.raiseAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmState2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // TODO: consider checking current state to prevent unnecessary
      // database access

      dp.raiseAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemAlarmState(int[] keyIds, CosBooleanSeqHolder status,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // get alarm inhibit flag
      status.value[i] = dp.isInAlarm();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetItemAlarmState2(String[] items,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    status.value = new boolean[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // get alarm inhibit flag
      status.value[i] = dp.isInAlarm();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveItemAlarmState(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // TODO: consider checking current state to prevent unnecessary
      // database access

      // closing the alarm is done by both normalizing and acknowledging
      // the alarm
      dp.normalizeAlarm();
      dp.acknowledgeAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosRemoveItemAlarmState2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // TODO: consider checking current state to prevent unnecessary
      // database access

      // closing the alarm is done by both normalizing and acknowledging
      // the alarm
      dp.normalizeAlarm();
      dp.acknowledgeAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmAcknowledged(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // if the alarm is already acknowledged, ignore but do not raise
      // error
      // NOTE: the acknowledged here is the opposite of the "not ack"
      // variable inside datapoint!!!
      if (dp.isAlarmAcknowledged())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
      }

      // set alarm ack
      dp.acknowledgeAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmAcknowledged2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // if the alarm is already acknowledged, ignore but do not raise
      // error
      // NOTE: the acknowledged here is the opposite of the "not ack"
      // variable inside datapoint!!!
      if (dp.isAlarmAcknowledged())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
      }

      // set alarm ack
      dp.acknowledgeAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemAlarmAcknowledgedStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        status.value[i] = false;
        continue;
      }

      // can not set alarm for an output point. so just set to default
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        status.value[i] = false;
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // get alarm ack flag (note: it is the opposite of internal alarm
      // not-ack state)
      status.value[i] = dp.isAlarmAcknowledged();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetItemAlarmAcknowledgedStatus2(String[] items,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        status.value[i] = false;
        continue;
      }

      // can not set alarm for an output point. so just set to default
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        status.value[i] = false;
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // get alarm ack flag (note: it is the opposite of internal alarm
      // not-ack state)
      status.value[i] = dp.isAlarmAcknowledged();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmNormalized(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // if the alarm is already normalized, ignore but do not raise error
      // NOTE: the normalized flag here is the opposite of the "not ack"
      // variable inside datapoint!!!
      if (dp.isAlarmNormalized())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
      }

      // set alarm normalized
      dp.normalizeAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmNormalized2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not set alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if the alarm inhibit is set, error
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrIsInhibit;
        continue;
      }

      // if the alarm is already normalized, ignore but do not raise error
      // NOTE: the normalized flag here is the opposite of the "not ack"
      // variable inside datapoint!!!
      if (!dp.isAlarmNormalized())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
      }

      // set alarm normalized
      dp.normalizeAlarm();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemAlarmNormalizedStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        status.value[i] = false;
        continue;
      }

      // can not set alarm for an output point. so just set to default
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        status.value[i] = false;
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // get alarm norm flag (note: it is the opposite of internal alarm
      // not-norm state)
      status.value[i] = dp.isAlarmNormalized();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetItemAlarmNormalizedStatus2(String[] items,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        // default value
        status.value[i] = false;
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not set alarm for an output point. so just set to default
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        status.value[i] = false;
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // get alarm norm flag (note: it is the opposite of internal alarm
      // not-norm state)
      status.value[i] = dp.isAlarmNormalized();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmInhibit(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // can not inhibit alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if alarm is already inhibit, ignore. but do not raise error
      // NOTE: this is only useful to prevent unnecessary action such as
      // database update
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the alarm inhibit flag. this will include clearing the
      // current alarm status.
      // internally inside the alarm store, any existing alarm is
      // automatically ack-ed and norm-ed.
      // The above description is wrong!
      // When an alarm inhibit is set, the existing alarm should still be
      // kept.
      // Alarm inhibit flag only prevents new alarm to be raised
      dp.setAlarmInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosSetItemAlarmInhibit2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // can not inhibit alarm for an output point
      if (dp.getType() == EDataPointType.TYPE_OUTPUT)
      {
        errors.value[i] = CosDpErrorEnum.ErrOutputPoint;
        continue;
      }

      // if alarm is already inhibit, ignore. but do not raise error
      // NOTE: this is only useful to prevent unnecessary action such as
      // database update
      if (dp.isAlarmInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the alarm inhibit flag. this will include clearing the
      // current alarm status.
      // internally inside the alarm store, any existing alarm is
      // automatically ack-ed and norm-ed.
      // The above description is wrong!
      // When an alarm inhibit is set, the existing alarm should still be
      // kept.
      // Alarm inhibit flag only prevents new alarm to be raised
      dp.setAlarmInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public int cosGetItemAlarmInhibitStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        status.value[i] = false;
        continue;
      }

      // get alarm inhibit flag
      status.value[i] = dp.isAlarmInhibit();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetItemAlarmInhibitStatus2(String[] items,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    status.value = new boolean[items.length];
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        // default value
        status.value[i] = false;
        continue;
      }

      // get alarm inhibit flag
      status.value[i] = dp.isAlarmInhibit();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveItemAlarmInhibit(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // if it is not in inhibit, ignore. but do not raise error
      if (!dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the inhibit flag
      dp.removeAlarmInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  public synchronized int cosRemoveItemAlarmInhibit2(String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[items.length];

    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      // get the dp
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // if it is not in inhibit, ignore. but do not raise error
      if (!dp.isInhibit())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the inhibit flag
      dp.removeAlarmInhibit();

      // update the datapoint last known value in onDataPointChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the datastore timestamp
    if (counter > 0)
    {
      updateTimestamp_ = Calendar.getInstance().getTimeInMillis();
    }

    return counter;
  }

  /*
   * ------------------------------------------------------------------------
   * EQUIPMENT ACCESS METHODS
   * ------------------------------------------------------------------------
   */

  public int cosGetEquipmentKeyId(String[] equipments,
      CosHandleSeqHolder keyIds, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    keyIds.value = new int[equipments.length];
    errors.value = new CosDpErrorEnum[equipments.length];

    Equipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the equipment
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        keyIds.value[i] = 0;
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }
      // found one
      keyIds.value[i] = eqpt.keyId;
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentState(int[] keyIds,
      CosEquipmentStateSeqHolder states, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    states.value = new CosEquipmentStateStruct[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        states.value[i].equipmentState = 0;
        continue;
      }

      // get equipment state
      states.value[i].equipmentState = (short) eqpt.getEquipmentState();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentState2(String[] equipments,
      CosEquipmentStateSeqHolder states, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    states.value = new CosEquipmentStateStruct[equipments.length];
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        // default value
        states.value[i].equipmentState = 0;
        continue;
      }

      // get equipment state
      states.value[i].equipmentState = (short) eqpt.getEquipmentState();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetUpdatedEquipmentState(int[] keyIds, LongHolder timestamp,
      CosEquipmentStateSeqHolder states, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    long curtime = Calendar.getInstance().getTimeInMillis();
    long lasttime = timestamp.value;

    // return variable
    states.value = new CosEquipmentStateStruct[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    // special case when no updates has happened. (due to error? or
    // stopped?)
    // Note: since now the equipment can be updated directly, this is not
    // valid anymore!
    // if (lasttime >= updateTimestamp_)
    // {
    // for (int i=0; i < keyIds.length; i++)
    // {
    // errors.value[i] = CosDpErrorEnum.ErrNoUpdate;
    // //default value
    // states.value[i].equipmentState = 0;
    // }
    // timestamp.value = curtime;
    // return 0;
    // }

    // check the equipment one by one
    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the equipment
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        // default value
        states.value[i].equipmentState = 0;
        continue;
      }

      // only get the latest value if timestamp is later then the
      // reference/param timestamp
      if (lasttime >= eqpt.getUpdateTimestamp())
      {
        errors.value[i] = CosDpErrorEnum.ErrNoUpdate;
        // default value
        states.value[i].equipmentState = 0;
        continue;
      }

      // get equipment state
      states.value[i].equipmentState = (short) eqpt.getEquipmentState();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    // update the client timestamp. always use the earliest timestamp
    timestamp.value = curtime;

    logger_.debug("No of updated equipment: " + counter);
    return counter;
  }

  public int cosGetAllEquipments(CosStringSeqHolder equipments,
      CosHandleSeqHolder keyIds) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variables
    int arrLen = equipments_.size();
    equipments.value = new String[arrLen];
    keyIds.value = new int[arrLen];

    Equipment eqpt = null;
    for (int i = 0; i < arrLen; i++)
    {
      eqpt = equipments_.get(i);
      if (eqpt == null)
      {
        // invalid equipment, somehow!
        equipments.value[i] = "";
        keyIds.value[i] = 0;
      }
      else
      {
        // actual equipment
        equipments.value[i] = eqpt.name;
        keyIds.value[i] = eqpt.keyId;
      }
    }

    return arrLen;
  }

  public int cosGetAllUpdatedEquipmentState(LongHolder timestamp,
      CosHandleSeqHolder keyIds, CosEquipmentStateSeqHolder states)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    long curtime = Calendar.getInstance().getTimeInMillis();
    long lasttime = timestamp.value;

    // special case when no updates has happened. (due to error? or
    // stopped?)
    // Note: since now the equipment can be updated directly, this is not
    // valid anymore!
    // if (lasttime >= updateTimestamp_)
    // {
    // timestamp.value = curtime;
    // return 0;
    // }

    // temporary array for return value
    ArrayList<Equipment> updatedList = new ArrayList<Equipment>();

    // check all datapoints one by one
    Equipment eqpt = null;
    for (int i = 0; i < equipments_.size(); i++)
    {
      eqpt = equipments_.get(i);
      if (eqpt == null)
      {
        // invalid equipment, somehow!
        continue;
      }

      // only get the latest value if timestamp is later then the
      // reference/param timestamp
      if (lasttime > eqpt.getUpdateTimestamp())
      {
        continue;
      }

      // add into the update list
      updatedList.add(eqpt);
    }

    // build the return value
    int arrLen = updatedList.size();
    keyIds.value = new int[arrLen];
    states.value = new CosEquipmentStateStruct[arrLen];

    for (int i = 0; i < arrLen; i++)
    {
      eqpt = updatedList.get(i);
      // add the datapoint to the return parameter
      keyIds.value[i] = eqpt.keyId;
      states.value[i].equipmentState = (short) eqpt.getEquipmentState();
    }

    // update client timestamp. always use the earliest timestamp
    timestamp.value = curtime;

    logger_.debug("No of updated equipment: " + arrLen);
    return arrLen;
  }

  public synchronized int cosSetEquipmentNotes(int[] keyIds, String[] notes,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // set the note
      if (eqpt.setNote(notes[i]) < 0)
      {
        // can not set the note
        errors.value[i] = CosDpErrorEnum.ErrInvalidValue;
        continue;
      }

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetEquipmentNotes2(String[] equipments,
      String[] notes, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // set the note
      if (eqpt.setNote(notes[i]) < 0)
      {
        // can not set the note
        errors.value[i] = CosDpErrorEnum.ErrInvalidValue;
        continue;
      }

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentNotes(int[] keyIds, CosStringSeqHolder notes,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    notes.value = new String[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // get the note
      if (eqpt.hasNote())
      {
        notes.value[i] = eqpt.getNote();
      }
      else
      {
        notes.value[i] = "";
      }

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentNotes2(String[] equipments,
      CosStringSeqHolder notes, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    notes.value = new String[equipments.length];
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // get the note
      if (eqpt.hasNote())
      {
        notes.value[i] = eqpt.getNote();
      }
      else
      {
        notes.value[i] = "";
      }

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveEquipmentNotes(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // if no notes, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (!eqpt.hasNote())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the note
      // assume to be always successful because the worse is that it is
      // already cleared.
      eqpt.removeNote();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveEquipmentNotes2(String[] equipments,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // if no notes, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (!eqpt.hasNote())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // remove the note
      // assume to be always successful because the worse is that it is
      // already cleared.
      eqpt.removeNote();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetEquipmentTag(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // if tag is alread set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (eqpt.hasTag())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.setTag();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetEquipmentTag2(String[] equipments,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // if tag is alread set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (eqpt.hasTag())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.setTag();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentTagStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // get the tag status
      status.value[i] = eqpt.hasTag();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentTagStatus2(String[] equipments,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    status.value = new boolean[equipments.length];
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // get the tag status
      status.value[i] = eqpt.hasTag();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveEquipmentTag(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // if tag is not set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (!eqpt.hasTag())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.removeTag();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveEquipmentTag2(String[] equipments,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // if tag is not set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (!eqpt.hasTag())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.removeTag();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetEquipmentPermitToWork(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // if ptw is already set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (eqpt.hasPermitToWork())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.setPermitToWork();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosSetEquipmentPermitToWork2(String[] equipments,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // if ptw is alread set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (eqpt.hasPermitToWork())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.setPermitToWork();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentPermitToWorkStatus(int[] keyIds,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    status.value = new boolean[keyIds.length];
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // get the tag status
      status.value[i] = eqpt.hasPermitToWork();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public int cosGetEquipmentPermitToWorkStatus2(String[] equipments,
      CosBooleanSeqHolder status, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    status.value = new boolean[equipments.length];
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // get the tag status
      status.value[i] = eqpt.hasPermitToWork();

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveEquipmentPermitToWork(int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[keyIds.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByKeyId(keyIds[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // if tag is not set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (!eqpt.hasPermitToWork())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.removePermitToWork();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  public synchronized int cosRemoveEquipmentPermitToWork2(
      String[] equipments, CosDpErrorSeqHolder errors)
      throws CosDpServerException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerNotInControl,
          "Not In Control!");
    }

    // return variable
    errors.value = new CosDpErrorEnum[equipments.length];

    IEquipment eqpt = null;
    int counter = 0;
    for (int i = 0; i < equipments.length; i++)
    {
      // get the dp
      eqpt = equipments_.getByName(equipments[i]);
      if (eqpt == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // if tag is not set, ignore it. but do not raise error
      // meaningful to prevent unnecessary database update
      if (!eqpt.hasPermitToWork())
      {
        // success
        errors.value[i] = CosDpErrorEnum.ErrNoError;
        counter++;
        continue;
      }

      // set the tag
      eqpt.removePermitToWork();

      // update the equipment last known value in onEquipmentChange()
      // notification

      // success
      errors.value[i] = CosDpErrorEnum.ErrNoError;
      counter++;
    }

    return counter;
  }

  /*
   * ------------------------------------------------------------------------
   * DATAPOINT SUBSCRIPTION METHODS
   * ------------------------------------------------------------------------
   */

  public synchronized int cosCreateSubscriptionGroup(String name,
      int updateRate, ICosDataPointClient clientRef,
      boolean useSourceValue) throws CosDpServerException
  {
    int keyId = subscriptions_.size() + 1;

    SubscriptionGroup subgrp = new SubscriptionGroup(keyId, name,
        updateRate, clientRef, this);
    subgrp.useSourceValue(useSourceValue);

    // add into the list
    subscriptions_.put(keyId, subgrp);

    return keyId;
  }

  public synchronized int cosCreateSubscriptionGroup2(int updateRate,
      ICosDataPointClient clientRef, boolean useSourceValue)
      throws CosDpServerException
  {
    int keyId = subscriptions_.size() + 1;
    String name = generate_subscription_name();

    SubscriptionGroup subgrp = new SubscriptionGroup(keyId, name,
        updateRate, clientRef, this);
    subgrp.useSourceValue(useSourceValue);

    // add into the list
    subscriptions_.put(keyId, subgrp);

    return keyId;
  }

  public int cosDeleteSubscriptionGroup(int subGroupKeyId)
      throws CosDpServerException
  {
    // get the subscription group
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      return 0;
    }

    // stop the subscription group
    subgrp.stop();

    // remove from the list
    subscriptions_.remove(subGroupKeyId);

    return 1;
  }

  public int cosSubscribe(int subGroupKeyId, int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    // get the subscription group
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      return 0;
    }

    // return params
    errors.value = new CosDpErrorEnum[keyIds.length];

    // add subscription one by one
    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // add the subscription
      errors.value[i] = subgrp.subscribe(dp);

      if (errors.value[i] == CosDpErrorEnum.ErrNoError)
      {
        counter++;
      }
    }

    return counter;
  }

  public int cosSubscribe2(int subGroupKeyId, String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    // get the subscription group
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      return 0;
    }

    // return params
    errors.value = new CosDpErrorEnum[items.length];

    // add subscription one by one
    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // add the subscription
      errors.value[i] = subgrp.subscribe(dp);

      if (errors.value[i] == CosDpErrorEnum.ErrNoError)
      {
        counter++;
      }
    }

    return counter;
  }

  public int cosSubscribeAll(int subGroupKeyId) throws CosDpServerException
  {
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerGeneric,
          "cosSubscribeAll: invalid subscription group id");
    }
    // pass it to the subscription grou
    return subgrp.subscribeAll();
  }

  public int cosSubscribeAllRealItems(int subGroupKeyId)
      throws CosDpServerException
  {
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      throw new CosDpServerException(
          CosDpServerExceptionCodeEnum.ExceptionDpServerGeneric,
          "cosSubscribeAll: invalid subscription group id");
    }
    // pass it to the subscription grou
    return subgrp.subscribeAllReal();
  }

  public int cosUnsubscribe(int subGroupKeyId, int[] keyIds,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    // get the subscription group
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      return 0;
    }

    // return params
    errors.value = new CosDpErrorEnum[keyIds.length];

    // add subscription one by one
    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < keyIds.length; i++)
    {
      dp = datapoints_.getByKeyId(keyIds[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidHandle;
        continue;
      }

      // remote the subscription
      errors.value[i] = subgrp.unsubscribe(dp);

      if (errors.value[i] == CosDpErrorEnum.ErrNoError)
      {
        counter++;
      }
    }

    return counter;
  }

  public int cosUnsubscribe2(int subGroupKeyId, String[] items,
      CosDpErrorSeqHolder errors) throws CosDpServerException
  {
    // get the subscription group
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      return 0;
    }

    // return params
    errors.value = new CosDpErrorEnum[items.length];

    // add subscription one by one
    IDataPoint dp = null;
    int counter = 0;
    for (int i = 0; i < items.length; i++)
    {
      dp = datapoints_.getByName(items[i]);
      if (dp == null)
      {
        errors.value[i] = CosDpErrorEnum.ErrInvalidName;
        continue;
      }

      // remote the subscription
      errors.value[i] = subgrp.unsubscribe(dp);

      if (errors.value[i] == CosDpErrorEnum.ErrNoError)
      {
        counter++;
      }
    }

    return counter;
  }

  public int cosGetUpdatedSubscriptionItem(int subGroupKeyId,
      LongHolder timestamp, CosSubscriptionItemSeqHolder items)
      throws CosDpServerException
  {
    // get the subscription group
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      // empty data
      items.value = new CosSubscriptionItemStruct[0];
      return 0;
    }

    // pass it to the subscription group
    return subgrp.getUpdatedSubscriptionItem(timestamp, items);
  }

  public int cosGetAllSubscriptionItem(int subGroupKeyId,
      CosSubscriptionItemSeqHolder items) throws CosDpServerException
  {
    // get the subscription group
    SubscriptionGroup subgrp = subscriptions_.get(subGroupKeyId);
    if (subgrp == null)
    {
      // empty data
      items.value = new CosSubscriptionItemStruct[0];
      return 0;
    }

    // pass it to the subscription group
    return subgrp.getAllSubscriptionItem(items);
  }

  /*
   * ------------------------------------------------------------------------
   * MONITORED THREAD METHODS
   * ------------------------------------------------------------------------
   */

  public CosOperationModeEnum cosGetOperationMode()
  {
    if (state_ == CosProcessStatusEnum.StatGoingToControl
        && state_ == CosProcessStatusEnum.StatRunningControl)
    {
      return CosOperationModeEnum.OperControl;
    }
    else if (state_ == CosProcessStatusEnum.StatGoingToMonitor
        && state_ == CosProcessStatusEnum.StatRunningMonitor)
    {
      return CosOperationModeEnum.OperMonitor;
    }
    else
    {
      return CosOperationModeEnum.OperNotApplicable;
    }

  }

  public CosProcessStatusEnum cosGetProcessStatus()
  {
    return state_;
  }

  public long cosGetProcessId()
  {
    return pid_;
  }

  public CosProcessTypeEnum cosGetProcessType()
  {
    return CosProcessTypeEnum.ProcDataPointServer;
  }

  public void cosPoll() throws CosPollException
  {
    // just return
    return;
  }

  public void cosPollControl() throws CosPollNotInModeException,
      CosPollException
  {
    if (state_ != CosProcessStatusEnum.StatRunningControl)
    {
      throw new CosPollNotInModeException();
    }
    return;
  }

  public void cosPollMonitor() throws CosPollNotInModeException,
      CosPollException
  {
    if (state_ != CosProcessStatusEnum.StatRunningMonitor)
    {
      throw new CosPollNotInModeException();
    }
    return;
  }
}
TOP

Related Classes of tcg.scada.da.DataPointServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.