private void OnUpdate(object state)
{
try
{
IComDaGroupCallback callback = null;
List<int> clientHandles = null;
List<DaValue> values = null;
long now = HiResClock.UtcNow.Ticks;
lock (m_lock)
{
// check if updates are required.
if (!AreUpdatesRequired || m_updateInProgress)
{
TraceState("OnUpdate Skipped");
return;
}
// check if enough time has elapsed.
if (m_nextUpdateTime == -1 || m_nextUpdateTime > (now + 50*TimeSpan.TicksPerMillisecond))
{
return;
}
// Utils.Trace("NextUpdateTime={0:mm:ss.fff}, CurrentTime={1:mm:ss.fff}", new DateTime(m_nextUpdateTime), new DateTime(now));
// collect values to report.
for (int ii = 0; ii < m_items.Count; ii++)
{
ComDaGroupItem item = m_items[ii];
if (!item.Active)
{
continue;
}
if (item.CacheEntry == null || !item.CacheEntry.Changed)
{
continue;
}
// write buffered values first.
DaValue value = null;
if (item.CacheEntry.NextEntry != null)
{
Stack<DaCacheValue> stack = new Stack<DaCacheValue>();
for (DaCacheValue entry = item.CacheEntry; entry != null; entry = entry.NextEntry)
{
stack.Push(entry);
}
while (stack.Count > 1)
{
DaCacheValue entry = stack.Pop();
value = new DaValue();
entry.GetLatest(value);
UpdateReadResult(item, value);
if (item.LastSentValue != null)
{
if (value.Quality == item.LastSentValue.Quality)
{
if (Utils.IsEqual(item.LastSentValue.Value, value.Value))
{
continue;
}
}
}
if (clientHandles == null)
{
clientHandles = new List<int>();
values = new List<DaValue>();
}
clientHandles.Add(item.ClientHandle);
values.Add(value);
item.LastSentValue = value;
/*
TraceState(
"OnUpdate BUFFERED VALUE",
this.m_serverHandle,
item.ServerHandle,
item.ClientHandle,
new Variant(value.Value),
value.Timestamp.ToString("HH:mm:ss.fff"),
item.CacheEntry.Changed);
*/
}
// clear cache.
item.CacheEntry.NextEntry = null;
}
// check if enough time has elapsed for this item (used if the sampling rate > update rate).
if (item.NextUpdateTime != -1 && item.NextUpdateTime > now)
{
continue;
}
// add latest values.
value = new DaValue();
item.CacheEntry.GetLatest(value);
UpdateReadResult(item, value);
if (item.LastSentValue != null)
{
if (value.Quality == item.LastSentValue.Quality)
{
if (Utils.IsEqual(item.LastSentValue.Value, value.Value))
{
item.CacheEntry.Changed = false;
continue;
}
}
}
if (clientHandles == null)
{
clientHandles = new List<int>();
values = new List<DaValue>();
}
clientHandles.Add(item.ClientHandle);
values.Add(value);
item.LastSentValue = value;
/*
TraceState(
"OnUpdate LATEST VALUE",
this.m_serverHandle,
item.ServerHandle,
item.ClientHandle,
new Variant(value.Value),
value.Timestamp.ToString("HH:mm:ss.fff"),
item.CacheEntry.Changed);
*/
// clear change flag.
item.CacheEntry.Changed = false;
}
// nothing to report unless the keep alive expired.
if (clientHandles == null || clientHandles.Count == 0)
{
if (m_keepAliveTime == 0 || m_lastUpdateTime + m_keepAliveTime*TimeSpan.TicksPerMillisecond > now)
{
ScheduleNextUpdate();
return;
}
}
callback = m_callback;
m_updateInProgress = true;
m_lastUpdateTime = now;
// schedule next update.
ScheduleNextUpdate();
}
// send callback.
try
{
callback.ReadCompleted(
this.m_clientHandle,
false,
0,
0,
(clientHandles != null) ? clientHandles.ToArray() : new int[0],
(values != null) ? values.ToArray() : new DaValue[0]);
if (clientHandles.Count > 0)
{
m_manager.SetLastUpdateTime();
}
/*
TraceState(
"OnUpdate Completed",
this.m_serverHandle,
(values != null && values.Count > 0)?values[0].Value:"null",
(m_nextUpdateTime-now)/TimeSpan.TicksPerMillisecond);
*/
}
finally
{
lock (m_lock)
{
m_updateInProgress = false;
}
}
}
catch (Exception e)
{
Utils.Trace("Unexpected error during GroupUpdate. {0}", e.Message);
}
}