blob: c78a3fc9945c11f22dbe36144e24223be4a819d1 [file] [log] [blame]
#
# 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.
# NOTE: All param tuning can be done in the SetCassandraEnvironment Function below
#-----------------------------------------------------------------------------
Function SetCassandraHome()
{
if (! $env:CASSANDRA_HOME)
{
$cwd = [System.IO.Directory]::GetCurrentDirectory()
$cwd = Split-Path $cwd -parent
$env:CASSANDRA_HOME = $cwd -replace "\\", "/"
}
}
#-----------------------------------------------------------------------------
Function SetCassandraMain()
{
if (! $env:CASSANDRA_MAIN)
{
$env:CASSANDRA_MAIN="org.apache.cassandra.service.CassandraDaemon"
}
}
#-----------------------------------------------------------------------------
Function BuildClassPath
{
$cp = """$env:CASSANDRA_HOME\conf"""
foreach ($file in Get-ChildItem "$env:CASSANDRA_HOME\lib\*.jar")
{
$file = $file -replace "\\", "/"
$cp = $cp + ";" + """$file"""
}
# Add build/classes/main so it works in development
$cp = $cp + ";" + """$env:CASSANDRA_HOME\build\classes\main"";""$env:CASSANDRA_HOME\build\classes\thrift"""
$env:CLASSPATH=$cp
}
#-----------------------------------------------------------------------------
Function CalculateHeapSizes
{
# Check if swapping is enabled on the host and warn if so - reference CASSANDRA-7316
$osInfo = Get-WmiObject -class "Win32_computersystem"
$autoPage = $osInfo.AutomaticManagedPageFile
if ($autoPage)
{
echo "*---------------------------------------------------------------------*"
echo "*---------------------------------------------------------------------*"
echo ""
echo " WARNING! Automatic page file configuration detected."
echo " It is recommended that you disable swap when running Cassandra"
echo " for performance and stability reasons."
echo ""
echo "*---------------------------------------------------------------------*"
echo "*---------------------------------------------------------------------*"
}
else
{
$pageFileInfo = Get-WmiObject -class "Win32_PageFileSetting" -EnableAllPrivileges
$pageFileCount = $PageFileInfo.Count
if ($pageFileInfo)
{
$files = @()
$sizes = @()
$hasSizes = $FALSE
# PageFileCount isn't populated and obj comes back as single if there's only 1
if ([string]::IsNullOrEmpty($PageFileCount))
{
$PageFileCount = 1
$files += $PageFileInfo.Name
if ($PageFileInfo.MaximumSize -ne 0)
{
$hasSizes = $TRUE
$sizes += $PageFileInfo.MaximumSize
}
}
else
{
for ($i = 0; $i -le $PageFileCount; $i++)
{
$files += $PageFileInfo[$i].Name
if ($PageFileInfo[$i].MaximumSize -ne 0)
{
$hasSizes = $TRUE
$sizes += $PageFileInfo[$i].MaximumSize
}
}
}
echo "*---------------------------------------------------------------------*"
echo "*---------------------------------------------------------------------*"
echo ""
echo " WARNING! $PageFileCount swap file(s) detected"
for ($i = 0; $i -lt $PageFileCount; $i++)
{
$toPrint = " Name: " + $files[$i]
if ($hasSizes)
{
$toPrint = $toPrint + " Size: " + $sizes[$i]
$toPrint = $toPrint -replace [Environment]::NewLine, ""
}
echo $toPrint
}
echo " It is recommended that you disable swap when running Cassandra"
echo " for performance and stability reasons."
echo ""
echo "*---------------------------------------------------------------------*"
echo "*---------------------------------------------------------------------*"
}
}
# Validate that we need to run this function and that our config is good
if ($env:MAX_HEAP_SIZE -and $env:HEAP_NEWSIZE)
{
return
}
if ((($env:MAX_HEAP_SIZE -and !$env:HEAP_NEWSIZE) -or (!$env:MAX_HEAP_SIZE -and $env:HEAP_NEWSIZE)) -and ($using_cms -eq $true))
{
echo "Please set or unset MAX_HEAP_SIZE and HEAP_NEWSIZE in pairs. Aborting startup."
exit 1
}
$memObject = Get-WMIObject -class win32_physicalmemory
if ($memObject -eq $null)
{
echo "WARNING! Could not determine system memory. Defaulting to 2G heap, 512M newgen. Manually override in conf\jvm.options for different heap values."
$env:MAX_HEAP_SIZE = "2048M"
$env:HEAP_NEWSIZE = "512M"
return
}
$memory = ($memObject | Measure-Object Capacity -Sum).sum
$memoryMB = [Math]::Truncate($memory / (1024*1024))
$cpu = gwmi Win32_ComputerSystem | Select-Object NumberOfLogicalProcessors
$systemCores = $cpu.NumberOfLogicalProcessors
# set max heap size based on the following
# max(min(1/2 ram, 1024MB), min(1/4 ram, 8GB))
# calculate 1/2 ram and cap to 1024MB
# calculate 1/4 ram and cap to 8192MB
# pick the max
$halfMem = [Math]::Truncate($memoryMB / 2)
$quarterMem = [Math]::Truncate($halfMem / 2)
if ($halfMem -gt 1024)
{
$halfMem = 1024
}
if ($quarterMem -gt 8192)
{
$quarterMem = 8192
}
$maxHeapMB = ""
if ($halfMem -gt $quarterMem)
{
$maxHeapMB = $halfMem
}
else
{
$maxHeapMB = $quarterMem
}
$env:MAX_HEAP_SIZE = [System.Convert]::ToString($maxHeapMB) + "M"
# Young gen: min(max_sensible_per_modern_cpu_core * num_cores, 1/4
$maxYGPerCore = 100
$maxYGTotal = $maxYGPerCore * $systemCores
$desiredYG = [Math]::Truncate($maxHeapMB / 4)
if ($desiredYG -gt $maxYGTotal)
{
$env:HEAP_NEWSIZE = [System.Convert]::ToString($maxYGTotal) + "M"
}
else
{
$env:HEAP_NEWSIZE = [System.Convert]::ToString($desiredYG) + "M"
}
}
#-----------------------------------------------------------------------------
Function ParseJVMInfo
{
# grab info about the JVM
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "$env:JAVA_BIN"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "-d64 -version"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stderr = $p.StandardError.ReadToEnd()
$env:JVM_ARCH = "64-bit"
if ($stderr.Contains("Error"))
{
# 32-bit JVM. re-run w/out -d64
echo "Failed 64-bit check. Re-running to get version from 32-bit"
$pinfo.Arguments = "-version"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stderr = $p.StandardError.ReadToEnd()
$env:JVM_ARCH = "32-bit"
}
$sa = $stderr.Split("""")
$env:JVM_VERSION = $sa[1]
if ($stderr.Contains("OpenJDK"))
{
$env:JVM_VENDOR = "OpenJDK"
}
elseif ($stderr.Contains("Java(TM)"))
{
$env:JVM_VENDOR = "Oracle"
}
else
{
$JVM_VENDOR = "other"
}
$pa = $sa[1].Split("_")
$subVersion = $pa[1]
# Deal with -b (build) versions
if ($subVersion -contains '-')
{
$patchAndBuild = $subVersion.Split("-")
$subVersion = $patchAndBuild[0]
}
$env:JVM_PATCH_VERSION = $subVersion
}
#-----------------------------------------------------------------------------
Function SetCassandraEnvironment
{
if (Test-Path Env:\JAVA_HOME)
{
$env:JAVA_BIN = "$env:JAVA_HOME\bin\java.exe"
}
elseif (Get-Command "java.exe")
{
$env:JAVA_BIN = "java.exe"
}
else
{
echo "ERROR! No JAVA_HOME set and could not find java.exe in the path."
exit
}
SetCassandraHome
$env:CASSANDRA_CONF = "$env:CASSANDRA_HOME\conf"
$env:CASSANDRA_PARAMS="-Dcassandra -Dlogback.configurationFile=logback.xml"
$logdir = "$env:CASSANDRA_HOME\logs"
$storagedir = "$env:CASSANDRA_HOME\data"
$env:CASSANDRA_PARAMS = $env:CASSANDRA_PARAMS + " -Dcassandra.logdir=""$logdir"" -Dcassandra.storagedir=""$storagedir"""
SetCassandraMain
BuildClassPath
# Override these to set the amount of memory to allocate to the JVM at
# start-up. For production use you may wish to adjust this for your
# environment. MAX_HEAP_SIZE is the total amount of memory dedicated
# to the Java heap. HEAP_NEWSIZE refers to the size of the young
# generation. Both MAX_HEAP_SIZE and HEAP_NEWSIZE should be either set
# or not (if you set one, set the other).
#
# The main trade-off for the young generation is that the larger it
# is, the longer GC pause times will be. The shorter it is, the more
# expensive GC will be (usually).
#
# The example HEAP_NEWSIZE assumes a modern 8-core+ machine for decent
# times. If in doubt, and if you do not particularly want to tweak, go
# 100 MB per physical CPU core.
#GC log path has to be defined here since it needs to find CASSANDRA_HOME
$env:JVM_OPTS="$env:JVM_OPTS -Xloggc:""$env:CASSANDRA_HOME/logs/gc.log"""
# Read user-defined JVM options from jvm.options file
$content = Get-Content "$env:CASSANDRA_CONF\jvm.options"
for ($i = 0; $i -lt $content.Count; $i++)
{
$line = $content[$i]
if ($line.StartsWith("-"))
{
$env:JVM_OPTS = "$env:JVM_OPTS $line"
}
}
$defined_xmn = $env:JVM_OPTS -like '*Xmn*'
$defined_xmx = $env:JVM_OPTS -like '*Xmx*'
$defined_xms = $env:JVM_OPTS -like '*Xms*'
$using_cms = $env:JVM_OPTS -like '*UseConcMarkSweepGC*'
#$env:MAX_HEAP_SIZE="4096M"
#$env:HEAP_NEWSIZE="800M"
CalculateHeapSizes
ParseJVMInfo
# We only set -Xms and -Xmx if they were not defined on jvm.options file
# If defined, both Xmx and Xms should be defined together.
if (($defined_xmx -eq $false) -and ($defined_xms -eq $false))
{
$env:JVM_OPTS="$env:JVM_OPTS -Xms$env:MAX_HEAP_SIZE"
$env:JVM_OPTS="$env:JVM_OPTS -Xmx$env:MAX_HEAP_SIZE"
}
elseif (($defined_xmx -eq $false) -or ($defined_xms -eq $false))
{
echo "Please set or unset -Xmx and -Xms flags in pairs on jvm.options file."
exit
}
# We only set -Xmn flag if it was not defined in jvm.options file
# and if the CMS GC is being used
# If defined, both Xmn and Xmx should be defined together.
if (($defined_xmn -eq $true) -and ($defined_xmx -eq $false))
{
echo "Please set or unset -Xmx and -Xmn flags in pairs on jvm.options file."
exit
}
elseif (($defined_xmn -eq $false) -and ($using_cms -eq $true))
{
$env:JVM_OPTS="$env:JVM_OPTS -Xmn$env:HEAP_NEWSIZE"
}
if (($env:JVM_ARCH -eq "64-Bit") -and ($using_cms -eq $true))
{
$env:JVM_OPTS="$env:JVM_OPTS -XX:+UseCondCardMark"
}
# Add sigar env - see Cassandra-7838
$env:JVM_OPTS = "$env:JVM_OPTS -Djava.library.path=""$env:CASSANDRA_HOME\lib\sigar-bin"""
# Confirm we're on high performance power plan, warn if not
# Change to $true to suppress this warning
$suppressPowerWarning = $false
if (!$suppressPowerWarning)
{
$currentProfile = powercfg /GETACTIVESCHEME
if (!$currentProfile.Contains("High performance"))
{
echo "*---------------------------------------------------------------------*"
echo "*---------------------------------------------------------------------*"
echo ""
echo " WARNING! Detected a power profile other than High Performance."
echo " Performance of this node will suffer."
echo " Modify conf\cassandra.env.ps1 to suppress this warning."
echo ""
echo "*---------------------------------------------------------------------*"
echo "*---------------------------------------------------------------------*"
}
}
# provides hints to the JIT compiler
$env:JVM_OPTS = "$env:JVM_OPTS -XX:CompileCommandFile=""$env:CASSANDRA_CONF\hotspot_compiler"""
# add the jamm javaagent
if (($env:JVM_VENDOR -ne "OpenJDK") -or ($env:JVM_VERSION.CompareTo("1.6.0") -eq 1) -or
(($env:JVM_VERSION -eq "1.6.0") -and ($env:JVM_PATCH_VERSION.CompareTo("22") -eq 1)))
{
$env:JVM_OPTS = "$env:JVM_OPTS -javaagent:""$env:CASSANDRA_HOME\lib\jamm-0.3.0.jar"""
}
# set jvm HeapDumpPath with CASSANDRA_HEAPDUMP_DIR
if ($env:CASSANDRA_HEAPDUMP_DIR)
{
$unixTimestamp = [int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds
$env:JVM_OPTS="$env:JVM_OPTS -XX:HeapDumpPath=""$env:CASSANDRA_HEAPDUMP_DIR\cassandra-$unixTimestamp-pid$pid.hprof"""
}
# stop the jvm on OutOfMemoryError as it can result in some data corruption
# uncomment the preferred option
# ExitOnOutOfMemoryError and CrashOnOutOfMemoryError require a JRE greater or equals to 1.7 update 101 or 1.8 update 92
# $env:JVM_OPTS="$env:JVM_OPTS -XX:+ExitOnOutOfMemoryError"
# $env:JVM_OPTS="$env:JVM_OPTS -XX:+CrashOnOutOfMemoryError"
$env:JVM_OPTS="$env:JVM_OPTS -XX:OnOutOfMemoryError=""taskkill /F /PID %p"""
# print an heap histogram on OutOfMemoryError
# $env:JVM_OPTS="$env:JVM_OPTS -Dcassandra.printHeapHistogramOnOutOfMemoryError=true"
if ($env:JVM_VERSION.CompareTo("1.8.0") -eq -1 -or [convert]::ToInt32($env:JVM_PATCH_VERSION) -lt 40)
{
echo "Cassandra 3.0 and later require Java 8u40 or later."
exit
}
# Specifies the default port over which Cassandra will be available for
# JMX connections.
$JMX_PORT="7199"
# store in env to check if it's avail in verification
$env:JMX_PORT=$JMX_PORT
# Configure the following for JEMallocAllocator and if jemalloc is not available in the system
# library path.
# set LD_LIBRARY_PATH=<JEMALLOC_HOME>/lib/
# $env:JVM_OPTS="$env:JVM_OPTS -Djava.library.path=<JEMALLOC_HOME>/lib/"
# jmx: metrics and administration interface
#
# add this if you're having trouble connecting:
# $env:JVM_OPTS="$env:JVM_OPTS -Djava.rmi.server.hostname=<public name>"
#
# see
# https://blogs.oracle.com/jmxetc/entry/troubleshooting_connection_problems_in_jconsole
# for more on configuring JMX through firewalls, etc. (Short version:
# get it working with no firewall first.)
#
# Due to potential security exploits, Cassandra ships with JMX accessible
# *only* from localhost. To enable remote JMX connections, uncomment lines below
# with authentication and ssl enabled. See https://wiki.apache.org/cassandra/JmxSecurity
#
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.port=$JMX_PORT"
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.rmi.port=$JMX_PORT"
#
# JMX SSL options
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.ssl=true"
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.ssl.need.client.auth=true"
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.protocols=<enabled-protocols>"
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.ssl.enabled.cipher.suites=<enabled-cipher-suites>"
#$env:JVM_OPTS="$env:JVM_OPTS -Djavax.net.ssl.keyStore=C:/keystore"
#$env:JVM_OPTS="$env:JVM_OPTS -Djavax.net.ssl.keyStorePassword=<keystore-password>"
#$env:JVM_OPTS="$env:JVM_OPTS -Djavax.net.ssl.trustStore=C:/truststore"
#$env:JVM_OPTS="$env:JVM_OPTS -Djavax.net.ssl.trustStorePassword=<truststore-password>"
#
# JMX auth options
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.authenticate=true"
## Basic file based authn & authz
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.password.file=C:/jmxremote.password"
#$env:JVM_OPTS="$env:JVM_OPTS -Dcom.sun.management.jmxremote.access.file=C:/jmxremote.access"
## Custom auth settings which can be used as alternatives to JMX's out of the box auth utilities.
## JAAS login modules can be used for authentication by uncommenting these two properties.
## Cassandra ships with a LoginModule implementation - org.apache.cassandra.auth.CassandraLoginModule -
## which delegates to the IAuthenticator configured in cassandra.yaml
#$env:JVM_OPTS="$env:JVM_OPTS -Dcassandra.jmx.remote.login.config=CassandraLogin"
#$env:JVM_OPTS="$env:JVM_OPTS -Djava.security.auth.login.config=C:/cassandra-jaas.config"
## Cassandra also ships with a helper for delegating JMX authz calls to the configured IAuthorizer,
## uncomment this to use it. Requires one of the two authentication options to be enabled
#$env:JVM_OPTS="$env:JVM_OPTS -Dcassandra.jmx.authorizer=org.apache.cassandra.auth.jmx.AuthorizationProxy"
# Default JMX setup, bound to local loopback address only
$env:JVM_OPTS="$env:JVM_OPTS -Dcassandra.jmx.local.port=$JMX_PORT"
$env:JVM_OPTS="$env:JVM_OPTS $env:JVM_EXTRA_OPTS"
}