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

            try
            {
                using (Repository repo = new Repository())
                {

                    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");
                            }

                            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()
                                };

                                changeRange.Add(range);
                            }

                            //logger.Trace("ChangeRange : " + changeRange.Count);

                            foreach (var item in changeRange)
                            {

                                var actualPath = GetActualPath(journal, item.Entry as Win32Api.UsnEntry );

                                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;
                                }

                               var itemMin = item.Min.Truncate(TimeSpan.TicksPerMillisecond);
                                var itemMax = item.Max.Truncate(TimeSpan.TicksPerMillisecond);

                                var count = repo.Count<USNJournalSyncLog>(f =>

                                   f.Action.RelativePath == relativePath && f.DestinationMachine == Singleton.Instance.CurrentServer &&
                                    (
                                        (
                                            (f.ActionStartDate.HasValue && f.ActionStartDate <= itemMin)
                                            &&
                                            (f.ActionFinishDate.HasValue && f.ActionFinishDate >= itemMax)
                                        )

                                        ||

                                        (
                                            (
                                                ( ( f.ActionStartDate.HasValue && f.ActionStartDate >= itemMin) && f.ActionFinishDate.HasValue && f.ActionFinishDate <= itemMin )
                                                    &&
                                                (f.ActionFinishDate.HasValue && f.ActionFinishDate >= itemMax)
                                            )
                                            ||
                                            (
                                                (f.ActionStartDate.HasValue && f.ActionStartDate <= itemMin)
                                                &&
                                                ((f.ActionFinishDate.HasValue && f.ActionFinishDate <= itemMax) && f.ActionStartDate.HasValue && f.ActionStartDate >= itemMin )
                                            )
                                            ||
                                            (
                                                (f.ActionStartDate.HasValue && f.ActionStartDate >= itemMin)
                                                &&
                                                (f.ActionFinishDate.HasValue && f.ActionFinishDate <= itemMax)
                                            )
                                        )
                                    )
                                );

                                if (count > 0)
                                {
                                    //logger.Info("Count is " + count);
                                    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())
                            {
                                repo.Add<USNChangeRange>(changeRange);
                                repo.Add<RawUSNEntry>(entries);

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

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

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

                            repo.Update(sourceMount);

                        }
                        else
                        {
                            logger.Error("Error on Monitor - " + rtn.ToString());
                            throw new UsnJournalException(rtn);
                        }
                    }
                }
            }

            catch (Exception e)
            {
                logger.Error(e, "Error in USNJournalMonitor");
            }
        }
Ejemplo n.º 2
0
 private void PopulateFlags(RawUSNEntry dbEntry, Win32Api.UsnEntry entry)
 {
     uint value = entry.Reason & Win32Api.USN_REASON_DATA_OVERWRITE;
     if (0 != value)
     {
         dbEntry.DataOverwrite = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_DATA_EXTEND;
     if (0 != value)
     {
         dbEntry.DataExtend = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_DATA_TRUNCATION;
     if (0 != value)
     {
         dbEntry.DataTruncation = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_NAMED_DATA_OVERWRITE;
     if (0 != value)
     {
         dbEntry.NamedDataOverwrite = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_NAMED_DATA_EXTEND;
     if (0 != value)
     {
         dbEntry.NamedDataExtend = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_NAMED_DATA_TRUNCATION;
     if (0 != value)
     {
         dbEntry.NamedDataTruncation = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_FILE_CREATE;
     if (0 != value)
     {
         dbEntry.FileCreate = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_FILE_DELETE;
     if (0 != value)
     {
         dbEntry.FileDelete = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_EA_CHANGE;
     if (0 != value)
     {
         dbEntry.EaChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_SECURITY_CHANGE;
     if (0 != value)
     {
         dbEntry.SecurityChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_RENAME_OLD_NAME;
     if (0 != value)
     {
         dbEntry.RenameOldName = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_RENAME_NEW_NAME;
     if (0 != value)
     {
         dbEntry.RenameNewName = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_INDEXABLE_CHANGE;
     if (0 != value)
     {
         dbEntry.IndexableChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_BASIC_INFO_CHANGE;
     if (0 != value)
     {
         dbEntry.BasicInfoChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_HARD_LINK_CHANGE;
     if (0 != value)
     {
         dbEntry.HardLinkChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_COMPRESSION_CHANGE;
     if (0 != value)
     {
         dbEntry.CompressionChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_ENCRYPTION_CHANGE;
     if (0 != value)
     {
         dbEntry.EncryptionChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_OBJECT_ID_CHANGE;
     if (0 != value)
     {
         dbEntry.ObjectIdChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_REPARSE_POINT_CHANGE;
     if (0 != value)
     {
         dbEntry.ReparsePointChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_STREAM_CHANGE;
     if (0 != value)
     {
         dbEntry.StreamChange = true;
     }
     value = entry.Reason & Win32Api.USN_REASON_CLOSE;
     if (0 != value)
     {
         dbEntry.Close = true;
     }
 }