< Summary

Class:Microsoft.Azure.Batch.Conventions.Files.TrackedFile
Assembly:Microsoft.Azure.Batch.Conventions.Files
File(s):C:\Git\azure-sdk-for-net\sdk\batch\Microsoft.Azure.Batch.Conventions.Files\src\TrackedFile.cs
Covered lines:1
Uncovered lines:41
Coverable lines:42
Total lines:129
Line coverage:2.3% (1 of 42)
Covered branches:0
Total branches:12
Branch coverage:0% (0 of 12)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.cctor()-100%100%
.ctor(...)-0%100%
OnTimer(...)-0%100%
Flush(...)-0%0%
OnFlushError(...)-0%0%
Dispose()-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\batch\Microsoft.Azure.Batch.Conventions.Files\src\TrackedFile.cs

#LineLine coverage
 1// Copyright (c) Microsoft and contributors.  All rights reserved.
 2//
 3// Licensed under the Apache License, Version 2.0 (the "License");
 4// you may not use this file except in compliance with the License.
 5// You may obtain a copy of the License at
 6// http://www.apache.org/licenses/LICENSE-2.0
 7//
 8// Unless required by applicable law or agreed to in writing, software
 9// distributed under the License is distributed on an "AS IS" BASIS,
 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 11//
 12// See the License for the specific language governing permissions and
 13// limitations under the License.
 14
 15using System;
 16using System.Collections.Generic;
 17using System.Linq;
 18using System.Text;
 19using System.Threading;
 20using System.Threading.Tasks;
 21using Microsoft.WindowsAzure.Storage;
 22using Microsoft.WindowsAzure.Storage.Blob;
 23using System.IO;
 24
 25namespace Microsoft.Azure.Batch.Conventions.Files
 26{
 27    internal sealed class TrackedFile : ITrackedSaveOperation
 28    {
 129        public static readonly TimeSpan DefaultFlushInterval = TimeSpan.FromMinutes(1);
 30
 31        private readonly Timer _timer;
 32        private readonly CloudAppendBlob _blob;
 33        private readonly string _filePath;
 34        private long _flushPointer = 0;
 035        private readonly object _lock = new object();
 36
 037        public TrackedFile(string filePath, CloudAppendBlob blob, TimeSpan interval)
 38        {
 039            _filePath = filePath;
 040            _blob = blob;
 041            _timer = new Timer(OnTimer, null, TimeSpan.FromMilliseconds(1), interval);
 042        }
 43
 44        public void OnTimer(object state)
 45        {
 046            Flush(FlushMode.IfIdle);
 047        }
 48
 49        private void Flush(FlushMode flushMode)
 50        {
 51            // If this is the forced flush on Dispose, wait until we acquire the lock.  Otherwise,
 52            // just check to see if the lock is available, and if not, we are still processing the
 53            // last tranche of appends, so bail out and wait for the next flush interval.
 054            var lockTimeout = (flushMode == FlushMode.IfIdle ? TimeSpan.Zero : Timeout.InfiniteTimeSpan);
 055            bool acquiredLock = false;
 056            Monitor.TryEnter(_lock, lockTimeout, ref acquiredLock);
 57
 058            if (!acquiredLock)
 59            {
 060                return;
 61            }
 62
 63            try
 64            {
 065                var file = new FileInfo(_filePath);
 66
 067                if (!file.Exists)
 68                {
 069                    return;
 70                }
 71
 072                var uploadPointer = file.Length;
 73
 074                if (uploadPointer <= _flushPointer)
 75                {
 076                    return;
 77                }
 78
 079                using (var stm = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
 80                {
 081                    stm.Seek(_flushPointer, SeekOrigin.Begin);
 082                    _blob.AppendFromStreamAsync(stm, uploadPointer - _flushPointer).GetAwaiter().GetResult();
 083                    _flushPointer = uploadPointer;
 084                }
 085            }
 086            catch (Exception ex)
 87            {
 088                if (flushMode == FlushMode.IfIdle)
 89                {
 090                    OnFlushError(ex);
 91                }
 92                else
 93                {
 094                    throw;
 95                }
 096            }
 97            finally
 98            {
 099                Monitor.Exit(_lock);
 0100            }
 0101        }
 102
 103        private enum FlushMode
 104        {
 105            IfIdle,
 106            Force,
 107        }
 108
 109        public event EventHandler<Exception> FlushError;
 110
 111        private void OnFlushError(Exception exception)
 112        {
 0113            var handler = FlushError;
 0114            if (handler != null)
 115            {
 0116                handler(this, exception);
 117            }
 0118        }
 119
 120        public void Dispose()
 121        {
 0122            _timer.Change(Timeout.Infinite, Timeout.Infinite);
 0123            _timer.Dispose();
 124
 0125            Flush(FlushMode.Force);
 0126        }
 127    }
 128}
 129