Exemplo n.º 1
0
        public void ReadToEnd()
        {
            WithVolumeHandle(
                volumeHandle =>
            {
                byte[] buffer = new byte[4096];

                while (true)
                {
                    QueryUsnJournalData journalState = QueryJournal(volumeHandle);

                    ReadUsnJournalResult readJournalResult = FileUtilities.TryReadUsnJournal(
                        volumeHandle,
                        buffer,
                        journalState.UsnJournalId,
                        startUsn: journalState.NextUsn);
                    XAssert.AreEqual(ReadUsnJournalStatus.Success, readJournalResult.Status);

                    XAssert.IsFalse(readJournalResult.NextUsn.IsZero);
                    XAssert.IsTrue(readJournalResult.NextUsn >= journalState.NextUsn);

                    if (readJournalResult.Records.Count == 0)
                    {
                        break;
                    }
                }
            });
        }
Exemplo n.º 2
0
        public void ReadEarliestUsnRecords()
        {
            WithVolumeHandle(
                volumeHandle =>
            {
                QueryUsnJournalData journalState = QueryJournal(volumeHandle);

                byte[] buffer = new byte[4096];
                ReadUsnJournalResult readJournalResult = FileUtilities.TryReadUsnJournal(volumeHandle, buffer, journalState.UsnJournalId, startUsn: new Usn(0));
                XAssert.AreEqual(ReadUsnJournalStatus.Success, readJournalResult.Status);

                XAssert.IsFalse(readJournalResult.NextUsn.IsZero);
                XAssert.IsTrue(readJournalResult.NextUsn >= journalState.FirstUsn);

                XAssert.AreNotEqual(0, readJournalResult.Records.Count, "It is unlikely that this journal should be empty, since this test's execution has written to the volume.");

                var firstRecord = readJournalResult.Records.First();

                XAssert.IsTrue(firstRecord.Usn == journalState.FirstUsn);
                XAssert.IsTrue(firstRecord.Usn < readJournalResult.NextUsn);

                var lastUsn = firstRecord.Usn;

                foreach (UsnRecord record in readJournalResult.Records.Skip(1))
                {
                    XAssert.IsTrue(record.Usn > lastUsn, "Expected USNs to be monotically increasing.");
                    lastUsn = record.Usn;

                    XAssert.IsTrue(record.Usn >= journalState.FirstUsn);
                    XAssert.IsTrue(record.Usn < readJournalResult.NextUsn);
                }
            });
        }
Exemplo n.º 3
0
        private void ExpectChangesSinceUsn(
            UsnChangeReasons expectedChangeReasons,
            SafeFileHandle volumeHandle,
            Usn startUsn,
            FileId fileId,
            out Usn nextUsn,
            TimeSpan?timeLimit = default(TimeSpan?))
        {
            const int DefaultTimeLimitForScanningInSecond = 30; // 30 sec for scanning.

            QueryUsnJournalData journalState = QueryJournal(volumeHandle);

            byte[] buffer = new byte[64 * 1024]; // 655 records per read.
            timeLimit = timeLimit.HasValue ? timeLimit : TimeSpan.FromSeconds(DefaultTimeLimitForScanningInSecond);
            var stopWatch = System.Diagnostics.Stopwatch.StartNew();
            UsnChangeReasons foundChangeReasons = 0;

            nextUsn = startUsn;

            while (true)
            {
                if (stopWatch.ElapsedTicks > timeLimit.Value.Ticks)
                {
                    break;
                }

                ReadUsnJournalResult result = FileUtilities.TryReadUsnJournal(
                    volumeHandle,
                    buffer,
                    journalState.UsnJournalId,
                    startUsn);

                nextUsn = result.NextUsn;

                if (!result.Succeeded)
                {
                    break;
                }

                if (result.Records.Count == 0)
                {
                    break;
                }

                foundChangeReasons |= UsnJournalUtilities.GetAggregateChangeReasons(fileId, result.Records);

                if (expectedChangeReasons == (foundChangeReasons & expectedChangeReasons))
                {
                    // Found all expected change reasons.
                    return;
                }

                startUsn = result.NextUsn;
            }

            XAssert.AreEqual(expectedChangeReasons, foundChangeReasons & expectedChangeReasons);
        }
Exemplo n.º 4
0
        private ReadUsnJournalResult ReadChangesSinceUsn(SafeFileHandle volumeHandle, Usn startUsn)
        {
            QueryUsnJournalData journalState = QueryJournal(volumeHandle);

            // TODO: On a busy volume, we may need to read up to a particular expected USN - or we will fill up the single buffer before finding the expected records.
            byte[] buffer = new byte[32768];
            ReadUsnJournalResult readJournalResult = FileUtilities.TryReadUsnJournal(volumeHandle, buffer, journalState.UsnJournalId, startUsn: startUsn);

            XAssert.AreEqual(ReadUsnJournalStatus.Success, readJournalResult.Status);

            return(readJournalResult);
        }
Exemplo n.º 5
0
        /// <inheritdoc />
        public MaybeResponse <ReadJournalResponse> ReadJournal(ReadJournalRequest request, Action <UsnRecord> onUsnRecordReceived)
        {
            Contract.Assert(request.VolumeGuidPath.IsValid);

            SafeFileHandle volumeHandle;
            OpenFileResult volumeOpenResult = OpenVolumeHandle(request.VolumeGuidPath, out volumeHandle);

            using (volumeHandle)
            {
                if (!volumeOpenResult.Succeeded)
                {
                    string message = I($"Failed to open a volume handle for the volume '{request.VolumeGuidPath.Path}'");
                    return(new MaybeResponse <ReadJournalResponse>(
                               new ErrorResponse(ErrorStatus.FailedToOpenVolumeHandle, message)));
                }

                Usn  startUsn         = request.StartUsn;
                Usn  endUsn           = request.EndUsn ?? Usn.Zero;
                int  extraReadCount   = request.ExtraReadCount ?? -1;
                long timeLimitInTicks = request.TimeLimit?.Ticks ?? -1;
                var  sw = new StopwatchVar();

                using (var swRun = sw.Start())
                {
                    byte[] buffer = new byte[JournalReadBufferSize];
                    while (true)
                    {
                        if (timeLimitInTicks >= 0 && timeLimitInTicks < swRun.ElapsedTicks)
                        {
                            return(new MaybeResponse <ReadJournalResponse>(
                                       new ReadJournalResponse(status: ReadUsnJournalStatus.Success, nextUsn: startUsn, timeout: true)));
                        }

                        ReadUsnJournalResult result = FileUtilities.TryReadUsnJournal(
                            volumeHandle,
                            buffer,
                            request.JournalId,
                            startUsn,
                            isJournalUnprivileged: IsJournalUnprivileged);

                        if (!result.Succeeded)
                        {
                            // Bug #1164760 shows that the next USN can be non-zero.
                            return(new MaybeResponse <ReadJournalResponse>(new ReadJournalResponse(status: result.Status, nextUsn: result.NextUsn)));
                        }

                        if (result.Records.Count == 0)
                        {
                            return
                                (new MaybeResponse <ReadJournalResponse>(
                                     new ReadJournalResponse(status: ReadUsnJournalStatus.Success, nextUsn: result.NextUsn)));
                        }

                        foreach (var record in result.Records)
                        {
                            onUsnRecordReceived(record);
                        }

                        Contract.Assume(startUsn < result.NextUsn);
                        startUsn = result.NextUsn;

                        if (!endUsn.IsZero)
                        {
                            if (startUsn >= endUsn && (--extraReadCount) < 0)
                            {
                                return(new MaybeResponse <ReadJournalResponse>(
                                           new ReadJournalResponse(status: ReadUsnJournalStatus.Success, nextUsn: result.NextUsn)));
                            }
                        }
                    }
                }
            }
        }