Ejemplo n.º 1
0
        private static void GetVersionLoop()
        {
            while (loopFlag)
            {
                // sleep for timeout
                Thread.Sleep(timeout);

                // don't want two concurrent updates
                if (checkingFlag || updatingFlag)
                {
                    continue;
                }

                try
                {
                    // locking is overkill here because only one thread that wakes up every <timeout>
                    checkingFlag = true;

                    WebServiceHelper.GetCurrentSoftwareVersion(
                        VersionUrl,
                        new WebServiceHelper.AccountDelegate((version) =>
                    {
                        if (string.IsNullOrEmpty(version))
                        {
                            TraceLog.TraceError("Could not download version file");
                            checkingFlag = false;
                            return;
                        }
                        try
                        {
                            // compare versions
                            var newVersion = new Version(version);
                            if (newVersion > CurrentVersion)
                            {
                                TraceLog.TraceInfo(string.Format(
                                                       "New version {0} more recent than current version {1}; downloading new version",
                                                       newVersion, CurrentVersion));
                                updatingFlag = true;

                                // download and install new software
                                WebServiceHelper.DownloadCurrentSoftware(
                                    DownloadUrl,
                                    new WebServiceHelper.AccountDelegate((filename) =>
                                {
                                    // install the new software
                                    TraceLog.TraceInfo(string.Format("Download successful; installing {0}", filename));
                                    Install(filename);
                                }),
                                    new WebServiceHelper.NetOpDelegate((inProgress, status) =>
                                {
                                    // cleanup the checking flag based on network operation status (typically failures)
                                    if (inProgress == false)
                                    {
                                        updatingFlag = false;
                                    }
                                }));
                            }
                            checkingFlag = false;
                        }
                        catch (Exception ex)
                        {
                            TraceLog.TraceException("Version check failed", ex);
                            checkingFlag = false;
                            updatingFlag = false;
                        }
                    }),
                        new WebServiceHelper.NetOpDelegate((inProgress, status) =>
                    {
                        // cleanup the checking flag based on network operation status (typically failures)
                        if (inProgress == false)
                        {
                            checkingFlag = false;
                        }
                    }));
                }
                catch (Exception ex)
                {
                    TraceLog.TraceException("GetVersionLoop failed", ex);
                    checkingFlag = false;
                    updatingFlag = false;
                }
            }
        }
Ejemplo n.º 2
0
        private static void Send()
        {
            try
            {
                // snap the record list
                var recordList = CollectorClient.GetRecords();

                // if no records, may need to recover capture service
                if (recordList.Count == 0)
                {
                    if (recovering)
                    {
                        // this is the second timeout period that we didn't see records.
                        // attempt to restart the collector
                        CollectorClient.Start();
                        recovering = false;
                    }
                    else
                    {
                        // this will trigger recovery if the next run through also has zero records
                        recovering = true;
                    }

                    // nothing to do this time (no records to process)
                    return;
                }
                else
                {
                    // reset recovery mode
                    recovering = false;
                }

                // compact the record list
                var uniqueHosts = recordList.Select(r => r.HostMacAddress).Distinct();
                foreach (var host in uniqueHosts)
                {
                    var uniqueDests = recordList.Where(r => r.HostMacAddress == host).Select(r => r.WebsiteName).Distinct();
                    foreach (var dest in uniqueDests)
                    {
                        var records = recordList.Where(r => r.HostMacAddress == host && r.WebsiteName == dest).OrderBy(r => r.Timestamp);

                        // only keep the first and last record so that the duration calculated on the server will be > 0
                        var firstRecord = records.FirstOrDefault();
                        var lastRecord  = records.LastOrDefault();

                        // if the last record is a second or more later, add the duration to the first record
                        TimeSpan duration;
                        if (lastRecord != null && lastRecord != firstRecord &&
                            (duration = Convert.ToDateTime(lastRecord.Timestamp) - Convert.ToDateTime(firstRecord.Timestamp))
                            >= TimeSpan.FromSeconds(1.0))
                        {
                            firstRecord.Duration = (int)duration.TotalSeconds;
                        }

                        lock (sendQueue)
                        {
                            var existingRecord = sendQueue.FirstOrDefault(r => r.HostMacAddress == host && r.WebsiteName == dest);
                            if (existingRecord == null ||
                                Convert.ToDateTime(firstRecord.Timestamp) - (Convert.ToDateTime(existingRecord.Timestamp) + TimeSpan.FromSeconds(existingRecord.Duration)) >= TimeSpan.FromSeconds(300.0)) // more than 5 minutes between records
                            {
                                // add the record to the send queue
                                sendQueue.Add(firstRecord);
                            }
                            else
                            {
                                // augment existing record with new duration
                                duration = Convert.ToDateTime(firstRecord.Timestamp) - Convert.ToDateTime(existingRecord.Timestamp) + TimeSpan.FromSeconds(firstRecord.Duration);
                                existingRecord.Duration = (int)duration.TotalSeconds;
                            }
                        }
                    }
                }

                if (sendQueue.Count > 0)
                {
                    // snap the send queue
                    var recordBuffer = new List <Record>();
                    lock (sendQueue)
                    {
                        // clear this buffer if collection is suspended
                        if (collectionStatus == ControlMessage.SuspendCollection)
                        {
                            sendQueue.Clear();
                            TraceLog.TraceInfo("Probing for new collection status");
                        }
                        else
                        {
                            recordBuffer.AddRange(sendQueue);
                            TraceLog.TraceInfo(String.Format("Sending records: {0}", JsonConvert.SerializeObject(sendQueue)));
                        }
                    }

                    var sendList = new RecordList()
                    {
                        DeviceId        = deviceId,
                        DeviceName      = deviceName,
                        SoftwareVersion = UpdateClient.CurrentVersion.ToString(),
                        Records         = recordBuffer
                    };

                    // send the queue to the web service
                    WebServiceHelper.PostRecords(
                        credentials,
                        sendList,
                        new WebServiceHelper.PostRecordsDelegate((response) =>
                    {
                        // a callback means the service processed the records successfully; we can free them now.
                        // note a slight race condition - if the callback takes longer than the sleep interval, we
                        // could lose a buffer.  since the sleep interval is 60sec, this isn't an important issue
                        // to address.
                        lock (sendQueue)
                        {
                            sendQueue.Clear();
                        }
                        var msg = (ControlMessage)response.controlMessage;
                        if (collectionStatus == msg)
                        {
                            return;
                        }

                        // process the control message
                        lock (configLock)
                        {
                            switch (msg)
                            {
                            case ControlMessage.Normal:
                                TraceLog.TraceInfo("Changing collection status to Normal");
                                collectionStatus = msg;
                                ConfigClient.Write(ConfigClient.Disabled, Convert.ToString(false));
                                break;

                            case ControlMessage.SuspendCollection:
                                TraceLog.TraceInfo("Changing collection status to Suspended");
                                collectionStatus = msg;
                                ConfigClient.Write(ConfigClient.Disabled, Convert.ToString(true));
                                break;

                            case ControlMessage.DisableDevice:
                                TraceLog.TraceInfo("Disabling the device by wiping the config");
                                collectionStatus = msg;
                                deviceId         = null;
                                deviceName       = null;
                                // wipe the config
                                ConfigClient.Clear();
                                break;

                            default:
                                // new message we don't understand yet
                                TraceLog.TraceInfo(string.Format("Received unknown control message {0}", msg));
                                break;
                            }
                        }
                    }),
                        new WebServiceHelper.NetOpDelegate((inProgress, status) =>
                    {
                        if (status == OperationStatus.Retry)
                        {
                            // no need to do anything: next iteration will send original credentials
                        }
                        // no failure state to clean up
                    }));
                }
            }
            catch (Exception ex)
            {
                TraceLog.TraceException("Upload processing failed", ex);
            }
        }