Exemplo n.º 1
0
        private static void ClearTokenByResourceId(SessionContainerState self, string resourceId)
        {
            if (!string.IsNullOrEmpty(resourceId))
            {
                ResourceId resource = ResourceId.Parse(resourceId);
                if (resource.DocumentCollection != 0)
                {
                    ulong rid = resource.UniqueDocumentCollectionId;

                    self.rwlock.EnterWriteLock();
                    try
                    {
                        if (self.collectionResourceIdByName.ContainsKey(rid))
                        {
                            string collectionName = self.collectionResourceIdByName[rid];
                            _ = self.sessionTokensRIDBased.TryRemove(rid, out _);
                            _ = self.collectionResourceIdByName.TryRemove(rid, out _);
                            _ = self.collectionNameByResourceId.TryRemove(collectionName, out _);
                        }
                    }
                    finally
                    {
                        self.rwlock.ExitWriteLock();
                    }
                }
            }
        }
        private static void ClearTokenByCollectionFullname(SessionContainerState self, string collectionFullname)
        {
            if (!string.IsNullOrEmpty(collectionFullname))
            {
                string collectionName = PathsHelper.GetCollectionPath(collectionFullname);

                self.rwlock.EnterWriteLock();
                try
                {
                    if (self.collectionNameByResourceId.ContainsKey(collectionName))
                    {
                        string ignoreString;
                        ulong  ignoreUlong;

                        ulong rid = self.collectionNameByResourceId[collectionName];
                        ConcurrentDictionary <string, ISessionToken> ignored;
                        self.sessionTokensRIDBased.TryRemove(rid, out ignored);
                        self.collectionResourceIdByName.TryRemove(rid, out ignoreString);
                        self.collectionNameByResourceId.TryRemove(collectionName, out ignoreUlong);
                    }
                }
                finally
                {
                    self.rwlock.ExitWriteLock();
                }
            }
        }
        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);
        }
Exemplo n.º 5
0
        private static void SetSessionToken(SessionContainerState self, string collectionRid, string collectionFullname, INameValueCollection responseHeaders)
        {
            ResourceId resourceId     = ResourceId.Parse(collectionRid);
            string     collectionName = PathsHelper.GetCollectionPath(collectionFullname);
            string     token          = responseHeaders[HttpConstants.HttpHeaders.SessionToken];

            if (!string.IsNullOrEmpty(token))
            {
                SessionContainer.SetSessionToken(self, resourceId, collectionName, token);
            }
        }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
0
        private static void SetSessionToken(SessionContainerState self, DocumentServiceRequest request, INameValueCollection responseHeaders)
        {
            string token = responseHeaders[HttpConstants.HttpHeaders.SessionToken];

            if (!string.IsNullOrEmpty(token))
            {
                if (SessionContainer.ShouldUpdateSessionToken(request, responseHeaders, out ResourceId resourceId, out string collectionName))
                {
                    SessionContainer.SetSessionToken(self, resourceId, collectionName, token);
                }
            }
        }
Exemplo n.º 8
0
 private static SessionContainerSnapshot MakeSnapshot(SessionContainerState self)
 {
     self.rwlock.EnterReadLock();
     try
     {
         return(new SessionContainerSnapshot(self.collectionNameByResourceId, self.collectionResourceIdByName, self.sessionTokensRIDBased));
     }
     finally
     {
         self.rwlock.ExitReadLock();
     }
 }
Exemplo n.º 9
0
        private static string GetSessionToken(SessionContainerState self, string collectionLink)
        {
            bool arePathSegmentsParsed = PathsHelper.TryParsePathSegments(
                collectionLink,
                out _,
                out _,
                out string resourceIdOrFullName,
                out bool isNameBased);

            ConcurrentDictionary <string, ISessionToken> partitionKeyRangeIdToTokenMap = null;

            if (arePathSegmentsParsed)
            {
                ulong?maybeRID = null;

                if (isNameBased)
                {
                    string collectionName = PathsHelper.GetCollectionPath(resourceIdOrFullName);

                    if (self.collectionNameByResourceId.TryGetValue(collectionName, out ulong rid))
                    {
                        maybeRID = rid;
                    }
                }
                else
                {
                    ResourceId resourceId = ResourceId.Parse(resourceIdOrFullName);
                    if (resourceId.DocumentCollection != 0)
                    {
                        maybeRID = resourceId.UniqueDocumentCollectionId;
                    }
                }

                if (maybeRID.HasValue)
                {
                    self.sessionTokensRIDBased.TryGetValue(maybeRID.Value, out partitionKeyRangeIdToTokenMap);
                }
            }

            if (partitionKeyRangeIdToTokenMap == null)
            {
                return(string.Empty);
            }

            return(SessionContainer.GetSessionTokenString(partitionKeyRangeIdToTokenMap));
        }
 private static void AddSessionToken(SessionContainerState self, ulong rid, string partitionKeyRangeId, ISessionToken token)
 {
     self.sessionTokensRIDBased.AddOrUpdate(
         rid,
         (ridKey) =>
     {
         ConcurrentDictionary <string, ISessionToken> tokens = new ConcurrentDictionary <string, ISessionToken>();
         tokens[partitionKeyRangeId] = token;
         return(tokens);
     },
         (ridKey, tokens) =>
     {
         tokens.AddOrUpdate(
             partitionKeyRangeId,
             token,
             (existingPartitionKeyRangeId, existingToken) => existingToken.Merge(token));
         return(tokens);
     });
 }
Exemplo n.º 11
0
        private static void AddSessionToken(SessionContainerState self, ulong rid, string partitionKeyRangeId, ISessionToken token)
        {
            // Avoid using GetOrAdd because it adds lock contention with the inner AddOrUpdate call
            if (!self.sessionTokensRIDBased.TryGetValue(rid, out ConcurrentDictionary <string, ISessionToken> tokens))
            {
                tokens = new ConcurrentDictionary <string, ISessionToken>();
                if (!self.sessionTokensRIDBased.TryAdd(rid, tokens))
                {
                    // Handle if there was a race condition and a different thread did
                    // the add after the initial read
                    if (!self.sessionTokensRIDBased.TryGetValue(rid, out tokens))
                    {
                        throw new InternalServerErrorException("AddSessionToken failed to get or add the session token dictionary.");
                    }
                }
            }

            tokens.AddOrUpdate(
                key: partitionKeyRangeId,
                addValue: token,
                updateValueFactory: (existingPartitionKeyRangeId, existingToken) => existingToken.Merge(token));
        }
Exemplo n.º 12
0
            public override bool Equals(object obj)
            {
                if (obj == null || GetType() != obj.GetType())
                {
                    return(false);
                }

                SessionContainerState sibling = (SessionContainerState)obj;

                if (!AreDictionariesEqual(collectionNameByResourceId, sibling.collectionNameByResourceId, (x, y) => x == y))
                {
                    return(false);
                }
                if (!AreDictionariesEqual(collectionResourceIdByName, sibling.collectionResourceIdByName, (x, y) => x == y))
                {
                    return(false);
                }
                if (!AreDictionariesEqual(sessionTokensRIDBased, sibling.sessionTokensRIDBased, (x, y) => AreDictionariesEqual(x, y, (a, b) => a.Equals(b))))
                {
                    return(false);
                }

                return(true);
            }
Exemplo n.º 13
0
 public SessionContainer(string hostName)
 {
     this.state = new SessionContainerState(hostName);
 }
Exemplo n.º 14
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;
 }
Exemplo n.º 15
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();
                }
            }
        }
Exemplo n.º 16
0
        private static ConcurrentDictionary <string, ISessionToken> GetPartitionKeyRangeIdToTokenMap(SessionContainerState self, DocumentServiceRequest request)
        {
            ulong?maybeRID = null;

            if (request.IsNameBased)
            {
                string collectionName = PathsHelper.GetCollectionPath(request.ResourceAddress);

                if (self.collectionNameByResourceId.TryGetValue(collectionName, out ulong rid))
                {
                    maybeRID = rid;
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(request.ResourceId))
                {
                    ResourceId resourceId = ResourceId.Parse(request.ResourceId);
                    if (resourceId.DocumentCollection != 0)
                    {
                        maybeRID = resourceId.UniqueDocumentCollectionId;
                    }
                }
            }

            ConcurrentDictionary <string, ISessionToken> partitionKeyRangeIdToTokenMap = null;

            if (maybeRID.HasValue)
            {
                self.sessionTokensRIDBased.TryGetValue(maybeRID.Value, out partitionKeyRangeIdToTokenMap);
            }

            return(partitionKeyRangeIdToTokenMap);
        }
Exemplo n.º 17
0
 private static ISessionToken ResolvePartitionLocalSessionToken(SessionContainerState self, DocumentServiceRequest request, string partitionKeyRangeId)
 {
     return(SessionTokenHelper.ResolvePartitionLocalSessionToken(request, partitionKeyRangeId, SessionContainer.GetPartitionKeyRangeIdToTokenMap(self, request)));
 }