示例#1
0
        //When a new shard is added, do the following
        public void OnShardAdded(ShardInfo shard)
        {
            if (shard != null)
            {
                if (shard.Name != context.LocalShardName && _remoteShards != null && !_remoteShards.ContainsKey(shard.Name))
                {
                    if (_clusterConfigMgr != null)
                    {
                        _clusterConfigMgr.UpdateClusterConfiguration();
                        ShardConfiguration sConfig = _clusterConfigMgr.GetShardConfiguration(context.LocalShardName);
                        if (sConfig == null)
                        {
                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Warn("ClusterManager.OnShardAdded() ", "The shard " + shard.Name + " does not exist in the configuration.");
                            }
                            return;
                        }

                        IShard remoteShard = new RemoteShard(new DualChannelFactory(), new ShardChannelFormatter(), context, _connectionRestoration);
                        remoteShard.Initialize(sConfig);
                        remoteShard.RegisterShardListener(Common.MiscUtil.CLUSTER_MANAGER, this);
                        lock (_remoteShards)
                        {
                            _remoteShards.Add(shard.Name, remoteShard);
                        }
                    }
                }
            }
        }
示例#2
0
        public Shard(GatewaySettings settings, ShardInfo info, IGatewayRatelimiter ratelimiter, string url, ILogger logger)
        {
            _jsonSerializerOptions = new JsonSerializerOptions().ConfigureForMyriad();

            _settings     = settings;
            _info         = info;
            _ratelimiter  = ratelimiter;
            _url          = url;
            _logger       = logger.ForContext <Shard>().ForContext("ShardId", info.ShardId);
            _stateManager = new ShardStateManager(info, _jsonSerializerOptions, logger)
            {
                HandleEvent   = HandleEvent,
                SendHeartbeat = SendHeartbeat,
                SendIdentify  = SendIdentify,
                SendResume    = SendResume,
                Connect       = ConnectInner,
                Reconnect     = Reconnect,
            };
            _stateManager.OnHeartbeatReceived += latency =>
            {
                HeartbeatReceived?.Invoke(latency);
            };

            _conn = new ShardConnection(_jsonSerializerOptions, _logger);
        }
示例#3
0
        private HttpWebRequest CreateRequest(long instart, long inend, File file, bool doBanCurrentShard)
        {
            if (doBanCurrentShard)
            {
                _cloud.Account.BanShardInfo(_shard);
            }

            _shard = GetShard(file);

            string downloadkey = string.Empty;

            if (_shard.Type == ShardType.WeblinkGet)
            {
                downloadkey = _cloud.Account.DownloadToken.Value;
            }

            var request = _shard.Type == ShardType.Get
                ? (HttpWebRequest)WebRequest.Create($"{_shard.Url}{Uri.EscapeDataString(file.FullPath)}")
                : (HttpWebRequest)WebRequest.Create($"{_shard.Url}{new Uri(file.PublicLink).PathAndQuery.Remove(0, "/public".Length)}?key={downloadkey}");

            request.Headers.Add("Accept-Ranges", "bytes");
            request.AddRange(instart, inend);
            request.Proxy                    = _cloud.Account.Proxy;
            request.CookieContainer          = _cloud.Account.Cookies;
            request.Method                   = "GET";
            request.ContentType              = MediaTypeNames.Application.Octet;
            request.Accept                   = "*/*";
            request.UserAgent                = ConstSettings.UserAgent;
            request.AllowReadStreamBuffering = false;

            request.Timeout = 15 * 1000;

            return(request);
        }
        //public HttpWebRequest DownloadRequest(long instart, long inend, File file, ShardInfo shard)
        //{
        //    string downloadkey = string.Empty;
        //    if (shard.Type == ShardType.WeblinkGet)
        //        downloadkey = Authent.DownloadToken;

        //    string url = shard.Type == ShardType.Get
        //        ? $"{shard.Url}{Uri.EscapeDataString(file.FullPath)}"
        //        : $"{shard.Url}{new Uri(ConstSettings.PublishFileLink + file.PublicLink).PathAndQuery.Remove(0, "/public".Length)}?key={downloadkey}";

        //    var request = (HttpWebRequest)WebRequest.Create(url);

        //    request.Headers.Add("Accept-Ranges", "bytes");
        //    request.AddRange(instart, inend);
        //    request.Proxy = HttpSettings.Proxy;
        //    request.CookieContainer = Authent.Cookies;
        //    request.Method = "GET";
        //    request.ContentType = MediaTypeNames.Application.Octet;
        //    request.Accept = "*/*";
        //    request.UserAgent = HttpSettings.UserAgent;
        //    request.AllowReadStreamBuffering = false;

        //    request.Timeout = 15 * 1000;

        //    return request;
        //}


        public void BanShardInfo(ShardInfo banShard)
        {
            if (!_bannedShards.Value.Any(bsh => bsh.Type == banShard.Type && bsh.Url == banShard.Url))
            {
                Logger.Warn($"Shard {banShard.Url} temporarily banned");
                _bannedShards.Value.Add(banShard);
            }
        }
        public UploadStream(string destinationPath, CloudApi cloud, long size)
        {
            _cloud = cloud;

            _file  = new File(destinationPath, size, null);
            _shard = _cloud.Account.GetShardInfo(ShardType.Upload).Result;

            Initialize();
        }
示例#6
0
        public Shard(ILogger logger, Uri uri, GatewaySettings settings, ShardInfo info,
                     ShardSessionInfo?sessionInfo = null)
        {
            _logger = logger.ForContext <Shard>();
            _uri    = uri;

            Settings    = settings;
            ShardInfo   = info;
            SessionInfo = sessionInfo ?? new ShardSessionInfo();
        }
 private void OnPrimaryGone(ShardInfo shardInfo)
 {
     if (_primary == null)
     {
         return;
     }
     _primary = null;
     _primaryChannel.Disconnect();
     _primaryChannel = null;
 }
示例#8
0
 private ShardInfo TryGetShard(DiscordClient shard)
 {
     // If we haven't seen this shard before, add it to the dict!
     // I don't think this will ever occur since the shard number is constant up-front and we handle those
     // in the RefreshShardList handler above but you never know, I guess~
     if (!_shardInfo.TryGetValue(shard.ShardId, out var info))
     {
         _shardInfo[shard.ShardId] = info = new ShardInfo();
     }
     return(info);
 }
示例#9
0
        public void Init(DiscordShardedClient client)
        {
            for (var i = 0; i < client.Shards.Count; i++)
            {
                _shardInfo[i] = new ShardInfo();
            }

            client.ShardConnected      += ShardConnected;
            client.ShardDisconnected   += ShardDisconnected;
            client.ShardReady          += ShardReady;
            client.ShardLatencyUpdated += ShardLatencyUpdated;
        }
示例#10
0
        public override Task <ShardInfo> GetShardInfo(ShardType shardType)
        {
            //TODO: must hide shard functionality into repo after DownloadStream and UploadStream refact

            var shi = new ShardInfo
            {
                Url  = _metaServer.Value.Url,
                Type = shardType
            };

            return(Task.FromResult(shi));
        }
示例#11
0
 public async Task SaveShard(ShardInfo shard)
 {
     try
     {
         var shardFileName = Path.Combine(shardPath, shard.UploadId, $"{shard.UploadId}_{shard.Shard}_{shard.totalShard}");
         using (var file = File.Create(shardFileName))
         {
             await file.WriteAsync(shard.Data);
         }
     }
     catch (IOException e)
     {
         throw new ServiceFrameworkException("保存分片文件失败", e);
     }
 }
示例#12
0
        public ShardValueDetail(string nodeName, ShardConfiguration configuration, string[] pathChunks)
        {
            NodeName       = nodeName;
            NodeType       = PathType.Shard;
            IsContainer    = true;
            IsValid        = true;
            Configuration  = configuration;
            PathChunks     = pathChunks;
            ChilderanTable = new PrintableTable();
            ChilderanName  = new List <string>();
            ClusterInfo       clusterInfo = ConfigurationConnection.ClusterInfo;
            ShardInfo         shardInfo   = clusterInfo.GetShard(nodeName);
            List <ServerInfo> running     = new List <ServerInfo>();

            if (shardInfo != null)
            {
                if (shardInfo.RunningNodes != null)
                {
                    running = shardInfo.RunningNodes.Values.ToList();
                }
            }
            ChilderanTable.AddHeader("Node IP Address", "Running Status", "Primary Status", "Priority");

            foreach (ServerNode node in configuration.Servers.Nodes.Values)
            {
                ServerInfo serverInfo = null;
                string     isPrimery  = ProviderUtil.NOT_PRIMARY;
                string     isRunning  = ProviderUtil.NOT_RUNNING;
                if (running != null)
                {
                    serverInfo = running.Find(x => x.Address.ip.Equals(node.Name));
                }

                if (serverInfo != null)
                {
                    if (running.Contains(serverInfo))
                    {
                        isRunning = ProviderUtil.RUNNING;
                    }
                    if (shardInfo.Primary != null && serverInfo.Equals(shardInfo.Primary))
                    {
                        isPrimery = ProviderUtil.PRIMARY;
                    }
                }
                ChilderanTable.AddRow(node.Name, isRunning, isPrimery, node.Priority.ToString());
                ChilderanName.Add(node.Name);
            }
        }
示例#13
0
        public ShardsDetail(string nodeName, DeploymentConfiguration configuration, string[] pathChunks)
        {
            NodeName       = nodeName;
            NodeType       = PathType.Shards;
            IsContainer    = true;
            IsValid        = true;
            Configuration  = configuration;
            ChilderanTable = new PrintableTable();
            PathChunks     = pathChunks;
            ChilderanName  = new List <string>();
            ChilderanTable.AddHeader("Shard Name", "Node(s)", "Status", "Shard Port");
            ClusterInfo clusterInfo = ConfigurationConnection.ClusterInfo;

            foreach (ShardConfiguration shard in configuration.Shards.Values)
            {
                List <string> status    = new List <string>();
                ShardInfo     shardInfo = clusterInfo.GetShard(shard.Name);
                if (shardInfo != null)
                {
                    foreach (String node in shard.Servers.Nodes.Keys)
                    {
                        string statusString = "";
                        if (shardInfo.RunningNodes.Values.ToList().Exists(k => k.Address.IpAddress.ToString().Equals(node)))
                        {
                            statusString = ProviderUtil.STARTED;

                            if (shardInfo.Primary != null)
                            {
                                if (shardInfo.Primary.Address.IpAddress.ToString().Equals(node))
                                {
                                    statusString += ProviderUtil.PRIMARY_STATUS;
                                }
                            }
                        }
                        else
                        {
                            statusString = ProviderUtil.STOPPED;
                        }
                        status.Add(statusString);
                    }
                }

                ChilderanTable.AddMultiLineRow(new string[] { shard.Name }, shard.Servers.Nodes.Keys.ToArray(), status.ToArray(), new string[] { shard.Port.ToString() });
                ChilderanName.Add(shard.Name);
            }
        }
示例#14
0
        private void OnPrimarySelected(ShardInfo shardInfo)
        {
            _primary = shardInfo.Primary.ToServer();

            string key = ConvertToKey(shardInfo.Primary.Address); // IP:Port

            lock (_secondaryChannels)
            {
                if (_secondaryChannels.ContainsKey(key))
                {
                    _primaryChannel = _secondaryChannels[key];
                    _secondaryChannels.Remove(key);
                    return;
                }
            }
            _primaryChannel = CreateConnection(shardInfo.Primary.Address.IpAddress.ToString(),
                                               shardInfo.Primary.Address.Port);
        }
        //TODO: broken now, replace with PUT request
        public HttpWebRequest UploadRequest(ShardInfo shard, File file, UploadMultipartBoundary boundary)
        {
            var url = new Uri($"{shard.Url}?cloud_domain=2&{Authent.Login}");

            var request = (HttpWebRequest)WebRequest.Create(url.OriginalString);

            request.Proxy           = HttpSettings.Proxy;
            request.CookieContainer = Authent.Cookies;
            request.Method          = "PUT";
            request.ContentLength   = file.OriginalSize; // + boundary.Start.LongLength + boundary.End.LongLength;
            request.Referer         = $"{ConstSettings.CloudDomain}/home/{Uri.EscapeDataString(file.Path)}";
            request.Headers.Add("Origin", ConstSettings.CloudDomain);
            request.Host = url.Host;
            //request.ContentType = $"multipart/form-data; boundary=----{boundary.Guid}";
            request.Accept    = "*/*";
            request.UserAgent = HttpSettings.UserAgent;
            request.AllowWriteStreamBuffering = false;
            return(request);
        }
        public DownloadStream(IList <File> files, CloudApi cloud, long?start = null, long?end = null)
        {
            var globalLength = files.Sum(f => f.Size);

            _cloud = cloud;
            _shard = files.All(f => string.IsNullOrEmpty(f.PublicLink))
                ? _cloud.Account.GetShardInfo(ShardType.Get).Result
                : _cloud.Account.GetShardInfo(ShardType.WeblinkGet).Result;

            _files = files;
            _start = start;
            _end   = end >= globalLength ? globalLength - 1 : end;

            Length = _start != null && _end != null
                ? _end.Value - _start.Value + 1
                : globalLength;

            Initialize();
        }
        public HttpWebRequest DownloadRequest(long instart, long inend, File file, ShardInfo shard)
        {
            string url = $"{_downloadServer.Value.Url}{Uri.EscapeDataString(file.FullPath)}?token={Authent.AccessToken}&client_id={HttpSettings.ClientId}";

            var request = (HttpWebRequest)WebRequest.Create(url);

            request.Headers.Add("Accept-Ranges", "bytes");
            request.AddRange(instart, inend);
            request.Proxy                    = HttpSettings.Proxy;
            request.CookieContainer          = Authent.Cookies;
            request.Method                   = "GET";
            request.ContentType              = MediaTypeNames.Application.Octet;
            request.Accept                   = "*/*";
            request.UserAgent                = HttpSettings.UserAgent;
            request.AllowReadStreamBuffering = false;

            request.Timeout = 15 * 1000;

            return(request);
        }
示例#18
0
        public HttpWebRequest UploadRequest(ShardInfo shard, File file, UploadMultipartBoundary boundary)
        {
            var url = new Uri($"{shard.Url}?client_id={HttpSettings.ClientId}&token={Authent.AccessToken}");

            var request = (HttpWebRequest)WebRequest.Create(url);

            request.Proxy                     = HttpSettings.Proxy;
            request.CookieContainer           = Authent.Cookies;
            request.Method                    = "PUT";
            request.ContentLength             = file.OriginalSize;
            request.Accept                    = "*/*";
            request.UserAgent                 = HttpSettings.UserAgent;
            request.AllowWriteStreamBuffering = false;

            request.Timeout          = 15 * 1000;
            request.ReadWriteTimeout = 15 * 1000;
            //request.ServicePoint.ConnectionLimit = int.MaxValue;

            return(request);
        }
示例#19
0
        private async Task RefreshShardList()
        {
            // This callback doesn't actually receive the shard that was opening, so we just try to check we have 'em all (so far)
            foreach (var(id, shard) in _client.ShardClients)
            {
                // Get or insert info in the client dict
                if (_shardInfo.TryGetValue(id, out var info))
                {
                    // Skip adding listeners if we've seen this shard & already added listeners to it
                    if (info.HasAttachedListeners)
                    {
                        continue;
                    }
                }
                else
                {
                    _shardInfo[id] = info = new ShardInfo();
                }


                // Call our own SocketOpened listener manually (and then attach the listener properly)
                await SocketOpened(shard);

                shard.SocketOpened += () => SocketOpened(shard);

                // Register listeners for new shards
                _logger.Information("Attaching listeners to new shard #{Shard}", shard.ShardId);
                shard.Resumed      += Resumed;
                shard.Ready        += Ready;
                shard.SocketClosed += SocketClosed;
                shard.Heartbeated  += Heartbeated;

                // Register that we've seen it
                info.HasAttachedListeners = true;
            }
        }
示例#20
0
        public RemoteShardConnections(IChannelFactory factory, IChannelFormatter channelFormatter, ShardInfo shardInfo,
                                      TraceProvider traceProvider, SessionTypes sessionType)
        {
            _clientContexts    = new Dictionary <string, ClientContext>();
            _clientCredentials = new Dictionary <string, ClientCredential>();

            _factory          = factory;
            _channelFormatter = channelFormatter;
            _shardInfo        = shardInfo;
            _traceProvider    = traceProvider;
            if (shardInfo.Primary != null)
            {
                _primary =
                    new Server(
                        new Address(shardInfo.Primary.Address.IpAddress.ToString(), _shardInfo.Primary.Address.Port),
                        Status.Running); // If its primary it must be running
            }
            else
            {
                // TODO: Write exception to log
                //throw new Exception("At Query Distributor: No primary exists for " + shardInfo.Name);
            }
            _sessionType = sessionType;
        }
示例#21
0
 public Task SaveShard(ShardInfo shard)
 {
     throw new System.NotImplementedException();
 }
示例#22
0
        public void OnConfigurationChanged(ConfigChangeEventArgs arguments)
        {
            ChangeType type = ChangeType.None;

            if (arguments != null)
            {
                string clusterName = arguments.GetParamValue <string>(EventParamName.ClusterName);
                if (clusterName != null && !clusterName.Equals(context.ClusterName))
                {
                    return;
                }

                type = arguments.GetParamValue <ChangeType>(EventParamName.ConfigurationChangeType);
                switch (type)
                {
                case ChangeType.DistributionStrategyConfigured:
                case ChangeType.DatabaseCreated:
                case ChangeType.DatabaseDropped:
                case ChangeType.CollectionCreated:
                case ChangeType.CollectionMoved:
                case ChangeType.CollectionDropped:
                case ChangeType.ConfigRestored:
                case ChangeType.ResyncDatabase:
                case ChangeType.IntraShardStateTrxferCompleted:
                    if (this.configChangeListener != null)
                    {
                        configChangeListener.OnConfigurationChanged(arguments);
                    }
                    break;

                case ChangeType.ConfigurationUpdated:
                    break;

                case ChangeType.ShardAdded:
                {
                    ShardInfo newShard = null;

                    if (context.ConfigurationSession != null)
                    {
                        ClusterInfo latestInfo = context.ConfigurationSession.GetDatabaseClusterInfo(arguments.GetParamValue <string>(EventParamName.ClusterName));
                        newShard = latestInfo.GetShardInfo(arguments.GetParamValue <string>(EventParamName.ShardName));
                    }

                    OnShardAdded(newShard);

                    if (this._clusterListener != null)
                    {
                        _clusterListener.OnShardAdd(newShard);
                    }
                }
                break;

                case ChangeType.ShardRemovedForceful:
                    if (this._clusterListener != null)
                    {
                        ShardInfo removedShard = new ShardInfo()
                        {
                            Name = arguments.GetParamValue <string>(EventParamName.ShardName)
                        };
                        _clusterListener.OnShardRemove(removedShard, false);
                    }
                    break;

                case ChangeType.ShardRemovedGraceful:
                    if (this._clusterListener != null)
                    {
                        ShardInfo removedShard = new ShardInfo()
                        {
                            Name = arguments.GetParamValue <string>(EventParamName.ShardName)
                        };
                        _clusterListener.OnShardRemove(removedShard, true);
                    }
                    break;

                case ChangeType.DistributionChanged:
                    if (this._clusterListener != null)
                    {
                        _clusterListener.OnDistributionChanged();
                    }
                    break;
                //write code for check if the primary has been changed for remote shard(s) connect with the new one

                case ChangeType.MembershipChanged:
                case ChangeType.PrimarySelected:
                case ChangeType.NodeJoined:

                    // AR: This should be removing the node from the restoration manager of the local shard.


                    //if (arguments.ConfigurationChangeType == ChangeType.PrimarySelected || arguments.ConfigurationChangeType == ChangeType.PrimaryGone)
                    //{
                    // ControlConfigurationChangeTask(arguments);
                    if (arguments.GetParamValue <ChangeType>(EventParamName.ConfigurationChangeType) == ChangeType.MembershipChanged)
                    {
                        HandlePrimaryChangeForRemoteshard(arguments);
                    }

                    //}

                    //if (arguments.ConfigurationChangeType.Equals(ChangeType.PrimarySelected) && arguments.Membership.Primary != null || (arguments.ConfigurationChangeType.Equals(ChangeType.PrimaryGone) && arguments.Membership.Primary == null))
                    //{


                    //HandleMembershipChangeForRemoteShard();
                    //}
                    //OnMembershipChanged(arguments);
                    //HandlePrimaryChangeForRemoteshard(arguments);
                    //HandleMembershipChanged();
                    break;

                case ChangeType.NodeAdded:
                case ChangeType.NodeRemoved:
                case ChangeType.PriorityChanged:
                case ChangeType.NodeLeft:
                case ChangeType.PrimaryGone:
                    if (_localShard != null)
                    {
                        ((LocalShard)_localShard).OnConfigurationChanged(arguments);
                    }

                    break;

                case ChangeType.RangeUpdated:
                    _clusterListener.OnRangesUpdated();
                    break;

                case ChangeType.NewRangeAdded:
                    _clusterListener.OnNewRangeAdded();
                    break;

                default:
                    //write code for check if the primary has been changed for remote shard(s) connect with the new one

                    break;
                }
            }
        }
        /// <summary>
        /// Speculative Phase:
        /// 1. We search for the node with the latest op-log entry. This detail bears the highest value.
        /// 2. Next, if multiple nodes have the same op-log entry, we move onto the next step.
        /// 3. All those nodes which have the same op-log entry AND are connected to the CS are considered.
        /// 4. Highest priority from amongst these active nodes are taken into consideration.
        /// 5. If this node fulfills all of the above, it successfully passes the speculative phase.
        /// </summary>
        /// <param name="heartbeatReport"></param>
        /// <returns></returns>

        private bool ShouldIInitiateElection(LocalShardHeartbeatReporting heartbeatReport, Activity activity)
        {
            IList <Address> activeNodes = null;

            if (heartbeatReport != null)
            {
                activeNodes = heartbeatReport.GetReportTable.Keys.ToList();
                OperationId    maxOplog = null;
                IList <string> matchingOplogServerIPs = new List <string>();

                HeartbeatInfo localHeartbeat = heartbeatReport.GetHeartbeatInfo(_context.LocalAddress);
                if (localHeartbeat == null)
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Warn(
                            "ElectionBasedMembershipStrategy.ShouldIInititateElections()",
                            "local node heartbeat is null");
                    }
                    return(false);
                }

                OperationId lastRepId = null;


                if (activity.Equals(Activity.TakeoverElectionsTriggered))
                {
                    HeartbeatInfo info = null;
                    if (_shard != null && _shard.Primary != null)
                    {
                        info = heartbeatReport.GetHeartbeatInfo(_shard.Primary.Address);
                    }
                }

                else
                {
                    ShardConfiguration sConfig       = _clusterConfigMgr.GetShardConfiguration(_context.LocalShardName);
                    int         configuredNodesCount = 0;
                    OperationId OpIdAtCS             = null;
                    if (sConfig != null && sConfig.Servers != null && sConfig.Servers.Nodes != null)
                    {
                        configuredNodesCount = sConfig.Servers.Nodes.Count;
                    }
                    if (configuredNodesCount > 0 && activeNodes != null && activeNodes.Count < configuredNodesCount)
                    {
                        ShardInfo   sInfo = null;
                        ClusterInfo cInfo = _context.ConfigurationSession.GetDatabaseClusterInfo(_context.ClusterName);
                        if (cInfo != null)
                        {
                            sInfo = cInfo.GetShardInfo(_context.LocalShardName);
                        }
                        if (sInfo != null)
                        {
                            OpIdAtCS = sInfo.LastOperationId;
                        }
                        if (OpIdAtCS > lastRepId)
                        {
                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Info(
                                    "electBasedMemSt.ShouldIInitElections()",
                                    "CS has an operation newer than my operation. Hence, waiting.");
                            }

                            if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsInfoEnabled)
                            {
                                if (OpIdAtCS != null)
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()",
                                        "Operation ID on the CS:- " + OpIdAtCS.ElectionId + ":"
                                        + OpIdAtCS.ElectionBasedSequenceId);
                                }
                                else
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()", "The operation ID at the CS is set to null.");
                                }
                                if (lastRepId != null)
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()", "Local node Operation ID:- " + lastRepId.ElectionId +
                                        ":" + lastRepId.ElectionBasedSequenceId);
                                }
                                else
                                {
                                    LoggerManager.Instance.ShardLogger.Info(
                                        "electBasedMemSt.ShouldIInitElections()", "The local node operation ID is set to null.");
                                }
                            }
                            //We maintain the last replicated operation log entry with the CS.
                            //If a node in a shard with older data (usually the previous secondary) is up before the node with the
                            //latest data(usually the previous primary), it waits for a configurable amount of time (2 minutes for
                            //now) before proceeding with the election procedure if it is still unable to detect a primary node.
                            //This way we give the node with the latest data a chance to become primary and therefore avoid data loss.
                            lock (_mutexOnWait)
                            {
                                Monitor.Wait(_mutexOnWait, _waitTimeout);
                            }
                        }
                    }

                    for (int i = 0; i < activeNodes.Count; i++)
                    {
                        HeartbeatInfo info           = heartbeatReport.GetHeartbeatInfo(activeNodes[i]);
                        OperationId   currIndexOplog = info.LastOplogOperationId;
                        if (currIndexOplog > maxOplog)
                        {
                            maxOplog = currIndexOplog;
                        }

                        if (((localHeartbeat.LastOplogOperationId == null && info.LastOplogOperationId == null) || localHeartbeat.LastOplogOperationId != null && localHeartbeat.LastOplogOperationId.Equals(info.LastOplogOperationId)) &&
                            info.CSStatus == ConnectivityStatus.Connected)
                        {
                            matchingOplogServerIPs.Add(activeNodes[i].IpAddress.ToString());
                        }
                    }
                }

                if (localHeartbeat.LastOplogOperationId != null && maxOplog != null && maxOplog > localHeartbeat.LastOplogOperationId && (lastRepId == null || maxOplog > lastRepId))
                {
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "Local operation log is behind max op log wrt " + _context.LocalShardName + " shard.");
                    }
                    if (maxOplog != null && LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "maxOplog: " + maxOplog.ElectionId + ":" + maxOplog.ElectionBasedSequenceId);
                    }
                    if (localHeartbeat.LastOplogOperationId != null && LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "local opLog (from the heartbeat): " + localHeartbeat.LastOplogOperationId.ElectionId + ":" + localHeartbeat.LastOplogOperationId.ElectionBasedSequenceId);
                    }
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled && lastRepId != null)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "LastOpFromOpLog (from the replication module): " + lastRepId.ElectionId + ":" + lastRepId.ElectionBasedSequenceId);
                    }

                    return(false);
                }
                else if (maxOplog == localHeartbeat.LastOplogOperationId || (lastRepId != null && lastRepId.Equals(maxOplog)))
                {
                    //if: there are multiple nodes that have the same oplog entry,
                    //decision will be made on the basis of the priorities.
                    //else: the node with the highest oplog entry will be considered eligible.
                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                    {
                        LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "Local operation log is equal to the max op log wrt " + _context.LocalShardName + " shard.");
                    }
                    if (maxOplog != null && (localHeartbeat != null && localHeartbeat.LastOplogOperationId != null))
                    {
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "maxOplog: " + maxOplog.ElectionId + ":" + maxOplog.ElectionBasedSequenceId);
                        }
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "local opLog (from the heartbeat): " + localHeartbeat.LastOplogOperationId.ElectionId + ":" + localHeartbeat.LastOplogOperationId.ElectionBasedSequenceId);
                        }
                        if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsDebugEnabled && lastRepId != null)
                        {
                            LoggerManager.Instance.ShardLogger.Debug("electBasedMemSt.ShouldIInitiateElect()", "LastOpFromOpLog (from the replication module): " + lastRepId.ElectionId + ":" + lastRepId.ElectionBasedSequenceId);
                        }
                    }
                    if (matchingOplogServerIPs.Count > 0)
                    {
                        int highestRunningNodePriority = _manager.GetHighestNodePriority(activeNodes,
                                                                                         matchingOplogServerIPs);

                        if (highestRunningNodePriority.Equals(_manager.LocalServerPriority))
                        {
                            if (LoggerManager.Instance.ShardLogger != null &&
                                LoggerManager.Instance.ShardLogger.IsDebugEnabled)
                            {
                                LoggerManager.Instance.ShardLogger.Debug(
                                    "ElectionBasedMembershipStrategy.ShouldIInitiateElection()",
                                    "Node : " + _context.LocalAddress.IpAddress.ToString() + " in shard: " +
                                    _context.LocalShardName + " is eligible having priority: " +
                                    highestRunningNodePriority + " .");
                            }
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }
            }
            return(false);
        }
示例#24
0
        //private void OnMembershipChanged(ConfigChangeEventArgs args)
        //{
        //    // needs to be reviewed. Esp for the remote shard purposes.
        //    //Refactoring required.
        //    //if (_localShard != null)
        //    //    _localShard.OnMembershipChanged(args);

        //    if (args.ConfigurationChangeType.Equals(ChangeType.PrimarySelected) && args.Membership.Primary != null || (args.ConfigurationChangeType.Equals(ChangeType.PrimaryGone) && args.Membership.Primary==null))
        //    {

        //        HandlePrimaryChangeForRemoteshard(args);

        //        //HandleMembershipChangeForRemoteShard();
        //    }

        //}

        private void HandlePrimaryChangeForRemoteshard(ConfigChangeEventArgs args)
        {
            try
            {
                if (_localShard.NodeRole == NodeRole.Primary)
                {
                    if (_remoteShards != null && _remoteShards.Count > 0)
                    {
                        string clusterName = args.GetParamValue <string>(EventParamName.ClusterName);
                        string shardName   = args.GetParamValue <string>(EventParamName.ShardName);
                        if (clusterName == null || shardName == null)
                        {
                            return;
                        }
                        foreach (KeyValuePair <String, IShard> remoteShard in _remoteShards)
                        {
                            if (args != null && clusterName == this.context.ClusterName &&
                                shardName == remoteShard.Key)
                            {
                                if (remoteShard.Value != null)
                                {
                                    //if (!((RemoteShard)remoteShard.Value).IsStarted)
                                    //    remoteShard.Value.Start();
                                    //else
                                    //{
                                    if (context.ConfigurationSession != null)
                                    {
                                        //RTD: Should the dependency on CS be removed?
                                        ClusterInfo latestInfo =
                                            context.ConfigurationSession.GetDatabaseClusterInfo(context.ClusterName);
                                        ShardInfo latestShard = null;
                                        if (latestInfo != null)
                                        {
                                            latestShard = latestInfo.GetShardInfo(remoteShard.Key);
                                        }
                                        if (latestShard != null)
                                        {
                                            ((RemoteShard)remoteShard.Value).OnPrimaryChanged(latestShard.Primary,
                                                                                              latestShard.Port);
                                        }
                                    }
                                    //}
                                    break;
                                }
                            }
                        }
                    }
                    //if (context.ConfigurationSession != null)
                    //{
                    //    ClusterInfo latestInfo = context.ConfigurationSession.GetDatabaseClusterInfo(context.ClusterName);
                    //    ShardInfo[] latestShards = latestInfo.ShardInfo;
                    //    if (latestShards.Length > 1)
                    //    {
                    //        foreach (ShardInfo info in latestShards)
                    //        {
                    //            if (info.Name != context.LocalShardName)
                    //            {
                    //                RemoteShard remoteShard = _remoteShards[info.Name] as RemoteShard;
                    //                if (remoteShard != null)
                    //                    remoteShard.OnPrimaryChanged(info.Primary, info.Port);
                    //            }
                    //        }
                    //    }
                    //}
                }
            }
            catch (Exception ex)
            {
                if (LoggerManager.Instance.ServerLogger != null && LoggerManager.Instance.ServerLogger.IsErrorEnabled)
                {
                    LoggerManager.Instance.ServerLogger.Error("ClusterManager.HandlePrimaryChangedForRemoteshard() ", "HandlePrimaryChangeForRemoteshard :" + ex);
                }
            }
        }
 public HttpWebRequest UploadRequest(ShardInfo shard, File file, UploadMultipartBoundary boundary)
 {
     throw new NotImplementedException();
 }
示例#26
0
        public void Run()
        {
            try
            {
                LoggerManager.Instance.SetThreadContext(new LoggerContext {
                    ShardName = _nodeContext.LocalShardName ?? "", DatabaseName = _dbName
                });
                _startSignal.WaitOne();

                if (_nodeContext.ConfigurationSession != null)
                {
                    ((OutProcConfigurationSession)_nodeContext.ConfigurationSession).RegisterListener(this);
                }

                while (_running)
                {
                    if (_dbStore != null && _dbStore.Collections != null)
                    {
                        List <string> collectionKeys = _dbStore.Collections.Keys.ToList();
                        if (collectionKeys.Count > 0)
                        {
                            foreach (string col in collectionKeys)
                            {
                                if (_dbStore.Collections.ContainsKey(col))
                                {
                                    var shardInfo = new ShardInfo
                                    {
                                        ShardName  = _nodeContext.LocalShardName,
                                        Statistics = new ShardStatistics()
                                    };
                                    var colValue = _dbStore.Collections[col] as BaseCollection;
                                    if (colValue != null)
                                    {
                                        shardInfo.Statistics.LocalBuckets = new HashVector <HashMapBucket, BucketStatistics>();
                                        if (colValue.BucketStatistics != null && colValue.BucketStatistics.Count > 0)
                                        {
                                            lock (colValue.BucketStatistics)
                                            {
                                                foreach (var kvp in colValue.BucketStatistics.Values)
                                                {
                                                    if (kvp.Value.IsDirty)
                                                    {
                                                        shardInfo.Statistics.LocalBuckets.Add(kvp.Key, kvp.Value);
                                                    }
                                                    colValue.BucketStatistics[kvp.Key.BucketId].Value.IsDirty = false;
                                                }
                                            }

                                            try
                                            {
                                                if (_nodeContext.ConfigurationSession != null)
                                                {
                                                    _nodeContext.ConfigurationSession.UpdateBucketStatistics(_nodeContext.ClusterName, _dbName, col, shardInfo);
                                                }
                                            }
                                            catch (ManagementException e)
                                            {
                                                if (e.Message.Contains("No configuration server is available to process the request"))
                                                {
                                                    Pause();
                                                    if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsWarnEnabled)
                                                    {
                                                        LoggerManager.Instance.ShardLogger.Warn("UpdateBucketInfo.Run()", "Node disconnected with the Configuration server.");
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    Thread.Sleep(PoolingThreshold);

                    _startSignal.WaitOne();
                }
            }
            catch (ThreadAbortException)
            {
                _bucketInfoThread = null;
            }
            catch (Exception e)
            {
                if (LoggerManager.Instance.ShardLogger != null && LoggerManager.Instance.ShardLogger.IsErrorEnabled)
                {
                    LoggerManager.Instance.ShardLogger.Error("UpdateBucketInfo.Run()", e.ToString());
                }
            }
        }
示例#27
0
        public IList <Server> UpdateConnections(ShardInfo shardInfo)
        {
            IList <Server> serversAdded = new List <Server>();

            if (shardInfo.Primary == null)
            {
                OnPrimaryGone(shardInfo);
            }
            else if (_primary == null)
            {
                OnPrimarySelected(shardInfo);
                serversAdded.Add(Primary);
            }
            else
            {
                Server shardInfoPrimary = shardInfo.Primary.ToServer();
                if (!this._primary.Equals(shardInfoPrimary))
                {
                    lock (_secondaryChannels)
                    {
                        _secondaryChannels[ConvertToKey(_primary.Address)] = _primaryChannel;
                    }
                    OnPrimarySelected(shardInfo);
                    serversAdded.Add(Primary);
                }
            }

            foreach (var secondary in shardInfo.Secondaries)
            {
                string key = ConvertToKey(secondary.Address); //IP:port
                lock (_secondaryChannels)
                {
                    if (!_secondaryChannels.ContainsKey(key))
                    {
                        IRequestResponseChannel channel = CreateConnection(secondary.Address.IpAddress.ToString(),
                                                                           secondary.Address.Port);
                        //channel.IsAuthenticated = Authenticate(_shardInfo.Primary.Address.IpAddress.ToString(), _shardInfo.Primary.Address.Port);
                        _secondaryChannels.Add(key, channel);
                        serversAdded.Add(new Server(secondary.Address, Status.Running));
                    }
                }
            }

            var secondariesRemoved =
                from existingSecondary in _secondaryChannels.Keys
                where
                !shardInfo.Secondaries.Any(
                    newSecondary => ConvertToKey(newSecondary.Address).Equals(existingSecondary))
                select existingSecondary;

            foreach (var removedChannel in secondariesRemoved)
            {
                lock (_secondaryChannels)
                {
                    _secondaryChannels[removedChannel].Disconnect();
                    _secondaryChannels.Remove(removedChannel);
                }
            }
            _shardInfo = shardInfo;
            return(serversAdded);
        }
示例#28
0
        //public HttpWebRequest DownloadRequest(long instart, long inend, File file, ShardInfo shard)
        //{
        //    string url = $"{_downloadServer.Value.Url}{Uri.EscapeDataString(file.FullPath)}?token={Authent.AccessToken}&client_id={HttpSettings.ClientId}";

        //    var request = (HttpWebRequest)WebRequest.Create(url);

        //    request.Headers.Add("Accept-Ranges", "bytes");
        //    request.AddRange(instart, inend);
        //    request.Proxy = HttpSettings.Proxy;
        //    request.CookieContainer = Authent.Cookies;
        //    request.Method = "GET";
        //    request.ContentType = MediaTypeNames.Application.Octet;
        //    request.Accept = "*/*";
        //    request.UserAgent = HttpSettings.UserAgent;
        //    request.AllowReadStreamBuffering = false;

        //    request.Timeout = 15 * 1000;

        //    return request;
        //}


        public void BanShardInfo(ShardInfo banShard)
        {
            //TODO: implement
            Logger.Warn($"{nameof(MobileRequestRepo)}.{nameof(BanShardInfo)} not implemented");
        }
示例#29
0
        public async Task <ResponseResult> UploadShard(ShardInfo shard)
        {
            await _fileService.SaveShard(shard);

            return(new ResponseResult());
        }