diff --git a/database.cc b/database.cc index b2e226f978..11ba21eebf 100644 --- a/database.cc +++ b/database.cc @@ -1471,6 +1471,18 @@ database::query_mutations(const query::read_command& cmd, const query::partition } } +std::unordered_set database::get_initial_tokens() { + std::unordered_set tokens; + sstring tokens_string = get_config().initial_token(); + try { + boost::split(tokens, tokens_string, boost::is_any_of(sstring(","))); + } catch (...) { + throw std::runtime_error(sprint("Unable to parse initial_token=%s", tokens_string)); + } + tokens.erase(""); + return tokens; +} + std::ostream& operator<<(std::ostream& out, const atomic_cell_or_collection& c) { return out << to_hex(c._data); } diff --git a/database.hh b/database.hh index 711f6d8de8..8c351f559d 100644 --- a/database.hh +++ b/database.hh @@ -633,6 +633,8 @@ public: const logalloc::region_group& dirty_memory_region_group() const { return _dirty_memory_region_group; } + + std::unordered_set get_initial_tokens(); }; // FIXME: stub diff --git a/db/config.hh b/db/config.hh index 3fe7a2abb2..a30343c534 100644 --- a/db/config.hh +++ b/db/config.hh @@ -406,7 +406,7 @@ public: "The IP address a node tells other nodes in the cluster to contact it by. It allows public and private address to be different. For example, use the broadcast_address parameter in topologies where not all nodes have access to other nodes by their private IP addresses.\n" \ "If your Cassandra cluster is deployed across multiple Amazon EC2 regions and you use the EC2MultiRegionSnitch , set the broadcast_address to public IP address of the node and the listen_address to the private IP." \ ) \ - val(initial_token, sstring, /* N/A */, Unused, \ + val(initial_token, sstring, /* N/A */, Used, \ "Used in the single-node-per-token architecture, where a node owns exactly one contiguous range in the ring space. Setting this property overrides num_tokens.\n" \ "If you not using vnodes or have num_tokens set it to 1 or unspecified (#num_tokens), you should always specify this parameter when setting up a production cluster for the first time and when adding capacity. For more information, see this parameter in the Cassandra 1.1 Node and Cluster Configuration documentation.\n" \ "This parameter can be used with num_tokens (vnodes ) in special cases such as Restoring from a snapshot." \ diff --git a/dht/boot_strapper.cc b/dht/boot_strapper.cc index a940c8fedf..3e9275912a 100644 --- a/dht/boot_strapper.cc +++ b/dht/boot_strapper.cc @@ -71,33 +71,33 @@ future<> boot_strapper::bootstrap() { } std::unordered_set boot_strapper::get_bootstrap_tokens(token_metadata metadata, database& db) { -#if 0 - Collection initialTokens = DatabaseDescriptor.getInitialTokens(); + auto initial_tokens = db.get_initial_tokens(); // if user specified tokens, use those - if (initialTokens.size() > 0) - { - logger.debug("tokens manually specified as {}", initialTokens); - List tokens = new ArrayList(initialTokens.size()); - for (String tokenString : initialTokens) - { - Token token = StorageService.getPartitioner().getTokenFactory().fromString(tokenString); - if (metadata.getEndpoint(token) != null) - throw new ConfigurationException("Bootstrapping to existing token " + tokenString + " is not allowed (decommission/removenode the old node first)."); - tokens.add(token); + if (initial_tokens.size() > 0) { + logger.debug("tokens manually specified as {}", initial_tokens); + std::unordered_set tokens; + for (auto& token_string : initial_tokens) { + auto token = dht::global_partitioner().from_sstring(token_string); + if (metadata.get_endpoint(token)) { + throw std::runtime_error(sprint("Bootstrapping to existing token %s is not allowed (decommission/removenode the old node first).", token_string)); + } + tokens.insert(token); } + logger.debug("Get manually specified bootstrap_tokens={}", tokens); return tokens; } -#endif + size_t num_tokens = db.get_config().num_tokens(); if (num_tokens < 1) { throw std::runtime_error("num_tokens must be >= 1"); } - // if (numTokens == 1) - // logger.warn("Picking random token for a single vnode. You should probably add more vnodes; failing that, you should probably specify the token manually"); + if (num_tokens == 1) { + logger.warn("Picking random token for a single vnode. You should probably add more vnodes; failing that, you should probably specify the token manually"); + } auto tokens = get_random_tokens(metadata, num_tokens); - logger.debug("Get bootstrap_tokens={}", tokens); + logger.debug("Get random bootstrap_tokens={}", tokens); return tokens; } diff --git a/dht/murmur3_partitioner.cc b/dht/murmur3_partitioner.cc index 1b3f2fb505..a9744e3a05 100644 --- a/dht/murmur3_partitioner.cc +++ b/dht/murmur3_partitioner.cc @@ -75,6 +75,9 @@ token murmur3_partitioner::get_random_token() { } inline int64_t long_token(const token& t) { + if (t.is_minimum()) { + return std::numeric_limits::min(); + } if (t._data.size() != sizeof(int64_t)) { throw runtime_exception(sprint("Invalid token. Should have size %ld, has size %ld\n", sizeof(int64_t), t._data.size())); diff --git a/service/storage_service.cc b/service/storage_service.cc index 0d7a4affe4..49cc758dec 100644 --- a/service/storage_service.cc +++ b/service/storage_service.cc @@ -115,11 +115,6 @@ std::experimental::optional get_replace_address() { return {}; } -std::unordered_set get_initial_tokens() { - // FIXME: DatabaseDescriptor.getInitialTokens(); - return std::unordered_set(); -} - bool get_property_join_ring() { // FIXME: Boolean.parseBoolean(System.getProperty("cassandra.join_ring", "true"))) return true; @@ -313,7 +308,7 @@ void storage_service::join_token_ring(int delay) { size_t num_tokens = _db.local().get_config().num_tokens(); _bootstrap_tokens = db::system_keyspace::get_saved_tokens().get0(); if (_bootstrap_tokens.empty()) { - auto initial_tokens = get_initial_tokens(); + auto initial_tokens = _db.local().get_initial_tokens(); if (initial_tokens.size() < 1) { _bootstrap_tokens = boot_strapper::get_random_tokens(_token_metadata, num_tokens); if (num_tokens == 1) {