/// <summary> /// Compares one request to another to determine if they are the same. /// </summary> /// <param name="obj">The object being compared.</param> /// <returns>If the object contains the same value as this instance.</returns> public int CompareTo(object obj) { RequestRecord candidate = obj as RequestRecord; if (candidate != null) { if (candidate.LastActiveDate < LastActiveDate) { return(-1); } if (candidate.LastActiveDate > LastActiveDate) { return(1); } if (candidate.Key < Key) { return(-1); } if (candidate.Key > Key) { return(1); } return(0); } throw new MobileException( String.Format( "Can not compare object of type '{0}' with '{1}'.", obj.GetType(), GetType())); }
/// <summary> /// Read the records that should be retained in the sync file. /// </summary> /// <param name="stream">Stream for the sync file.</param> /// <param name="purgeDate">Date before which records should be removed.</param> /// <returns></returns> private static byte[] ReadRecords(FileStream stream, long purgeDate) { byte[] buffer = null; long offset = 0; BinaryReader reader = new BinaryReader(stream); RequestRecord record = new RequestRecord(); stream.Position = 0; for (offset = 0; offset < stream.Length; offset += RECORD_LENGTH) { record.Read(reader); // Check to see if the current record is newer than the purgeDate // and isn't equal to zero. Zero date indicates the record should be // removed from the history. if (record.LastActiveDate > purgeDate && record.LastActiveDate != 0) { break; } } if (offset > 0 && offset < stream.Length) { int length = (int)(stream.Length - offset); buffer = new byte[length]; stream.Position = offset; stream.Read(buffer, 0, length); } return(buffer); }
/// <summary> /// Checks to find out if the device associated with the HttpRequest /// has already been seen by the application. Always returns false /// if the sync file has not been specified. /// </summary> /// <param name="request">HttpRequest to be checked.</param> /// <returns>True if the device associated with the request has been seen.</returns> public bool IsPresent(HttpRequest request) { if (_syncFilePath != null) { RequestRecord record = new RequestRecord(request); // Check to see if new request data needs to be loaded. RefreshSyncFile(); long expiryDateTime; if (_previous.Requests.TryGetValue(record.Key, out expiryDateTime)) { // If redirect timeout is zero then simply check to see if the // device is present in the list of previous devices. if (_redirectTimeout == 0) { return(true); } // Is it still valid? return((new DateTime(expiryDateTime).AddMinutes(_redirectTimeout)).Ticks >= record.LastActiveDate); } } return(false); }
/// <summary> /// Adds this device request to the previous devices list. /// </summary> /// <param name="request">HttpRequest of the device.</param> public void Set(HttpRequest request) { if (_syncFilePath != null) { RequestRecord record = new RequestRecord(request); // Get the latest data. RefreshSyncFile(); // Add this most recent request to the sync file. Add(record); // Check if the sync file needs to be serviced. CheckIfServiceRequired(); } }
/// <summary> /// Removes this device request from the previous devices list. /// </summary> /// <param name="request">HttpRequest of the device.</param> public void Remove(HttpRequest request) { if (_syncFilePath != null) { RequestRecord record = new RequestRecord(request); // Get the latest data. RefreshSyncFile(); // Does the device exist in the previous devices list? if (_previous.Requests.ContainsKey(record.Key)) { // Set the last active date to zero so that it will be // removed when the sync file is serviced. record.LastActiveDate = 0; // Add this most recent request to the sync file. Add(record); } } }
private void ProcessSyncFile() { // Record if the sync file exists to avoid repeated calls // to the operating system. if (_syncFileExists == false) { _syncFileExists = File.Exists(_syncFilePath); } if (_syncFileExists) { // Used to indicate if the process should be repeated. bool repeatProcess = false; // Lock the list of devices we're about to update to ensure they can't be // changed by subsequent requests to this callback. lock (_previous.Requests) { // Open the sync file for read access ensuring it's disposed // as soon as possible. FileStream stream = OpenSyncFilePath(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); if (stream != null) { // Record the length of the file so that if it changes we can abandon this // update and rely on a subsequent call to this methd to complete // processing. using (BinaryReader reader = new BinaryReader(stream)) { long length = stream.Length; RequestRecord record = new RequestRecord(); RequestRecord firstDevice = null; long rows = length / RECORD_LENGTH; for (long row = 0; row < rows; row++) { // Read the current row in reverse order. Capture EOF exceptions // in case the file length has changed since we started processing. try { stream.Position = ((rows - row) * RECORD_LENGTH) - RECORD_LENGTH; record.Read(reader); } catch (EndOfStreamException ex) { // The file has been trimmed by another process. Break and // allow the resulting call to this event to complete // processing. EventLog.Debug(ex); break; } // If the current record is the same as the last one we got last time // this method was called then stop processing more records. if (record.CompareTo(_previous.lastRequest) == 0) { break; } // Update the memory version. if (record.LastActiveDate == 0) { // Remove from the device as the last active date is zero. _previous.Requests.Remove(record.Key); } else { // Update or insert a new record. if (_previous.Requests.ContainsKey(record.Key)) { _previous.Requests[record.Key] = record.LastActiveDate; } else { _previous.Requests.Add(record.Key, record.LastActiveDate); } } if (firstDevice == null) { firstDevice = new RequestRecord(record); } } // If the length of the file hasn't changed during the processing // then update the last device record to limit the number of rows // examined in future file changes. if (length == stream.Length && firstDevice != null) { _previous.lastRequest = firstDevice; } // Signal to all the method again if the length of the file // has changed during processing. repeatProcess = length != stream.Length; } } } // If the file was altered during the processing then call the method // again to capture any new records. if (repeatProcess) { ProcessSyncFile(); } } }
/// <summary> /// Constructs a new instance of <see cref="RequestRecord"/> class. /// Copies the values of the <see cref="RequestRecord"/> provided to /// the new instance. /// </summary> /// <param name="recordToCopy"></param> protected internal RequestRecord(RequestRecord recordToCopy) { _key = recordToCopy.Key; _lastActiveDate = recordToCopy.LastActiveDate; }
/// <summary> /// Constructs a new instance of <see cref="RequestRecord"/> class. /// Copies the values of the <see cref="RequestRecord"/> provided to /// the new instance. /// </summary> /// <param name="recordToCopy"></param> protected internal RequestRecord(RequestRecord recordToCopy) { _key = recordToCopy.Key; _lastActiveDate = recordToCopy.LastActiveDate; }
/// <summary> /// Read the records that should be retained in the sync file. /// </summary> /// <param name="stream">Stream for the sync file.</param> /// <param name="purgeDate">Date before which records should be removed.</param> /// <returns></returns> private static byte[] ReadRecords(FileStream stream, long purgeDate) { byte[] buffer = null; long offset = 0; BinaryReader reader = new BinaryReader(stream); RequestRecord record = new RequestRecord(); stream.Position = 0; for (offset = 0; offset < stream.Length; offset += RECORD_LENGTH) { record.Read(reader); // Check to see if the current record is newer than the purgeDate // and isn't equal to zero. Zero date indicates the record should be // removed from the history. if (record.LastActiveDate > purgeDate && record.LastActiveDate != 0) break; } if (offset > 0 && offset < stream.Length) { int length = (int) (stream.Length - offset); buffer = new byte[length]; stream.Position = offset; stream.Read(buffer, 0, length); } return buffer; }
private void ProcessSyncFile() { // Record if the sync file exists to avoid repeated calls // to the operating system. if (_syncFileExists == false) _syncFileExists = File.Exists(_syncFilePath); if (_syncFileExists) { // Used to indicate if the process should be repeated. bool repeatProcess = false; // Lock the list of devices we're about to update to ensure they can't be // changed by subsequent requests to this callback. lock (_previous.Requests) { // Open the sync file for read access ensuring it's disposed // as soon as possible. using (FileStream stream = OpenSyncFilePath(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { if (stream != null) { // Record the length of the file so that if it changes we can abandon this // update and rely on a subsequent call to this methd to complete // processing. long length = stream.Length; BinaryReader reader = new BinaryReader(stream); RequestRecord record = new RequestRecord(); RequestRecord firstDevice = null; long rows = length/RECORD_LENGTH; for (long row = 0; row < rows; row++) { // Read the current row in reverse order. Capture EOF exceptions // in case the file length has changed since we started processing. try { stream.Position = ((rows - row)*RECORD_LENGTH) - RECORD_LENGTH; record.Read(reader); } catch (EndOfStreamException ex) { // The file has been trimmed by another process. Break and // allow the resulting call to this event to complete // processing. EventLog.Debug(ex); break; } // If the current record is the same as the last one we got last time // this method was called then stop processing more records. if (record.CompareTo(_previous.lastRequest) == 0) break; // Update the memory version. if (record.LastActiveDate == 0) { // Remove from the device as the last active date is zero. _previous.Requests.Remove(record.Key); } else { // Update or insert a new record. if (_previous.Requests.ContainsKey(record.Key)) _previous.Requests[record.Key] = record.LastActiveDate; else _previous.Requests.Add(record.Key, record.LastActiveDate); } if (firstDevice == null) firstDevice = new RequestRecord(record); } // If the length of the file hasn't changed during the processing // then update the last device record to limit the number of rows // examined in future file changes. if (length == stream.Length && firstDevice != null) _previous.lastRequest = firstDevice; // Signal to all the method again if the length of the file // has changed during processing. repeatProcess = length != stream.Length; reader.Close(); } } } // If the file was altered during the processing then call the method // again to capture any new records. if (repeatProcess) ProcessSyncFile(); } }
/// <summary> /// Removes this device request from the previous devices list. /// </summary> /// <param name="request">HttpRequest of the device.</param> public void Remove(HttpRequest request) { if (_syncFilePath != null) { RequestRecord record = new RequestRecord(request); // Get the latest data. RefreshSyncFile(); // Does the device exist in the previous devices list? if (_previous.Requests.ContainsKey(record.Key)) { // Set the last active date to zero so that it will be // removed when the sync file is serviced. record.LastActiveDate = 0; // Add this most recent request to the sync file. Add(record); } } }
/// <summary> /// Adds this device request to the previous devices list. /// </summary> /// <param name="request">HttpRequest of the device.</param> public void Set(HttpRequest request) { if (_syncFilePath != null) { RequestRecord record = new RequestRecord(request); // Get the latest data. RefreshSyncFile(); // Add this most recent request to the sync file. Add(record); // Check if the sync file needs to be serviced. CheckIfServiceRequired(); } }
/// <summary> /// Checks to find out if the device associated with the HttpRequest /// has already been seen by the application. Always returns false /// if the sync file has not been specified. /// </summary> /// <param name="request">HttpRequest to be checked.</param> /// <returns>True if the device associated with the request has been seen.</returns> public bool IsPresent(HttpRequest request) { if (_syncFilePath != null) { RequestRecord record = new RequestRecord(request); // Check to see if new request data needs to be loaded. RefreshSyncFile(); long expiryDateTime; if (_previous.Requests.TryGetValue(record.Key, out expiryDateTime)) { // If redirect timeout is zero then simply check to see if the // device is present in the list of previous devices. if (_redirectTimeout == 0) return true; // Is it still valid? return (new DateTime(expiryDateTime).AddMinutes(_redirectTimeout)).Ticks >= record.LastActiveDate; } } return false; }