private void StartForeignRequest( TrackerStateHolder trackerStateHolder )
        {
            LocationRequest locationRequest = PrepareLocationRequest( trackerStateHolder );

              if ( locationRequest == null )
            return;

              try
              {
            if ( !HolderRwLock.TryEnterWriteLock( ) )
            {
              Log.ErrorFormat( "Can't enter write mode in BeginRequest for {0}", trackerStateHolder.ForeignId );
              return;
            }

            try
            {
              trackerStateHolder.CurrentRequest = locationRequest;
              trackerStateHolder.RequestStartTime = TimeService.Now;
            }
            finally
            {
              HolderRwLock.ExitWriteLock( );
            }

            // Despite TrackerStateHolder having CurrentRequest field, locationRequest still need to
            // be passed as an implicit parameter because there is no guarantee that at the moment when
            // OnEndReadLocation is called there will be no other request started. E.g. this request
            // can be stuck, aborted by timeout, and then suddenly pop in again in OnEndReadLocation.
            // It's unlikely but still possible. So pass locationRequest to avoid any chance that
            // EndReadLocation is called on wrong locationRequest.
            Tuple<TrackerStateHolder, LocationRequest> paramTuple =
              new Tuple<TrackerStateHolder, LocationRequest>( trackerStateHolder, locationRequest );

            DateTime requestStart = TimeService.Now;

            locationRequest.BeginReadLocation( OnEndReadLocation, paramTuple );
            this.statistics.AddRequestStartEvent( trackerStateHolder.ForeignId, requestStart );
              }
              catch
              {
            this.statistics.AddRequestErrorEvent(trackerStateHolder.ForeignId.Type);

            trackerStateHolder.CurrentRequest = null; // no-good => no CurrentRequest, no setting ScheduledTime to null.
            throw;
              }

              Thread.MemoryBarrier( ); // set ScheduledTime only _after_ successful BeginReadLocation.

              trackerStateHolder.ScheduledTime = null;
        }
Esempio n. 2
0
        private static int CompareHolders( TrackerStateHolder x, TrackerStateHolder y )
        {
            bool areEqual;
              TrackerStateHolder moreStale = Scheduler.GetMoreStaleTracker( x, y, out areEqual );

              if ( areEqual )
            return string.Compare( x.ForeignId.Id, y.ForeignId.Id, StringComparison.InvariantCultureIgnoreCase );

              if ( ReferenceEquals( moreStale, x ) )
            return -1;

              return 1;
        }
        private LocationRequest PrepareLocationRequest( TrackerStateHolder trackerStateHolder )
        {
            LocationRequestFactory requestFactory =
            ForeignAccessCentral.LocationRequestFactories[trackerStateHolder.ForeignId.Type];

              RequestParams requestParams;
              requestParams.Id = trackerStateHolder.ForeignId.Id;

              // Read lock needed to read trackerStateHolder.Snapshot.Position
              if ( !HolderRwLock.TryEnterReadLock( ) )
              {
            Log.ErrorFormat( "Can't enter read mode in PrepareLocationRequest for {0}", trackerStateHolder.ForeignId );
            return null;
              }

              try
              {
            // Potentially, the snapshot with the existing track might change while the new data is being requested.
            // But it's not a problem because the old track is valid anyway - to make sure that, the requesting
            // algorithm will check if the old track's starting section matches new data loaded from the foreign
            // system. So existing track (most probably its trailing points) would be in use anyway.
            if ( trackerStateHolder.Snapshot == null ||
             trackerStateHolder.Snapshot.Position == null )
            {
              requestParams.ExistingTrack = null;
            }
            else
            {
              requestParams.ExistingTrack = trackerStateHolder.Snapshot.Position.FullTrack;
            }
              }
              finally
              {
            HolderRwLock.ExitReadLock( );
              }

              return requestFactory.CreateRequest( requestParams );
        }