예제 #1
0
 public override void Start0()
 {
     /*
      * We will start hazelcast in its own thread. Hazelcast blocks until the minimum cluster size is available
      * and during that block it ignores interrupts. This blocks the whole startup process and since it is the
      * main thread that controls lifecycle and the main thread is not daemon, it will block ignoring signals
      * and any shutdown attempts. The solution is to start hazelcast instance creation in its own thread which
      * we set as daemon. All subsequent uses of hazelcastInstance in this class will still block on it being
      * available (see waitOnHazelcastInstanceCreation() ) but they do so while checking for interrupt and
      * exiting if one happens. This provides us with a way to exit before hazelcastInstance creation completes.
      */
     _startingThread = new Thread(() =>
     {
         Log.info("Cluster discovery service starting");
         _hazelcastInstance = CreateHazelcastInstance();
         // We may be interrupted by the stop method after hazelcast returns. This is courtesy and not really
         // necessary
         if (Thread.CurrentThread.Interrupted)
         {
             return;
         }
         _refreshJob = _scheduler.scheduleRecurring(Group.HZ_TOPOLOGY_REFRESH, _refreshPeriod, HazelcastCoreTopologyService.this.refreshTopology);
         Log.info("Cluster discovery service started");
     });
     _startingThread.Daemon = true;
     _startingThread.Name   = "HZ Starting Thread";
     _startingThread.Start();
 }
예제 #2
0
        internal static IDictionary <MemberId, ReadReplicaInfo> ReadReplicas(HazelcastInstance hazelcastInstance, Log log)
        {
            Pair <ISet <string>, IDictionary <string, IMap <string, string> > > validatedSimpleAttrMaps = validatedSimpleAttrMaps(hazelcastInstance);
            ISet <string> missingAttrKeys = validatedSimpleAttrMaps.First();
            IDictionary <string, IMap <string, string> > simpleAttrMaps = validatedSimpleAttrMaps.Other();

            MultiMap <string, string> serverGroupsMap = hazelcastInstance.getMultiMap(SERVER_GROUPS_MULTIMAP);

            if (serverGroupsMap == null)
            {
                missingAttrKeys.Add(SERVER_GROUPS_MULTIMAP);
            }

            if (missingAttrKeys.Count > 0)
            {
                // We might well not have any read replicas, in which case missing maps is not an error, but we *can't* have some maps and not others
//JAVA TO C# CONVERTER TODO TASK: There is no .NET equivalent to the java.util.Collection 'containsAll' method:
                bool missingAllKeys = missingAttrKeys.containsAll(RrAttrKeys) && missingAttrKeys.Contains(SERVER_GROUPS_MULTIMAP);
                if (!missingAllKeys)
                {
                    string missingAttrs = string.join(", ", missingAttrKeys);
                    log.Warn("Some, but not all, of the read replica attribute maps are null, including %s", missingAttrs);
                }

                return(emptyMap());
            }

            Stream <string> readReplicaHzIds = simpleAttrMaps[READ_REPLICA_BOLT_ADDRESS_MAP].Keys.stream();

//JAVA TO C# CONVERTER TODO TASK: Method reference arbitrary object instance method syntax is not converted by Java to C# Converter:
            IDictionary <MemberId, ReadReplicaInfo> validatedReadReplicas = readReplicaHzIds.flatMap(hzId => Streams.ofNullable(BuildReadReplicaFromAttrMap(hzId, simpleAttrMaps, serverGroupsMap, log))).collect(Collectors.toMap(Pair::first, Pair::other));

            return(validatedReadReplicas);
        }
예제 #3
0
        internal static void CasLeaders(HazelcastInstance hazelcastInstance, LeaderInfo leaderInfo, string dbName, Log log)
        {
            IAtomicReference <LeaderInfo> leaderRef = hazelcastInstance.getAtomicReference(DB_NAME_LEADER_TERM_PREFIX + dbName);

            LeaderInfo            current    = leaderRef.get();
            Optional <LeaderInfo> currentOpt = Optional.ofNullable(current);

//JAVA TO C# CONVERTER TODO TASK: Method reference arbitrary object instance method syntax is not converted by Java to C# Converter:
            bool sameLeader = currentOpt.map(LeaderInfo::memberId).Equals(Optional.ofNullable(leaderInfo.MemberId()));

            int termComparison = currentOpt.map(l => Long.compare(l.term(), leaderInfo.Term())).orElse(-1);

            bool greaterTermExists = termComparison > 0;

            bool sameTermButNoStepdown = termComparison == 0 && !leaderInfo.SteppingDown;

            if (sameLeader || greaterTermExists || sameTermButNoStepdown)
            {
                return;
            }

            bool success = leaderRef.compareAndSet(current, leaderInfo);

            if (!success)
            {
                log.Warn("Fail to set new leader info: %s. Latest leader info: %s.", leaderInfo, leaderRef.get());
            }
        }
예제 #4
0
        internal static bool CasClusterId(HazelcastInstance hazelcastInstance, ClusterId clusterId, string dbName)
        {
            IMap <string, System.Guid> uuidPerDbCluster = hazelcastInstance.getMap(CLUSTER_UUID_DB_NAME_MAP);

            System.Guid uuid = uuidPerDbCluster.putIfAbsent(dbName, clusterId.Uuid());
            return(uuid == null || clusterId.Uuid().Equals(uuid));
        }
예제 #5
0
        private static ClusterId GetClusterId(HazelcastInstance hazelcastInstance, string dbName)
        {
            IMap <string, System.Guid> uuidPerDbCluster = hazelcastInstance.getMap(CLUSTER_UUID_DB_NAME_MAP);

            System.Guid uuid = uuidPerDbCluster.get(dbName);
            return(uuid != null ? new ClusterId(uuid) : null);
        }
예제 #6
0
        public static IDictionary <MemberId, RoleInfo> GetCoreRoles(HazelcastInstance hazelcastInstance, ISet <MemberId> coreMembers)
        {
            ISet <string> dbNames = GetDBNames(hazelcastInstance);
//JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter:
            ISet <MemberId> allLeaders = dbNames.Select(n => GetLeaderForDBName(hazelcastInstance, n)).Where(Optional.isPresent).Select(l => l.get().memberId()).collect(Collectors.toSet());

            System.Func <MemberId, RoleInfo> roleMapper = m => allLeaders.Contains(m) ? RoleInfo.Leader : RoleInfo.Follower;

            return(coreMembers.ToDictionary(System.Func.identity(), roleMapper));
        }
예제 #7
0
        internal static void RefreshGroups(HazelcastInstance hazelcastInstance, string memberId, IList <string> groups)
        {
            MultiMap <string, string> groupsMap = hazelcastInstance.getMultiMap(SERVER_GROUPS_MULTIMAP);
            ICollection <string>      existing  = groupsMap.get(memberId);

//JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter:
            ISet <string> superfluous = existing.Where(t => !groups.Contains(t)).collect(Collectors.toSet());
//JAVA TO C# CONVERTER TODO TASK: Most Java stream collectors are not converted by Java to C# Converter:
            ISet <string> missing = groups.Where(t => !existing.Contains(t)).collect(Collectors.toSet());

            missing.forEach(group => groupsMap.put(memberId, group));
            superfluous.forEach(group => groupsMap.remove(memberId, group));
        }
예제 #8
0
        private static bool CanBeBootstrapped(HazelcastInstance hazelcastInstance, Config config)
        {
            ISet <Member> members = hazelcastInstance.Cluster.Members;
            string        dbName  = config.Get(CausalClusteringSettings.database);

            System.Predicate <Member> acceptsToBeLeader = m => !m.getBooleanAttribute(REFUSE_TO_BE_LEADER_KEY);
            System.Predicate <Member> hostsMyDb         = m => dbName.Equals(m.getStringAttribute(MEMBER_DB_NAME));

            Stream <Member> membersWhoCanLeadForMyDb = members.Where(acceptsToBeLeader).Where(hostsMyDb);

            Optional <Member> firstAppropriateMember = membersWhoCanLeadForMyDb.findFirst();

            return(firstAppropriateMember.map(Member.localMember).orElse(false));
        }
예제 #9
0
        internal static ReadReplicaTopology GetReadReplicaTopology(HazelcastInstance hazelcastInstance, Log log)
        {
            IDictionary <MemberId, ReadReplicaInfo> readReplicas = emptyMap();

            if (hazelcastInstance != null)
            {
                readReplicas = readReplicas(hazelcastInstance, log);
            }
            else
            {
                log.Info("Cannot currently bind to distributed discovery service.");
            }

            return(new ReadReplicaTopology(readReplicas));
        }
예제 #10
0
        internal static CoreTopology GetCoreTopology(HazelcastInstance hazelcastInstance, Config config, Log log)
        {
            IDictionary <MemberId, CoreServerInfo> coreMembers = emptyMap();
            bool      canBeBootstrapped = false;
            ClusterId clusterId         = null;
            string    dbName            = config.Get(CausalClusteringSettings.database);

            if (hazelcastInstance != null)
            {
                ISet <Member> hzMembers = hazelcastInstance.Cluster.Members;
                canBeBootstrapped = canBeBootstrapped(hazelcastInstance, config);

                coreMembers = ToCoreMemberMap(hzMembers, log, hazelcastInstance);

                clusterId = GetClusterId(hazelcastInstance, dbName);
            }
            else
            {
                log.Info("Cannot currently bind to distributed discovery service.");
            }

            return(new CoreTopology(clusterId, canBeBootstrapped, coreMembers));
        }
예제 #11
0
        private HazelcastInstance CreateHazelcastInstance()
        {
            JoinConfig joinConfig = new JoinConfig();

            joinConfig.MulticastConfig.Enabled = false;
            TcpIpConfig tcpIpConfig = joinConfig.TcpIpConfig;

            tcpIpConfig.Enabled = true;

//JAVA TO C# CONVERTER TODO TASK: Method reference arbitrary object instance method syntax is not converted by Java to C# Converter:
            ICollection <string> initialMembers = _remoteMembersResolver.resolve(SocketAddress::toString);

            initialMembers.forEach(tcpIpConfig.addMember);

            ListenSocketAddress hazelcastAddress = Config.get(discovery_listen_address);
            NetworkConfig       networkConfig    = new NetworkConfig();

            if (!hazelcastAddress.Wildcard)
            {
                InterfacesConfig interfaces = new InterfacesConfig();
                interfaces.addInterface(hazelcastAddress.Hostname);
                interfaces.Enabled       = true;
                networkConfig.Interfaces = interfaces;
            }

            networkConfig.Port = hazelcastAddress.Port;
            networkConfig.Join = joinConfig;
            networkConfig.PortAutoIncrement = false;

            // We'll use election_timeout as a base value to calculate HZ timeouts. We multiply by 1.5
            long?electionTimeoutMillis      = Config.get(CausalClusteringSettings.leader_election_timeout).toMillis();
            long?baseHazelcastTimeoutMillis = (3 * electionTimeoutMillis) / 2;

            /*
             * Some HZ settings require the value in seconds. Adding the divider and subtracting 1 is equivalent to the
             * ceiling function for integers ( Math.ceil() returns double ). Anything < 0 will return 0, any
             * multiple of 1000 returns the result of the division by 1000, any non multiple of 1000 returns the result
             * of the division + 1. In other words, values in millis are rounded up.
             */
            long baseHazelcastTimeoutSeconds = (baseHazelcastTimeoutMillis + 1000 - 1) / 1000;

            com.hazelcast.config.Config c = new com.hazelcast.config.Config();
            c.setProperty(OPERATION_CALL_TIMEOUT_MILLIS.Name, baseHazelcastTimeoutMillis.ToString());
            c.setProperty(MERGE_NEXT_RUN_DELAY_SECONDS.Name, baseHazelcastTimeoutSeconds.ToString());
            c.setProperty(MERGE_FIRST_RUN_DELAY_SECONDS.Name, baseHazelcastTimeoutSeconds.ToString());
            c.setProperty(INITIAL_MIN_CLUSTER_SIZE.Name, HAZELCAST_MIN_CLUSTER.ToString());

            if (Config.get(disable_middleware_logging))
            {
                c.setProperty(LOGGING_TYPE.Name, "none");
            }

            if (hazelcastAddress.IPv6)
            {
                c.setProperty(PREFER_IPv4_STACK.Name, "false");
            }

            c.NetworkConfig = networkConfig;

            MemberAttributeConfig memberAttributeConfig = HazelcastClusterTopology.BuildMemberAttributesForCore(MyselfConflict, Config);

            c.MemberAttributeConfig = memberAttributeConfig;
            LogConnectionInfo(initialMembers);
            c.addListenerConfig(new ListenerConfig(new OurMembershipListener(this)));

            JobHandle logJob = _scheduler.schedule(Group.HZ_TOPOLOGY_HEALTH, _hazelcastIsHealthyTimeoutMs, () => Log.warn("The server has not been able to connect in a timely fashion to the " + "cluster. Please consult the logs for more details. Rebooting the server may " + "solve the problem."));

            try
            {
                _hazelcastInstance = Hazelcast.newHazelcastInstance(c);
                logJob.Cancel(true);
            }
            catch (HazelcastException e)
            {
                string errorMessage = string.Format("Hazelcast was unable to start with setting: {0} = {1}", discovery_listen_address.name(), Config.get(discovery_listen_address));
                UserLog.error(errorMessage);
                Log.error(errorMessage, e);
                throw new Exception(e);
            }

            IList <string> groups = Config.get(CausalClusteringSettings.server_groups);

            refreshGroups(_hazelcastInstance, MyselfConflict.Uuid.ToString(), groups);

            return(_hazelcastInstance);
        }
예제 #12
0
        internal static IDictionary <MemberId, CoreServerInfo> ToCoreMemberMap(ISet <Member> members, Log log, HazelcastInstance hazelcastInstance)
        {
            IDictionary <MemberId, CoreServerInfo> coreMembers = new Dictionary <MemberId, CoreServerInfo>();
            MultiMap <string, string> serverGroupsMMap         = hazelcastInstance.getMultiMap(SERVER_GROUPS_MULTIMAP);

            foreach (Member member in members)
            {
                IDictionary <string, string> attrMap = new Dictionary <string, string>();
                bool incomplete = false;
                foreach (string attrKey in CoreAttrKeys)
                {
                    string attrValue = member.getStringAttribute(attrKey);
                    if (string.ReferenceEquals(attrValue, null))
                    {
                        log.Warn("Missing member attribute '%s' for member %s", attrKey, member);
                        incomplete = true;
                    }
                    else
                    {
                        attrMap[attrKey] = attrValue;
                    }
                }

                if (incomplete)
                {
                    continue;
                }

//JAVA TO C# CONVERTER TODO TASK: Method reference constructor syntax is not converted by Java to C# Converter:
                CoreServerInfo coreServerInfo = new CoreServerInfo(socketAddress(attrMap[RAFT_SERVER], AdvertisedSocketAddress::new), socketAddress(attrMap[TRANSACTION_SERVER], AdvertisedSocketAddress::new), ClientConnectorAddresses.FromString(attrMap[CLIENT_CONNECTOR_ADDRESSES]), asSet(serverGroupsMMap.get(attrMap[MEMBER_UUID])), attrMap[MEMBER_DB_NAME], member.getBooleanAttribute(REFUSE_TO_BE_LEADER_KEY));

                MemberId memberId = new MemberId(System.Guid.Parse(attrMap[MEMBER_UUID]));
                coreMembers[memberId] = coreServerInfo;
            }

            return(coreMembers);
        }
예제 #13
0
        private static Optional <LeaderInfo> GetLeaderForDBName(HazelcastInstance hazelcastInstance, string dbName)
        {
            IAtomicReference <LeaderInfo> leader = hazelcastInstance.getAtomicReference(DB_NAME_LEADER_TERM_PREFIX + dbName);

            return(Optional.ofNullable(leader.get()));
        }
예제 #14
0
        /// <summary>
        /// Retrieves the various maps containing attributes about read replicas from hazelcast. If any maps do not exist, keep track of their keys for logging.
        /// </summary>
        private static Pair <ISet <string>, IDictionary <string, IMap <string, string> > > ValidatedSimpleAttrMaps(HazelcastInstance hazelcastInstance)
        {
            ISet <string> missingAttrKeys = new HashSet <string>();
            IDictionary <string, IMap <string, string> > validatedSimpleAttrMaps = new Dictionary <string, IMap <string, string> >();

            foreach (string attrMapKey in RrAttrKeys)
            {
                IMap <string, string> attrMap = hazelcastInstance.getMap(attrMapKey);
                if (attrMap == null)
                {
                    missingAttrKeys.Add(attrMapKey);
                }
                else
                {
                    validatedSimpleAttrMaps[attrMapKey] = attrMap;
                }
            }

            return(Pair.of(missingAttrKeys, validatedSimpleAttrMaps));
        }
예제 #15
0
        private static ISet <string> GetDBNames(HazelcastInstance hazelcastInstance)
        {
            IMap <string, System.Guid> uuidPerDbCluster = hazelcastInstance.getMap(CLUSTER_UUID_DB_NAME_MAP);

            return(uuidPerDbCluster.Keys);
        }