185 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			185 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System.Collections.Generic; | ||
|  | 
 | ||
|  | using Codice; | ||
|  | using Codice.Client.Commands.WkTree; | ||
|  | using Codice.Client.Common; | ||
|  | using Codice.Client.Common.Locks; | ||
|  | using Codice.Client.Common.Threading; | ||
|  | using Codice.Client.Common.WkTree; | ||
|  | using Codice.CM.Common; | ||
|  | using Codice.CM.Common.Mount; | ||
|  | using Codice.Utils; | ||
|  | using PlasticGui.WorkspaceWindow; | ||
|  | using PlasticGui.WorkspaceWindow.Items.Locks; | ||
|  | using Unity.PlasticSCM.Editor.AssetUtils; | ||
|  | 
 | ||
|  | namespace Unity.PlasticSCM.Editor.AssetsOverlays.Cache | ||
|  | { | ||
|  |     internal class LockStatusCache | ||
|  |     { | ||
|  |         internal LockStatusCache( | ||
|  |             WorkspaceInfo wkInfo) | ||
|  |         { | ||
|  |             mWkInfo = wkInfo; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal AssetStatus GetStatus(string fullPath) | ||
|  |         { | ||
|  |             LockStatusData lockStatusData = GetLockStatusData(fullPath); | ||
|  | 
 | ||
|  |             if (lockStatusData == null) | ||
|  |                 return AssetStatus.None; | ||
|  | 
 | ||
|  |             return lockStatusData.Status; | ||
|  |         } | ||
|  | 
 | ||
|  |         internal LockStatusData GetLockStatusData(string fullPath) | ||
|  |         { | ||
|  |             lock (mLock) | ||
|  |             { | ||
|  |                 if (mStatusByPathCache == null) | ||
|  |                 { | ||
|  |                     mStatusByPathCache = BuildPathDictionary.ForPlatform<LockStatusData>(); | ||
|  | 
 | ||
|  |                     mCurrentCancelToken.Cancel(); | ||
|  |                     mCurrentCancelToken = new CancelToken(); | ||
|  |                     AsyncCalculateStatus(mCurrentCancelToken); | ||
|  | 
 | ||
|  |                     return null; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 LockStatusData result; | ||
|  | 
 | ||
|  |                 if (mStatusByPathCache.TryGetValue(fullPath, out result)) | ||
|  |                     return result; | ||
|  | 
 | ||
|  |                 return null; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         internal void Clear() | ||
|  |         { | ||
|  |             lock (mLock) | ||
|  |             { | ||
|  |                 mCurrentCancelToken.Cancel(); | ||
|  | 
 | ||
|  |                 mStatusByPathCache = null; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         internal void Cancel() | ||
|  |         { | ||
|  |             lock (mLock) | ||
|  |             { | ||
|  |                 mCurrentCancelToken.Cancel(); | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         void AsyncCalculateStatus(CancelToken cancelToken) | ||
|  |         { | ||
|  |             Dictionary<string, LockStatusData> statusByPathCache = null; | ||
|  | 
 | ||
|  |             IThreadWaiter waiter = ThreadWaiter.GetWaiter(50); | ||
|  |             waiter.Execute( | ||
|  |                 /*threadOperationDelegate*/ delegate | ||
|  |                 { | ||
|  |                     Dictionary<MountPointWithPath, List<WorkspaceTreeNode>> lockCandidates = | ||
|  |                         new Dictionary<MountPointWithPath, List<WorkspaceTreeNode>>(); | ||
|  | 
 | ||
|  |                     FillLockCandidates.ForTree(mWkInfo, lockCandidates); | ||
|  | 
 | ||
|  |                     if (cancelToken.IsCancelled()) | ||
|  |                         return; | ||
|  | 
 | ||
|  |                     Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode = | ||
|  |                         SearchLocks.GetLocksInfo(mWkInfo, lockCandidates); | ||
|  | 
 | ||
|  |                     if (cancelToken.IsCancelled()) | ||
|  |                         return; | ||
|  | 
 | ||
|  |                     statusByPathCache = BuildStatusByNodeCache. | ||
|  |                         ForLocks(mWkInfo.ClientPath, lockInfoByNode); | ||
|  |                 }, | ||
|  |                 /*afterOperationDelegate*/ delegate | ||
|  |                 { | ||
|  |                     if (cancelToken.IsCancelled()) | ||
|  |                         return; | ||
|  | 
 | ||
|  |                     if (waiter.Exception != null) | ||
|  |                     { | ||
|  |                         ExceptionsHandler.LogException( | ||
|  |                             "LockStatusCache", | ||
|  |                             waiter.Exception); | ||
|  |                         return; | ||
|  |                     } | ||
|  | 
 | ||
|  |                     lock (mLock) | ||
|  |                     { | ||
|  |                         mStatusByPathCache = statusByPathCache; | ||
|  |                     } | ||
|  | 
 | ||
|  |                     RepaintEditor.AllWindowsWithOverlays(); | ||
|  |                 }); | ||
|  |         } | ||
|  | 
 | ||
|  |         static class BuildStatusByNodeCache | ||
|  |         { | ||
|  |             internal static Dictionary<string, LockStatusData> ForLocks( | ||
|  |                 string wkPath, | ||
|  |                 Dictionary<WorkspaceTreeNode, LockInfo> lockInfoByNode) | ||
|  |             { | ||
|  |                 Dictionary<string, LockStatusData> result = | ||
|  |                     BuildPathDictionary.ForPlatform<LockStatusData>(); | ||
|  | 
 | ||
|  |                 LockOwnerNameResolver nameResolver = new LockOwnerNameResolver(); | ||
|  | 
 | ||
|  |                 foreach (WorkspaceTreeNode node in lockInfoByNode.Keys) | ||
|  |                 { | ||
|  |                     LockStatusData lockStatusData = BuildLockStatusData( | ||
|  |                        node, lockInfoByNode[node], nameResolver); | ||
|  | 
 | ||
|  |                     string nodeWkPath = WorkspacePath.GetWorkspacePathFromCmPath( | ||
|  |                         wkPath, | ||
|  |                         WorkspaceNodeOperations.GetCmPath(node), | ||
|  |                         PathHelper.GetDirectorySeparatorChar(wkPath)); | ||
|  | 
 | ||
|  |                     result.Add(nodeWkPath, lockStatusData); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 return result; | ||
|  |             } | ||
|  | 
 | ||
|  |             static LockStatusData BuildLockStatusData( | ||
|  |                 WorkspaceTreeNode node, | ||
|  |                 LockInfo lockInfo, | ||
|  |                 LockOwnerNameResolver nameResolver) | ||
|  |             { | ||
|  |                 return new LockStatusData( | ||
|  |                     GetAssetStatus(node, lockInfo), | ||
|  |                     nameResolver.GetSeidName(lockInfo.SEIDData), | ||
|  |                     BranchInfoCache.GetProtectedBranchName( | ||
|  |                         node.RepSpec, lockInfo.HolderBranchId)); | ||
|  |             } | ||
|  | 
 | ||
|  |             static AssetStatus GetAssetStatus( | ||
|  |                 WorkspaceTreeNode node, | ||
|  |                 LockInfo lockInfo) | ||
|  |             { | ||
|  |                 if (lockInfo.Status == LockInfo.LockStatus.Retained) | ||
|  |                     return AssetStatus.Retained; | ||
|  | 
 | ||
|  |                 return CheckWorkspaceTreeNodeStatus.IsCheckedOut(node) ? | ||
|  |                     AssetStatus.Locked : AssetStatus.LockedRemote; | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         CancelToken mCurrentCancelToken = new CancelToken(); | ||
|  | 
 | ||
|  |         Dictionary<string, LockStatusData> mStatusByPathCache; | ||
|  | 
 | ||
|  |         readonly WorkspaceInfo mWkInfo; | ||
|  | 
 | ||
|  |         static object mLock = new object(); | ||
|  |     } | ||
|  | } |