/// <summary> /// Update this position after reading another data item /// </summary> /// <param name="lastReadDataItem"> /// Last data item that has been read from this folder /// </param> public void Update(IDataItem lastReadDataItem) { if (Time == lastReadDataItem.DateTime) { ++NumberOfItemsWithTheTimestampRead; } else { Time = lastReadDataItem.DateTime; NumberOfItemsWithTheTimestampRead = 1; } VerificationLastReadItemHash = lastReadDataItem.GetBusinessHashCode(); }
private void SkipItemsByExactPosition() { Check.Require(_position.IsExact, "Position must be exact"); Check.Require(!_listReader.HasItem || _timeComparison.Compare(_listReader.Current.DateTime, _position.Time) >= 0 , "Reader must be alredy rolled forward to the position time"); IDataItem itemFromPosition = null; string warningMessage = string.Empty; // skipping items with the timestamp equal to the position time which had already been read // note that in exact positions (where IsExact equals true) NumberOfItemsWithTheTimestampRead is always greater than zero, // otherwise it's not an exact position and versification is not required; // this loop will be executed for exact positions only, at least once (thus we either detect position restore issue or move forward // until past the last read item as recorded in the position); // if the file does not contain item with timestamp equal to the last read item timestamp in the exact position // the item from position will not be found FolderSeekStatus.PositionStatus status = FolderSeekStatus.PositionStatus.Success; for ( int n = 0; status == FolderSeekStatus.PositionStatus.Success && n < _position.NumberOfItemsWithTheTimestampRead; ++n) { if (!_listReader.HasItem || _listReader.Current.DateTime != _position.Time) { // using Round-trip date/time pattern: 2009-06-15T13:45:30.0900000 _log.WarnFormat("Restoring position for {0} found item by time ({1:O}) and number ({2})" , TargetFolder.FolderKey , _position.Time , _position.NumberOfItemsWithTheTimestampRead); // loop will break status = FolderSeekStatus.PositionStatus.DataItemNotFound; } else { if (_position.NumberOfItemsWithTheTimestampRead - 1 == n) { // last iteration of the loop: found item by time and number itemFromPosition = _listReader.Current; } // moving to the next only if time matches with position time _listReader.MoveNext(); } } if (itemFromPosition != null) { // have item from position; check hashes if (itemFromPosition.GetBusinessHashCode() != _position.VerificationLastReadItemHash) { warningMessage = string.Format( "Restoring position for {0} found item by time and number, but its verification failed: hash in position: {1:X8}, actual: {2:X8}" , TargetFolder.FolderKey , _position.VerificationLastReadItemHash , itemFromPosition.GetBusinessHashCode()); _log.Warn(warningMessage); status = FolderSeekStatus.PositionStatus.DataItemHashMismatch; } else { _log.InfoFormat("Exact position for {0} restored successfully", TargetFolder.FolderKey); } } else { Check.Ensure(status == FolderSeekStatus.PositionStatus.DataItemNotFound); } // reporting issues only if (status != FolderSeekStatus.PositionStatus.Success) { MasterReader.SeekStatusCallback(new FolderSeekStatus(TargetFolder.FolderKey, status, warningMessage)); } }