Remove Windows-specific classes and related code

patch by Stefan Miklosovic; reviewed by Joshua McKenzie, Bowen Song, Berenguer Blasi for CASSANDRA-16956
This commit is contained in:
Stefan Miklosovic 2022-02-05 15:41:33 +01:00
parent 28eea6e8cd
commit da47849b50
53 changed files with 80 additions and 953 deletions

View File

@ -223,9 +223,6 @@
<url url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-freebsd-6.so"/> <url url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-freebsd-6.so"/>
<url url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-linux.so"/> <url url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-linux.so"/>
<url url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-solaris.so"/> <url url="${lib.download.base.url}/lib/sigar-bin/libsigar-x86-solaris.so"/>
<url url="${lib.download.base.url}/lib/sigar-bin/sigar-amd64-winnt.dll"/>
<url url="${lib.download.base.url}/lib/sigar-bin/sigar-x86-winnt.dll"/>
<url url="${lib.download.base.url}/lib/sigar-bin/sigar-x86-winnt.lib"/>
</get> </get>
<copy todir="${build.lib}" quiet="true"> <copy todir="${build.lib}" quiet="true">
@ -254,9 +251,6 @@
<file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-freebsd-6.so"/> <file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-freebsd-6.so"/>
<file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-linux.so"/> <file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-linux.so"/>
<file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-solaris.so"/> <file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/libsigar-x86-solaris.so"/>
<file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/sigar-amd64-winnt.dll"/>
<file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/sigar-x86-winnt.dll"/>
<file file="${local.repository}/org/apache/cassandra/deps/sigar-bin/sigar-x86-winnt.lib"/>
</copy> </copy>
</target> </target>
</project> </project>

View File

@ -1,4 +1,5 @@
4.1 4.1
* Remove support for Windows (CASSANDRA-16956)
* Runtime-configurable YAML option to prohibit USE statements (CASSANDRA-17318) * Runtime-configurable YAML option to prohibit USE statements (CASSANDRA-17318)
* When streaming sees a ClosedChannelException this triggers the disk failure policy (CASSANDRA-17116) * When streaming sees a ClosedChannelException this triggers the disk failure policy (CASSANDRA-17116)
* Add a virtual table for exposing prepared statements metrics (CASSANDRA-17224) * Add a virtual table for exposing prepared statements metrics (CASSANDRA-17224)

View File

@ -119,14 +119,6 @@ if [ -z "$CASSANDRA_LOG_DIR" ]; then
CASSANDRA_LOG_DIR=$CASSANDRA_HOME/logs CASSANDRA_LOG_DIR=$CASSANDRA_HOME/logs
fi fi
# Special-case path variables.
case "`uname`" in
CYGWIN*|MINGW*)
CLASSPATH=`cygpath -p -w "$CLASSPATH"`
CASSANDRA_CONF=`cygpath -p -w "$CASSANDRA_CONF"`
;;
esac
# Cassandra uses an installed jemalloc via LD_PRELOAD / DYLD_INSERT_LIBRARIES by default to improve off-heap # Cassandra uses an installed jemalloc via LD_PRELOAD / DYLD_INSERT_LIBRARIES by default to improve off-heap
# memory allocation performance. The following code searches for an installed libjemalloc.dylib/.so/.1.so using # memory allocation performance. The following code searches for an installed libjemalloc.dylib/.so/.1.so using
# Linux and OS-X specific approaches. # Linux and OS-X specific approaches.

View File

@ -28,6 +28,7 @@ import os
import platform import platform
import re import re
import stat import stat
import subprocess
import sys import sys
import traceback import traceback
import warnings import warnings
@ -44,7 +45,6 @@ if platform.python_implementation().startswith('Jython'):
sys.exit("\nCQL Shell does not run on Jython\n") sys.exit("\nCQL Shell does not run on Jython\n")
UTF8 = 'utf-8' UTF8 = 'utf-8'
CP65001 = 'cp65001' # Win utf-8 variant
description = "CQL Shell for Apache Cassandra" description = "CQL Shell for Apache Cassandra"
version = "6.0.0" version = "6.0.0"
@ -92,14 +92,8 @@ if webbrowser._tryorder and webbrowser._tryorder[0] == 'xdg-open' and os.environ
# use bundled lib for python-cql if available. if there # use bundled lib for python-cql if available. if there
# is a ../lib dir, use bundled libs there preferentially. # is a ../lib dir, use bundled libs there preferentially.
ZIPLIB_DIRS = [os.path.join(CASSANDRA_PATH, 'lib')] ZIPLIB_DIRS = [os.path.join(CASSANDRA_PATH, 'lib')]
myplatform = platform.system()
is_win = myplatform == 'Windows'
# Workaround for supporting CP65001 encoding on python < 3.3 (https://bugs.python.org/issue13216) if platform.system() == 'Linux':
if is_win and sys.version_info < (3, 3):
codecs.register(lambda name: codecs.lookup(UTF8) if name == CP65001 else None)
if myplatform == 'Linux':
ZIPLIB_DIRS.append('/usr/share/cassandra/lib') ZIPLIB_DIRS.append('/usr/share/cassandra/lib')
if os.environ.get('CQLSH_NO_BUNDLED', ''): if os.environ.get('CQLSH_NO_BUNDLED', ''):
@ -211,7 +205,7 @@ parser.add_option('--debug', action='store_true',
parser.add_option('--coverage', action='store_true', parser.add_option('--coverage', action='store_true',
help='Collect coverage data') help='Collect coverage data')
parser.add_option("--encoding", help="Specify a non-default encoding for output." parser.add_option("--encoding", help="Specify a non-default encoding for output."
" (Default: %s)" % (UTF8,)) + " (Default: %s)" % (UTF8,))
parser.add_option("--cqlshrc", help="Specify an alternative cqlshrc file location.") parser.add_option("--cqlshrc", help="Specify an alternative cqlshrc file location.")
parser.add_option("--credentials", help="Specify an alternative credentials file location.") parser.add_option("--credentials", help="Specify an alternative credentials file location.")
parser.add_option('--cqlversion', default=None, parser.add_option('--cqlversion', default=None,
@ -261,9 +255,9 @@ OLD_CONFIG_FILE = os.path.expanduser(os.path.join('~', '.cqlshrc'))
if os.path.exists(OLD_CONFIG_FILE): if os.path.exists(OLD_CONFIG_FILE):
if os.path.exists(CONFIG_FILE): if os.path.exists(CONFIG_FILE):
print('\nWarning: cqlshrc config files were found at both the old location ({0})' print('\nWarning: cqlshrc config files were found at both the old location ({0})'
' and the new location ({1}), the old config file will not be migrated to the new' + ' and the new location ({1}), the old config file will not be migrated to the new'
' location, and the new location will be used for now. You should manually' + ' location, and the new location will be used for now. You should manually'
' consolidate the config files at the new location and remove the old file.' + ' consolidate the config files at the new location and remove the old file.'
.format(OLD_CONFIG_FILE, CONFIG_FILE)) .format(OLD_CONFIG_FILE, CONFIG_FILE))
else: else:
os.rename(OLD_CONFIG_FILE, CONFIG_FILE) os.rename(OLD_CONFIG_FILE, CONFIG_FILE)
@ -508,7 +502,6 @@ class Shell(cmd.Cmd):
self.tty = tty self.tty = tty
self.encoding = encoding self.encoding = encoding
self.check_windows_encoding()
self.output_codec = codecs.lookup(encoding) self.output_codec = codecs.lookup(encoding)
@ -543,15 +536,7 @@ class Shell(cmd.Cmd):
@property @property
def is_using_utf8(self): def is_using_utf8(self):
# utf8 encodings from https://docs.python.org/{2,3}/library/codecs.html # utf8 encodings from https://docs.python.org/{2,3}/library/codecs.html
return self.encoding.replace('-', '_').lower() in ['utf', 'utf_8', 'u8', 'utf8', CP65001] return self.encoding.replace('-', '_').lower() in ['utf', 'utf_8', 'u8', 'utf8']
def check_windows_encoding(self):
if is_win and os.name == 'nt' and self.tty and \
self.is_using_utf8 and sys.stdout.encoding != CP65001:
self.printerr("\nWARNING: console codepage must be set to cp65001 "
"to support {} encoding on Windows platforms.\n"
"If you experience encoding problems, change your console"
" codepage with 'chcp 65001' before starting cqlsh.\n".format(self.encoding))
def set_expanded_cql_version(self, ver): def set_expanded_cql_version(self, ver):
ver, vertuple = full_cql_version(ver) ver, vertuple = full_cql_version(ver)
@ -817,8 +802,6 @@ class Shell(cmd.Cmd):
try: try:
import readline import readline
except ImportError: except ImportError:
if is_win:
print("WARNING: pyreadline dependency missing. Install to enable tab completion.")
pass pass
else: else:
old_completer = readline.get_completer() old_completer = readline.get_completer()
@ -1886,8 +1869,7 @@ class Shell(cmd.Cmd):
Clears the console. Clears the console.
""" """
import subprocess subprocess.call('clear', shell=True)
subprocess.call(['clear', 'cls'][is_win], shell=True)
do_cls = do_clear do_cls = do_clear
def do_debug(self, parsed): def do_debug(self, parsed):
@ -2098,7 +2080,6 @@ def should_use_color():
if os.environ.get('TERM', '') in ('dumb', ''): if os.environ.get('TERM', '') in ('dumb', ''):
return False return False
try: try:
import subprocess
p = subprocess.Popen(['tput', 'colors'], stdout=subprocess.PIPE) p = subprocess.Popen(['tput', 'colors'], stdout=subprocess.PIPE)
stdout, _ = p.communicate() stdout, _ = p.communicate()
if int(stdout.strip()) < 8: if int(stdout.strip()) < 8:
@ -2111,11 +2092,6 @@ def should_use_color():
def is_file_secure(filename): def is_file_secure(filename):
if is_win:
# We simply cannot tell whether the file is seucre on Windows,
# because os.stat().st_uid is always 0 and os.stat().st_mode is meaningless
return True
try: try:
st = os.stat(filename) st = os.stat(filename)
except OSError as e: except OSError as e:
@ -2359,9 +2335,9 @@ def main(options, hostname, port):
# does contain a TZ part) was specified # does contain a TZ part) was specified
if options.time_format != DEFAULT_TIMESTAMP_FORMAT: if options.time_format != DEFAULT_TIMESTAMP_FORMAT:
sys.stderr.write("Warning: custom timestamp format specified in cqlshrc, " sys.stderr.write("Warning: custom timestamp format specified in cqlshrc, "
"but local timezone could not be detected.\n" + "but local timezone could not be detected.\n"
"Either install Python 'tzlocal' module for auto-detection " + "Either install Python 'tzlocal' module for auto-detection "
"or specify client timezone in your cqlshrc.\n\n") + "or specify client timezone in your cqlshrc.\n\n")
try: try:
shell = Shell(hostname, shell = Shell(hostname,
@ -2414,7 +2390,7 @@ def main(options, hostname, port):
# always call this regardless of module name: when a sub-process is spawned # always call this regardless of module name: when a sub-process is spawned
# on Windows then the module name is not __main__, see CASSANDRA-9304 # on Windows then the module name is not __main__, see CASSANDRA-9304 (Windows support was dropped in CASSANDRA-16956)
insert_driver_hooks() insert_driver_hooks()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -36,14 +36,6 @@ if [ -f "$CASSANDRA_CONF/cassandra-env.sh" ]; then
. "$CASSANDRA_CONF/cassandra-env.sh" . "$CASSANDRA_CONF/cassandra-env.sh"
fi fi
# Special-case path variables.
case "`uname`" in
CYGWIN*|MINGW*)
CLASSPATH="`cygpath -p -w "$CLASSPATH"`"
CASSANDRA_CONF="`cygpath -p -w "$CASSANDRA_CONF"`"
;;
esac
class="org.apache.cassandra.transport.Client" class="org.apache.cassandra.transport.Client"
cassandra_parms="-Dlogback.configurationFile=logback-tools.xml" cassandra_parms="-Dlogback.configurationFile=logback-tools.xml"
"$JAVA" $JVM_OPTS $cassandra_parms -cp "$CLASSPATH" "$class" $@ "$JAVA" $JVM_OPTS $cassandra_parms -cp "$CLASSPATH" "$class" $@

View File

@ -1319,14 +1319,6 @@ enable_user_defined_functions: false
# This option has no effect, if enable_user_defined_functions is false. # This option has no effect, if enable_user_defined_functions is false.
enable_scripted_user_defined_functions: false enable_scripted_user_defined_functions: false
# The default Windows kernel timer and scheduling resolution is 15.6ms for power conservation.
# Lowering this value on Windows can provide much tighter latency and better throughput, however
# some virtualized environments may see a negative performance impact from changing this setting
# below their system default. The sysinternals 'clockres' tool can confirm your system's default
# setting.
windows_timer_interval: 1
# Enables encrypting data at-rest (on disk). Different key providers can be plugged in, but the default reads from # Enables encrypting data at-rest (on disk). Different key providers can be plugged in, but the default reads from
# a JCE-style keystore. A single keystore can hold multiple keys, but the one referenced by # a JCE-style keystore. A single keystore can hold multiple keys, but the one referenced by
# the "key_alias" is the only key that will be used for encrypt opertaions; previously used keys # the "key_alias" is the only key that will be used for encrypt opertaions; previously used keys

View File

@ -327,8 +327,8 @@ the first based on standard JMX security and the second which integrates
more closely with Cassandra's own auth subsystem. more closely with Cassandra's own auth subsystem.
The default settings for Cassandra make JMX accessible only from The default settings for Cassandra make JMX accessible only from
localhost. To enable remote JMX connections, edit `cassandra-env.sh` (or localhost. To enable remote JMX connections, edit `cassandra-env.sh`
`cassandra-env.ps1` on Windows) to change the `LOCAL_JMX` setting to to change the `LOCAL_JMX` setting to
`no`. Under the standard configuration, when remote JMX connections are `no`. Under the standard configuration, when remote JMX connections are
enabled, `standard JMX authentication <standard-jmx-auth>` is also enabled, `standard JMX authentication <standard-jmx-auth>` is also
switched on. switched on.
@ -490,7 +490,7 @@ See also: xref:cql/security.adoc#permissions[`Permissions`].
JMX SSL configuration is controlled by a number of system properties, JMX SSL configuration is controlled by a number of system properties,
some of which are optional. To turn on SSL, edit the relevant lines in some of which are optional. To turn on SSL, edit the relevant lines in
`cassandra-env.sh` (or `cassandra-env.ps1` on Windows) to uncomment and `cassandra-env.sh` to uncomment and
set the values of these properties as required: set the values of these properties as required:
`com.sun.management.jmxremote.ssl`:: `com.sun.management.jmxremote.ssl`::

View File

@ -884,7 +884,7 @@ class FilesReader(object):
self.max_rows = options.copy['maxrows'] self.max_rows = options.copy['maxrows']
self.skip_rows = options.copy['skiprows'] self.skip_rows = options.copy['skiprows']
self.fname = fname self.fname = fname
self.sources = None # must be created later due to pickle problems on Windows self.sources = None # might be initialised directly here? (see CASSANDRA-17350)
self.num_sources = 0 self.num_sources = 0
self.current_source = None self.current_source = None
self.num_read = 0 self.num_read = 0
@ -1299,9 +1299,9 @@ class FeedingProcess(mp.Process):
self.inpipe = inpipe self.inpipe = inpipe
self.outpipe = outpipe self.outpipe = outpipe
self.worker_pipes = worker_pipes self.worker_pipes = worker_pipes
self.inmsg = None # must be created after forking on Windows self.inmsg = None # might be initialised directly here? (see CASSANDRA-17350)
self.outmsg = None # must be created after forking on Windows self.outmsg = None # might be initialised directly here? (see CASSANDRA-17350)
self.worker_channels = None # must be created after forking on Windows self.worker_channels = None # might be initialised directly here? (see CASSANDRA-17350)
self.reader = FilesReader(fname, options) if fname else PipeReader(inpipe, options) self.reader = FilesReader(fname, options) if fname else PipeReader(inpipe, options)
self.send_meter = RateMeter(log_fcn=None, update_interval=1) self.send_meter = RateMeter(log_fcn=None, update_interval=1)
self.ingest_rate = options.copy['ingestrate'] self.ingest_rate = options.copy['ingestrate']
@ -1405,8 +1405,8 @@ class ChildProcess(mp.Process):
super(ChildProcess, self).__init__(target=target) super(ChildProcess, self).__init__(target=target)
self.inpipe = params['inpipe'] self.inpipe = params['inpipe']
self.outpipe = params['outpipe'] self.outpipe = params['outpipe']
self.inmsg = None # must be initialized after fork on Windows self.inmsg = None # might be initialised directly here? (see CASSANDRA-17350)
self.outmsg = None # must be initialized after fork on Windows self.outmsg = None # might be initialised directly here? (see CASSANDRA-17350)
self.ks = params['ks'] self.ks = params['ks']
self.table = params['table'] self.table = params['table']
self.local_dc = params['local_dc'] self.local_dc = params['local_dc']

View File

@ -35,8 +35,6 @@ from . import wcwidth
from .displaying import colorme, get_str, FormattedValue, DEFAULT_VALUE_COLORS, NO_COLOR_MAP from .displaying import colorme, get_str, FormattedValue, DEFAULT_VALUE_COLORS, NO_COLOR_MAP
from .util import UTC from .util import UTC
is_win = platform.system() == 'Windows'
unicode_controlchars_re = re.compile(r'[\x00-\x31\x7f-\xa0]') unicode_controlchars_re = re.compile(r'[\x00-\x31\x7f-\xa0]')
controlchars_re = re.compile(r'[\x00-\x31\x7f-\xff]') controlchars_re = re.compile(r'[\x00-\x31\x7f-\xff]')

View File

@ -30,15 +30,8 @@ from . import basecase
from os.path import join, normpath from os.path import join, normpath
def is_win(): import pty
return sys.platform in ("cygwin", "win32") DEFAULT_PREFIX = os.linesep
if is_win():
from .winpty import WinPty
DEFAULT_PREFIX = ''
else:
import pty
DEFAULT_PREFIX = os.linesep
DEFAULT_CQLSH_PROMPT = DEFAULT_PREFIX + '(\S+@)?cqlsh(:\S+)?> ' DEFAULT_CQLSH_PROMPT = DEFAULT_PREFIX + '(\S+@)?cqlsh(:\S+)?> '
DEFAULT_CQLSH_TERM = 'xterm' DEFAULT_CQLSH_TERM = 'xterm'
@ -56,13 +49,12 @@ def get_smm_sequence(term='xterm'):
before each prompt. before each prompt.
""" """
result = '' result = ''
if not is_win(): tput_proc = subprocess.Popen(['tput', '-T{}'.format(term), 'smm'], stdout=subprocess.PIPE)
tput_proc = subprocess.Popen(['tput', '-T{}'.format(term), 'smm'], stdout=subprocess.PIPE) tput_stdout = tput_proc.communicate()[0]
tput_stdout = tput_proc.communicate()[0] if (tput_stdout and (tput_stdout != b'')):
if (tput_stdout and (tput_stdout != b'')): result = tput_stdout
result = tput_stdout if isinstance(result, bytes):
if isinstance(result, bytes): result = result.decode("utf-8")
result = result.decode("utf-8")
return result return result
DEFAULT_SMM_SEQUENCE = get_smm_sequence() DEFAULT_SMM_SEQUENCE = get_smm_sequence()
@ -97,7 +89,7 @@ class TimeoutError(Exception):
pass pass
@contextlib.contextmanager @contextlib.contextmanager
def timing_out_itimer(seconds): def timing_out(seconds):
if seconds is None: if seconds is None:
yield yield
return return
@ -111,36 +103,6 @@ def timing_out_itimer(seconds):
finally: finally:
signal.setitimer(signal.ITIMER_REAL, 0) signal.setitimer(signal.ITIMER_REAL, 0)
@contextlib.contextmanager
def timing_out_alarm(seconds):
if seconds is None:
yield
return
with raising_signal(signal.SIGALRM, TimeoutError):
oldval = signal.alarm(int(math.ceil(seconds)))
if oldval != 0:
signal.alarm(oldval)
raise RuntimeError("SIGALRM already in use")
try:
yield
finally:
signal.alarm(0)
if is_win():
try:
import eventlet
except ImportError as e:
sys.exit("evenlet library required to run cqlshlib tests on Windows")
def timing_out(seconds):
return eventlet.Timeout(seconds, TimeoutError)
else:
# setitimer is new in 2.6, but it's still worth supporting, for potentially
# faster tests because of sub-second resolution on timeouts.
if hasattr(signal, 'setitimer'):
timing_out = timing_out_itimer
else:
timing_out = timing_out_alarm
def noop(*a): def noop(*a):
pass pass
@ -149,8 +111,7 @@ class ProcRunner:
def __init__(self, path, tty=True, env=None, args=()): def __init__(self, path, tty=True, env=None, args=()):
self.exe_path = path self.exe_path = path
self.args = args self.args = args
self.tty = bool(tty) self.tty = tty
self.realtty = self.tty and not is_win()
if env is None: if env is None:
env = {} env = {}
self.env = env self.env = env
@ -163,7 +124,7 @@ class ProcRunner:
stdin = stdout = stderr = None stdin = stdout = stderr = None
cqlshlog.info("Spawning %r subprocess with args: %r and env: %r" cqlshlog.info("Spawning %r subprocess with args: %r and env: %r"
% (self.exe_path, self.args, self.env)) % (self.exe_path, self.args, self.env))
if self.realtty: if self.tty:
masterfd, slavefd = pty.openpty() masterfd, slavefd = pty.openpty()
preexec = (lambda: set_controlling_pty(masterfd, slavefd)) preexec = (lambda: set_controlling_pty(masterfd, slavefd))
self.proc = subprocess.Popen((self.exe_path,) + tuple(self.args), self.proc = subprocess.Popen((self.exe_path,) + tuple(self.args),
@ -181,15 +142,11 @@ class ProcRunner:
env=self.env, stdin=stdin, stdout=stdout, env=self.env, stdin=stdin, stdout=stdout,
stderr=stderr, bufsize=0, close_fds=False) stderr=stderr, bufsize=0, close_fds=False)
self.send = self.send_pipe self.send = self.send_pipe
if self.tty: self.read = self.read_pipe
self.winpty = WinPty(self.proc.stdout)
self.read = self.read_winpty
else:
self.read = self.read_pipe
def close(self): def close(self):
cqlshlog.info("Closing %r subprocess." % (self.exe_path,)) cqlshlog.info("Closing %r subprocess." % (self.exe_path,))
if self.realtty: if self.tty:
os.close(self.childpty) os.close(self.childpty)
else: else:
self.proc.stdin.close() self.proc.stdin.close()
@ -216,12 +173,6 @@ class ProcRunner:
buf = buf.decode("utf-8") buf = buf.decode("utf-8")
return buf return buf
def read_winpty(self, blksize, timeout=None):
buf = self.winpty.read(blksize, timeout)
if isinstance(buf, bytes):
buf = buf.decode("utf-8")
return buf
def read_until(self, until, blksize=4096, timeout=None, def read_until(self, until, blksize=4096, timeout=None,
flags=0, ptty_timeout=None, replace=[]): flags=0, ptty_timeout=None, replace=[]):
if not isinstance(until, Pattern): if not isinstance(until, Pattern):
@ -273,8 +224,7 @@ class ProcRunner:
class CqlshRunner(ProcRunner): class CqlshRunner(ProcRunner):
def __init__(self, path=None, host=None, port=None, keyspace=None, cqlver=None, def __init__(self, path=None, host=None, port=None, keyspace=None, cqlver=None,
args=(), prompt=DEFAULT_CQLSH_PROMPT, env=None, args=(), prompt=DEFAULT_CQLSH_PROMPT, env=None, tty=True, **kwargs):
win_force_colors=True, tty=True, **kwargs):
if path is None: if path is None:
path = join(basecase.cqlsh_dir, 'cqlsh') path = join(basecase.cqlsh_dir, 'cqlsh')
if host is None: if host is None:
@ -283,9 +233,6 @@ class CqlshRunner(ProcRunner):
port = basecase.TEST_PORT port = basecase.TEST_PORT
if env is None: if env is None:
env = {} env = {}
if is_win():
env['PYTHONUNBUFFERED'] = '1'
env.update(os.environ.copy())
env.setdefault('TERM', 'xterm') env.setdefault('TERM', 'xterm')
env.setdefault('CQLSH_NO_BUNDLED', os.environ.get('CQLSH_NO_BUNDLED', '')) env.setdefault('CQLSH_NO_BUNDLED', os.environ.get('CQLSH_NO_BUNDLED', ''))
env.setdefault('PYTHONPATH', os.environ.get('PYTHONPATH', '')) env.setdefault('PYTHONPATH', os.environ.get('PYTHONPATH', ''))
@ -297,11 +244,6 @@ class CqlshRunner(ProcRunner):
args += ('--cqlversion', str(cqlver)) args += ('--cqlversion', str(cqlver))
if keyspace is not None: if keyspace is not None:
args += ('--keyspace', keyspace.lower()) args += ('--keyspace', keyspace.lower())
if tty and is_win():
args += ('--tty',)
args += ('--encoding', 'utf-8')
if win_force_colors:
args += ('--color',)
if coverage: if coverage:
args += ('--coverage',) args += ('--coverage',)
self.keyspace = keyspace self.keyspace = keyspace
@ -330,7 +272,7 @@ class CqlshRunner(ProcRunner):
output = output.replace(' \r', '') output = output.replace(' \r', '')
output = output.replace('\r', '') output = output.replace('\r', '')
output = output.replace(' \b', '') output = output.replace(' \b', '')
if self.realtty: if self.tty:
echo, output = output.split('\n', 1) echo, output = output.split('\n', 1)
assert echo == cmd, "unexpected echo %r instead of %r" % (echo, cmd) assert echo == cmd, "unexpected echo %r instead of %r" % (echo, cmd)
try: try:

View File

@ -21,11 +21,9 @@
import locale import locale
import os import os
import re import re
from .basecase import BaseTestCase, cqlsh, cqlshlog from .basecase import BaseTestCase, cqlsh
from .cassconnect import create_db, remove_db, testrun_cqlsh from .cassconnect import create_db, remove_db, testrun_cqlsh
from .run_cqlsh import TimeoutError from .run_cqlsh import TimeoutError
import unittest
import sys
BEL = '\x07' # the terminal-bell character BEL = '\x07' # the terminal-bell character
CTRL_C = '\x03' CTRL_C = '\x03'
@ -39,8 +37,6 @@ COMPLETION_RESPONSE_TIME = 0.5
completion_separation_re = re.compile(r'\s+') completion_separation_re = re.compile(r'\s+')
@unittest.skipIf(sys.platform == "win32", 'Tab completion tests not supported on Windows')
class CqlshCompletionCase(BaseTestCase): class CqlshCompletionCase(BaseTestCase):
@classmethod @classmethod

View File

@ -22,8 +22,6 @@ from __future__ import unicode_literals, with_statement
import locale import locale
import os import os
import re import re
import subprocess
import sys
import six import six
import unittest import unittest
@ -124,8 +122,7 @@ class TestCqlshOutput(BaseTestCase):
for termname in ('', 'dumb', 'vt100'): for termname in ('', 'dumb', 'vt100'):
cqlshlog.debug('TERM=%r' % termname) cqlshlog.debug('TERM=%r' % termname)
env['TERM'] = termname env['TERM'] = termname
with testrun_cqlsh(tty=True, env=env, with testrun_cqlsh(tty=True, env=env) as c:
win_force_colors=False) as c:
c.send('select * from has_all_types;\n') c.send('select * from has_all_types;\n')
self.assertNoHasColors(c.read_to_next_prompt()) self.assertNoHasColors(c.read_to_next_prompt())
c.send('select count(*) from has_all_types;\n') c.send('select count(*) from has_all_types;\n')
@ -588,7 +585,7 @@ class TestCqlshOutput(BaseTestCase):
outputlines = c.read_to_next_prompt().splitlines() outputlines = c.read_to_next_prompt().splitlines()
start_index = 0 start_index = 0
if c.realtty: if c.tty:
self.assertEqual(outputlines[start_index], 'use NONEXISTENTKEYSPACE;') self.assertEqual(outputlines[start_index], 'use NONEXISTENTKEYSPACE;')
start_index = 1 start_index = 1
@ -781,7 +778,6 @@ class TestCqlshOutput(BaseTestCase):
self.assertRegex(output, '^Connected to .* at %s:%d$' self.assertRegex(output, '^Connected to .* at %s:%d$'
% (re.escape(TEST_HOST), TEST_PORT)) % (re.escape(TEST_HOST), TEST_PORT))
@unittest.skipIf(sys.platform == "win32", 'EOF signaling not supported on Windows')
def test_eof_prints_newline(self): def test_eof_prints_newline(self):
with testrun_cqlsh(tty=True, env=self.default_env) as c: with testrun_cqlsh(tty=True, env=self.default_env) as c:
c.send(CONTROL_D) c.send(CONTROL_D)
@ -796,9 +792,8 @@ class TestCqlshOutput(BaseTestCase):
with testrun_cqlsh(tty=True, env=self.default_env) as c: with testrun_cqlsh(tty=True, env=self.default_env) as c:
cmd = 'exit%s\n' % semicolon cmd = 'exit%s\n' % semicolon
c.send(cmd) c.send(cmd)
if c.realtty: out = c.read_lines(1)[0].replace('\r', '')
out = c.read_lines(1)[0].replace('\r', '') self.assertEqual(out, cmd)
self.assertEqual(out, cmd)
with self.assertRaises(BaseException) as cm: with self.assertRaises(BaseException) as cm:
c.read_lines(1) c.read_lines(1)
self.assertIn(type(cm.exception), (EOFError, OSError)) self.assertIn(type(cm.exception), (EOFError, OSError))

View File

@ -392,8 +392,6 @@ public class Config
*/ */
public volatile ConsistencyLevel ideal_consistency_level = null; public volatile ConsistencyLevel ideal_consistency_level = null;
public int windows_timer_interval = 0;
/** /**
* Size of the CQL prepared statements cache in MB. * Size of the CQL prepared statements cache in MB.
* Defaults to 1/256th of the heap size or 10MB, whichever is greater. * Defaults to 1/256th of the heap size or 10MB, whichever is greater.

View File

@ -564,10 +564,6 @@ public class DatabaseDescriptor
if (conf.cdc_enabled) if (conf.cdc_enabled)
{ {
// Windows memory-mapped CommitLog files is incompatible with CDC as we hard-link files in cdc_raw. Confirm we don't have both enabled.
if (FBUtilities.isWindows && conf.commitlog_compression == null)
throw new ConfigurationException("Cannot enable cdc on Windows with uncompressed commitlog.");
if (conf.cdc_raw_directory == null) if (conf.cdc_raw_directory == null)
{ {
conf.cdc_raw_directory = storagedirFor("cdc_raw"); conf.cdc_raw_directory = storagedirFor("cdc_raw");
@ -2803,7 +2799,7 @@ public class DatabaseDescriptor
public static int getSSTablePreemptiveOpenIntervalInMB() public static int getSSTablePreemptiveOpenIntervalInMB()
{ {
return FBUtilities.isWindows ? -1 : conf.sstable_preemptive_open_interval_in_mb; return conf.sstable_preemptive_open_interval_in_mb;
} }
public static void setSSTablePreemptiveOpenIntervalInMB(int mb) public static void setSSTablePreemptiveOpenIntervalInMB(int mb)
{ {
@ -3046,11 +3042,6 @@ public class DatabaseDescriptor
return conf.tracetype_query_ttl; return conf.tracetype_query_ttl;
} }
public static int getWindowsTimerInterval()
{
return conf.windows_timer_interval;
}
public static long getPreparedStatementsCacheSizeMB() public static long getPreparedStatementsCacheSizeMB()
{ {
return preparedStatementsCacheSizeInMB; return preparedStatementsCacheSizeInMB;

View File

@ -58,7 +58,6 @@ import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.service.snapshot.SnapshotManifest; import org.apache.cassandra.service.snapshot.SnapshotManifest;
import org.apache.cassandra.service.snapshot.TableSnapshot; import org.apache.cassandra.service.snapshot.TableSnapshot;
import org.apache.cassandra.utils.DirectorySizeCalculator; import org.apache.cassandra.utils.DirectorySizeCalculator;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.JVMStabilityInspector; import org.apache.cassandra.utils.JVMStabilityInspector;
import org.apache.cassandra.utils.Pair; import org.apache.cassandra.utils.Pair;
@ -1112,10 +1111,7 @@ public class Directories
} }
catch (FSWriteError e) catch (FSWriteError e)
{ {
if (FBUtilities.isWindows) throw e;
SnapshotDeletingTask.addFailedSnapshot(snapshotDir);
else
throw e;
} }
} }
} }

View File

@ -1,117 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.db;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import com.google.common.annotations.VisibleForTesting;
import org.apache.cassandra.io.util.File;
import org.apache.cassandra.io.util.FileOutputStreamPlus;
import org.apache.cassandra.io.util.FileReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.io.util.FileUtils;
import static org.apache.cassandra.io.util.File.WriteMode.APPEND;
public class WindowsFailedSnapshotTracker
{
private static final Logger logger = LoggerFactory.getLogger(WindowsFailedSnapshotTracker.class);
private static PrintWriter _failedSnapshotFile;
@VisibleForTesting
// Need to handle null for unit tests
public static final String TODELETEFILE = System.getenv("CASSANDRA_HOME") == null
? ".toDelete"
: System.getenv("CASSANDRA_HOME") + File.pathSeparator() + ".toDelete";
public static void deleteOldSnapshots()
{
if (new File(TODELETEFILE).exists())
{
try
{
try (BufferedReader reader = new BufferedReader(new FileReader(TODELETEFILE)))
{
String snapshotDirectory;
while ((snapshotDirectory = reader.readLine()) != null)
{
File f = new File(snapshotDirectory);
// Skip folders that aren't a subset of temp or a data folder. We don't want people to accidentally
// delete something important by virtue of adding something invalid to the .toDelete file.
boolean validFolder = FileUtils.isSubDirectory(new File(System.getenv("TEMP")), f);
for (String s : DatabaseDescriptor.getAllDataFileLocations())
validFolder |= FileUtils.isSubDirectory(new File(s), f);
if (!validFolder)
{
logger.warn("Skipping invalid directory found in .toDelete: {}. Only %TEMP% or data file subdirectories are valid.", f);
continue;
}
// Could be a non-existent directory if deletion worked on previous JVM shutdown.
if (f.exists())
{
logger.warn("Discovered obsolete snapshot. Deleting directory [{}]", snapshotDirectory);
FileUtils.deleteRecursive(new File(snapshotDirectory));
}
}
}
// Only delete the old .toDelete file if we succeed in deleting all our known bad snapshots.
new File(TODELETEFILE).delete();
}
catch (IOException e)
{
logger.warn("Failed to open {}. Obsolete snapshots from previous runs will not be deleted.", TODELETEFILE, e);
}
}
try
{
_failedSnapshotFile = new PrintWriter(new OutputStreamWriter(new FileOutputStreamPlus(TODELETEFILE, APPEND)));
}
catch (IOException e)
{
throw new RuntimeException(String.format("Failed to create failed snapshot tracking file [%s]. Aborting", TODELETEFILE));
}
}
public static synchronized void handleFailedSnapshot(File dir)
{
assert _failedSnapshotFile != null : "_failedSnapshotFile not initialized within WindowsFailedSnapshotTracker";
FileUtils.deleteRecursiveOnExit(dir);
_failedSnapshotFile.println(dir.toString());
_failedSnapshotFile.flush();
}
@VisibleForTesting
public static void resetForTests()
{
_failedSnapshotFile.close();
}
}

View File

@ -351,7 +351,6 @@ public class CommitLogSegmentManagerCDC extends AbstractCommitLogSegmentManager
try try
{ {
resetSize(); resetSize();
// The Arrays.stream approach is considerably slower on Windows than linux
Files.walkFileTree(path.toPath(), this); Files.walkFileTree(path.toPath(), this);
sizeInProgress.getAndSet(getAllocatedSize()); sizeInProgress.getAndSet(getAllocatedSize());
} }

View File

@ -70,7 +70,6 @@ import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.sstable.ISSTableScanner; import org.apache.cassandra.io.sstable.ISSTableScanner;
import org.apache.cassandra.io.sstable.IndexSummaryRedistribution; import org.apache.cassandra.io.sstable.IndexSummaryRedistribution;
import org.apache.cassandra.io.sstable.SSTableRewriter; import org.apache.cassandra.io.sstable.SSTableRewriter;
import org.apache.cassandra.io.sstable.SnapshotDeletingTask;
import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.io.sstable.format.SSTableWriter; import org.apache.cassandra.io.sstable.format.SSTableWriter;
import org.apache.cassandra.io.sstable.metadata.MetadataCollector; import org.apache.cassandra.io.sstable.metadata.MetadataCollector;
@ -1846,7 +1845,6 @@ public class CompactionManager implements CompactionManagerMBean
static class CompactionExecutor extends WrappedExecutorPlus static class CompactionExecutor extends WrappedExecutorPlus
{ {
static final ThreadGroup compactionThreadGroup = executorFactory().newThreadGroup("compaction"); static final ThreadGroup compactionThreadGroup = executorFactory().newThreadGroup("compaction");
private static final WithResources RESCHEDULE_FAILED = () -> SnapshotDeletingTask::rescheduleFailedTasks;
public CompactionExecutor() public CompactionExecutor()
{ {
@ -1901,12 +1899,12 @@ public class CompactionManager implements CompactionManagerMBean
public void execute(Runnable command) public void execute(Runnable command)
{ {
executor.execute(RESCHEDULE_FAILED, command); executor.execute(command);
} }
public <T> Future<T> submit(Callable<T> task) public <T> Future<T> submit(Callable<T> task)
{ {
return executor.submit(RESCHEDULE_FAILED, task); return executor.submit(task);
} }
public <T> Future<T> submit(Runnable task, T result) public <T> Future<T> submit(Runnable task, T result)

View File

@ -171,9 +171,6 @@ public class CompactionTask extends AbstractCompactionTask
long[] mergedRowCounts; long[] mergedRowCounts;
long totalSourceCQLRows; long totalSourceCQLRows;
// SSTableScanners need to be closed before markCompactedSSTablesReplaced call as scanners contain references
// to both ifile and dfile and SSTR will throw deletion errors on Windows if it tries to delete before scanner is closed.
// See CASSANDRA-8019 and CASSANDRA-8399
int nowInSec = FBUtilities.nowInSeconds(); int nowInSec = FBUtilities.nowInSeconds();
try (Refs<SSTableReader> refs = Refs.ref(actuallyCompact); try (Refs<SSTableReader> refs = Refs.ref(actuallyCompact);
AbstractCompactionStrategy.ScannerList scanners = strategy.getScanners(actuallyCompact); AbstractCompactionStrategy.ScannerList scanners = strategy.getScanners(actuallyCompact);

View File

@ -30,7 +30,6 @@ import org.slf4j.LoggerFactory;
import org.apache.cassandra.io.FSError; import org.apache.cassandra.io.FSError;
import org.apache.cassandra.io.FSReadError; import org.apache.cassandra.io.FSReadError;
import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.NativeLibrary;
import static org.apache.cassandra.config.CassandraRelevantProperties.IGNORE_MISSING_NATIVE_FILE_HINTS; import static org.apache.cassandra.config.CassandraRelevantProperties.IGNORE_MISSING_NATIVE_FILE_HINTS;
@ -49,7 +48,7 @@ import static org.apache.cassandra.config.CassandraRelevantProperties.IGNORE_MIS
final class LogReplica implements AutoCloseable final class LogReplica implements AutoCloseable
{ {
private static final Logger logger = LoggerFactory.getLogger(LogReplica.class); private static final Logger logger = LoggerFactory.getLogger(LogReplica.class);
private static final boolean REQUIRE_FD = !FBUtilities.isWindows && !IGNORE_MISSING_NATIVE_FILE_HINTS.getBoolean(); private static final boolean REQUIRE_FD = !IGNORE_MISSING_NATIVE_FILE_HINTS.getBoolean();
private final File file; private final File file;
private int directoryDescriptor; private int directoryDescriptor;
@ -67,7 +66,7 @@ final class LogReplica implements AutoCloseable
static LogReplica open(File file) static LogReplica open(File file)
{ {
int folderFD = NativeLibrary.tryOpenDirectory(file.parent().path()); int folderFD = NativeLibrary.tryOpenDirectory(file.parent().path());
if (folderFD == -1 && !FBUtilities.isWindows) if (folderFD == -1)
throw new FSReadError(new IOException(String.format("Invalid folder descriptor trying to create log replica %s", file.parent().path())), file.parent().path()); throw new FSReadError(new IOException(String.format("Invalid folder descriptor trying to create log replica %s", file.parent().path())), file.parent().path());
return new LogReplica(file, folderFD); return new LogReplica(file, folderFD);

View File

@ -44,7 +44,6 @@ import org.apache.cassandra.io.FSWriteError;
import org.apache.cassandra.io.sstable.Component; import org.apache.cassandra.io.sstable.Component;
import org.apache.cassandra.io.sstable.Descriptor; import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.sstable.SSTable; import org.apache.cassandra.io.sstable.SSTable;
import org.apache.cassandra.io.sstable.SnapshotDeletingTask;
import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.io.util.File; import org.apache.cassandra.io.util.File;
import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.io.util.FileUtils;
@ -114,8 +113,7 @@ class LogTransaction extends Transactional.AbstractTransactional implements Tran
// We need an explicit lock because the transaction tidier cannot store a reference to the transaction // We need an explicit lock because the transaction tidier cannot store a reference to the transaction
private final Object lock; private final Object lock;
private final Ref<LogTransaction> selfRef; private final Ref<LogTransaction> selfRef;
// Deleting sstables is tricky because the mmapping might not have been finalized yet, // Deleting sstables is tricky because the mmapping might not have been finalized yet.
// and delete will fail (on Windows) until it is (we only force the unmapping on SUN VMs).
// Additionally, we need to make sure to delete the data file first, so on restart the others // Additionally, we need to make sure to delete the data file first, so on restart the others
// will be recognized as GCable. // will be recognized as GCable.
private static final Queue<Runnable> failedDeletions = new ConcurrentLinkedQueue<>(); private static final Queue<Runnable> failedDeletions = new ConcurrentLinkedQueue<>();
@ -433,9 +431,6 @@ class LogTransaction extends Transactional.AbstractTransactional implements Tran
Runnable task; Runnable task;
while ( null != (task = failedDeletions.poll())) while ( null != (task = failedDeletions.poll()))
ScheduledExecutors.nonPeriodicTasks.submit(task); ScheduledExecutors.nonPeriodicTasks.submit(task);
// On Windows, snapshots cannot be deleted so long as a segment of the root element is memory-mapped in NTFS.
SnapshotDeletingTask.rescheduleFailedTasks();
} }
static void waitForDeletions() static void waitForDeletions()

View File

@ -155,8 +155,7 @@ public class CassandraOutgoingFile implements OutgoingStream
{ {
// Acquire lock to avoid concurrent sstable component mutation because of stats update or index summary // Acquire lock to avoid concurrent sstable component mutation because of stats update or index summary
// redistribution, otherwise file sizes recorded in component manifest will be different from actual // redistribution, otherwise file sizes recorded in component manifest will be different from actual
// file sizes. (Note: Windows doesn't support atomic replace and index summary redistribution deletes // file sizes.
// existing file first)
// Recreate the latest manifest and hard links for mutatable components in case they are modified. // Recreate the latest manifest and hard links for mutatable components in case they are modified.
try (ComponentContext context = sstable.runWithLock(ignored -> ComponentContext.create(sstable.descriptor))) try (ComponentContext context = sstable.runWithLock(ignored -> ComponentContext.create(sstable.descriptor)))
{ {

View File

@ -34,7 +34,6 @@ import org.apache.cassandra.io.FSError;
import org.apache.cassandra.io.FSReadError; import org.apache.cassandra.io.FSReadError;
import org.apache.cassandra.io.FSWriteError; import org.apache.cassandra.io.FSWriteError;
import org.apache.cassandra.io.util.FileUtils; import org.apache.cassandra.io.util.FileUtils;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.NativeLibrary;
import org.apache.cassandra.utils.SyncUtil; import org.apache.cassandra.utils.SyncUtil;
@ -162,7 +161,7 @@ final class HintsCatalog
FileUtils.handleFSErrorAndPropagate(e); FileUtils.handleFSErrorAndPropagate(e);
} }
} }
else if (!FBUtilities.isWindows) else
{ {
logger.error("Unable to open directory {}", hintsDirectory.absolutePath()); logger.error("Unable to open directory {}", hintsDirectory.absolutePath());
FileUtils.handleFSErrorAndPropagate(new FSWriteError(new IOException(String.format("Unable to open hint directory %s", hintsDirectory.absolutePath())), hintsDirectory.absolutePath())); FileUtils.handleFSErrorAndPropagate(new FSWriteError(new IOException(String.format("Unable to open hint directory %s", hintsDirectory.absolutePath())), hintsDirectory.absolutePath()));

View File

@ -1,81 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.io.sstable;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import com.google.common.annotations.VisibleForTesting;
import org.apache.cassandra.io.util.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.concurrent.ScheduledExecutors;
import org.apache.cassandra.db.WindowsFailedSnapshotTracker;
import org.apache.cassandra.io.FSWriteError;
import org.apache.cassandra.io.util.FileUtils;
public class SnapshotDeletingTask implements Runnable
{
private static final Logger logger = LoggerFactory.getLogger(SnapshotDeletingTask.class);
public final File path;
private static final Queue<Runnable> failedTasks = new ConcurrentLinkedQueue<>();
public static void addFailedSnapshot(File path)
{
logger.warn("Failed to delete snapshot [{}]. Will retry after further sstable deletions. Folder will be deleted on JVM shutdown or next node restart on crash.", path);
WindowsFailedSnapshotTracker.handleFailedSnapshot(path);
failedTasks.add(new SnapshotDeletingTask(path));
}
private SnapshotDeletingTask(File path)
{
this.path = path;
}
public void run()
{
try
{
FileUtils.deleteRecursive(path);
logger.info("Successfully deleted snapshot {}.", path);
}
catch (FSWriteError e)
{
failedTasks.add(this);
}
}
/**
* Retry all failed deletions.
*/
public static void rescheduleFailedTasks()
{
Runnable task;
while ( null != (task = failedTasks.poll()))
ScheduledExecutors.nonPeriodicTasks.submit(task);
}
@VisibleForTesting
public static int pendingDeletionCount()
{
return failedTasks.size();
}
}

View File

@ -36,7 +36,6 @@ import org.apache.cassandra.io.sstable.Component;
import org.apache.cassandra.io.sstable.CorruptSSTableException; import org.apache.cassandra.io.sstable.CorruptSSTableException;
import org.apache.cassandra.io.sstable.Descriptor; import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.sstable.format.Version; import org.apache.cassandra.io.sstable.format.Version;
import org.apache.cassandra.utils.FBUtilities;
import static org.apache.cassandra.utils.FBUtilities.updateChecksumInt; import static org.apache.cassandra.utils.FBUtilities.updateChecksumInt;
@ -268,10 +267,6 @@ public class MetadataSerializer implements IMetadataSerializer
Throwables.throwIfInstanceOf(e, FileNotFoundException.class); Throwables.throwIfInstanceOf(e, FileNotFoundException.class);
throw new FSWriteError(e, filePath); throw new FSWriteError(e, filePath);
} }
// we cant move a file on top of another file in windows:
if (FBUtilities.isWindows)
FileUtils.delete(descriptor.filenameFor(Component.STATS));
FileUtils.renameWithConfirm(filePath, descriptor.filenameFor(Component.STATS)); FileUtils.renameWithConfirm(filePath, descriptor.filenameFor(Component.STATS));
} }
} }

View File

@ -352,8 +352,6 @@ public final class PathUtils
public static boolean tryRename(Path from, Path to) public static boolean tryRename(Path from, Path to)
{ {
logger.trace("Renaming {} to {}", from, to); logger.trace("Renaming {} to {}", from, to);
// this is not FSWE because usually when we see it it's because we didn't close the file before renaming it,
// and Windows is picky about that.
try try
{ {
atomicMoveWithFallback(from, to); atomicMoveWithFallback(from, to);
@ -369,8 +367,6 @@ public final class PathUtils
public static void rename(Path from, Path to) public static void rename(Path from, Path to)
{ {
logger.trace("Renaming {} to {}", from, to); logger.trace("Renaming {} to {}", from, to);
// this is not FSWE because usually when we see it it's because we didn't close the file before renaming it,
// and Windows is picky about that.
try try
{ {
atomicMoveWithFallback(from, to); atomicMoveWithFallback(from, to);

View File

@ -177,9 +177,7 @@ public class InboundConnectionInitiator
throw new ConfigurationException(bind + " is in use by another process. Change listen_address:storage_port " + throw new ConfigurationException(bind + " is in use by another process. Change listen_address:storage_port " +
"in cassandra.yaml to values that do not conflict with other services"); "in cassandra.yaml to values that do not conflict with other services");
} }
// looking at the jdk source, solaris/windows bind failue messages both use the phrase "cannot assign requested address". else if (causeString.contains("cannot assign requested address"))
// windows message uses "Cannot" (with a capital 'C'), and solaris (a/k/a *nux) doe not. hence we search for "annot" <sigh>
else if (causeString.contains("annot assign requested address"))
{ {
throw new ConfigurationException("Unable to bind to address " + bind throw new ConfigurationException("Unable to bind to address " + bind
+ ". Set listen_address in cassandra.yaml to an interface you can bind to, e.g., your private IP address on EC2"); + ". Set listen_address in cassandra.yaml to an interface you can bind to, e.g., your private IP address on EC2");

View File

@ -23,14 +23,12 @@ import com.google.common.base.Joiner;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Range; import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token; import org.apache.cassandra.dht.Token;
import org.apache.cassandra.streaming.PreviewKind; import org.apache.cassandra.streaming.PreviewKind;
import org.apache.cassandra.repair.RepairParallelism; import org.apache.cassandra.repair.RepairParallelism;
import org.apache.cassandra.utils.FBUtilities;
/** /**
* Repair options. * Repair options.
@ -285,16 +283,8 @@ public class RepairOption
public RepairOption(RepairParallelism parallelism, boolean primaryRange, boolean incremental, boolean trace, int jobThreads, Collection<Range<Token>> ranges, boolean isSubrangeRepair, boolean pullRepair, boolean forceRepair, PreviewKind previewKind, boolean optimiseStreams, boolean ignoreUnreplicatedKeyspaces) public RepairOption(RepairParallelism parallelism, boolean primaryRange, boolean incremental, boolean trace, int jobThreads, Collection<Range<Token>> ranges, boolean isSubrangeRepair, boolean pullRepair, boolean forceRepair, PreviewKind previewKind, boolean optimiseStreams, boolean ignoreUnreplicatedKeyspaces)
{ {
if (FBUtilities.isWindows &&
(DatabaseDescriptor.getDiskAccessMode() != Config.DiskAccessMode.standard || DatabaseDescriptor.getIndexAccessMode() != Config.DiskAccessMode.standard) &&
parallelism == RepairParallelism.SEQUENTIAL)
{
logger.warn("Sequential repair disabled when memory-mapped I/O is configured on Windows. Reverting to parallel.");
this.parallelism = RepairParallelism.PARALLEL;
}
else
this.parallelism = parallelism;
this.parallelism = parallelism;
this.primaryRange = primaryRange; this.primaryRange = primaryRange;
this.incremental = incremental; this.incremental = incremental;
this.trace = trace; this.trace = trace;

View File

@ -54,10 +54,10 @@ public final class SchemaConstants
public static final Set<String> REPLICATED_SYSTEM_KEYSPACE_NAMES = public static final Set<String> REPLICATED_SYSTEM_KEYSPACE_NAMES =
ImmutableSet.of(TRACE_KEYSPACE_NAME, AUTH_KEYSPACE_NAME, DISTRIBUTED_KEYSPACE_NAME); ImmutableSet.of(TRACE_KEYSPACE_NAME, AUTH_KEYSPACE_NAME, DISTRIBUTED_KEYSPACE_NAME);
/** /**
* longest permissible KS or CF name. Our main concern is that filename not be more than 255 characters; * The longest permissible KS or CF name.
* the filename will contain both the KS and CF names. Since non-schema-name components only take up *
* ~64 characters, we could allow longer names than this, but on Windows, the entire path should be not greater than * Before CASSANDRA-16956, we used to care about not having the entire path longer than 255 characters because of
* 255 characters, so a lower limit here helps avoid problems. See CASSANDRA-4110. * Windows support but this limit is by implementing CASSANDRA-16956 not in effect anymore.
*/ */
public static final int NAME_LENGTH = 48; public static final int NAME_LENGTH = 48;

View File

@ -60,7 +60,6 @@ import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.SizeEstimatesRecorder; import org.apache.cassandra.db.SizeEstimatesRecorder;
import org.apache.cassandra.db.SystemKeyspace; import org.apache.cassandra.db.SystemKeyspace;
import org.apache.cassandra.db.SystemKeyspaceMigrator40; import org.apache.cassandra.db.SystemKeyspaceMigrator40;
import org.apache.cassandra.db.WindowsFailedSnapshotTracker;
import org.apache.cassandra.db.commitlog.CommitLog; import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.db.virtual.SystemViewsKeyspace; import org.apache.cassandra.db.virtual.SystemViewsKeyspace;
import org.apache.cassandra.db.virtual.VirtualKeyspaceRegistry; import org.apache.cassandra.db.virtual.VirtualKeyspaceRegistry;
@ -84,7 +83,6 @@ import org.apache.cassandra.utils.JVMStabilityInspector;
import org.apache.cassandra.utils.MBeanWrapper; import org.apache.cassandra.utils.MBeanWrapper;
import org.apache.cassandra.utils.Mx4jTool; import org.apache.cassandra.utils.Mx4jTool;
import org.apache.cassandra.utils.NativeLibrary; import org.apache.cassandra.utils.NativeLibrary;
import org.apache.cassandra.utils.WindowsTimer;
import org.apache.cassandra.utils.concurrent.Future; import org.apache.cassandra.utils.concurrent.Future;
import org.apache.cassandra.utils.concurrent.FutureCombiner; import org.apache.cassandra.utils.concurrent.FutureCombiner;
@ -241,10 +239,6 @@ public class CassandraDaemon
exitOrFail(StartupException.ERR_WRONG_DISK_STATE, e.getMessage(), e); exitOrFail(StartupException.ERR_WRONG_DISK_STATE, e.getMessage(), e);
} }
// Delete any failed snapshot deletions on Windows - see CASSANDRA-9658
if (FBUtilities.isWindows)
WindowsFailedSnapshotTracker.deleteOldSnapshots();
maybeInitJmx(); maybeInitJmx();
Mx4jTool.maybeLoad(); Mx4jTool.maybeLoad();
@ -699,11 +693,6 @@ public class CassandraDaemon
destroyClientTransports(); destroyClientTransports();
StorageService.instance.setRpcReady(false); StorageService.instance.setRpcReady(false);
// On windows, we need to stop the entire system as prunsrv doesn't have the jsvc hooks
// We rely on the shutdown hook to drain the node
if (FBUtilities.isWindows)
System.exit(0);
if (jmxServer != null) if (jmxServer != null)
{ {
try try
@ -744,13 +733,6 @@ public class CassandraDaemon
registerNativeAccess(); registerNativeAccess();
if (FBUtilities.isWindows)
{
// We need to adjust the system timer on windows from the default 15ms down to the minimum of 1ms as this
// impacts timer intervals, thread scheduling, driver interrupts, etc.
WindowsTimer.startTimerPeriod(DatabaseDescriptor.getWindowsTimerInterval());
}
setup(); setup();
String pidFile = CASSANDRA_PID_FILE.getString(); String pidFile = CASSANDRA_PID_FILE.getString();

View File

@ -140,8 +140,6 @@ public class StartupChecks
{ {
public void execute() public void execute()
{ {
if (FBUtilities.isWindows)
return;
String jemalloc = System.getProperty("cassandra.libjemalloc"); String jemalloc = System.getProperty("cassandra.libjemalloc");
if (jemalloc == null) if (jemalloc == null)
logger.warn("jemalloc shared library could not be preloaded to speed up memory allocations"); logger.warn("jemalloc shared library could not be preloaded to speed up memory allocations");

View File

@ -784,10 +784,6 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
public void runMayThrow() throws InterruptedException, ExecutionException, IOException public void runMayThrow() throws InterruptedException, ExecutionException, IOException
{ {
drain(true); drain(true);
if (FBUtilities.isWindows)
WindowsTimer.endTimerPeriod(DatabaseDescriptor.getWindowsTimerInterval());
LoggingSupportFactory.getLoggingSupport().onShutdown(); LoggingSupportFactory.getLoggingSupport().onShutdown();
} }
}, "StorageServiceShutdownHook"); }, "StorageServiceShutdownHook");
@ -892,9 +888,6 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
if (drainOnShutdown != null) if (drainOnShutdown != null)
Runtime.getRuntime().removeShutdownHook(drainOnShutdown); Runtime.getRuntime().removeShutdownHook(drainOnShutdown);
if (FBUtilities.isWindows)
WindowsTimer.endTimerPeriod(DatabaseDescriptor.getWindowsTimerInterval());
} }
private boolean shouldBootstrap() private boolean shouldBootstrap()

View File

@ -217,7 +217,6 @@ public class SSTableExport
} }
catch (IOException e) catch (IOException e)
{ {
// throwing exception outside main with broken pipe causes windows cmd to hang
e.printStackTrace(System.err); e.printStackTrace(System.err);
} }

View File

@ -103,7 +103,6 @@ public class FBUtilities
private static final String DEFAULT_TRIGGER_DIR = "triggers"; private static final String DEFAULT_TRIGGER_DIR = "triggers";
private static final String OPERATING_SYSTEM = System.getProperty("os.name").toLowerCase(); private static final String OPERATING_SYSTEM = System.getProperty("os.name").toLowerCase();
public static final boolean isWindows = OPERATING_SYSTEM.contains("windows");
public static final boolean isLinux = OPERATING_SYSTEM.contains("linux"); public static final boolean isLinux = OPERATING_SYSTEM.contains("linux");
private static volatile InetAddress localInetAddress; private static volatile InetAddress localInetAddress;

View File

@ -38,7 +38,6 @@ import static org.apache.cassandra.config.CassandraRelevantProperties.OS_ARCH;
import static org.apache.cassandra.config.CassandraRelevantProperties.OS_NAME; import static org.apache.cassandra.config.CassandraRelevantProperties.OS_NAME;
import static org.apache.cassandra.utils.NativeLibrary.OSType.LINUX; import static org.apache.cassandra.utils.NativeLibrary.OSType.LINUX;
import static org.apache.cassandra.utils.NativeLibrary.OSType.MAC; import static org.apache.cassandra.utils.NativeLibrary.OSType.MAC;
import static org.apache.cassandra.utils.NativeLibrary.OSType.WINDOWS;
import static org.apache.cassandra.utils.NativeLibrary.OSType.AIX; import static org.apache.cassandra.utils.NativeLibrary.OSType.AIX;
public final class NativeLibrary public final class NativeLibrary
@ -50,7 +49,6 @@ public final class NativeLibrary
{ {
LINUX, LINUX,
MAC, MAC,
WINDOWS,
AIX, AIX,
OTHER; OTHER;
} }
@ -99,7 +97,6 @@ public final class NativeLibrary
switch (osType) switch (osType)
{ {
case MAC: wrappedLibrary = new NativeLibraryDarwin(); break; case MAC: wrappedLibrary = new NativeLibraryDarwin(); break;
case WINDOWS: wrappedLibrary = new NativeLibraryWindows(); break;
case LINUX: case LINUX:
case AIX: case AIX:
case OTHER: case OTHER:
@ -143,10 +140,8 @@ public final class NativeLibrary
return LINUX; return LINUX;
else if (osName.contains("mac")) else if (osName.contains("mac"))
return MAC; return MAC;
else if (osName.contains("windows"))
return WINDOWS;
logger.warn("the current operating system, {}, is unsupported by cassandra", osName); logger.warn("the current operating system, {}, is unsupported by Cassandra", osName);
if (osName.contains("aix")) if (osName.contains("aix"))
return AIX; return AIX;
else else

View File

@ -1,127 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.utils;
import java.util.Collections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jna.LastErrorException;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
/**
* A {@code NativeLibraryWrapper} implementation for Windows.
* <p> This implementation only offers support for the {@code callGetpid} method
* using the Windows/Kernel32 library.</p>
*
* @see org.apache.cassandra.utils.NativeLibraryWrapper
* @see NativeLibrary
*/
@Shared
public class NativeLibraryWindows implements NativeLibraryWrapper
{
private static final Logger logger = LoggerFactory.getLogger(NativeLibraryWindows.class);
private static boolean available;
static
{
try
{
Native.register(com.sun.jna.NativeLibrary.getInstance("kernel32", Collections.emptyMap()));
available = true;
}
catch (NoClassDefFoundError e)
{
logger.warn("JNA not found. Native methods will be disabled.");
}
catch (UnsatisfiedLinkError e)
{
logger.error("Failed to link the Windows/Kernel32 library against JNA. Native methods will be unavailable.", e);
}
catch (NoSuchMethodError e)
{
logger.warn("Obsolete version of JNA present; unable to register Windows/Kernel32 library. Upgrade to JNA 3.2.7 or later");
}
}
/**
* Retrieves the process identifier of the calling process (<a href='https://msdn.microsoft.com/en-us/library/windows/desktop/ms683180(v=vs.85).aspx'>GetCurrentProcessId function</a>).
*
* @return the process identifier of the calling process
*/
private static native long GetCurrentProcessId() throws LastErrorException;
public int callMlockall(int flags) throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
public int callMunlockall() throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
public int callFcntl(int fd, int command, long flags) throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
public int callPosixFadvise(int fd, long offset, int len, int flag) throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
public int callOpen(String path, int flags) throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
public int callFsync(int fd) throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
public int callClose(int fd) throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
public Pointer callStrerror(int errnum) throws UnsatisfiedLinkError, RuntimeException
{
throw new UnsatisfiedLinkError();
}
/**
* @return the PID of the JVM running
* @throws UnsatisfiedLinkError if we fail to link against Sigar
* @throws RuntimeException if another unexpected error is thrown by Sigar
*/
public long callGetpid() throws UnsatisfiedLinkError, RuntimeException
{
return GetCurrentProcessId();
}
public boolean isAvailable()
{
return available;
}
}

View File

@ -113,10 +113,6 @@ public class SigarLibrary
private boolean hasAcceptableAddressSpace() private boolean hasAcceptableAddressSpace()
{ {
// Check is invalid on Windows
if (FBUtilities.isWindows)
return true;
try try
{ {
long fileMax = sigar.getResourceLimit().getVirtualMemoryMax(); long fileMax = sigar.getResourceLimit().getVirtualMemoryMax();

View File

@ -1,69 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sun.jna.LastErrorException;
import com.sun.jna.Native;
public final class WindowsTimer
{
private static final Logger logger = LoggerFactory.getLogger(WindowsTimer.class);
static
{
try
{
Native.register("winmm");
}
catch (NoClassDefFoundError e)
{
logger.warn("JNA not found. winmm.dll cannot be registered. Performance will be negatively impacted on this node.");
}
catch (Exception e)
{
logger.error("Failed to register winmm.dll. Performance will be negatively impacted on this node.");
}
}
private static native int timeBeginPeriod(int period) throws LastErrorException;
private static native int timeEndPeriod(int period) throws LastErrorException;
private WindowsTimer() {}
public static void startTimerPeriod(int period)
{
if (period == 0)
return;
assert(period > 0);
if (timeBeginPeriod(period) != 0)
logger.warn("Failed to set timer to : {}. Performance will be degraded.", period);
}
public static void endTimerPeriod(int period)
{
if (period == 0)
return;
assert(period > 0);
if (timeEndPeriod(period) != 0)
logger.warn("Failed to end accelerated timer period. System timer will remain set to: {} ms.", period);
}
}

View File

@ -1,4 +1 @@
cdc_enabled: true cdc_enabled: true
# Compression enabled since uncompressed + cdc isn't compatible w/Windows
commitlog_compression:
- class_name: LZ4Compressor

View File

@ -64,11 +64,6 @@ public class DirectorySizerBench
// [java] Statistics: (min, avg, max) = (73.687, 74.714, 76.872), stdev = 0.835 // [java] Statistics: (min, avg, max) = (73.687, 74.714, 76.872), stdev = 0.835
// [java] Confidence interval (99.9%): [74.156, 75.272] // [java] Confidence interval (99.9%): [74.156, 75.272]
// Throttle CPU on the Windows box to .87GHZ from 4.3GHZ turbo single-core, and #'s for 25600:
// [java] Result: 298.628 (99.9%) 14.755 ms/op [Average]
// [java] Statistics: (min, avg, max) = (291.245, 298.628, 412.881), stdev = 22.085
// [java] Confidence interval (99.9%): [283.873, 313.383]
// Test w/25,600 files, 100x the load of a full default CommitLog (8192) divided by size (32 per) // Test w/25,600 files, 100x the load of a full default CommitLog (8192) divided by size (32 per)
populateRandomFiles(tempDir, 25600); populateRandomFiles(tempDir, 25600);
sizer = new DirectorySizeCalculator(tempDir); sizer = new DirectorySizeCalculator(tempDir);

View File

@ -121,14 +121,6 @@ public class LogbackStatusListener implements StatusListener, LoggerContextListe
return; return;
} }
//Filter out Windows newline
if (size() == 2)
{
byte[] bytes = toByteArray();
if (bytes[0] == 0xD && bytes[1] == 0xA)
return;
}
String statement; String statement;
if (encoding != null) if (encoding != null)
statement = new String(toByteArray(), encoding); statement = new String(toByteArray(), encoding);

View File

@ -131,11 +131,10 @@ public final class ServerTestUtils
} }
/** /**
* Cleanup the directories used by the server, creating them if they do not exists. * Cleanup the directories used by the server, creating them if they do not exist.
*/ */
public static void cleanupAndLeaveDirs() throws IOException public static void cleanupAndLeaveDirs() throws IOException
{ {
// We need to stop and unmap all CLS instances prior to cleanup() or we'll get failures on Windows.
CommitLog.instance.stopUnsafe(true); CommitLog.instance.stopUnsafe(true);
mkdirs(); // Creates the directories if they does not exists mkdirs(); // Creates the directories if they does not exists
cleanup(); // Ensure that the directories are all empty cleanup(); // Ensure that the directories are all empty

View File

@ -220,11 +220,6 @@ public class ColumnFamilyStoreTest
@Test @Test
public void testClearEphemeralSnapshots() throws Throwable public void testClearEphemeralSnapshots() throws Throwable
{ {
// We don't do snapshot-based repair on Windows so we don't have ephemeral snapshots from repair that need clearing.
// This test will fail as we'll revert to the WindowsFailedSnapshotTracker and counts will be off, but since we
// don't do snapshot-based repair on Windows, we just skip this test.
Assume.assumeTrue(!FBUtilities.isWindows);
ColumnFamilyStore cfs = Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_INDEX1); ColumnFamilyStore cfs = Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_INDEX1);
//cleanup any previous test gargbage //cleanup any previous test gargbage

View File

@ -33,7 +33,6 @@ import org.apache.cassandra.cql3.QueryProcessor;
import org.apache.cassandra.cql3.UntypedResultSet; import org.apache.cassandra.cql3.UntypedResultSet;
import org.apache.cassandra.dht.ByteOrderedPartitioner.BytesToken; import org.apache.cassandra.dht.ByteOrderedPartitioner.BytesToken;
import org.apache.cassandra.dht.Token; import org.apache.cassandra.dht.Token;
import org.apache.cassandra.schema.SchemaKeyspace;
import org.apache.cassandra.transport.ProtocolVersion; import org.apache.cassandra.transport.ProtocolVersion;
import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.FBUtilities;
@ -53,9 +52,6 @@ public class SystemKeyspaceTest
{ {
DatabaseDescriptor.daemonInitialization(); DatabaseDescriptor.daemonInitialization();
CommitLog.instance.start(); CommitLog.instance.start();
if (FBUtilities.isWindows)
WindowsFailedSnapshotTracker.deleteOldSnapshots();
} }
@Test @Test
@ -98,26 +94,9 @@ public class SystemKeyspaceTest
assert firstId.equals(secondId) : String.format("%s != %s%n", firstId.toString(), secondId.toString()); assert firstId.equals(secondId) : String.format("%s != %s%n", firstId.toString(), secondId.toString());
} }
private void assertDeletedOrDeferred(int expectedCount) private void assertDeleted()
{ {
if (FBUtilities.isWindows) assertTrue(getSystemSnapshotFiles(SchemaConstants.SYSTEM_KEYSPACE_NAME).isEmpty());
assertEquals(expectedCount, getDeferredDeletionCount());
else
assertTrue(getSystemSnapshotFiles(SchemaConstants.SYSTEM_KEYSPACE_NAME).isEmpty());
}
private int getDeferredDeletionCount()
{
try
{
Class c = Class.forName("java.io.DeleteOnExitHook");
LinkedHashSet<String> files = (LinkedHashSet<String>)FBUtilities.getProtectedField(c, "files").get(c);
return files.size();
}
catch (Exception e)
{
throw new RuntimeException(e);
}
} }
@Test @Test
@ -128,15 +107,13 @@ public class SystemKeyspaceTest
cfs.clearUnsafe(); cfs.clearUnsafe();
Keyspace.clearSnapshot(null, SchemaConstants.SYSTEM_KEYSPACE_NAME); Keyspace.clearSnapshot(null, SchemaConstants.SYSTEM_KEYSPACE_NAME);
int baseline = getDeferredDeletionCount();
SystemKeyspace.snapshotOnVersionChange(); SystemKeyspace.snapshotOnVersionChange();
assertDeletedOrDeferred(baseline); assertDeleted();
// now setup system.local as if we're upgrading from a previous version // now setup system.local as if we're upgrading from a previous version
setupReleaseVersion(getOlderVersionString()); setupReleaseVersion(getOlderVersionString());
Keyspace.clearSnapshot(null, SchemaConstants.SYSTEM_KEYSPACE_NAME); Keyspace.clearSnapshot(null, SchemaConstants.SYSTEM_KEYSPACE_NAME);
assertDeletedOrDeferred(baseline); assertDeleted();
// Compare versions again & verify that snapshots were created for all tables in the system ks // Compare versions again & verify that snapshots were created for all tables in the system ks
SystemKeyspace.snapshotOnVersionChange(); SystemKeyspace.snapshotOnVersionChange();
@ -153,10 +130,9 @@ public class SystemKeyspaceTest
SystemKeyspace.snapshotOnVersionChange(); SystemKeyspace.snapshotOnVersionChange();
// snapshotOnVersionChange for upgrade case will open a SSTR when the CFS is flushed. On Windows, we won't be // snapshotOnVersionChange for upgrade case will open a SSTR when the CFS is flushed.
// able to delete hard-links to that file while segments are memory-mapped, so they'll be marked for deferred deletion.
// 10 files expected. // 10 files expected.
assertDeletedOrDeferred(baseline + 10); assertDeleted();
Keyspace.clearSnapshot(null, SchemaConstants.SYSTEM_KEYSPACE_NAME); Keyspace.clearSnapshot(null, SchemaConstants.SYSTEM_KEYSPACE_NAME);
} }

View File

@ -1,107 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.db.commitlog;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.Util;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.DecoratedKey;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.RowUpdateBuilder;
import org.apache.cassandra.db.WindowsFailedSnapshotTracker;
import org.apache.cassandra.io.sstable.SnapshotDeletingTask;
import org.apache.cassandra.schema.KeyspaceParams;
import org.apache.cassandra.service.GCInspector;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
public class SnapshotDeletingTest
{
private static final String KEYSPACE1 = "Keyspace1";
private static final String CF_STANDARD1 = "CF_STANDARD1";
@BeforeClass
public static void defineSchema() throws Exception
{
DatabaseDescriptor.daemonInitialization();
GCInspector.register();
// Needed to init the output file where we print failed snapshots. This is called on node startup.
WindowsFailedSnapshotTracker.deleteOldSnapshots();
SchemaLoader.prepareServer();
SchemaLoader.createKeyspace(KEYSPACE1,
KeyspaceParams.simple(1),
SchemaLoader.standardCFMD(KEYSPACE1, CF_STANDARD1));
}
@Test
public void testCompactionHook() throws Exception
{
Assume.assumeTrue(FBUtilities.isWindows);
Keyspace keyspace = Keyspace.open(KEYSPACE1);
ColumnFamilyStore store = keyspace.getColumnFamilyStore(CF_STANDARD1);
store.clearUnsafe();
populate(10000);
store.snapshot("snapshot1");
// Confirm snapshot deletion fails. Sleep for a bit just to make sure the SnapshotDeletingTask has
// time to run and fail.
Thread.sleep(500);
store.clearSnapshot("snapshot1");
assertEquals(1, SnapshotDeletingTask.pendingDeletionCount());
// Compact the cf and confirm that the executor's after hook calls rescheduleDeletion
populate(20000);
store.forceBlockingFlush();
store.forceMajorCompaction();
long start = System.currentTimeMillis();
while (System.currentTimeMillis() - start < 1000 && SnapshotDeletingTask.pendingDeletionCount() > 0)
{
Thread.yield();
}
assertEquals(0, SnapshotDeletingTask.pendingDeletionCount());
}
private void populate(int rowCount) {
long timestamp = System.currentTimeMillis();
TableMetadata cfm = Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_STANDARD1).metadata();
for (int i = 0; i <= rowCount; i++)
{
DecoratedKey key = Util.dk(Integer.toString(i));
for (int j = 0; j < 10; j++)
{
new RowUpdateBuilder(cfm, timestamp, 0, key.getKey())
.clustering(Integer.toString(j))
.add("val", ByteBufferUtil.EMPTY_BYTE_BUFFER)
.build()
.applyUnsafe();
}
}
}
}

View File

@ -1290,8 +1290,7 @@ public class LogTransactionTest extends AbstractTransactionalTest
} }
// Check either that a temporary file is expected to exist (in the existingFiles) or that // Check either that a temporary file is expected to exist (in the existingFiles) or that
// it does not exist any longer (on Windows we need to check File.exists() because a list // it does not exist any longer.
// might return a file as existing even if it does not)
private static void assertFiles(Iterable<String> existingFiles, Set<File> temporaryFiles) private static void assertFiles(Iterable<String> existingFiles, Set<File> temporaryFiles)
{ {
for (String filePath : existingFiles) for (String filePath : existingFiles)

View File

@ -97,7 +97,6 @@ public class SSTableLoaderTest
FileUtils.deleteRecursive(tmpdir); FileUtils.deleteRecursive(tmpdir);
} catch (FSWriteError e) { } catch (FSWriteError e) {
/* /*
Windows does not allow a mapped file to be deleted, so we probably forgot to clean the buffers somewhere.
We force a GC here to force buffer deallocation, and then try deleting the directory again. We force a GC here to force buffer deallocation, and then try deleting the directory again.
For more information, see: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4715154 For more information, see: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4715154
If this is not the problem, the exception will be rethrown anyway. If this is not the problem, the exception will be rethrown anyway.

View File

@ -33,7 +33,6 @@ import org.apache.cassandra.db.rows.*;
import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.io.sstable.format.SSTableReadsListener; import org.apache.cassandra.io.sstable.format.SSTableReadsListener;
import org.apache.cassandra.io.sstable.format.SSTableWriter; import org.apache.cassandra.io.sstable.format.SSTableWriter;
import org.apache.cassandra.utils.FBUtilities;
import static junit.framework.Assert.fail; import static junit.framework.Assert.fail;
import static org.apache.cassandra.service.ActiveRepairService.NO_PENDING_REPAIR; import static org.apache.cassandra.service.ActiveRepairService.NO_PENDING_REPAIR;
@ -44,7 +43,7 @@ import static org.junit.Assert.assertTrue;
public class SSTableWriterTest extends SSTableWriterTestBase public class SSTableWriterTest extends SSTableWriterTestBase
{ {
@Test @Test
public void testAbortTxnWithOpenEarlyShouldRemoveSSTable() throws InterruptedException public void testAbortTxnWithOpenEarlyShouldRemoveSSTable()
{ {
Keyspace keyspace = Keyspace.open(KEYSPACE); Keyspace keyspace = Keyspace.open(KEYSPACE);
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(CF); ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(CF);
@ -81,13 +80,9 @@ public class SSTableWriterTest extends SSTableWriterTestBase
int datafiles = assertFileCounts(dir.tryListNames()); int datafiles = assertFileCounts(dir.tryListNames());
assertEquals(datafiles, 1); assertEquals(datafiles, 1);
// These checks don't work on Windows because the writer has the channel still LifecycleTransaction.waitForDeletions();
// open till .abort() is called (via the builder) assertFileCounts(dir.tryListNames());
if (!FBUtilities.isWindows)
{
LifecycleTransaction.waitForDeletions();
assertFileCounts(dir.tryListNames());
}
writer.abort(); writer.abort();
txn.abort(); txn.abort();
LifecycleTransaction.waitForDeletions(); LifecycleTransaction.waitForDeletions();
@ -130,13 +125,9 @@ public class SSTableWriterTest extends SSTableWriterTestBase
assertEquals(datafiles, 1); assertEquals(datafiles, 1);
sstable.selfRef().release(); sstable.selfRef().release();
// These checks don't work on Windows because the writer has the channel still
// open till .abort() is called (via the builder) LifecycleTransaction.waitForDeletions();
if (!FBUtilities.isWindows) assertFileCounts(dir.tryListNames());
{
LifecycleTransaction.waitForDeletions();
assertFileCounts(dir.tryListNames());
}
txn.abort(); txn.abort();
LifecycleTransaction.waitForDeletions(); LifecycleTransaction.waitForDeletions();
@ -184,13 +175,9 @@ public class SSTableWriterTest extends SSTableWriterTestBase
int datafiles = assertFileCounts(dir.tryListNames()); int datafiles = assertFileCounts(dir.tryListNames());
assertEquals(datafiles, 2); assertEquals(datafiles, 2);
// These checks don't work on Windows because the writer has the channel still LifecycleTransaction.waitForDeletions();
// open till .abort() is called (via the builder) assertFileCounts(dir.tryListNames());
if (!FBUtilities.isWindows)
{
LifecycleTransaction.waitForDeletions();
assertFileCounts(dir.tryListNames());
}
txn.abort(); txn.abort();
LifecycleTransaction.waitForDeletions(); LifecycleTransaction.waitForDeletions();
datafiles = assertFileCounts(dir.tryListNames()); datafiles = assertFileCounts(dir.tryListNames());

View File

@ -44,7 +44,6 @@ import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.io.sstable.format.SSTableReader; import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.io.sstable.format.SSTableWriter; import org.apache.cassandra.io.sstable.format.SSTableWriter;
import org.apache.cassandra.schema.KeyspaceParams; import org.apache.cassandra.schema.KeyspaceParams;
import org.apache.cassandra.utils.FBUtilities;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@ -67,15 +66,6 @@ public class SSTableWriterTestBase extends SchemaLoader
{ {
DatabaseDescriptor.daemonInitialization(); DatabaseDescriptor.daemonInitialization();
if (FBUtilities.isWindows)
{
standardMode = DatabaseDescriptor.getDiskAccessMode();
indexMode = DatabaseDescriptor.getIndexAccessMode();
DatabaseDescriptor.setDiskAccessMode(Config.DiskAccessMode.standard);
DatabaseDescriptor.setIndexAccessMode(Config.DiskAccessMode.standard);
}
SchemaLoader.prepareServer(); SchemaLoader.prepareServer();
SchemaLoader.createKeyspace(KEYSPACE, SchemaLoader.createKeyspace(KEYSPACE,
KeyspaceParams.simple(1), KeyspaceParams.simple(1),

View File

@ -26,14 +26,12 @@ import java.util.Set;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.apache.cassandra.config.Config;
import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Murmur3Partitioner; import org.apache.cassandra.dht.Murmur3Partitioner;
import org.apache.cassandra.dht.Range; import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token; import org.apache.cassandra.dht.Token;
import org.apache.cassandra.repair.RepairParallelism; import org.apache.cassandra.repair.RepairParallelism;
import org.apache.cassandra.utils.FBUtilities;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@ -52,11 +50,7 @@ public class RepairOptionTest
// parse with empty options // parse with empty options
RepairOption option = RepairOption.parse(new HashMap<String, String>(), partitioner); RepairOption option = RepairOption.parse(new HashMap<String, String>(), partitioner);
assertTrue(option.getParallelism() == RepairParallelism.SEQUENTIAL);
if (FBUtilities.isWindows && (DatabaseDescriptor.getDiskAccessMode() != Config.DiskAccessMode.standard || DatabaseDescriptor.getIndexAccessMode() != Config.DiskAccessMode.standard))
assertTrue(option.getParallelism() == RepairParallelism.PARALLEL);
else
assertTrue(option.getParallelism() == RepairParallelism.SEQUENTIAL);
assertFalse(option.isPrimaryRange()); assertFalse(option.isPrimaryRange());
assertFalse(option.isIncremental()); assertFalse(option.isIncremental());

View File

@ -19,9 +19,7 @@
package org.apache.cassandra.service; package org.apache.cassandra.service;
import org.apache.cassandra.io.util.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.*; import java.util.*;
@ -37,7 +35,6 @@ import org.junit.Test;
import org.apache.cassandra.audit.AuditLogManager; import org.apache.cassandra.audit.AuditLogManager;
import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.Keyspace; import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.db.WindowsFailedSnapshotTracker;
import org.apache.cassandra.db.commitlog.CommitLog; import org.apache.cassandra.db.commitlog.CommitLog;
import org.apache.cassandra.dht.Murmur3Partitioner; import org.apache.cassandra.dht.Murmur3Partitioner;
import org.apache.cassandra.dht.Murmur3Partitioner.LongToken; import org.apache.cassandra.dht.Murmur3Partitioner.LongToken;
@ -53,13 +50,11 @@ import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.locator.PropertyFileSnitch; import org.apache.cassandra.locator.PropertyFileSnitch;
import org.apache.cassandra.locator.TokenMetadata; import org.apache.cassandra.locator.TokenMetadata;
import org.apache.cassandra.schema.*; import org.apache.cassandra.schema.*;
import org.apache.cassandra.io.util.FileWriter;
import org.apache.cassandra.utils.FBUtilities; import org.apache.cassandra.utils.FBUtilities;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
public class StorageServiceServerTest public class StorageServiceServerTest
{ {
@ -88,75 +83,6 @@ public class StorageServiceServerTest
StorageService.instance.takeSnapshot(UUID.randomUUID().toString()); StorageService.instance.takeSnapshot(UUID.randomUUID().toString());
} }
private void checkTempFilePresence(File f, boolean exist)
{
for (int i = 0; i < 5; i++)
{
File subdir = new File(f, Integer.toString(i));
subdir.tryCreateDirectory();
for (int j = 0; j < 5; j++)
{
File subF = new File(subdir, Integer.toString(j));
assert(exist ? subF.exists() : !subF.exists());
}
}
}
@Test
public void testSnapshotFailureHandler() throws IOException
{
assumeTrue(FBUtilities.isWindows);
// Initial "run" of Cassandra, nothing in failed snapshot file
WindowsFailedSnapshotTracker.deleteOldSnapshots();
File f = new File(System.getenv("TEMP") + File.pathSeparator() + Integer.toString(new Random().nextInt()));
f.tryCreateDirectory();
f.deleteOnExit();
for (int i = 0; i < 5; i++)
{
File subdir = new File(f, Integer.toString(i));
subdir.tryCreateDirectory();
for (int j = 0; j < 5; j++)
new File(subdir, Integer.toString(j)).createFileIfNotExists();
}
checkTempFilePresence(f, true);
// Confirm deletion is recursive
for (int i = 0; i < 5; i++)
WindowsFailedSnapshotTracker.handleFailedSnapshot(new File(f, Integer.toString(i)));
assertTrue(new File(WindowsFailedSnapshotTracker.TODELETEFILE).exists());
// Simulate shutdown and restart of C* node, closing out the list of failed snapshots.
WindowsFailedSnapshotTracker.resetForTests();
// Perform new run, mimicking behavior of C* at startup
WindowsFailedSnapshotTracker.deleteOldSnapshots();
checkTempFilePresence(f, false);
// Check to make sure we don't delete non-temp, non-datafile locations
WindowsFailedSnapshotTracker.resetForTests();
PrintWriter tempPrinter = new PrintWriter(new FileWriter(new File(WindowsFailedSnapshotTracker.TODELETEFILE), File.WriteMode.APPEND));
tempPrinter.println(".safeDir");
tempPrinter.close();
File protectedDir = new File(".safeDir");
protectedDir.tryCreateDirectory();
File protectedFile = new File(protectedDir, ".safeFile");
protectedFile.createFileIfNotExists();
WindowsFailedSnapshotTracker.handleFailedSnapshot(protectedDir);
WindowsFailedSnapshotTracker.deleteOldSnapshots();
assertTrue(protectedDir.exists());
assertTrue(protectedFile.exists());
protectedFile.tryDelete();
protectedDir.tryDelete();
}
@Test @Test
public void testTableSnapshot() throws IOException public void testTableSnapshot() throws IOException
{ {

View File

@ -43,11 +43,11 @@ public class MonotonicClockTest
nowNanos = Math.max(nowNanos, nanoTime()); nowNanos = Math.max(nowNanos, nanoTime());
long convertedNow = approxTime.translate().toMillisSinceEpoch(nowNanos); long convertedNow = approxTime.translate().toMillisSinceEpoch(nowNanos);
int maxDiff = FBUtilities.isWindows ? 15 : 1; int maxDiff = 1;
assertTrue("convertedNow = " + convertedNow + " lastConverted = " + lastConverted + " in iteration " + ii, assertTrue("convertedNow = " + convertedNow + " lastConverted = " + lastConverted + " in iteration " + ii,
convertedNow >= (lastConverted - maxDiff)); convertedNow >= (lastConverted - maxDiff));
maxDiff = FBUtilities.isWindows ? 25 : 2; maxDiff = 2;
assertTrue("now = " + now + " convertedNow = " + convertedNow + " in iteration " + ii, assertTrue("now = " + now + " convertedNow = " + convertedNow + " in iteration " + ii,
(maxDiff - 2) <= convertedNow); (maxDiff - 2) <= convertedNow);

View File

@ -24,8 +24,6 @@ import java.net.SocketException;
import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.stress.settings.StressSettings; import org.apache.cassandra.stress.settings.StressSettings;
import org.apache.cassandra.stress.util.MultiResultLogger; import org.apache.cassandra.stress.util.MultiResultLogger;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.WindowsTimer;
import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.exception.ExceptionUtils;
public final class Stress public final class Stress
@ -57,18 +55,9 @@ public final class Stress
public static void main(String[] arguments) throws Exception public static void main(String[] arguments) throws Exception
{ {
if (FBUtilities.isWindows) System.exit(run(arguments));
WindowsTimer.startTimerPeriod(1);
int exitCode = run(arguments);
if (FBUtilities.isWindows)
WindowsTimer.endTimerPeriod(1);
System.exit(exitCode);
} }
private static int run(String[] arguments) private static int run(String[] arguments)
{ {
try try