root / trunk / Pithos.Core / Agents / SnapshotDifferencer.cs @ dccd340f
History | View | Annotate | Download (8.5 kB)
1 | 255f5f86 | Panagiotis Kanavos | #region |
---|---|---|---|
2 | 255f5f86 | Panagiotis Kanavos | /* ----------------------------------------------------------------------- |
3 | 255f5f86 | Panagiotis Kanavos | * <copyright file="SnapshotDifferencer.cs" company="GRNet"> |
4 | 255f5f86 | Panagiotis Kanavos | * |
5 | 255f5f86 | Panagiotis Kanavos | * Copyright 2011-2012 GRNET S.A. All rights reserved. |
6 | 255f5f86 | Panagiotis Kanavos | * |
7 | 255f5f86 | Panagiotis Kanavos | * Redistribution and use in source and binary forms, with or |
8 | 255f5f86 | Panagiotis Kanavos | * without modification, are permitted provided that the following |
9 | 255f5f86 | Panagiotis Kanavos | * conditions are met: |
10 | 255f5f86 | Panagiotis Kanavos | * |
11 | 255f5f86 | Panagiotis Kanavos | * 1. Redistributions of source code must retain the above |
12 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
13 | 255f5f86 | Panagiotis Kanavos | * disclaimer. |
14 | 255f5f86 | Panagiotis Kanavos | * |
15 | 255f5f86 | Panagiotis Kanavos | * 2. Redistributions in binary form must reproduce the above |
16 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
17 | 255f5f86 | Panagiotis Kanavos | * disclaimer in the documentation and/or other materials |
18 | 255f5f86 | Panagiotis Kanavos | * provided with the distribution. |
19 | 255f5f86 | Panagiotis Kanavos | * |
20 | 255f5f86 | Panagiotis Kanavos | * |
21 | 255f5f86 | Panagiotis Kanavos | * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
22 | 255f5f86 | Panagiotis Kanavos | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
23 | 255f5f86 | Panagiotis Kanavos | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | 255f5f86 | Panagiotis Kanavos | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
25 | 255f5f86 | Panagiotis Kanavos | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | 255f5f86 | Panagiotis Kanavos | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | 255f5f86 | Panagiotis Kanavos | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
28 | 255f5f86 | Panagiotis Kanavos | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
29 | 255f5f86 | Panagiotis Kanavos | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | 255f5f86 | Panagiotis Kanavos | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
31 | 255f5f86 | Panagiotis Kanavos | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | 255f5f86 | Panagiotis Kanavos | * POSSIBILITY OF SUCH DAMAGE. |
33 | 255f5f86 | Panagiotis Kanavos | * |
34 | 255f5f86 | Panagiotis Kanavos | * The views and conclusions contained in the software and |
35 | 255f5f86 | Panagiotis Kanavos | * documentation are those of the authors and should not be |
36 | 255f5f86 | Panagiotis Kanavos | * interpreted as representing official policies, either expressed |
37 | 255f5f86 | Panagiotis Kanavos | * or implied, of GRNET S.A. |
38 | 255f5f86 | Panagiotis Kanavos | * </copyright> |
39 | 255f5f86 | Panagiotis Kanavos | * ----------------------------------------------------------------------- |
40 | 255f5f86 | Panagiotis Kanavos | */ |
41 | 255f5f86 | Panagiotis Kanavos | #endregion |
42 | 7f0e1c1e | Panagiotis Kanavos | using System.Collections.Concurrent; |
43 | b666b39a | Panagiotis Kanavos | using System.Diagnostics.Contracts; |
44 | 039d89ea | Panagiotis Kanavos | using Pithos.Interfaces; |
45 | a0622735 | Panagiotis Kanavos | using Pithos.Network; |
46 | 64171b56 | Panagiotis Kanavos | using System.Collections.Generic; |
47 | 64171b56 | Panagiotis Kanavos | using System.Linq; |
48 | 039d89ea | Panagiotis Kanavos | |
49 | 039d89ea | Panagiotis Kanavos | namespace Pithos.Core.Agents |
50 | 039d89ea | Panagiotis Kanavos | { |
51 | 039d89ea | Panagiotis Kanavos | |
52 | 039d89ea | Panagiotis Kanavos | /// <summary> |
53 | 64171b56 | Panagiotis Kanavos | /// Calculates the differences between two ObjectInfo snapshots. |
54 | 039d89ea | Panagiotis Kanavos | /// </summary> |
55 | 039d89ea | Panagiotis Kanavos | public class SnapshotDifferencer |
56 | 039d89ea | Panagiotis Kanavos | { |
57 | 64171b56 | Panagiotis Kanavos | /// <summary> |
58 | 64171b56 | Panagiotis Kanavos | /// Contains the previous and current listings. |
59 | 64171b56 | Panagiotis Kanavos | /// Using a separate class for the state simplifies the Post method |
60 | 64171b56 | Panagiotis Kanavos | /// which has to modify the listings |
61 | 64171b56 | Panagiotis Kanavos | /// </summary> |
62 | 64171b56 | Panagiotis Kanavos | private class State |
63 | 64171b56 | Panagiotis Kanavos | { |
64 | 64171b56 | Panagiotis Kanavos | /// <summary> |
65 | 64171b56 | Panagiotis Kanavos | /// The previous snapshot listing |
66 | 64171b56 | Panagiotis Kanavos | /// </summary> |
67 | 2ea0ca4f | Panagiotis Kanavos | public readonly ObjectInfo[] Previous; |
68 | 64171b56 | Panagiotis Kanavos | |
69 | 64171b56 | Panagiotis Kanavos | /// <summary> |
70 | 64171b56 | Panagiotis Kanavos | /// The current snapshot listing |
71 | 64171b56 | Panagiotis Kanavos | /// </summary> |
72 | 2ea0ca4f | Panagiotis Kanavos | public readonly ObjectInfo[] Current; |
73 | 64171b56 | Panagiotis Kanavos | |
74 | b666b39a | Panagiotis Kanavos | public readonly Dictionary<string, ObjectInfo> CurrentDict; |
75 | b666b39a | Panagiotis Kanavos | |
76 | b666b39a | Panagiotis Kanavos | public readonly Dictionary<string, ObjectInfo> PreviousDict; |
77 | b666b39a | Panagiotis Kanavos | |
78 | b666b39a | Panagiotis Kanavos | |
79 | 64171b56 | Panagiotis Kanavos | /// <summary> |
80 | 64171b56 | Panagiotis Kanavos | /// Common objects, lazily evalueated. |
81 | 64171b56 | Panagiotis Kanavos | /// The common objects are used to calculate both the Changed and Unchanged objects |
82 | 64171b56 | Panagiotis Kanavos | /// </summary> |
83 | 89472316 | Panagiotis Kanavos | public readonly IEnumerable<ObjectInfo> Common; |
84 | 64171b56 | Panagiotis Kanavos | |
85 | 6ef37eeb | Panagiotis Kanavos | private readonly static ObjectInfo[] Empty = new ObjectInfo[0]; |
86 | 6ef37eeb | Panagiotis Kanavos | |
87 | b666b39a | Panagiotis Kanavos | [ContractInvariantMethod] |
88 | b666b39a | Panagiotis Kanavos | private void StatInvariant() |
89 | b666b39a | Panagiotis Kanavos | { |
90 | b666b39a | Panagiotis Kanavos | // ReSharper disable InvocationIsSkipped |
91 | b666b39a | Panagiotis Kanavos | Contract.Invariant(Current!=null); |
92 | b666b39a | Panagiotis Kanavos | Contract.Invariant(Previous!=null); |
93 | b666b39a | Panagiotis Kanavos | Contract.Invariant(CurrentDict!=null); |
94 | b666b39a | Panagiotis Kanavos | Contract.Invariant(PreviousDict!=null); |
95 | b666b39a | Panagiotis Kanavos | Contract.Invariant(Common!=null); |
96 | b666b39a | Panagiotis Kanavos | // ReSharper restore InvocationIsSkipped |
97 | b666b39a | Panagiotis Kanavos | } |
98 | b666b39a | Panagiotis Kanavos | |
99 | 2ea0ca4f | Panagiotis Kanavos | public State(ObjectInfo[] previous, ObjectInfo[] current) |
100 | 64171b56 | Panagiotis Kanavos | { |
101 | 6ef37eeb | Panagiotis Kanavos | Previous = previous ?? Empty; |
102 | 6ef37eeb | Panagiotis Kanavos | Current = current ?? Empty; |
103 | b666b39a | Panagiotis Kanavos | CurrentDict = Current.ToDictionary(info => info.UUID); |
104 | b666b39a | Panagiotis Kanavos | PreviousDict = Previous.ToDictionary(info => info.UUID); |
105 | 64171b56 | Panagiotis Kanavos | |
106 | 89472316 | Panagiotis Kanavos | //Attach the previous version to the current listings |
107 | 89472316 | Panagiotis Kanavos | foreach (var info in Current) |
108 | 89472316 | Panagiotis Kanavos | { |
109 | 89472316 | Panagiotis Kanavos | ObjectInfo prev; |
110 | 89472316 | Panagiotis Kanavos | if (PreviousDict.TryGetValue(info.UUID, out prev)) |
111 | 89472316 | Panagiotis Kanavos | info.SetPrevious(prev); |
112 | 89472316 | Panagiotis Kanavos | } |
113 | 89472316 | Panagiotis Kanavos | |
114 | 89472316 | Panagiotis Kanavos | Common=Current.Where(c=>c.Previous !=null); |
115 | 64171b56 | Panagiotis Kanavos | } |
116 | 64171b56 | Panagiotis Kanavos | } |
117 | 64171b56 | Panagiotis Kanavos | |
118 | 039d89ea | Panagiotis Kanavos | |
119 | 64171b56 | Panagiotis Kanavos | private State _state; |
120 | 64171b56 | Panagiotis Kanavos | |
121 | 64171b56 | Panagiotis Kanavos | /// <summary> |
122 | 64171b56 | Panagiotis Kanavos | /// Default constructor. Initializes the Current and Previous listings to empty lists |
123 | 64171b56 | Panagiotis Kanavos | /// </summary> |
124 | 039d89ea | Panagiotis Kanavos | public SnapshotDifferencer() |
125 | 6ef37eeb | Panagiotis Kanavos | { |
126 | 6ef37eeb | Panagiotis Kanavos | _state = new State(null, null); |
127 | 039d89ea | Panagiotis Kanavos | } |
128 | 64171b56 | Panagiotis Kanavos | |
129 | 64171b56 | Panagiotis Kanavos | /// <summary> |
130 | 64171b56 | Panagiotis Kanavos | /// Posts a new listing |
131 | 64171b56 | Panagiotis Kanavos | /// </summary> |
132 | 64171b56 | Panagiotis Kanavos | /// <param name="list"></param> |
133 | 64171b56 | Panagiotis Kanavos | /// <returns></returns> |
134 | 039d89ea | Panagiotis Kanavos | public SnapshotDifferencer Post(IEnumerable<ObjectInfo> list) |
135 | 039d89ea | Panagiotis Kanavos | { |
136 | 2ea0ca4f | Panagiotis Kanavos | ObjectInfo[] newCurrent=null; |
137 | 64171b56 | Panagiotis Kanavos | if (list != null) |
138 | 99e6329f | Panagiotis Kanavos | { |
139 | 64171b56 | Panagiotis Kanavos | //The state field holds the old state |
140 | 64171b56 | Panagiotis Kanavos | var oldState = _state; |
141 | 64171b56 | Panagiotis Kanavos | //Replace any NoModification entries with previous values that have |
142 | 64171b56 | Panagiotis Kanavos | //the same account, container and possibly, folder |
143 | 64171b56 | Panagiotis Kanavos | newCurrent = list.Replace( |
144 | 64171b56 | Panagiotis Kanavos | info => info is NoModificationInfo, |
145 | 64171b56 | Panagiotis Kanavos | noMod => oldState.Current.Where(noMod.CorrespondsTo)) |
146 | 2ea0ca4f | Panagiotis Kanavos | .ToArray(); |
147 | 99e6329f | Panagiotis Kanavos | } |
148 | 64171b56 | Panagiotis Kanavos | //Set the new state |
149 | 64171b56 | Panagiotis Kanavos | _state = new State(_state.Current, newCurrent); |
150 | 99e6329f | Panagiotis Kanavos | |
151 | 422c9598 | Panagiotis Kanavos | return this; |
152 | 039d89ea | Panagiotis Kanavos | } |
153 | 039d89ea | Panagiotis Kanavos | |
154 | b666b39a | Panagiotis Kanavos | /// <summary> |
155 | b666b39a | Panagiotis Kanavos | /// Deleted objects are those that existed in the Previous listing |
156 | 89472316 | Panagiotis Kanavos | /// but are not found in the Current listing |
157 | b666b39a | Panagiotis Kanavos | /// </summary> |
158 | 039d89ea | Panagiotis Kanavos | public IEnumerable<ObjectInfo> Deleted |
159 | 039d89ea | Panagiotis Kanavos | { |
160 | 89472316 | Panagiotis Kanavos | get { return _state.Previous |
161 | b666b39a | Panagiotis Kanavos | .Where(info=>!_state.CurrentDict.ContainsKey(info.UUID)); } |
162 | 039d89ea | Panagiotis Kanavos | } |
163 | b666b39a | Panagiotis Kanavos | |
164 | b666b39a | Panagiotis Kanavos | /// <summary> |
165 | b666b39a | Panagiotis Kanavos | /// Created objects are those that exist in the Current listing |
166 | 89472316 | Panagiotis Kanavos | /// but are not found in the Previous listing |
167 | b666b39a | Panagiotis Kanavos | /// </summary> |
168 | 039d89ea | Panagiotis Kanavos | public IEnumerable<ObjectInfo> Created |
169 | 039d89ea | Panagiotis Kanavos | { |
170 | 89472316 | Panagiotis Kanavos | get { return _state.Current |
171 | b666b39a | Panagiotis Kanavos | .Where(info=>!_state.PreviousDict.ContainsKey(info.UUID)); } |
172 | 64171b56 | Panagiotis Kanavos | } |
173 | 64171b56 | Panagiotis Kanavos | |
174 | 64171b56 | Panagiotis Kanavos | public IEnumerable<ObjectInfo> Common |
175 | 64171b56 | Panagiotis Kanavos | { |
176 | 89472316 | Panagiotis Kanavos | get { return _state.Common; } |
177 | 039d89ea | Panagiotis Kanavos | } |
178 | 64171b56 | Panagiotis Kanavos | |
179 | 039d89ea | Panagiotis Kanavos | public IEnumerable<ObjectInfo> Changed |
180 | 039d89ea | Panagiotis Kanavos | { |
181 | 5e10d44f | Panagiotis Kanavos | get |
182 | 5e10d44f | Panagiotis Kanavos | { |
183 | 89472316 | Panagiotis Kanavos | return Common.Where(info => |
184 | 89472316 | Panagiotis Kanavos | //The hash is different |
185 | 89472316 | Panagiotis Kanavos | info.PreviousHash != info.Hash |
186 | 89472316 | Panagiotis Kanavos | //And the Uri is unchanged or there is no previous version |
187 | 89472316 | Panagiotis Kanavos | && (info.Previous == null || info.Uri == info.Previous.Uri)); |
188 | 89472316 | Panagiotis Kanavos | } |
189 | 039d89ea | Panagiotis Kanavos | } |
190 | 89472316 | Panagiotis Kanavos | |
191 | 89472316 | Panagiotis Kanavos | /// <summary> |
192 | 89472316 | Panagiotis Kanavos | /// Unchanged objects have the same current and previous hash |
193 | 89472316 | Panagiotis Kanavos | /// </summary> |
194 | 039d89ea | Panagiotis Kanavos | public IEnumerable<ObjectInfo> Unchanged |
195 | 039d89ea | Panagiotis Kanavos | { |
196 | 64171b56 | Panagiotis Kanavos | get{ return Common.Where(i => i.PreviousHash == i.Hash);} |
197 | 039d89ea | Panagiotis Kanavos | } |
198 | b666b39a | Panagiotis Kanavos | |
199 | 89472316 | Panagiotis Kanavos | /// <summary> |
200 | 89472316 | Panagiotis Kanavos | /// Moved objects have a previous version with a different name |
201 | 89472316 | Panagiotis Kanavos | /// </summary> |
202 | b666b39a | Panagiotis Kanavos | public IEnumerable<ObjectInfo> Moved |
203 | b666b39a | Panagiotis Kanavos | { |
204 | b666b39a | Panagiotis Kanavos | get |
205 | 89472316 | Panagiotis Kanavos | { |
206 | 89472316 | Panagiotis Kanavos | return Common.Where(info=> |
207 | 89472316 | Panagiotis Kanavos | //A previous version exists |
208 | 89472316 | Panagiotis Kanavos | info.Previous!= null |
209 | 89472316 | Panagiotis Kanavos | //and the Uri is different |
210 | 89472316 | Panagiotis Kanavos | && info.Uri!=info.Previous.Uri); |
211 | b666b39a | Panagiotis Kanavos | } |
212 | b666b39a | Panagiotis Kanavos | } |
213 | 039d89ea | Panagiotis Kanavos | } |
214 | a0622735 | Panagiotis Kanavos | |
215 | a0622735 | Panagiotis Kanavos | public class AccountsDifferencer |
216 | a0622735 | Panagiotis Kanavos | { |
217 | 64171b56 | Panagiotis Kanavos | readonly ConcurrentDictionary<string, SnapshotDifferencer> _differencers = new ConcurrentDictionary<string, SnapshotDifferencer>(); |
218 | a0622735 | Panagiotis Kanavos | |
219 | 7f0e1c1e | Panagiotis Kanavos | public ConcurrentDictionary<string, SnapshotDifferencer> Differencers { get { return _differencers; } } |
220 | a0622735 | Panagiotis Kanavos | |
221 | a0622735 | Panagiotis Kanavos | public SnapshotDifferencer PostSnapshot(AccountInfo accountInfo, List<ObjectInfo> cleanRemotes) |
222 | a0622735 | Panagiotis Kanavos | { |
223 | a0622735 | Panagiotis Kanavos | SnapshotDifferencer differencer; |
224 | a0622735 | Panagiotis Kanavos | if (!_differencers.TryGetValue(accountInfo.UserName, out differencer)) |
225 | a0622735 | Panagiotis Kanavos | { |
226 | a0622735 | Panagiotis Kanavos | differencer = new SnapshotDifferencer(); |
227 | a0622735 | Panagiotis Kanavos | _differencers[accountInfo.UserName] = differencer; |
228 | a0622735 | Panagiotis Kanavos | } |
229 | a0622735 | Panagiotis Kanavos | differencer.Post(cleanRemotes); |
230 | a0622735 | Panagiotis Kanavos | return differencer; |
231 | a0622735 | Panagiotis Kanavos | } |
232 | a0622735 | Panagiotis Kanavos | |
233 | a0622735 | Panagiotis Kanavos | } |
234 | 039d89ea | Panagiotis Kanavos | } |