Merge branch 'cassandra-2.0' into cassandra-2.1

This commit is contained in:
Robert Stupp 2015-05-14 10:37:22 +02:00
commit 5e631a8fda
3 changed files with 73 additions and 15 deletions

View File

@ -23,6 +23,7 @@
* Repair waits for anticompaction to finish (CASSANDRA-9097)
* Fix streaming not holding ref when stream error (CASSANDRA-9295)
Merged from 2.0:
* token-generator - generated tokens too long (CASSANDRA-9300)
* Fix counting of tombstones for TombstoneOverwhelmingException (CASSANDRA-9299)
* Fix ReconnectableSnitch reconnecting to peers during upgrade (CASSANDRA-6702)
* Include keyspace and table name in error log for collections over the size

View File

@ -30,24 +30,38 @@ from tempfile import NamedTemporaryFile
description = '''Given a list of numbers indicating the number of nodes
in each separate datacenter, outputs a recommended list of tokens to use
with RandomPartitioner: one for each node in each datacenter.
with Murmur3Partitioner (by default) or with RandomPartitioner.
The list contains one token for each node in each datacenter.
'''
usage = "%prog <nodes_in_dc1> [<nodes_in_dc2> [...]]"
parser = optparse.OptionParser(description=description, usage=usage)
def part_murmur3(option, opt, value, parser):
parser.values.ringoffset=-(1<<63)
parser.values.ringrange=(1<<64)
return
def part_random(option, opt, value, parser):
parser.values.ringoffset=0
parser.values.ringrange=(1<<127)
return
parser.add_option('--murmur3', action='callback', callback=part_murmur3,
help='Generate tokens for Murmur3Partitioner (default).')
parser.add_option('--random', action='callback', callback=part_random,
help='Generate tokens for RandomPartitioner.')
parser.add_option('--ringoffset', type='int',
help=optparse.SUPPRESS_HELP)
parser.add_option('--ringrange', type='int',
help='Specify a numeric maximum token value for your ring, '
'different from the default value of 2^127.')
help=optparse.SUPPRESS_HELP)
parser.add_option('--graph', action='store_true',
help='Show a rendering of the generated tokens as line '
'segments in a circle, colored according to datacenter')
parser.add_option('-n', '--nts', action='store_const', dest='strat', const='nts',
help='Optimize multi-cluster distribution for '
'NetworkTopologyStrategy [default]')
help=optparse.SUPPRESS_HELP)
parser.add_option('-o', '--onts', action='store_const', dest='strat', const='onts',
help='Optimize multi-cluster distribution for '
'OldNetworkTopologyStrategy')
help=optparse.SUPPRESS_HELP)
parser.add_option('--test', action='store_true',
help='Run in test mode, outputting an HTML file to display '
@ -58,8 +72,11 @@ parser.add_option('--browser-wait-time', type='float', help=optparse.SUPPRESS_HE
parser.add_option('--test-colors', help=optparse.SUPPRESS_HELP)
parser.add_option('--test-graphsize', type='int', help=optparse.SUPPRESS_HELP)
parser.set_defaults(
ringrange=(1<<127),
# default is Murmur3
ringoffset=-(1<<63),
ringrange=(1<<64),
# whether to create (and try to display) graph output
graph=False,
@ -94,7 +111,8 @@ class Ring:
MIN_DC_OFFSET_DIVIDER = 235
offset_spacer = 2
def __init__(self, dc_counts, ringrange, strategy='nts'):
def __init__(self, dc_counts, ringoffset, ringrange, strategy='nts'):
self.ringoffset = ringoffset
self.ringrange = ringrange
self.dc_counts = dc_counts
self.calculate_offset_tokens = getattr(self, 'calc_offset_tokens_' + strategy)
@ -110,13 +128,18 @@ class Ring:
division = max(lowest_division, self.MIN_DC_OFFSET_DIVIDER)
return -self.ringrange // division
def bound_token(self, tok):
if tok < self.ringoffset:
tok += self.ringrange
return tok
def calc_offset_tokens_nts(self):
dc_offset = self.best_per_dc_offset()
dcs = []
for (dcnum, dccount) in enumerate(self.dc_counts):
offset = dcnum * dc_offset
arcsize = self.ringrange // (dccount or 1)
dcs.append([(n * arcsize + offset) % self.ringrange for n in xrange(dccount)])
dcs.append(sorted([self.bound_token((n * arcsize + offset) - self.ringoffset % self.ringrange) for n in xrange(dccount)]))
return dcs
def calc_offset_tokens_onts(self):
@ -127,7 +150,7 @@ class Ring:
final = [[] for x in dcs_by_count]
for pos, dc in enumerate(layout):
final[dc].append(pos * self.ringrange // len(layout))
final[dc].append(self.ringoffset + pos * self.ringrange // len(layout))
return final
@ -139,8 +162,8 @@ def print_tokens(tokens, tokenwidth, indent=0):
for tnum, tok in enumerate(toklist):
print "%s Node #%0*d: % *d" % (indentstr, nwidth, tnum + 1, tokenwidth, tok)
def calculate_ideal_tokens(datacenters, ringrange, strategy):
return Ring(datacenters, ringrange, strategy).calculate_offset_tokens()
def calculate_ideal_tokens(datacenters, ringoffset, ringrange, strategy):
return Ring(datacenters, ringoffset, ringrange, strategy).calculate_offset_tokens()
def file_to_url(path):
path = os.path.abspath(path)
@ -248,7 +271,7 @@ def run_tests(opts):
tokensets = []
for test in tests:
print "Test %r" % (test,)
tokens = calculate_ideal_tokens(test, opts.ringrange, opts.strat)
tokens = calculate_ideal_tokens(test, opts.ringoffset, opts.ringrange, opts.strat)
print_tokens(tokens, len(str(opts.ringrange)) + 1, indent=2)
tokensets.append(tokens)
return tokensets
@ -315,7 +338,7 @@ def main(opts, args):
parser.error('Arguments should be integers.')
renderer = RingRenderer(ringrange=opts.ringrange, graphsize=opts.graphsize,
colors=opts.colorlist)
tokens = calculate_ideal_tokens(datacenters, opts.ringrange, opts.strat)
tokens = calculate_ideal_tokens(datacenters, opts.ringoffset, opts.ringrange, opts.strat)
print_tokens(tokens, len(str(opts.ringrange)) + 1)
tokensets = [tokens]

View File

@ -0,0 +1,34 @@
@ECHO OFF
@REM
@REM Licensed to the Apache Software Foundation (ASF) under one or more
@REM contributor license agreements. See the NOTICE file distributed with
@REM this work for additional information regarding copyright ownership.
@REM The ASF licenses this file to You under the Apache License, Version 2.0
@REM (the "License"); you may not use this file except in compliance with
@REM the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing, software
@REM distributed under the License is distributed on an "AS IS" BASIS,
@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@REM See the License for the specific language governing permissions and
@REM limitations under the License.
@echo off
if "%OS%" == "Windows_NT" setlocal
python -V >nul 2>&1
if ERRORLEVEL 1 goto err
python "%~dp0\token-generator" %*
goto finally
:err
echo Can't detect Python version!
:finally
ENDLOCAL