Statistics
| Branch: | Revision:

root / trunk / Pithos.Core / NetworkGate.cs @ b9f5b594

History | View | Annotate | Download (6.4 kB)

1
// -----------------------------------------------------------------------
2
// <copyright file="NetworkGate.cs" company="GRNET">
3
// Copyright 2011 GRNET S.A. All rights reserved.
4
// 
5
// Redistribution and use in source and binary forms, with or
6
// without modification, are permitted provided that the following
7
// conditions are met:
8
// 
9
//   1. Redistributions of source code must retain the above
10
//      copyright notice, this list of conditions and the following
11
//      disclaimer.
12
// 
13
//   2. Redistributions in binary form must reproduce the above
14
//      copyright notice, this list of conditions and the following
15
//      disclaimer in the documentation and/or other materials
16
//      provided with the distribution.
17
// 
18
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
// POSSIBILITY OF SUCH DAMAGE.
30
// 
31
// The views and conclusions contained in the software and
32
// documentation are those of the authors and should not be
33
// interpreted as representing official policies, either expressed
34
// or implied, of GRNET S.A.
35
// </copyright>
36
// -----------------------------------------------------------------------
37

    
38
using System;
39
using System.Collections.Concurrent;
40
using System.Collections.Generic;
41
using System.Diagnostics.Contracts;
42
using System.IO;
43

    
44
namespace Pithos.Core
45
{
46
    public enum NetworkOperation
47
    {
48
        None,
49
        Uploading,
50
        Downloading,
51
        Deleting,
52
        Renaming
53
    }
54

    
55
    //The NetworkGate prevents starting download/uploads for files that are already in the process of downloading,
56
    //uploading.   
57
    public class NetworkGate:IDisposable
58
    {
59
        public string FilePath { get; private set; }
60
        public NetworkOperation Operation { get; private set; }
61

    
62
        [ContractInvariantMethod]
63
        private void Invariants()
64
        {
65
            Contract.Invariant(!String.IsNullOrWhiteSpace(FilePath));
66
            Contract.Invariant(Path.IsPathRooted(FilePath));
67
        }
68

    
69
        //The state of each file is stored in a thread-safe dictionary
70
        static readonly ConcurrentDictionary<string, NetworkOperation> NetworkState = new ConcurrentDictionary<string, NetworkOperation>();
71

    
72
        public static NetworkOperation GetNetworkState(string path)
73
        {
74
            if (String.IsNullOrWhiteSpace(path))
75
                throw new ArgumentNullException("path");
76
            if (!Path.IsPathRooted(path))
77
                throw new ArgumentException("path must be a rooted path", "path");
78
            Contract.EndContractBlock();
79

    
80
            NetworkOperation operation;
81
            var lower = path.ToLower();
82
            if (NetworkState.TryGetValue(lower, out operation))
83
                return operation;
84
            return NetworkOperation.None;
85
        }
86

    
87
        //Store a network operation for the specified path
88
        public static void SetNetworkState(string path, NetworkOperation operation)
89
        {
90
            if (String.IsNullOrWhiteSpace(path))
91
                throw new ArgumentNullException("path");
92
            if (!Path.IsPathRooted(path))
93
                throw new ArgumentException("path must be a rooted path", "path");
94
            Contract.EndContractBlock();
95

    
96
            var lower = path.ToLower();
97
            NetworkState[lower] = operation;            
98
            //By default, None values don't need to be stored. They are stored anyway
99
            //because TryRemove may fail.
100
            if (operation == NetworkOperation.None)
101
            {
102
                NetworkOperation oldOperation;
103
                NetworkState.TryRemove(lower, out oldOperation);
104
            }
105
        }
106

    
107
        //Clients should acquire a NetworkGate before starting any network operation.
108
        //If Acquire fails, another network operation is already in progress
109
        public static NetworkGate Acquire(string path, NetworkOperation operation)
110
        {
111
            if (String.IsNullOrWhiteSpace(path))
112
                throw new ArgumentNullException("path");
113
            if (!Path.IsPathRooted(path))
114
                throw new ArgumentException("path must be a rooted path", "path");
115
            Contract.EndContractBlock();
116

    
117
            var lower = path.ToLower();
118
            var state = GetNetworkState(lower);
119
            //If no operation is in progress, return a NetworkGate
120
            return (state == NetworkOperation.None)
121
                       ? new NetworkGate(lower, operation)
122
                   //otherwise return a gate with Fail flagged
123
                       : new NetworkGate(lower, NetworkOperation.None);
124
        }
125

    
126

    
127

    
128

    
129

    
130

    
131
        private NetworkGate(string path,NetworkOperation operation)
132
        {
133
            if (String.IsNullOrWhiteSpace(path))
134
                throw new ArgumentNullException("path");
135
            if (!Path.IsPathRooted(path))
136
                throw new ArgumentException("path must be rooted","path");
137
            Contract.EndContractBlock();
138

    
139
            Operation = operation;
140
            FilePath = path.ToLower();            
141

    
142
            //Skip dummy operations (those with Operation == None)
143
            if (Operation != NetworkOperation.None)
144
                //and store the file's operation
145
                SetNetworkState(FilePath, operation);
146
        }
147

    
148
        //A NetworkGate has Failed if its operation is None
149
        public bool Failed { get { return Operation == NetworkOperation.None; } }
150

    
151
        //Release a gate by setting the NetworkOperation to None
152
        public void Release()
153
        {
154
            //Skip Failed flags
155
            if (!Failed)
156
                //And reset the operation state for the file
157
                SetNetworkState(FilePath,NetworkOperation.None);
158
        }
159

    
160

    
161
        public void Dispose()
162
        {
163
            Dispose(true);
164
            GC.SuppressFinalize(this);
165
        }
166

    
167
        protected void Dispose(bool disposing)
168
        {
169
            if (disposing)
170
            {
171
                Release();
172
            }
173
        }
174

    
175
    }
176
}