private bool IsSessionRunning(Guid sessionId)
 {
     // Hmmm, is it really done, or still running after calling EndSession()?
     using (InterprocessLock sessionLock = InterprocessLockManager.Lock(this, m_SessionLockFolder, sessionId.ToString(), 0, true))
     {
         if (sessionLock == null)
         {
             // It's holding the lock, so it must still be active!
             return(true);
         }
         // Otherwise, it has released the lock, so it really is closed as it said.  We're good.
         return(false);
     }
 }
        private void Initialize()
        {
            if (m_Initialized)
            {
                return;
            }

            //we need to grab a lock on this session to prevent it from being transported to the same endpoint at the same time.
            string sessionWorkingFileNamePath = GenerateTemporarySessionFileNamePath();

            //we aren't going to do Using - we keep the lock!
            if (m_SessionTransportLock == null) //if we are retrying to initialize after a failure we may already have it.
            {
                m_SessionTransportLock = InterprocessLockManager.Lock(this, GenerateTemporarySessionPath(), GenerateTemporarySessionFileName(), 0, true);
            }

            //we aren't waiting to see if we can get the lock - if anyone else has it they must be transferring the session.
            if (m_SessionTransportLock != null)
            {
                //Lets figure out if we're restarting a previous send or starting a new one.
                m_TempSessionProgressFileNamePath = sessionWorkingFileNamePath + ".txt";

                m_BytesWritten = 0;
                if (File.Exists(m_TempSessionProgressFileNamePath))
                {
                    //load up the existing transfer state.
                    try
                    {
                        m_BytesWritten = LoadProgressTrackingFile();
                    }
                    catch
                    {
                        //oh well, assume no progress.
                        m_PerformCleanup = true;

                        SafeDeleteFile(m_TempSessionProgressFileNamePath);
                    }
                }
                else
                {
                    //make sure we didn't get started, but not finish, writing our temp file.
                    SafeDeleteFile(m_TempSessionProgressFileNamePath);
                }

                m_Initialized = true;
            }
        }
Пример #3
0
        /// <summary>
        /// Get the unique lock for the active session, to be held until the session exits.
        /// </summary>
        private void GetSessionFileLock()
        {
            if (m_SessionFileLock != null)
            {
                return;
            }

            var sessionId       = Log.SessionSummary.Id;
            var sessionLockName = sessionId.ToString();

            try
            {
                m_SessionFileLock = InterprocessLockManager.Lock(this, m_SessionLockFolder, sessionLockName, 0, true);

                if (m_SessionFileLock == null)
                {
                    Log.Write(LogMessageSeverity.Information, LogCategory, "Loupe Agent unable to get the unique lock for a new session",
                              "The Loupe Agent's FileMessenger was not able to lock this active session as Running.  " +
                              "This could interfere with efficiently distinguishing whether this session has crashed or is still running.");
#if DEBUG
                    if (Debugger.IsAttached)
                    {
                        Debugger.Break();
                    }
#endif
                }
            }
            catch (Exception ex) //we don't want failure to get the session file lock to be fatal...
            {
                if (!Log.SilentMode)
                {
                    Log.Write(LogMessageSeverity.Information, LogWriteMode.Queued, ex, true, LogCategory,
                              "Loupe Agent unable to get the unique lock for a new session due to " + ex.GetBaseException().GetType(),
                              "The Loupe Agent's FileMessenger was not able to lock this active session as Running.  " +
                              "This could interfere with efficiently distinguishing whether this session has crashed or is still running.");
                }
            }
        }
 /// <summary>
 /// Get a multiprocess lock for the subscription engine.
 /// </summary>
 /// <param name="timeout"></param>
 /// <returns></returns>
 private InterprocessLock GetLock(int timeout)
 {
     return(InterprocessLockManager.Lock(this, m_RepositoryFolder, m_MultiprocessLockName, timeout));
 }
        private void Initialize()
        {
            if (m_Initialized)
            {
                return;
            }

            //we need to grab a lock on this session to prevent it from being transported to the same endpoint at the same time.
            var sessionWorkingFileNamePath = GenerateTemporarySessionFileNamePath();

            //we aren't going to do Using - we keep the lock!
            if (m_SessionTransportLock == null) //if we are retrying to initialize after a failure we may already have it.
            {
                m_SessionTransportLock = InterprocessLockManager.Lock(this, GenerateTemporarySessionPath(), GenerateTemporarySessionFileName(), 0, true);
            }

            //we aren't waiting to see if we can get the lock - if anyone else has it they must be transferring the session.
            if (m_SessionTransportLock != null)
            {
                //grab a lock on the actual data file - if it's not there, no point in continuing.
                m_SessionFileStream = Repository.LoadSessionFileStream(SessionId, FileId.Value);

                //calculate our SHA1 Hash...
                try
                {
                    using (var csp = SHA1.Create())
                    {
                        m_SessionFileHash = BitConverter.ToString(csp.ComputeHash(m_SessionFileStream));
                    }

                    //now back up the stream to the beginning so we can send the actual data.
                    m_SessionFileStream.Position = 0;
                }
                catch (Exception ex)
                {
                    if (!Log.SilentMode)
                    {
                        Log.Write(LogMessageSeverity.Error, LogWriteMode.Queued, ex, RepositoryPublishClient.LogCategory, "Unable to calculate hash for session file due to " + ex.GetType() + " exception.", "The upload will proceed but without the hash to check the accuracy of the upload.\r\nException: {0}\r\n{1}\r\n", ex.GetType(), ex.Message);
                    }
                }

                //Lets figure out if we're restarting a previous send or starting a new one.
                m_TempSessionProgressFileNamePath = sessionWorkingFileNamePath;

                m_BytesWritten = 0;
                if (File.Exists(m_TempSessionProgressFileNamePath))
                {
                    //load up the existing transfer state.
                    try
                    {
                        m_BytesWritten = LoadProgressTrackingFile();
                    }
                    catch
                    {
                        //oh well, assume no progress.
                        m_PerformCleanup = true;

                        SafeDeleteFile(m_TempSessionProgressFileNamePath);
                    }
                }
                else
                {
                    //make sure we didn't get started, but not finish, writing our temp file.
                    SafeDeleteFile(m_TempSessionProgressFileNamePath);
                }

                m_Initialized = true;
            }
        }
        /// <summary>
        /// Execute repository maintenance on a background thread.
        /// </summary>
        private void AsyncPerformMaintenance(object state)
        {
            try
            {
                //make sure if we log something it never blocks, since that could ultimately result in a deadlock.
                Publisher.ThreadMustNotBlock();

                bool collectionChanged = false;

                //since external objects can freely modify our configuration, save a copy so we run with a consistent perspective.
                int maxSizeMegabytes = MaxSizeMegabytes;
                int maxAgeDays       = MaxAgeDays;
                if (m_LoggingEnabled)
                {
                    Log.Write(LogMessageSeverity.Information, LogCategory, "Starting Repository Maintenance", "Starting repository maintenance on repository stored at {0}, removing fragments older than {1} days and keeping the repository under {2:N0} megabytes.", RepositoryPath, maxAgeDays, maxSizeMegabytes);
                }

                //before we do anything more, we have to get the maintenance lock.
                using (InterprocessLock maintenanceLock = InterprocessLockManager.Lock(this, m_RepositoryPath, MutiprocessLockName, 0, true))
                {
                    if (maintenanceLock == null)
                    {
                        //we couldn't get the lock, so no maintenance today.
                        if (m_LoggingEnabled)
                        {
                            Log.Write(LogMessageSeverity.Warning, LogCategory, "Unable to Perform Maintenance - Repository Locked", "Unable to get the maintenance file lock on the repository stored at {0}, not performing maintenance.", RepositoryPath);
                        }
                        return;
                    }

                    //We may not be able to do pruning - we used to be used just for index DB update (not valid any more)
                    if ((string.IsNullOrEmpty(ApplicationName) == false) && (Log.IsSessionEnding == false))
                    {
                        //find out if there is any maintenance to do - we start by age and it'll let us know if we have anything else to do.
                        bool capacityPruningRequired;
                        bool sessionsRemoved = ProcessPruneForAge(maxAgeDays, maxSizeMegabytes, out capacityPruningRequired);
                        collectionChanged = (collectionChanged || sessionsRemoved);

                        //make sure capacity pruning is enabled.
                        if (maxSizeMegabytes <= 0)
                        {
                            capacityPruningRequired = false;
                        }

                        //anything more to do?
                        if ((capacityPruningRequired) && (Log.IsSessionEnding == false))
                        {
                            sessionsRemoved   = ProcessPruneForSize(MaxSizeMegabytes);
                            collectionChanged = (collectionChanged || sessionsRemoved);
                        }

                        ////and do crashed session conversion.
                        //bool crashedSessionsChanged = ProcessCrashedSessionConversion();
                        //collectionChanged = (collectionChanged || crashedSessionsChanged);
                    }
                }

                if (collectionChanged)
                {
                    OnCollectionChanged(new CollectionChangeEventArgs(CollectionChangeAction.Refresh, null));
                }
                if (m_LoggingEnabled)
                {
                    Log.Write(LogMessageSeverity.Information, LogCategory, "Repository Maintenance Complete", "Repository maintenance completed on repository stored at {0}", RepositoryPath);
                }
            }
            catch (Exception ex)
            {
                GC.KeepAlive(ex);
                if (m_LoggingEnabled)
                {
                    Log.Write(LogMessageSeverity.Warning, LogCategory, "Unable to Perform Repository Maintenance", "Unable to complete repository maintenance successfully due to an exception: {0}", ex);
                }
            }
            finally
            {
                //now we need to mark that we're done, and this is done with a lock for multithread purity.
                lock (m_Lock)
                {
                    m_PerformingMaintenance = false;
                    System.Threading.Monitor.PulseAll(m_Lock);
                }
            }
        }