public string GetSessionToken(string collectionLink) { bool isNameBased; bool isFeed; string resourceTypeString; string resourceIdOrFullName; bool arePathSegmentsParsed = PathsHelper.TryParsePathSegments(collectionLink, out isFeed, out resourceTypeString, out resourceIdOrFullName, out isNameBased); ConcurrentDictionary <string, ISessionToken> partitionKeyRangeIdToTokenMap = null; if (arePathSegmentsParsed) { ulong?maybeRID = null; if (isNameBased) { string collectionName = PathsHelper.GetCollectionPath(resourceIdOrFullName); ulong rid; if (this.collectionNameByResourceId.TryGetValue(collectionName, out rid)) { maybeRID = rid; } } else { ResourceId resourceId = ResourceId.Parse(resourceIdOrFullName); if (resourceId.DocumentCollection != 0) { maybeRID = resourceId.UniqueDocumentCollectionId; } } if (maybeRID.HasValue) { this.sessionTokensRIDBased.TryGetValue(maybeRID.Value, out partitionKeyRangeIdToTokenMap); } } if (partitionKeyRangeIdToTokenMap == null) { return(string.Empty); } return(SessionContainer.GetSessionTokenString(partitionKeyRangeIdToTokenMap)); }
// used in unit tests to check if two SessionContainer are equal // a.MakeSnapshot().Equals(b.MakeSnapshot()) public object MakeSnapshot() { return(SessionContainer.MakeSnapshot(this.state)); }
public void SetSessionToken(DocumentServiceRequest request, INameValueCollection responseHeaders) { SessionContainer.SetSessionToken(this.state, request, responseHeaders); }
public void SetSessionToken(string collectionRid, string collectionFullname, INameValueCollection responseHeaders) { SessionContainer.SetSessionToken(this.state, collectionRid, collectionFullname, responseHeaders); }
public void ClearTokenByResourceId(string resourceId) { SessionContainer.ClearTokenByResourceId(this.state, resourceId); }
public void ClearTokenByCollectionFullname(string collectionFullname) { SessionContainer.ClearTokenByCollectionFullname(this.state, collectionFullname); }
public ISessionToken ResolvePartitionLocalSessionToken(DocumentServiceRequest request, string partitionKeyRangeId) { return(SessionContainer.ResolvePartitionLocalSessionToken(this.state, request, partitionKeyRangeId)); }
public string ResolveGlobalSessionToken(DocumentServiceRequest request) { return(SessionContainer.ResolveGlobalSessionToken(this.state, request)); }
public string GetSessionToken(string collectionLink) { return(SessionContainer.GetSessionToken(this.state, collectionLink)); }
// State may be replaced (from a different thread) during an execution of an instance method so in a straightforward // implementation the method may acquire lock on the initial state but release it on an replaced state resulting in an // error. To avoid this situation a method reads state into a local variable then it works only with the variable; also // it explicitly passes it to the utility methods. We put all logic in static methods since static methods don't have // access to instance members it eliminates the problem of accidental accessing state the second time. public void ReplaceCurrrentStateWithStateOf(SessionContainer comrade) { this.state = comrade.state; }
private static void SetSessionToken(SessionContainerState self, ResourceId resourceId, string collectionName, string encodedToken) { string partitionKeyRangeId; ISessionToken token; if (VersionUtility.IsLaterThan(HttpConstants.Versions.CurrentVersion, HttpConstants.VersionDates.v2015_12_16)) { string[] tokenParts = encodedToken.Split(':'); partitionKeyRangeId = tokenParts[0]; token = SessionTokenHelper.Parse(tokenParts[1], HttpConstants.Versions.CurrentVersion); } else { //todo: elasticcollections remove after first upgrade. partitionKeyRangeId = "0"; token = SessionTokenHelper.Parse(encodedToken, HttpConstants.Versions.CurrentVersion); } DefaultTrace.TraceVerbose("Update Session token {0} {1} {2}", resourceId.UniqueDocumentCollectionId, collectionName, token); bool isKnownCollection = false; self.rwlock.EnterReadLock(); try { isKnownCollection = self.collectionNameByResourceId.TryGetValue(collectionName, out ulong resolvedCollectionResourceId) && self.collectionResourceIdByName.TryGetValue(resourceId.UniqueDocumentCollectionId, out string resolvedCollectionName) && resolvedCollectionResourceId == resourceId.UniqueDocumentCollectionId && resolvedCollectionName == collectionName; if (isKnownCollection) { SessionContainer.AddSessionToken(self, resourceId.UniqueDocumentCollectionId, partitionKeyRangeId, token); } } finally { self.rwlock.ExitReadLock(); } if (!isKnownCollection) { self.rwlock.EnterWriteLock(); try { if (self.collectionNameByResourceId.TryGetValue(collectionName, out ulong resolvedCollectionResourceId)) { _ = self.sessionTokensRIDBased.TryRemove(resolvedCollectionResourceId, out _); _ = self.collectionResourceIdByName.TryRemove(resolvedCollectionResourceId, out _); } self.collectionNameByResourceId[collectionName] = resourceId.UniqueDocumentCollectionId; self.collectionResourceIdByName[resourceId.UniqueDocumentCollectionId] = collectionName; SessionContainer.AddSessionToken(self, resourceId.UniqueDocumentCollectionId, partitionKeyRangeId, token); } finally { self.rwlock.ExitWriteLock(); } } }
private static ISessionToken ResolvePartitionLocalSessionToken(SessionContainerState self, DocumentServiceRequest request, string partitionKeyRangeId) { return(SessionTokenHelper.ResolvePartitionLocalSessionToken(request, partitionKeyRangeId, SessionContainer.GetPartitionKeyRangeIdToTokenMap(self, request))); }
private static string ResolveGlobalSessionToken(SessionContainerState self, DocumentServiceRequest request) { ConcurrentDictionary <string, ISessionToken> partitionKeyRangeIdToTokenMap = SessionContainer.GetPartitionKeyRangeIdToTokenMap(self, request); if (partitionKeyRangeIdToTokenMap != null) { return(SessionContainer.GetSessionTokenString(partitionKeyRangeIdToTokenMap)); } return(string.Empty); }
private static string ResolvePartitionLocalSessionTokenForGateway(SessionContainerState self, DocumentServiceRequest request, string partitionKeyRangeId) { ConcurrentDictionary <string, ISessionToken> partitionKeyRangeIdToTokenMap = SessionContainer.GetPartitionKeyRangeIdToTokenMap(self, request); if (partitionKeyRangeIdToTokenMap != null) { if (partitionKeyRangeIdToTokenMap.TryGetValue(partitionKeyRangeId, out ISessionToken sessionToken)) { return(partitionKeyRangeId + SessionContainer.sessionTokenSeparator + sessionToken.ConvertToString()); } else if (request.RequestContext.ResolvedPartitionKeyRange.Parents != null) { ISessionToken parentSessionToken = null; for (int parentIndex = request.RequestContext.ResolvedPartitionKeyRange.Parents.Count - 1; parentIndex >= 0; parentIndex--) { if (partitionKeyRangeIdToTokenMap.TryGetValue(request.RequestContext.ResolvedPartitionKeyRange.Parents[parentIndex], out sessionToken)) { // A partition can have more than 1 parent (merge). In that case, we apply Merge to generate a token with both parent's max LSNs parentSessionToken = parentSessionToken != null?parentSessionToken.Merge(sessionToken) : sessionToken; } } // When we don't have the session token for a partition, we can leverage the session token of the parent(s) if (parentSessionToken != null) { return(partitionKeyRangeId + SessionContainer.sessionTokenSeparator + parentSessionToken.ConvertToString()); } } } return(null); }
private static string ResolvePartitionLocalSessionTokenForGateway(SessionContainerState self, DocumentServiceRequest request, string partitionKeyRangeId) { ConcurrentDictionary <string, ISessionToken> partitionKeyRangeIdToTokenMap = SessionContainer.GetPartitionKeyRangeIdToTokenMap(self, request); if (partitionKeyRangeIdToTokenMap != null) { if (partitionKeyRangeIdToTokenMap.TryGetValue(partitionKeyRangeId, out ISessionToken sessionToken)) { return(partitionKeyRangeId + ":" + sessionToken.ConvertToString()); } else if (request.RequestContext.ResolvedPartitionKeyRange.Parents != null) { for (int parentIndex = request.RequestContext.ResolvedPartitionKeyRange.Parents.Count - 1; parentIndex >= 0; parentIndex--) { if (partitionKeyRangeIdToTokenMap.TryGetValue(request.RequestContext.ResolvedPartitionKeyRange.Parents[parentIndex], out sessionToken)) { return(partitionKeyRangeId + ":" + sessionToken.ConvertToString()); } } } } return(null); }