Base class for all the server records. Offers the base fields as well as some of the logic.
        internal CAChannelMonitor(CARecord record, string property, CAServerChannel channel,
                                    EpicsType type, int dataCount, MonitorMask monitorMask, int subscriptionId)
        {
            Record = record;
            Property = property;
            Channel = channel;
            Type = type;
            DataCount = dataCount;
            MonitorMask = monitorMask;
            SubscriptionId = subscriptionId;

            try
            {
                object val = Record[Property.ToString()];
                if (val == null)
                    val = 0;
                byte[] realData = val.ToByteArray(Type, Record);
                Channel.TcpConnection.Send(Channel.Server.Filter.MonitorChangeMessage(SubscriptionId, Channel.ClientId, Type, DataCount, val.ToByteArray(Type, Record)));
                lastValue = Record[Property];
                Record.RecordProcessed += new EventHandler(Record_RecordProcessed);
            }
            catch (Exception e)
            {
                Channel.TcpConnection.Send(Channel.Server.Filter.MonitorChangeMessage(SubscriptionId, Channel.ClientId, Type, DataCount, new byte[0]));
            }
        }
 public CAServerChannel(CAServer cAServer, int serverId, int clientId, string channelName, CATcpConnection tcpConnection)
 {
     // TODO: Complete member initialization
     this.Server            = cAServer;
     this.ServerId          = serverId;
     this.ClientId          = clientId;
     this.ChannelName       = channelName;
     this.TcpConnection     = tcpConnection;
     tcpConnection.Closing += new EventHandler(tcpConnection_Closing);
     Property = "VAL";
     if (channelName.Contains("."))
     {
         string[] splitted = channelName.Split('.');
         Record   = Server.records[splitted[0]];
         Property = splitted[1].ToUpper();
     }
     else
     {
         Record = Server.records[ChannelName];
     }
     if (!Record.CanBeRemotlySet)
     {
         Access = AccessRights.ReadOnly;
     }
     TcpConnection.Send(Server.Filter.ChannelCreatedMessage(ClientId, ServerId, FindType(Record[Property].GetType()), Record.dataCount, Access));
 }
Example #3
0
        internal CAChannelMonitor(CARecord record, string property, CAServerChannel channel,
                                  EpicsType type, int dataCount, MonitorMask monitorMask, int subscriptionId)
        {
            Record         = record;
            Property       = property;
            Channel        = channel;
            Type           = type;
            DataCount      = dataCount;
            MonitorMask    = monitorMask;
            SubscriptionId = subscriptionId;

            try
            {
                object val = Record[Property.ToString()];
                if (val == null)
                {
                    val = 0;
                }
                byte[] realData = val.ToByteArray(Type, Record);
                using (Record.CreateAtomicChange(false))
                    Channel.TcpConnection.Send(Channel.Server.Filter.MonitorChangeMessage(SubscriptionId, Channel.ClientId, Type, DataCount, val.ToByteArray(Type, Record)));
                Record.RecordProcessed += new EventHandler(Record_RecordProcessed);
            }
            catch (Exception e)
            {
                Channel.TcpConnection.Send(Channel.Server.Filter.MonitorChangeMessage(SubscriptionId, Channel.ClientId, Type, DataCount, new byte[0]));
            }
        }
        internal ChannelMonitor(CARecord record, string property, CAServerChannel channel,
                                    EpicsType type, int dataCount, MonitorMask monitorMask, int subscriptionId)
        {
            Record = record;
            Property = property;
            Channel = channel;
            Type = type;
            DataCount = dataCount;
            MonitorMask = monitorMask;
            SubscriptionId = subscriptionId;

            try
            {
                object val = Record[Property.ToString()];
                if (val == null)
                    val = 0;
                byte[] realData = val.ToByteArray(Type, Record);
                Channel.sendMonitorChange(SubscriptionId, Type, DataCount, EpicsTransitionStatus.ECA_NORMAL, realData);
                lastValue = Record[Property];
                Record.RecordProcessed += new EventHandler(Record_RecordProcessed);
            }
            catch (Exception e)
            {
                Channel.sendMonitorChange(SubscriptionId, Type, DataCount, EpicsTransitionStatus.ECA_ADDFAIL, new byte[0]);
            }
        }
 internal void Remove(CARecord record)
 {
     lock (records)
     {
         records.Remove(record.Name);
     }
 }
 internal void Add(CARecord record)
 {
     lock (records)
     {
         records.Add(record.Name, record);
     }
 }
 internal void Add(CARecord record)
 {
     lock (records)
     {
         records.Add(record.Name, record);
     }
 }
Example #8
0
        /// <summary>
        /// recalls the object to Byte function with the right datatype-struct for easy coding
        /// </summary>
        internal static byte[] ToByteArray(this object src, EpicsType epicsType, CARecord record, int dataCount)
        {
            //Type valueType = record["VAL"].GetType();
            Type   valueType = src.GetType();
            object mySrc     = src;

            if (valueType.IsEnum)
            {
                return(ToByteArray <Enum>(src, epicsType, record, dataCount));
            }
            string name;

            if (valueType.IsGenericType && valueType.Name.Split(new char[] { '`' })[0] == "ArrayContainer")
            {
                name  = valueType.GetGenericArguments()[0].Name;
                mySrc = ((dynamic)src).arrayValues;
            }
            else if (valueType.IsArray)
            {
                name = valueType.GetElementType().Name;
            }
            else
            {
                name = valueType.Name;
            }
            switch (name)
            {
            case "String":
                return(ToByteArray <string>(mySrc, epicsType, record, dataCount));

            case "Int32":
                return(ToByteArray <int>(mySrc, epicsType, record, dataCount));

            case "Int16":
                return(ToByteArray <short>(mySrc, epicsType, record, dataCount));

            case "Single":
                return(ToByteArray <float>(mySrc, epicsType, record, dataCount));

            case "Double":
                return(ToByteArray <double>(mySrc, epicsType, record, dataCount));

            case "Byte":
                return(ToByteArray <byte>(mySrc, epicsType, record, dataCount));

            default:
                throw new Exception("Wrong DataType defined");
            }
        }
Example #9
0
        internal static byte[] LabelsToByteArray(this object src, CARecord record)
        {
            using (MemoryStream mem = new MemoryStream(424))
            {
                using (BinaryWriter writer = new BinaryWriter(mem))
                {
                    //writer.Write(ToByteArray(((IConvertible)src).ToInt32(null)));
                    writer.Write(ToByteArray(0));

                    /*writer.Write(ToByteArray((short)((int)src)));
                    *  writer.Write(ToByteArray((short)((int)src)));*/
                    //writer.Write(ToByteArray((int)src));
                    string[] names = Enum.GetNames(src.GetType());
                    writer.Write(ToByteArray((Int16)names.Length));
                    foreach (var i in names)
                    {
                        writer.Write(ToByteArray(i, 26));
                    }
                    writer.Seek(422, SeekOrigin.Begin);
                    writer.Write(ToByteArray((short)((int)src)));
                }
                return(mem.GetBuffer());
            }
        }
Example #10
0
        /// <summary>
        /// Function for full change from an Object to Byte.
        /// </summary>
        /// <typeparam name="dataType">Datatype of the source</typeparam>
        /// <param name="src">Src object which shall be transferred</param>
        /// <param name="epicsType">Target epics type</param>
        /// <param name="record">Record from where the value comes</param>
        /// <param name="dataCount">Count of data requested</param>
        /// <returns></returns>
        internal static byte[] ToByteArray <dataType>(object src, EpicsType epicsType, CARecord record, int dataCount)
        {
            dataType[] source;

            if (src.GetType().IsArray)
            {
                source = new dataType[dataCount];
                int i = 0;
                foreach (object element in ((System.Collections.IEnumerable)src))
                {
                    if (i >= source.Length)
                    {
                        break;
                    }
                    source[i] = (dataType)Convert.ChangeType(element, typeof(dataType));
                    i++;
                }
            }
            else
            {
                source = new dataType[] { (dataType)Convert.ChangeType(src, typeof(dataType)) }
            };

            using (MemoryStream mem = new MemoryStream())
            {
                using (BinaryWriter writer = new BinaryWriter(mem))
                {
                    switch (epicsType)
                    {
                        #region simple Types
                    case EpicsType.String:
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(source[i].ToString(), true));
                        }
                        return(mem.ToArray());

                    case EpicsType.Short:
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt16(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Float:
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToSingle(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Byte:
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToByte(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Int:
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt32(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Double:
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToDouble(source[i])));
                        }
                        return(mem.ToArray());

                        #endregion

                        #region StatusTypes
                    case EpicsType.Status_Double:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? -1)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? -1)));
                        writer.Write(ToByteArray((uint)0));     // Skip 4 bytes
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToDouble(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Status_Float:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToSingle(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Status_Int:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt32(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Status_Byte:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToByte(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Status_Short:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt16(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Status_String:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(source[i].ToString(), true));
                        }
                        return(mem.ToArray());

                        #endregion

                        #region TimeTypes
                    case EpicsType.Time_Double:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((DateTime)(record["TIME"] ?? 0)));
                        writer.Write(ToByteArray((UInt32)0));     // Skip 4 bytes
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToDouble(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Time_Float:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((DateTime)(record["TIME"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToSingle(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Time_Int:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((DateTime)(record["TIME"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt32(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Time_Short:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((DateTime)(record["TIME"] ?? 0)));
                        writer.Write(new byte[2]);
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt16(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Time_String:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((DateTime)(record["TIME"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(source[i].ToString(), true));
                        }
                        return(mem.ToArray());

                    case EpicsType.Time_Byte:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((DateTime)(record["TIME"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToByte(source[i])));
                        }
                        return(mem.ToArray());

                        #endregion

                        #region ControlTypes
                    case EpicsType.Control_Double:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((short)(record["PREC"] ?? 0)));
                        writer.Write(new byte[] { 0, 0 });
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetDouble("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetDouble("LOWDISP")));
                        writer.Write(ToByteArray(record.GetDouble("HIHI")));
                        writer.Write(ToByteArray(record.GetDouble("HIGH")));
                        writer.Write(ToByteArray(record.GetDouble("LOW")));
                        writer.Write(ToByteArray(record.GetDouble("LOLO")));
                        writer.Write(ToByteArray(record.GetDouble("HOPR")));
                        writer.Write(ToByteArray(record.GetDouble("LOPR")));

                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToDouble(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Control_Float:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((short)(record["PREC"] ?? 0)));
                        writer.Write(new byte[] { 0, 0 });
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetFloat("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetFloat("LOWDISP")));
                        writer.Write(ToByteArray(record.GetFloat("HIHI")));
                        writer.Write(ToByteArray(record.GetFloat("HIGH")));
                        writer.Write(ToByteArray(record.GetFloat("LOW")));
                        writer.Write(ToByteArray(record.GetFloat("LOLO")));
                        writer.Write(ToByteArray(record.GetFloat("HOPR")));
                        writer.Write(ToByteArray(record.GetFloat("LOPR")));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToSingle(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Control_Int:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        //writer.Write(new byte[] { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 });
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetInt("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetInt("LOWDISP")));
                        writer.Write(ToByteArray(record.GetInt("HIHI")));
                        writer.Write(ToByteArray(record.GetInt("HIGH")));
                        writer.Write(ToByteArray(record.GetInt("LOW")));
                        writer.Write(ToByteArray(record.GetInt("LOLO")));
                        writer.Write(ToByteArray(record.GetInt("HOPR")));
                        writer.Write(ToByteArray(record.GetInt("LOPR")));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt32(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Control_Short:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetShort("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetShort("LOWDISP")));
                        writer.Write(ToByteArray(record.GetShort("HIHI")));
                        writer.Write(ToByteArray(record.GetShort("HIGH")));
                        writer.Write(ToByteArray(record.GetShort("LOW")));
                        writer.Write(ToByteArray(record.GetShort("LOLO")));
                        writer.Write(ToByteArray(record.GetShort("HOPR")));
                        writer.Write(ToByteArray(record.GetShort("LOPR")));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt16(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Control_Byte:
                        throw new Exception("NOT IMPLEMENTED");

                    case EpicsType.Control_String:
                        writer.Write(ToByteArray((ushort)record["STAT"]));
                        writer.Write(ToByteArray((ushort)record["SEVR"]));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToString(source[i]), true));
                        }
                        return(mem.ToArray());

                        #endregion

                        #region GraphicsTypes
                    case EpicsType.Display_Double:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((short)(record["PREC"] ?? 0)));
                        writer.Write(new byte[] { 0, 0 });
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetDouble("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetDouble("LOWDISP")));
                        writer.Write(ToByteArray(record.GetDouble("HIHI")));
                        writer.Write(ToByteArray(record.GetDouble("HIGH")));
                        writer.Write(ToByteArray(record.GetDouble("LOW")));
                        writer.Write(ToByteArray(record.GetDouble("LOLO")));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToDouble(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Display_Float:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((short)(record["PREC"] ?? 0)));
                        writer.Write(new byte[] { 0, 0 });
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetFloat("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetFloat("LOWDISP")));
                        writer.Write(ToByteArray(record.GetFloat("HIHI")));
                        writer.Write(ToByteArray(record.GetFloat("HIGH")));
                        writer.Write(ToByteArray(record.GetFloat("LOW")));
                        writer.Write(ToByteArray(record.GetFloat("LOLO")));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToSingle(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Display_Int:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetInt("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetInt("LOWDISP")));
                        writer.Write(ToByteArray(record.GetInt("HIHI")));
                        writer.Write(ToByteArray(record.GetInt("HIGH")));
                        writer.Write(ToByteArray(record.GetInt("LOW")));
                        writer.Write(ToByteArray(record.GetInt("LOLO")));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt32(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Display_Short:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        writer.Write(ToByteArray((string)(record["EGU"] ?? ""), 8));
                        writer.Write(ToByteArray(record.GetShort("HIGHDISP")));
                        writer.Write(ToByteArray(record.GetShort("LOWDISP")));
                        writer.Write(ToByteArray(record.GetShort("HIHI")));
                        writer.Write(ToByteArray(record.GetShort("HIGH")));
                        writer.Write(ToByteArray(record.GetShort("LOW")));
                        writer.Write(ToByteArray(record.GetShort("LOLO")));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToInt16(source[i])));
                        }
                        return(mem.ToArray());

                    case EpicsType.Display_Byte:
                        throw new Exception("NOT IMPLEMENTED");

                    case EpicsType.Display_String:
                        writer.Write(ToByteArray((ushort)(record["STAT"] ?? 0)));
                        writer.Write(ToByteArray((ushort)(record["SEVR"] ?? 0)));
                        for (int i = 0; i < dataCount; i++)
                        {
                            writer.Write(ToByteArray(Convert.ToString(source[i]), true));
                        }
                        return(mem.ToArray());

                        #endregion
                    default:
                        return(null);
                    }
                }
            }
        }
Example #11
0
 internal static byte[] ToByteArray(this object src, EpicsType epicsType, CARecord record)
 {
     return(ToByteArray(src, epicsType, record, record.dataCount));
 }
 internal AtomicChange(CARecord record, bool withProcess)
 {
     this.record = record;
     record.updateMutex.WaitOne();
     this.withProcess = withProcess;
 }
 internal AtomicChange(CARecord record)
 {
     this.record = record;
     record.updateMutex.WaitOne();
 }
 internal void Remove(CARecord record)
 {
     lock (records)
     {
         records.Remove(record.Name);
     }
 }
        EpicsType FindType(CARecord record)
        {
            Type type = record.GetType();

            if (type == typeof(CAByteArrayRecord))
            {
                return EpicsType.SByte;
            }
            else if (type == typeof(CADoubleArrayRecord) || type == typeof(CADoubleRecord))
            {
                return EpicsType.Double;
            }
            else if (type == typeof(CAFloatArrayRecord) || type == typeof(CAFloatRecord))
            {
                return EpicsType.Float;
            }
            else if (type == typeof(CAIntArrayRecord) || type == typeof(CAIntRecord))
            {
                return EpicsType.Int;
            }
                else if (type == typeof(CAShortRecord))
            {
                    return EpicsType.Short;
            }
            else if (type == typeof(CAStringRecord))
            {
                return EpicsType.String;
            }
            else
            {
                Console.WriteLine("Unknown type " + type.Name);
                return EpicsType.Invalid;
            }
        }