A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3
4using Codice;
5using Codice.Client.Commands;
6using Codice.Client.Commands.WkTree;
7using Codice.Client.Common;
8using Codice.Client.Common.Locks;
9using Codice.Client.Common.Threading;
10using Codice.Client.Common.WkTree;
11using Codice.CM.Common;
12using Codice.CM.Common.Mount;
13using Codice.Utils;
14using PlasticGui.WorkspaceWindow;
15using PlasticGui.WorkspaceWindow.Items.Locks;
16
17namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache
18{
19 internal class LockStatusCache
20 {
21 internal LockStatusCache(
22 WorkspaceInfo wkInfo,
23 Action repaintProjectWindow,
24 Action repaintInspector)
25 {
26 mWkInfo = wkInfo;
27 mRepaintProjectWindow = repaintProjectWindow;
28 mRepaintInspector = repaintInspector;
29 }
30
31 internal AssetStatus GetStatus(string fullPath)
32 {
33 LockStatusData lockStatusData = GetLockStatusData(fullPath);
34
35 if (lockStatusData == null)
36 return AssetStatus.None;
37
38 return lockStatusData.Status;
39 }
40
41 internal LockStatusData GetLockStatusData(string fullPath)
42 {
43 lock (mLock)
44 {
45 if (mStatusByPathCache == null)
46 {
47 mStatusByPathCache = BuildPathDictionary.ForPlatform<LockStatusData>();
48
49 mCurrentCancelToken.Cancel();
50 mCurrentCancelToken = new CancelToken();
51 AsyncCalculateStatus(mCurrentCancelToken);
52
53 return null;
54 }
55
56 LockStatusData result;
57
58 if (mStatusByPathCache.TryGetValue(fullPath, out result))
59 return result;
60
61 return null;
62 }
63 }
64
65 internal void Clear()
66 {
67 lock (mLock)
68 {
69 mCurrentCancelToken.Cancel();
70
71 mStatusByPathCache = null;
72 }
73 }
74
75 internal void Cancel()
76 {
77 lock (mLock)
78 {
79 mCurrentCancelToken.Cancel();
80 }
81 }
82
83 void AsyncCalculateStatus(CancelToken cancelToken)
84 {
85 Dictionary<string, LockStatusData> statusByPathCache = null;
86
87 IThreadWaiter waiter = ThreadWaiter.GetWaiter(50);
88 waiter.Execute(
89 /*threadOperationDelegate*/ delegate
90 {
91 Dictionary<MountPointWithPath, List<WorkspaceTreeNode>> lockCandidates =
92 new Dictionary<MountPointWithPath, List<WorkspaceTreeNode>>();
93
94 FillLockCandidates.ForTree(mWkInfo, lockCandidates);
95
96 if (cancelToken.IsCancelled())
97 return;
98
99 Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode =
100 SearchLocks.GetLocksInfo(mWkInfo, lockCandidates);
101
102 if (cancelToken.IsCancelled())
103 return;
104
105 statusByPathCache = BuildStatusByNodeCache.
106 ForLocks(mWkInfo.ClientPath, lockInfoByNode);
107 },
108 /*afterOperationDelegate*/ delegate
109 {
110 if (cancelToken.IsCancelled())
111 return;
112
113 if (waiter.Exception != null)
114 {
115 ExceptionsHandler.LogException(
116 "LockStatusCache",
117 waiter.Exception);
118 return;
119 }
120
121 lock (mLock)
122 {
123 mStatusByPathCache = statusByPathCache;
124 }
125
126 mRepaintProjectWindow();
127 mRepaintInspector();
128 });
129 }
130
131 static class BuildStatusByNodeCache
132 {
133 internal static Dictionary<string, LockStatusData> ForLocks(
134 string wkPath,
135 Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode)
136 {
137 Dictionary<string, LockStatusData> result =
138 BuildPathDictionary.ForPlatform<LockStatusData>();
139
140 LockOwnerNameResolver nameResolver = new LockOwnerNameResolver();
141
142 foreach (WorkspaceTreeNode node in lockInfoByNode.Keys)
143 {
144 LockStatusData lockStatusData = BuildLockStatusData(
145 node, lockInfoByNode[node], nameResolver);
146
147 string nodeWkPath = WorkspacePath.GetWorkspacePathFromCmPath(
148 wkPath,
149 WorkspaceNodeOperations.GetCmPath(node),
150 PathHelper.GetDirectorySeparatorChar(wkPath));
151
152 result.Add(nodeWkPath, lockStatusData);
153 }
154
155 return result;
156 }
157
158 static LockStatusData BuildLockStatusData(
159 WorkspaceTreeNode node,
160 LockInfo lockInfo,
161 LockOwnerNameResolver nameResolver)
162 {
163 return new LockStatusData(
164 GetAssetStatus(node, lockInfo),
165 nameResolver.GetSeidName(lockInfo.SEIDData),
166 BranchInfoCache.GetProtectedBranchName(
167 node.RepSpec, lockInfo.HolderBranchId));
168 }
169
170 static AssetStatus GetAssetStatus(
171 WorkspaceTreeNode node,
172 LockInfo lockInfo)
173 {
174 if (lockInfo.Status == LockInfo.LockStatus.Retained)
175 return AssetStatus.Retained;
176
177 return CheckWorkspaceTreeNodeStatus.IsCheckedOut(node) ?
178 AssetStatus.Locked : AssetStatus.LockedRemote;
179 }
180 }
181
182 CancelToken mCurrentCancelToken = new CancelToken();
183
184 Dictionary<string, LockStatusData> mStatusByPathCache;
185
186 readonly Action mRepaintInspector;
187 readonly Action mRepaintProjectWindow;
188 readonly WorkspaceInfo mWkInfo;
189
190 static object mLock = new object();
191 }
192}