コード例 #1
0
        public virtual PredicateResults GetTheLock(ZooKeeper client, List <string> sortedChildren, string sequenceNodePath, int maxLeases)
        {
            var sequenceNodeName = ZKPaths.GetNodeFromPath(sequenceNodePath);
            var ourIndex         = sortedChildren.IndexOf(sequenceNodeName);

            if (ourIndex < 0)
            {
                throw new KeeperException.NoNodeException(sequenceNodePath);
            }

            var locked      = ourIndex < maxLeases;
            var nodeToWatch = locked ? null : sortedChildren[ourIndex - maxLeases];

            return(new PredicateResults(nodeToWatch, locked));
        }
コード例 #2
0
        private PredicateResults ReadLockPredicate(List <string> children, string sequenceNodePath)
        {
            // 已获取写锁可以直接获取读锁
            if (_writeLock.IsAcquiredLock())
            {
                return(new PredicateResults(null, true));
            }

            int watchWriteIndex  = int.MaxValue;
            int ourIndex         = -1;
            var sequenceNodeName = ZKPaths.GetNodeFromPath(sequenceNodePath);

            for (int index = 0; index < children.Count; index++)
            {
                var node = children[index];

                // 写锁节点
                if (node.Contains(ZookeeperReadWriteLock.WRITE_LOCK_NAME))
                {
                    watchWriteIndex = index;
                }
                // 当前读锁节点
                else if (node == sequenceNodeName)
                {
                    ourIndex = index;
                    break;
                }
            }

            if (ourIndex < 0)
            {
                throw new KeeperException.NoNodeException(sequenceNodePath);
            }

            var locked      = (ourIndex < watchWriteIndex);
            var pathToWatch = locked ? null : children[watchWriteIndex];

            return(new PredicateResults(pathToWatch, locked));
        }
コード例 #3
0
        /// <summary>
        /// 获取一个Lease
        /// </summary>
        /// <param name="startMs">开始毫秒数</param>
        /// <param name="waitMs">等待毫秒数</param>
        /// <returns>Lease节点名称</returns>
        private async Task <string> InternalAcquireOneLeaseAsync(long startMs, long waitMs)
        {
            // 获取剩余等待时间
            var remainingTime = GetRemainingWaitMs(startMs, waitMs);

            if (remainingTime <= 0)
            {
                new TimeoutException("等待超时");
            }
            // 获取分布式锁
            await _lock.AcquireAsync(remainingTime);

            string leasePath;
            var    success = false;

            try
            {
                // 创建Lease临时有序节点
                leasePath = await _zkClient.createAsync(ZKPaths.MakePath(_leasesPath, LEASE_BASE_NAME), null,
                                                        ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

                // 节点名称
                var leaseNodeName = ZKPaths.GetNodeFromPath(leasePath);

                try
                {
                    while (true)
                    {
                        var childrenResult = await _zkClient.getChildrenAsync(_leasesPath, _watcher);

                        // 找不到刚创建的Lease节点
                        if (!childrenResult.Children.Contains(leaseNodeName))
                        {
                            throw new KeeperException.NoNodeException("Sequential path not found - possible session loss");
                        }

                        // 成功获取一个Lease
                        if (childrenResult.Children.Count <= _maxLeases)
                        {
                            break;
                        }

                        // 剩余等待时间
                        remainingTime = GetRemainingWaitMs(startMs, waitMs);
                        if (remainingTime <= 0)
                        {
                            throw new TimeoutException("等待超时");
                        }

                        // 等待被唤醒
                        var result = await _signal.WaitAsync(remainingTime);

                        if (!result)
                        {
                            throw new TimeoutException("等待超时");
                        }
                    }
                    success = true;
                }
                finally
                {
                    if (!success)
                    {
                        await DeleteLease(leasePath);
                    }
                }
            }
            finally
            {
                await _lock.ReleaseAsync();
            }

            return(leasePath);
        }