private bool ShouldIgnore(string actualPath, Path drivePath, USNChangeRange range, NtfsUsnJournal journal)
        {
            if (actualPath == "Unavailable")
            {
                return(true);
            }

            string relativePath;

            try
            {
                Uri drivePathUri  = new Uri(drivePath.FullPath, UriKind.Absolute);
                Uri actualPathUri = new Uri(actualPath, UriKind.Absolute);

                relativePath = Uri.UnescapeDataString(drivePathUri.MakeRelativeUri(actualPathUri).ToString());
            }
            catch (Exception e)
            {
                relativePath = "#ERROR#";
            }

            if (relativePath == "#ERROR#" || relativePath.StartsWith("System Volume Information") || relativePath.StartsWith("$RECYCLE.BIN"))
            {
                return(true);
            }

            string renameFromRelativePath = "";

            if (range.RenameFrom != null)
            {
                string renameFromPath = GetActualPath(journal, range.RenameFrom);

                try
                {
                    Uri drivePathUri  = new Uri(drivePath.FullPath, UriKind.Absolute);
                    Uri actualPathUri = new Uri(renameFromPath, UriKind.Absolute);

                    renameFromRelativePath = Uri.UnescapeDataString(drivePathUri.MakeRelativeUri(actualPathUri).ToString());
                }
                catch (Exception e)
                {
                    renameFromRelativePath = "";
                }
            }

            if (!String.IsNullOrWhiteSpace(renameFromRelativePath) && renameFromRelativePath.StartsWith(".proximaTemp"))
            {
                return(true);
            }

            return(false);
        }
        public void Execute(IJobExecutionContext context)
        {
            if (Singleton.Instance.SourceMountpoints == null || Singleton.Instance.SourceMountpoints.Count == 0)
            {
                return;
            }

            try
            {
                foreach (var sourceMount in Singleton.Instance.SourceMountpoints)
                {
                    var construct = new DriveConstruct(sourceMount.MountPoint);
                    Win32Api.USN_JOURNAL_DATA newUsnState;
                    List <Win32Api.UsnEntry>  usnEntries;
                    NtfsUsnJournal            journal = new NtfsUsnJournal(construct.DriveLetter);

                    var drivePath = Path.Get(construct.DriveLetter);

                    logger.Trace("Polling for changes from " + sourceMount.CurrentUSNLocation);

                    var rtn = journal.GetUsnJournalEntries(construct.CurrentJournalData, reasonMask, out usnEntries, out newUsnState, OverrideLastUsn: sourceMount.CurrentUSNLocation);

                    if (rtn == NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
                    {
                        List <RawUSNEntry> entries = new List <RawUSNEntry>();
                        if (usnEntries.Any())
                        {
                            logger.Debug("USN returned with " + usnEntries.Count + " entries");
                            logger.Trace($"fsutil usn readjournal {construct.Volume} startusn={sourceMount.CurrentUSNLocation}");
                        }

                        List <USNChangeRange> changeRange = new List <USNChangeRange>();

                        foreach (var frn in usnEntries.Select(e => e.FileReferenceNumber).Distinct())
                        {
                            var entriesForFile = usnEntries.Where(f => f.FileReferenceNumber == frn).ToList();

                            if (entriesForFile.All(e => e.SourceInfo == Win32Api.UsnEntry.USNJournalSourceInfo.DataManagement || e.SourceInfo == Win32Api.UsnEntry.USNJournalSourceInfo.ReplicationManagement))
                            {
                                continue;
                            }

                            var actualPath = GetActualPath(journal, entriesForFile.FirstOrDefault());

                            if (actualPath == "Unavailable" || String.IsNullOrWhiteSpace(actualPath))
                            {
                                continue;
                            }

                            if (sourceMount.IgnoreList != null && sourceMount.IgnoreList.Any() && sourceMount.IgnoreList.Any(ignore => new Regex(ignore).IsMatch(actualPath)))
                            {
                                continue;
                            }

                            USNChangeRange range = new USNChangeRange
                            {
                                FRN        = frn,
                                Min        = entriesForFile.Min(e => e.TimeStamp),
                                Max        = entriesForFile.Max(e => e.TimeStamp),
                                Closed     = entriesForFile.OrderBy(f => f.TimeStamp).LastOrDefault() != null ? (entriesForFile.OrderBy(f => f.TimeStamp).LastOrDefault().Reason & Win32Api.USN_REASON_CLOSE) != 0 : false,
                                RenameFrom = entriesForFile.FirstOrDefault(e => (e.Reason & Win32Api.USN_REASON_RENAME_OLD_NAME) != 0),
                                Entry      = entriesForFile.OrderBy(f => f.TimeStamp).LastOrDefault()
                            };

                            bool alreadyCopiedItem = entriesForFile.GroupBy(r => r.ParentFileReferenceNumber).Select(r => r.First()).Distinct().Any(pfrn => GetActualPath(journal, pfrn).Contains("\\.proximaTemp\\"));

                            if (alreadyCopiedItem || ShouldIgnore(actualPath, drivePath, range, journal))
                            {
                                continue;
                            }

                            changeRange.Add(range);
                        }


                        foreach (var item in changeRange)
                        {
                            var actualPath = GetActualPath(journal, item.Entry);

                            if (actualPath == "Unavailable")
                            {
                                continue;
                            }

                            string relativePath;
                            try
                            {
                                Uri drivePathUri  = new Uri(drivePath.FullPath, UriKind.Absolute);
                                Uri actualPathUri = new Uri(actualPath, UriKind.Absolute);

                                relativePath = Uri.UnescapeDataString(drivePathUri.MakeRelativeUri(actualPathUri).ToString());
                            }
                            catch (Exception e)
                            {
                                relativePath = "#ERROR#";
                            }

                            if (relativePath == "#ERROR#" || relativePath.StartsWith("System Volume Information"))
                            {
                                continue;
                            }


                            string renameFromRelativePath = "";
                            if (item.RenameFrom != null)
                            {
                                string renameFromPath = GetActualPath(journal, ((Win32Api.UsnEntry)item.RenameFrom));

                                try
                                {
                                    Uri drivePathUri  = new Uri(drivePath.FullPath, UriKind.Absolute);
                                    Uri actualPathUri = new Uri(actualPath, UriKind.Absolute);

                                    renameFromRelativePath = Uri.UnescapeDataString(drivePathUri.MakeRelativeUri(actualPathUri).ToString());
                                }
                                catch (Exception e)
                                {
                                    renameFromRelativePath = "";
                                }
                            }

                            if (!String.IsNullOrWhiteSpace(renameFromRelativePath) && renameFromRelativePath.StartsWith(".proximaTemp"))
                            {
                                continue;
                            }

                            var dbEntry = new RawUSNEntry();

                            PopulateFlags(dbEntry, item.Entry);

                            dbEntry.Path         = actualPath;
                            dbEntry.RelativePath = relativePath;
                            dbEntry.File         = item.Entry.IsFile;
                            dbEntry.Directory    = item.Entry.IsFolder;
                            dbEntry.FRN          = item.Entry.FileReferenceNumber;
                            dbEntry.PFRN         = item.Entry.ParentFileReferenceNumber;
                            dbEntry.RecordLength = item.Entry.RecordLength;
                            dbEntry.USN          = item.Entry.USN;
                            dbEntry.Mountpoint   = sourceMount;

                            dbEntry.TimeStamp   = item.Entry.TimeStamp.Truncate(TimeSpan.TicksPerMillisecond);
                            dbEntry.SourceInfo  = item.Entry.SourceInfo.ToString();
                            dbEntry.ChangeRange = item;

                            if (actualPath != null && actualPath != "Unavailable" && actualPath.ToLowerInvariant().StartsWith($"{journal.MountPoint.TrimEnd('\\')}\\$".ToLowerInvariant()))
                            {
                                dbEntry.SystemFile = true;
                            }


                            if (item.RenameFrom != null)
                            {
                                dbEntry.RenameFromPath = GetActualPath(journal, ((Win32Api.UsnEntry)item.RenameFrom));
                                if (!string.IsNullOrWhiteSpace(dbEntry.RenameFromPath) && dbEntry.RenameFromPath != "Unavailable")
                                {
                                    dbEntry.RenameFromRelativePath = new Regex(Regex.Escape(drivePath.FullPath), RegexOptions.IgnoreCase).Replace(dbEntry.RenameFromPath, "", 1);
                                }
                            }

                            entries.Add(dbEntry);
                        }


                        if (changeRange.Any())
                        {
                            Singleton.Instance.Repository.Add <USNChangeRange>(changeRange);
                            Singleton.Instance.Repository.Add <RawUSNEntry>(entries);

                            var performRollup = RollupService.PerformRollup(entries, sourceMount, Singleton.Instance.Repository);
                            logger.Info(string.Format("[{3}] Adding [{2}CHANGE/{1}USN/{0}File]", performRollup.Count, entries.Count, changeRange.Count, sourceMount.Id));
                            foreach (var fileAction in performRollup)
                            {
                                //  logger.Trace("ADD: " + fileAction.RelativePath + ", USN:" + fileAction.USN);
                            }
                            Singleton.Instance.Repository.Add <FileAction>(performRollup);

                            //performRollup.ForEach(f=> logger.Debug("Added " + f.Id));
                        }

                        construct.CurrentJournalData   = newUsnState;
                        sourceMount.CurrentUSNLocation = newUsnState.NextUsn;
                        sourceMount.Volume             = construct.Volume;

                        Singleton.Instance.Repository.Update(sourceMount);
                    }
                    else
                    {
                        logger.Error("Error on Monitor - " + rtn.ToString());
                        throw new UsnJournalException(rtn);
                    }
                }
            }

            catch (Exception e)
            {
                logger.Error(e, "Error in USNJournalMonitor");
            }
        }