Пример #1
0
        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));
        }
Пример #2
0
 // used in unit tests to check if two SessionContainer are equal
 // a.MakeSnapshot().Equals(b.MakeSnapshot())
 public object MakeSnapshot()
 {
     return(SessionContainer.MakeSnapshot(this.state));
 }
Пример #3
0
 public void SetSessionToken(DocumentServiceRequest request, INameValueCollection responseHeaders)
 {
     SessionContainer.SetSessionToken(this.state, request, responseHeaders);
 }
Пример #4
0
 public void SetSessionToken(string collectionRid, string collectionFullname, INameValueCollection responseHeaders)
 {
     SessionContainer.SetSessionToken(this.state, collectionRid, collectionFullname, responseHeaders);
 }
Пример #5
0
 public void ClearTokenByResourceId(string resourceId)
 {
     SessionContainer.ClearTokenByResourceId(this.state, resourceId);
 }
Пример #6
0
 public void ClearTokenByCollectionFullname(string collectionFullname)
 {
     SessionContainer.ClearTokenByCollectionFullname(this.state, collectionFullname);
 }
Пример #7
0
 public ISessionToken ResolvePartitionLocalSessionToken(DocumentServiceRequest request, string partitionKeyRangeId)
 {
     return(SessionContainer.ResolvePartitionLocalSessionToken(this.state, request, partitionKeyRangeId));
 }
Пример #8
0
 public string ResolveGlobalSessionToken(DocumentServiceRequest request)
 {
     return(SessionContainer.ResolveGlobalSessionToken(this.state, request));
 }
Пример #9
0
 public string GetSessionToken(string collectionLink)
 {
     return(SessionContainer.GetSessionToken(this.state, collectionLink));
 }
Пример #10
0
 // 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;
 }
Пример #11
0
        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();
                }
            }
        }
Пример #12
0
 private static ISessionToken ResolvePartitionLocalSessionToken(SessionContainerState self, DocumentServiceRequest request, string partitionKeyRangeId)
 {
     return(SessionTokenHelper.ResolvePartitionLocalSessionToken(request, partitionKeyRangeId, SessionContainer.GetPartitionKeyRangeIdToTokenMap(self, request)));
 }
Пример #13
0
        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);
        }
Пример #14
0
        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);
        }