2 /* -----------------------------------------------------------------------
3 * <copyright file="NetworkGate.cs" company="GRNet">
5 * Copyright 2011-2012 GRNET S.A. All rights reserved.
7 * Redistribution and use in source and binary forms, with or
8 * without modification, are permitted provided that the following
11 * 1. Redistributions of source code must retain the above
12 * copyright notice, this list of conditions and the following
15 * 2. Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials
18 * provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * The views and conclusions contained in the software and
35 * documentation are those of the authors and should not be
36 * interpreted as representing official policies, either expressed
37 * or implied, of GRNET S.A.
39 * -----------------------------------------------------------------------
43 using System.Collections.Concurrent;
44 using System.Collections.Generic;
45 using System.Diagnostics.Contracts;
50 public enum NetworkOperation
59 //The NetworkGate prevents starting download/uploads for files that are already in the process of downloading,
61 public class NetworkGate:IDisposable
63 public string FilePath { get; private set; }
64 public NetworkOperation Operation { get; private set; }
66 [ContractInvariantMethod]
67 private void Invariants()
69 Contract.Invariant(!String.IsNullOrWhiteSpace(FilePath));
70 Contract.Invariant(Path.IsPathRooted(FilePath));
73 //The state of each file is stored in a thread-safe dictionary
74 static readonly ConcurrentDictionary<string, NetworkOperation> NetworkState = new ConcurrentDictionary<string, NetworkOperation>();
76 public static NetworkOperation GetNetworkState(string path)
78 if (String.IsNullOrWhiteSpace(path))
79 throw new ArgumentNullException("path");
80 if (!Path.IsPathRooted(path))
81 throw new ArgumentException("path must be a rooted path", "path");
82 Contract.EndContractBlock();
84 NetworkOperation operation;
85 var lower = path.ToLower();
86 if (NetworkState.TryGetValue(lower, out operation))
88 return NetworkOperation.None;
91 //Store a network operation for the specified path
92 public static void SetNetworkState(string path, NetworkOperation operation)
94 if (String.IsNullOrWhiteSpace(path))
95 throw new ArgumentNullException("path");
96 if (!Path.IsPathRooted(path))
97 throw new ArgumentException("path must be a rooted path", "path");
98 Contract.EndContractBlock();
100 var lower = path.ToLower();
101 NetworkState[lower] = operation;
102 //By default, None values don't need to be stored. They are stored anyway
103 //because TryRemove may fail.
104 if (operation == NetworkOperation.None)
106 NetworkOperation oldOperation;
107 NetworkState.TryRemove(lower, out oldOperation);
111 //Clients should acquire a NetworkGate before starting any network operation.
112 //If Acquire fails, another network operation is already in progress
113 public static NetworkGate Acquire(string path, NetworkOperation operation)
115 if (String.IsNullOrWhiteSpace(path))
116 throw new ArgumentNullException("path");
117 if (!Path.IsPathRooted(path))
118 throw new ArgumentException("path must be a rooted path", "path");
119 Contract.EndContractBlock();
121 var lower = path.ToLower();
122 var state = GetNetworkState(lower);
123 //If no operation is in progress, return a NetworkGate
124 return (state == NetworkOperation.None)
125 ? new NetworkGate(lower, operation)
126 //otherwise return a gate with Fail flagged
127 : new NetworkGate(lower, NetworkOperation.None);
135 private NetworkGate(string path,NetworkOperation operation)
137 if (String.IsNullOrWhiteSpace(path))
138 throw new ArgumentNullException("path");
139 if (!Path.IsPathRooted(path))
140 throw new ArgumentException("path must be rooted","path");
141 Contract.EndContractBlock();
143 Operation = operation;
144 FilePath = path.ToLower();
146 //Skip dummy operations (those with Operation == None)
147 if (Operation != NetworkOperation.None)
148 //and store the file's operation
149 SetNetworkState(FilePath, operation);
152 //A NetworkGate has Failed if its operation is None
153 public bool Failed { get { return Operation == NetworkOperation.None; } }
155 //Release a gate by setting the NetworkOperation to None
156 public void Release()
160 //And reset the operation state for the file
161 SetNetworkState(FilePath,NetworkOperation.None);
165 public void Dispose()
168 GC.SuppressFinalize(this);
171 protected void Dispose(bool disposing)