Exemple #1
0
        public void GeoFix_Serialize_Fields()
        {
            // Test serialization of specific fields

            GeoFix fix;

            fix = new GeoFix();
            Assert.AreEqual(",,,,,,,,,", fix.ToString(GeoFixField.All));

            fix = new GeoFix()
            {
                TimeUtc            = new DateTime(2011, 3, 3, 10, 55, 15),
                Latitude           = 1.1,
                Longitude          = 2.2,
                Altitude           = 3.3,
                Course             = 4.4,
                Speed              = 5.5,
                HorizontalAccuracy = 6.6,
                VerticalAccurancy  = 7.7,
                Technology         = GeoFixTechnology.Tower,
                NetworkStatus      = NetworkStatus.Gsm
            };

            Assert.AreEqual(string.Format("{0},,,,,,,,,", fix.TimeUtc.Value.Ticks), fix.ToString(GeoFixField.TimeUtc));
            Assert.AreEqual(",1.1,,,,,,,,", fix.ToString(GeoFixField.Latitude));
            Assert.AreEqual(",,2.2,,,,,,,", fix.ToString(GeoFixField.Longitude));
            Assert.AreEqual(",,,3.3,,,,,,", fix.ToString(GeoFixField.Altitude));
            Assert.AreEqual(",,,,4.4,,,,,", fix.ToString(GeoFixField.Course));
            Assert.AreEqual(",,,,,5.5,,,,", fix.ToString(GeoFixField.Speed));
            Assert.AreEqual(",,,,,,6.6,,,", fix.ToString(GeoFixField.HorizontalAccuracy));
            Assert.AreEqual(",,,,,,,7.7,,", fix.ToString(GeoFixField.VerticalAccurancy));
            Assert.AreEqual(",,,,,,,,Tower,", fix.ToString(GeoFixField.Technology));
            Assert.AreEqual(",,,,,,,,,Gsm", fix.ToString(GeoFixField.NetworkStatus));
        }
Exemple #2
0
        private void VerifyTestFix(GeoFix fix)
        {
            Assert.IsNotNull(fix);

            // The lat/lon may change.  I got these values from visiting http://maxmind.com and
            // performing a manual lookup on the test IP address.  These coordinates are
            // for Google in MountainView, CA.

            Assert.AreEqual(37.4192, Math.Round(fix.Latitude, 4, MidpointRounding.AwayFromZero));
            Assert.AreEqual(-122.0574, Math.Round(fix.Longitude, 4, MidpointRounding.AwayFromZero));
        }
Exemple #3
0
        public void GeoFix_Serialize()
        {
            GeoFix fix;

            string[] fields;

            // Default values

            fix    = new GeoFix();
            fields = fix.ToString().Split(',');

            Assert.AreEqual(10, fields.Length);
            Assert.AreEqual("", fields[0]);      // Null TimeUtc is rendered as empty string
            Assert.AreEqual("", fields[1]);      // NaN coordinates are rendered as empty strings
            Assert.AreEqual("", fields[2]);
            Assert.AreEqual("", fields[3]);
            Assert.AreEqual("", fields[4]);
            Assert.AreEqual("", fields[5]);
            Assert.AreEqual("", fields[6]);
            Assert.AreEqual("", fields[7]);
            Assert.AreEqual("", fields[8]);      // GetFixTechnology.Unknown is rendered as empty
            Assert.AreEqual("", fields[9]);      // NetworkStatus.Unknown is rendered as empty

            // Set values

            fix = new GeoFix()
            {
                TimeUtc            = new DateTime(2011, 3, 3, 10, 55, 15),
                Latitude           = 1.1,
                Longitude          = 2.2,
                Altitude           = 3.3,
                Course             = 4.4,
                Speed              = 5.5,
                HorizontalAccuracy = 6.6,
                VerticalAccurancy  = 7.7,
                Technology         = GeoFixTechnology.Tower,
                NetworkStatus      = NetworkStatus.Gsm
            };

            fields = fix.ToString().Split(',');

            Assert.AreEqual(10, fields.Length);
            Assert.AreEqual(fix.TimeUtc.Value.Ticks.ToString(), fields[0]);
            Assert.AreEqual("1.1", fields[1]);
            Assert.AreEqual("2.2", fields[2]);
            Assert.AreEqual("3.3", fields[3]);
            Assert.AreEqual("4.4", fields[4]);
            Assert.AreEqual("5.5", fields[5]);
            Assert.AreEqual("6.6", fields[6]);
            Assert.AreEqual("7.7", fields[7]);
            Assert.AreEqual("Tower", fields[8]);
            Assert.AreEqual("Gsm", fields[9]);
        }
Exemple #4
0
        /// <summary>
        /// Archives a location fix for an entity.
        /// </summary>
        /// <param name="entityID">The entity identifier.</param>
        /// <param name="groupID">The group identifier or <c>null</c>.</param>
        /// <param name="fix">The location fix.</param>
        /// <remarks>
        /// <note>
        /// <see cref="IGeoFixArchiver" /> implementations must silently handle any internal
        /// error conditions.  <see cref="GeoTrackerNode" /> does not expect to see any
        /// exceptions raised from calls to any of these methods.  Implementations should
        /// catch any exceptions thrown internally and log errors or warnings as necessary.
        /// </note>
        /// </remarks>
        public void Archive(string entityID, string groupID, GeoFix fix)
        {
            lock (syncLock)
            {
                if (!isRunning)
                {
                    return;
                }

                bufferedFixes.Add(new FixRecord(entityID, groupID, fix));
            }
        }
Exemple #5
0
        /// <summary>
        /// Prepends a <see cref="GeoFix" /> to the head of the list of fixes,
        /// dropping the fix from the end to keep the total number of fixes
        /// within the limit passed to the constructor.
        /// </summary>
        /// <param name="fix">The received fix.</param>
        /// <param name="groupID">The associated group ID or <c>null</c>.</param>
        public void AddFix(GeoFix fix, string groupID)
        {
            // Use server time for the timestamp if necessary.

            if (fix.TimeUtc.HasValue)
            {
                var now = DateTime.UtcNow;

                // Don't allow fixes to be recorded for the future.  This could happen due
                // to clock skew from the source or possibly software bugs.  Allowing a fix
                // from the future would effectively cause all subsequent fixes to be ignored
                // which seems like a really bad thing (perhaps requiring server restart in
                // extreme circumstances).

                if (fix.TimeUtc > now)
                {
                    fix.TimeUtc = now;
                }
            }
            else
            {
                fix.TimeUtc = DateTime.UtcNow;
            }

            lock (fixes)
            {
                // This is really simple and somewhat inefficient.  I'm just going
                // to insert the new fix at the beginning of the list, making sure
                // that the list size remains below the limit.

                while (fixes.Count >= MaxEntityFixes)
                {
                    fixes.RemoveAt(fixes.Count - 1);
                }

                fixes.Insert(0, fix);

                if (CurrentFix == null)
                {
                    CurrentFix = fix;
                }
                else if (CurrentFix.TimeUtc <= fix.TimeUtc)
                {
                    CurrentFix = fix;
                }

                if (groupID != null)
                {
                    AddGroup(groupID, fix.TimeUtc.Value);
                }
            }
        }
Exemple #6
0
        /// <summary>
        /// Initiates an asynchronous operation to submits a <see cref="GeoFix" />
        /// for an entity to the GeoTracker cluster.
        /// </summary>
        /// <param name="entityID">The unique entity ID.</param>
        /// <param name="groupID">The group ID or <c>null</c>.</param>
        /// <param name="fix">The <see cref="GeoFix" /> being submitted.</param>
        /// <param name="callback">The completion callback or <c>null</c>.</param>
        /// <param name="state">Application state or <c>null</c>.</param>
        /// <returns>The <see cref="IAsyncResult" /> to be used to track the progress of the operation.</returns>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="entityID" /> or <paramref name="fix" /> is <c>null</c>.</exception>
        /// <remarks>
        /// <note>
        /// All calls to <see cref="BeginSubmitEntityFix" /> must eventually be followed by a call to <see cref="EndSubmitEntityFix" />.
        /// </note>
        /// </remarks>
        public IAsyncResult BeginSubmitEntityFix(string entityID, string groupID, GeoFix fix, AsyncCallback callback, object state)
        {
            if (entityID == null)
            {
                throw new ArgumentNullException("entityID");
            }

            if (fix == null)
            {
                throw new ArgumentNullException("fix");
            }

            return(router.BeginQuery(settings.ServerEP, new GeoFixMsg(entityID, groupID, fix), callback, state));
        }
Exemple #7
0
        public void GeoFix_Deserialize()
        {
            GeoFix fix;
            string v;

            // Default values

            fix = new GeoFix();
            v   = fix.ToString();
            fix = new GeoFix(v);

            Assert.IsNull(fix.TimeUtc);
            Assert.AreEqual(double.NaN, fix.Latitude);
            Assert.AreEqual(double.NaN, fix.Longitude);
            Assert.AreEqual(double.NaN, fix.Altitude);
            Assert.AreEqual(double.NaN, fix.Course);
            Assert.AreEqual(double.NaN, fix.Speed);
            Assert.AreEqual(double.NaN, fix.HorizontalAccuracy);
            Assert.AreEqual(double.NaN, fix.VerticalAccurancy);
            Assert.AreEqual(GeoFixTechnology.Unknown, fix.Technology);
            Assert.AreEqual(NetworkStatus.Unknown, fix.NetworkStatus);

            // Set values

            fix = new GeoFix()
            {
                TimeUtc            = new DateTime(2011, 3, 3, 10, 55, 15),
                Latitude           = 1.1,
                Longitude          = 2.2,
                Altitude           = 3.3,
                Course             = 4.4,
                Speed              = 5.5,
                HorizontalAccuracy = 6.6,
                VerticalAccurancy  = 7.7,
                Technology         = GeoFixTechnology.GPS,
                NetworkStatus      = NetworkStatus.Cdma
            };

            Assert.AreEqual(new DateTime(2011, 3, 3, 10, 55, 15), fix.TimeUtc);
            Assert.AreEqual(1.1, fix.Latitude);
            Assert.AreEqual(2.2, fix.Longitude);
            Assert.AreEqual(3.3, fix.Altitude);
            Assert.AreEqual(4.4, fix.Course);
            Assert.AreEqual(5.5, fix.Speed);
            Assert.AreEqual(6.6, fix.HorizontalAccuracy);
            Assert.AreEqual(7.7, fix.VerticalAccurancy);
            Assert.AreEqual(GeoFixTechnology.GPS, fix.Technology);
            Assert.AreEqual(NetworkStatus.Cdma, fix.NetworkStatus);
        }
Exemple #8
0
        public void GeoFix_Defaults()
        {
            var fix = new GeoFix();

            Assert.IsNull(fix.TimeUtc);
            Assert.AreEqual(double.NaN, fix.Latitude);
            Assert.AreEqual(double.NaN, fix.Longitude);
            Assert.AreEqual(double.NaN, fix.Altitude);
            Assert.AreEqual(double.NaN, fix.Course);
            Assert.AreEqual(double.NaN, fix.Speed);
            Assert.AreEqual(double.NaN, fix.HorizontalAccuracy);
            Assert.AreEqual(double.NaN, fix.VerticalAccurancy);
            Assert.AreEqual(GeoFixTechnology.Unknown, fix.Technology);
            Assert.AreEqual(NetworkStatus.Unknown, fix.NetworkStatus);
        }
Exemple #9
0
        /// <summary>
        /// Loads the message payload from the stream passed.
        /// </summary>
        /// <param name="es">The enhanced stream where the output is to be written.</param>
        /// <param name="cbPayload">Number of bytes of payload data.</param>
        protected override void ReadPayload(EnhancedStream es, int cbPayload)
        {
            int cFixes;

            EntityID = es.ReadString16();
            GroupID  = es.ReadString16();

            cFixes = es.ReadInt32();
            Fixes  = new GeoFix[cFixes];

            for (int i = 0; i < cFixes; i++)
            {
                Fixes[i] = new GeoFix(es.ReadString16());
            }
        }
Exemple #10
0
        public void GeoFix_Parse()
        {
            GeoFix fix;

            // Test null or empty input strings.

            Assert.IsNull(GeoFix.Parse(null));
            Assert.IsNull(GeoFix.Parse(""));
            Assert.IsNull(GeoFix.Parse("    "));

            // Test actual parsing.

            fix = new GeoFix()
            {
                TimeUtc            = new DateTime(2011, 3, 3, 10, 55, 15),
                Latitude           = 1.1,
                Longitude          = 2.2,
                Altitude           = 3.3,
                Course             = 4.4,
                Speed              = 5.5,
                HorizontalAccuracy = 6.6,
                VerticalAccurancy  = 7.7,
                Technology         = GeoFixTechnology.GPS,
                NetworkStatus      = NetworkStatus.Cdma
            };

            fix = GeoFix.Parse(fix.ToString());

            Assert.AreEqual(new DateTime(2011, 3, 3, 10, 55, 15), fix.TimeUtc);
            Assert.AreEqual(1.1, fix.Latitude);
            Assert.AreEqual(2.2, fix.Longitude);
            Assert.AreEqual(3.3, fix.Altitude);
            Assert.AreEqual(4.4, fix.Course);
            Assert.AreEqual(5.5, fix.Speed);
            Assert.AreEqual(6.6, fix.HorizontalAccuracy);
            Assert.AreEqual(7.7, fix.VerticalAccurancy);
            Assert.AreEqual(GeoFixTechnology.GPS, fix.Technology);
            Assert.AreEqual(NetworkStatus.Cdma, fix.NetworkStatus);
        }
Exemple #11
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="entityID">The entity ID.</param>
 /// <param name="fix">The current <see cref="GeoFix" /> for the entity.</param>
 public EntityFix(string entityID, GeoFix fix)
 {
     this.EntityID = entityID;
     this.Fix      = fix;
 }
Exemple #12
0
 /// <summary>
 /// Adds an entity location fix to the cache.
 /// </summary>
 /// <param name="entityID">The entity ID.</param>
 /// <param name="groupID">The group ID or <c>null</c>.</param>
 /// <param name="fix">The location <see cref="GeoFix" />.</param>
 public void AddEntityFix(string entityID, string groupID, GeoFix fix)
 {
     AddEntityFixes(entityID, groupID, new GeoFix[] { fix });
 }
Exemple #13
0
        /// <summary>
        /// Synchronously submits a <see cref="GeoFix" /> for an entity to the GeoTracker cluster.
        /// </summary>
        /// <param name="entityID">The unique entity ID.</param>
        /// <param name="groupID">The group ID or <c>null</c>.</param>
        /// <param name="fix">The <see cref="GeoFix" /> being submitted.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="entityID" /> or <paramref name="fix" /> are <c>null</c>.</exception>
        public void SubmitEntityFix(string entityID, string groupID, GeoFix fix)
        {
            var ar = BeginSubmitEntityFix(entityID, groupID, fix, null, null);

            EndSubmitEntityFix(ar);
        }
Exemple #14
0
 public FixRecord(string entityID, string groupID, GeoFix fix)
 {
     this.EntityID = entityID;
     this.GroupID  = groupID;
     this.Fix      = fix;
 }
Exemple #15
0
 /// <summary>
 /// Archives a location fix for an entity.
 /// </summary>
 /// <param name="entityID">The entity identifier.</param>
 /// <param name="groupID">The group identifier or <c>null</c>.</param>
 /// <param name="fix">The location fix.</param>
 /// <remarks>
 /// <note>
 /// <see cref="IGeoFixArchiver" /> implementations must silently handle any internal
 /// error conditions.  <see cref="GeoTrackerNode" /> does not expect to see any
 /// exceptions raised from calls to any of these methods.  Implementations should
 /// catch any exceptions thrown internally and log errors or warnings as necessary.
 /// </note>
 /// </remarks>
 public void Archive(string entityID, string groupID, GeoFix fix)
 {
 }
Exemple #16
0
 /// <summary>
 /// Constructs a message with a single <see cref="GeoFix" />.
 /// </summary>
 /// <param name="entityID">The unique entity ID.</param>
 /// <param name="groupID">The group ID or <c>null</c>.</param>
 /// <param name="fix">The <see cref="GeoFix" /> to be recorded.</param>
 public GeoFixMsg(string entityID, string groupID, GeoFix fix)
 {
     this.EntityID = entityID;
     this.GroupID  = groupID;
     this.Fixes    = new GeoFix[] { fix };
 }
Exemple #17
0
        public void GeoTrackerMsgs_IPToGeoFixAck()
        {
            EnhancedStream es = new EnhancedMemoryStream();
            IPToGeoFixAck  msgIn, msgOut;
            GeoFix         fix;

            Msg.ClearTypes();
            LillTek.GeoTracker.Global.RegisterMsgTypes();

            // Test the return of an actual fix.

            fix = new GeoFix()
            {
                TimeUtc            = new DateTime(2011, 3, 3, 10, 55, 15),
                Latitude           = 1.1,
                Longitude          = 2.2,
                Altitude           = 3.3,
                Course             = 4.4,
                Speed              = 5.5,
                HorizontalAccuracy = 6.6,
                VerticalAccurancy  = 7.7,
                Technology         = GeoFixTechnology.GPS,
                NetworkStatus      = NetworkStatus.Cdma
            };

            msgOut = new IPToGeoFixAck(fix);

            Msg.Save(es, msgOut);
            es.Position = 0;
            msgIn       = (IPToGeoFixAck)Msg.Load(es);

            Assert.IsNotNull(msgIn);

            fix = msgIn.GeoFix;
            Assert.AreEqual(new DateTime(2011, 3, 3, 10, 55, 15), fix.TimeUtc);
            Assert.AreEqual(1.1, fix.Latitude);
            Assert.AreEqual(2.2, fix.Longitude);
            Assert.AreEqual(3.3, fix.Altitude);
            Assert.AreEqual(4.4, fix.Course);
            Assert.AreEqual(5.5, fix.Speed);
            Assert.AreEqual(6.6, fix.HorizontalAccuracy);
            Assert.AreEqual(7.7, fix.VerticalAccurancy);
            Assert.AreEqual(GeoFixTechnology.GPS, fix.Technology);
            Assert.AreEqual(NetworkStatus.Cdma, fix.NetworkStatus);

            // Test the return of a NULL fix.

            msgOut = new IPToGeoFixAck((GeoFix)null);

            es.Position = 0;
            Msg.Save(es, msgOut);
            es.Position = 0;
            msgIn       = (IPToGeoFixAck)Msg.Load(es);

            Assert.IsNotNull(msgIn);
            Assert.IsNull(msgIn.GeoFix);

            // Test exception encoding.

            msgOut = new IPToGeoFixAck(new NotImplementedException("This is a test"));

            es.Position = 0;
            Msg.Save(es, msgOut);
            es.Position = 0;
            msgIn       = (IPToGeoFixAck)Msg.Load(es);

            Assert.IsNotNull(msgIn);
            Assert.IsNull(msgIn.GeoFix);
            Assert.AreEqual("System.NotImplementedException", msgOut.ExceptionTypeName);
            Assert.AreEqual("This is a test", msgOut.Exception);

            // Test Clone()

            msgIn = (IPToGeoFixAck) new IPToGeoFixAck(fix).Clone();
            fix   = msgIn.GeoFix;
            Assert.AreEqual(new DateTime(2011, 3, 3, 10, 55, 15), fix.TimeUtc);
            Assert.AreEqual(1.1, fix.Latitude);
            Assert.AreEqual(2.2, fix.Longitude);
            Assert.AreEqual(3.3, fix.Altitude);
            Assert.AreEqual(4.4, fix.Course);
            Assert.AreEqual(5.5, fix.Speed);
            Assert.AreEqual(6.6, fix.HorizontalAccuracy);
            Assert.AreEqual(7.7, fix.VerticalAccurancy);
            Assert.AreEqual(GeoFixTechnology.GPS, fix.Technology);
            Assert.AreEqual(NetworkStatus.Cdma, fix.NetworkStatus);

            msgIn = (IPToGeoFixAck) new IPToGeoFixAck(new NotImplementedException("This is a test")).Clone();
            Assert.IsNotNull(msgIn);
            Assert.IsNull(msgIn.GeoFix);
            Assert.AreEqual("System.NotImplementedException", msgOut.ExceptionTypeName);
            Assert.AreEqual("This is a test", msgOut.Exception);
        }
Exemple #18
0
        /// <summary>
        /// Archives a location fix for an entity.
        /// </summary>
        /// <param name="entityID">The entity identifier.</param>
        /// <param name="groupID">The group identifier or <c>null</c>.</param>
        /// <param name="fix">The location fix.</param>
        /// <remarks>
        /// <note>
        /// <see cref="IGeoFixArchiver" /> implementations must silently handle any internal
        /// error conditions.  <see cref="GeoTrackerNode" /> does not expect to see any
        /// exceptions raised from calls to any of these methods.  Implementations should
        /// catch any exceptions thrown internally and log errors or warnings as necessary.
        /// </note>
        /// </remarks>
        public void Archive(string entityID, string groupID, GeoFix fix)
        {
            lock (syncLock)
            {
                try
                {
                    if (isStopped)
                    {
                        throw new InvalidOperationException("AppLogGeoFixArchiver: Cannot log to a stopped archiver.");
                    }

                    if (logWriter == null)
                    {
                        logWriter = new AppLogWriter(logName, SchemaName, SchemaVersion, maxSize);
                        logWriter.PurgeInterval = purgeInterval;
                    }

                    var record = new AppLogRecord();

                    if (entityID != null)
                    {
                        record["EntityID"] = entityID;
                    }

                    if (groupID != null)
                    {
                        record["GroupID"] = groupID;
                    }

                    if (fix.TimeUtc.HasValue)
                    {
                        record["TimeUtc"] = fix.TimeUtc;
                    }

                    record["Technology"] = fix.Technology;

                    if (!double.IsNaN(fix.Latitude))
                    {
                        record["Latitude"] = fix.Latitude;
                    }

                    if (!double.IsNaN(fix.Longitude))
                    {
                        record["Longitude"] = fix.Longitude;
                    }

                    if (!double.IsNaN(fix.Altitude))
                    {
                        record["Altitude"] = fix.Altitude;
                    }

                    if (!double.IsNaN(fix.Course))
                    {
                        record["Course"] = fix.Course;
                    }

                    if (!double.IsNaN(fix.Speed))
                    {
                        record["Speed"] = fix.Speed;
                    }

                    if (!double.IsNaN(fix.HorizontalAccuracy))
                    {
                        record["HorizontalAccuracy"] = fix.HorizontalAccuracy;
                    }

                    if (!double.IsNaN(fix.VerticalAccurancy))
                    {
                        record["VerticalAccurancy"] = fix.VerticalAccurancy;
                    }

                    record["NetworkStatus"] = fix.NetworkStatus;

                    logWriter.Write(record);
                    node.IncrementFixesReceivedBy(1);
                }
                catch (Exception e)
                {
                    SysLog.LogException(e);
                }
            }
        }
Exemple #19
0
 /// <summary>
 /// Constructs the ack instance to be used to communicate the configuration text
 /// text back to the client.
 /// </summary>
 /// <param name="fix">The <see cref="GeoFix" /> to be returned or <c>null</c>.
 /// </param>
 public IPToGeoFixAck(GeoFix fix)
 {
     this.GeoFix = fix;
 }
Exemple #20
0
        public void GeoTracker_Cluster_SubmitFix_Multiple()
        {
            // Submit multiple location fixes for several entities and verify.

            try
            {
                const int cEntities = 100;
                const int cFixes    = 10;

                int  cSubmitted;
                bool fail;

                TestInit();

                // Submit the fixes in parallel.

                cSubmitted = 0;
                fail       = false;

                for (int i = 0; i < cFixes; i++)
                {
                    for (int j = 0; j < cEntities; j++)
                    {
                        var fix = new GeoFix()
                        {
                            Latitude = 10 + i, Longitude = 20
                        };

                        client.BeginSubmitEntityFix(j.ToString(), "group", fix,
                                                    ar =>
                        {
                            try
                            {
                                client.EndSubmitEntityFix(ar);
                            }
                            catch (Exception e)
                            {
                                SysLog.LogException(e);
                                fail = true;
                            }
                            finally
                            {
                                Interlocked.Increment(ref cSubmitted);
                            }
                        },
                                                    null);
                    }
                }

                // Wait for the submissions to complete.

                Helper.WaitFor(() => cSubmitted == cEntities * cFixes, TimeSpan.FromMinutes(2));
                Assert.IsFalse(fail);

                // Verify that the fixes were distributed across the cluster.

                var instanceFixes = new int[clusterInstances.Length];

                for (int i = 0; i < clusterInstances.Length; i++)
                {
                    instanceFixes[i] = clusterInstances[i].Node.FixCache.EntityCount;
                    Assert.IsTrue(instanceFixes[i] >= cEntities / InstanceCount * 0.75);
                }
            }
            finally
            {
                TestCleanup();
            }
        }
Exemple #21
0
        /// <summary>
        /// Removes all fixes and group memberships with timestamps older than the specified value.
        /// </summary>
        /// <param name="purgeTimeUtc">The minimum age for retained fixes.</param>
        /// <returns><c>true</c> if the all fixes have been purged from the entity.</returns>
        public bool Purge(DateTime purgeTimeUtc)
        {
            int cPurged = 0;

            lock (fixes)
            {
                // Set the slots for purged fixes to NULL.

                for (int i = 0; i < fixes.Count; i++)
                {
                    if (fixes[i].TimeUtc < purgeTimeUtc)
                    {
                        fixes[i] = null;
                        cPurged++;
                    }
                }

                // Now go back and collapse out the null entries.

                if (cPurged == 0)
                {
                    CurrentFix = null;
                    return(fixes.Count == 0);
                }

                int pos = 0;

                for (int i = 0; i < fixes.Count; i++)
                {
                    if (fixes[i] != null)
                    {
                        fixes[pos++] = fixes[i];
                    }
                }

                for (int i = 0; i < cPurged; i++)
                {
                    fixes.RemoveAt(fixes.Count - 1);
                }

                if (fixes.Count == 0)
                {
                    groups     = null;
                    CurrentFix = null;
                    return(true);
                }
                else
                {
                    if (groups != null)
                    {
                        // Determine whether we need to remove any group references.

                        int retainCount = 0;

                        foreach (var group in groups)
                        {
                            if (group.FixTimeUtc >= purgeTimeUtc)
                            {
                                retainCount++;
                            }
                        }

                        if (retainCount < groups.Length)
                        {
                            var newGroups = new GroupMembership[retainCount];

                            pos = 0;
                            foreach (var group in groups)
                            {
                                if (group.FixTimeUtc >= purgeTimeUtc)
                                {
                                    newGroups[pos++] = group;
                                }
                            }

                            groups = newGroups;
                        }
                    }

                    return(false);
                }
            }
        }