| #!/bin/bash |
| # 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. |
| # |
| # Filename:- gp_bash_functions.sh |
| # Version:- $Revision$ |
| # Updated:- $Date$ |
| # Status:- Released |
| # Author:- G L Coombe (Greenplum) |
| # Contact:- gcoombe@greenplum.com |
| # Release date:- March 2006 |
| # Release stat:- Greenplum Internal |
| # Brief descn:- Common functions used by various scripts |
| #****************************************************************************** |
| # Update History |
| #****************************************************************************** |
| # Ver Date Who Update |
| #****************************************************************************** |
| # Detailed Description |
| #****************************************************************************** |
| # |
| #****************************************************************************** |
| # Prep Code |
| # |
| #*************************************************************** |
| # Location Functions |
| #****************************************************************************** |
| #Check that SHELL is /bin/bash |
| if [ $SHELL != /bin/bash ] && [ `ls -al /bin/sh|grep -c bash` -ne 1 ];then |
| echo "[FATAL]:-Scripts must be run by a user account that has SHELL=/bin/bash" |
| if [ -f /bin/bash ];then |
| echo "[INFO]:-/bin/bash exists, please update user account shell" |
| else |
| echo "[WARN]:-/bin/bash does not exist, does bash need to be installed?" |
| fi |
| exit 2 |
| fi |
| #CMDPATH is the list of locations to search for commands, in precedence order |
| declare -a CMDPATH |
| CMDPATH=(/usr/kerberos/bin /usr/sfw/bin /opt/sfw/bin /usr/local/bin /bin /usr/bin /sbin /usr/sbin /usr/ucb /sw/bin) |
| |
| #GPPATH is the list of possible locations for the Greenplum Database binaries, in precedence order |
| declare -a GPPATH |
| GPPATH=( $GPHOME $MPPHOME $BIZHOME ) |
| if [ ${#GPPATH[@]} -eq 0 ];then |
| echo "[FATAL]:-GPHOME is not set, need to set this within environment" |
| exit 2 |
| fi |
| |
| #GP_UNIQUE_COMMAND is used to identify the binary directory |
| GP_UNIQUE_COMMAND=gpsyncmaster |
| |
| |
| findCmdInPath() { |
| cmdtofind=$1 |
| |
| if [ $cmdtofind = 'awk' ] && [ `uname` = SunOS ]; then |
| if [ -f "/usr/xpg4/bin/awk" ]; then |
| CMD=/usr/xpg4/bin/awk |
| echo $CMD |
| return |
| else |
| echo $cmdtofind |
| return "Problem in gp_bash_functions, command '/usr/xpg4/bin/awk' not found. You will need to edit the script named gp_bash_functions.sh to properly locate the needed commands for your platform." |
| fi |
| fi |
| for pathel in ${CMDPATH[@]} |
| do |
| CMD=$pathel/$cmdtofind |
| if [ x"$CMD" != x"" ] && [ -f $CMD ]; then |
| echo $CMD |
| return |
| fi |
| done |
| echo $cmdtofind |
| return "Problem in gp_bash_functions, command '$cmdtofind' not found in COMMAND path. You will need to edit the script named gp_bash_functions.sh to properly locate the needed commands for your platform." |
| } |
| |
| findMppPath() { |
| cmdtofind=$GP_UNIQUE_COMMAND |
| |
| for pathel in ${GPPATH[@]} |
| do |
| CMD=`find $pathel -follow -name $cmdtofind | tail -1` |
| if [ x"$CMD" != x"" ] && [ -f $CMD ]; then |
| echo $CMD |
| return |
| fi |
| done |
| } |
| |
| #****************************************************************************** |
| # OS Command Variables |
| #****************************************************************************** |
| AWK=`findCmdInPath awk` |
| BASENAME=`findCmdInPath basename` |
| CAT=`findCmdInPath cat` |
| CLEAR=`findCmdInPath clear` |
| CKSUM=`findCmdInPath cksum` |
| CUT=`findCmdInPath cut` |
| DATE=`findCmdInPath date` |
| DD=`findCmdInPath dd` |
| DIRNAME=`findCmdInPath dirname` |
| DF=`findCmdInPath df` |
| DU=`findCmdInPath du` |
| ECHO=`findCmdInPath echo` |
| #ETHTOOL=`findCmdInPath ethtool` |
| EXPR=`findCmdInPath expr` |
| FIND=`findCmdInPath find` |
| TABECHO=$ECHO |
| PROMPT="$ECHO" |
| #TABECHO="$ECHO -e \t" |
| #PROMPT="$ECHO -n -e \t" |
| GREP=`findCmdInPath grep` |
| GZIPCMD=`findCmdInPath gzip` |
| EGREP=`findCmdInPath egrep` |
| HEAD=`findCmdInPath head` |
| HOSTNAME=`findCmdInPath hostname` |
| IPCS=`findCmdInPath ipcs` |
| IFCONFIG=`findCmdInPath ifconfig` |
| KILL=`findCmdInPath kill` |
| LESSCMD=`findCmdInPath less` |
| LS=`findCmdInPath ls` |
| LOCALE=`findCmdInPath locale` |
| MV=`findCmdInPath mv` |
| MORECMD=`findCmdInPath more` |
| MKDIR=`findCmdInPath mkdir` |
| MKFIFO=`findCmdInPath mkfifo` |
| NETSTAT=`findCmdInPath netstat` |
| PING=`findCmdInPath ping` |
| PS=`findCmdInPath ps` |
| PYTHON=${GPHOME}/ext/python/bin/python |
| RM=`findCmdInPath rm` |
| SCP=`findCmdInPath scp` |
| SED=`findCmdInPath sed` |
| SLEEP=`findCmdInPath sleep` |
| SORT=`findCmdInPath sort` |
| SPLIT=`findCmdInPath split` |
| SSH=`findCmdInPath ssh` |
| TAIL=`findCmdInPath tail` |
| TAR=`findCmdInPath tar` |
| TEE=`findCmdInPath tee` |
| TOUCH=`findCmdInPath touch` |
| #PTIME=`findCmdInPath ptime` |
| TR=`findCmdInPath tr` |
| WC=`findCmdInPath wc` |
| WHICH=`findCmdInPath which` |
| WHOAMI=`findCmdInPath whoami` |
| ZCAT=`findCmdInPath zcat` |
| #***************#****************************************************************************** |
| # Script Specific Variables |
| #****************************************************************************** |
| # By default set error logging level to verbose |
| VERBOSE=1 |
| USER_NAME=`id|$AWK '{print $1}'|$CUT -d"(" -f2|$TR -d ')'` |
| PROG_NAME=`echo $0 | $TR -d '-'` |
| PROG_NAME=`$BASENAME $PROG_NAME` |
| PROG_PIDNAME=`echo $$ $PROG_NAME | awk '{printf "%06d %s\n", $1, $2}'` |
| CALL_HOST=`$HOSTNAME|$CUT -d. -f1` |
| |
| #****************************************************************************** |
| # Locate the postgres routines from the Greenplum release |
| #****************************************************************************** |
| PSQLBIN=`findMppPath` |
| |
| if [ x"$PSQLBIN" = x"" ];then |
| echo "Problem in gp_bash_functions, command '$GP_UNIQUE_COMMAND' not found in Greenplum path. Try setting GPHOME to the location of your Greenplum distribution" |
| exit 99 |
| fi |
| |
| PSQLBIN=`$DIRNAME $PSQLBIN` |
| SCRIPTDIR="`$DIRNAME $PSQLBIN`/bin" |
| #****************************************************************************** |
| # Greenplum Scripts |
| #****************************************************************************** |
| GPACTIVATEMASTER=$SCRIPTDIR/gpactivatemaster |
| GPACTIVATESTANDBY=$SCRIPTDIR/gpactivatestandby |
| GPADDMIRRORS=$SCRIPTDIR/gpaddmirrors |
| GPINITSYSTEM=$SCRIPTDIR/gpinitsystem |
| GPCONFIG=$SCRIPTDIR/gpconfig |
| GPCRONDUMP=$SCRIPTDIR/gpcrondump |
| GPDELETESYSTEM=$SCRIPTDIR/gpdeletesystem |
| GPINITSTANDBY=$SCRIPTDIR/gpinitstandby |
| GPREBUILDCLUSTER=$SCRIPTDIR/gprebuildcluster |
| GPREBUILDSEG=$SCRIPTDIR/gprebuildseg |
| GPRECOVERSEG=$SCRIPTDIR/gprecoverseg |
| GPSIZECALC=$SCRIPTDIR/gpsizecalc |
| GPSKEW=$SCRIPTDIR/gpskew |
| GPSTART=$SCRIPTDIR/gpstart |
| GPSTATE=$SCRIPTDIR/gpstate |
| GPSTOP=$SCRIPTDIR/gpstop |
| MAILFILE=$SCRIPTDIR/mail_contacts |
| HMAILFILE=$HOME/mail_contacts |
| GPDOCDIR=${GPHOME}/docs/cli_help/ |
| GPSUBSCRIPTDIR=${SCRIPTDIR}/lib |
| #****************************************************************************** |
| # Greenplum Command Variables |
| #****************************************************************************** |
| INITDB=$PSQLBIN/initdb |
| MPPLOADER=$CMDBIN/loader.sh |
| PG_CTL=$PSQLBIN/pg_ctl |
| PG_DUMP=$PSQLBIN/pg_dump |
| PG_DUMPALL=$PSQLBIN/pg_dumpall |
| PG_RESTORE=$PSQLBIN/pg_restore |
| PSQL=$PSQLBIN/psql |
| GP_DUMP=$PSQLBIN/gp_dump |
| GP_RESTORE=$PSQLBIN/gp_restore |
| GPSYNCMASTER=$PSQLBIN/gpsyncmaster |
| GP_CHECK_HDFS=$PSQLBIN/gpcheckhdfs |
| |
| GPLISTDATABASEQTY="SELECT d.datname as \"Name\", |
| r.rolname as \"Owner\", |
| pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\" |
| FROM pg_catalog.pg_database d |
| JOIN pg_catalog.pg_authid r ON d.datdba = r.oid |
| ORDER BY 1;" |
| #****************************************************************************** |
| # Greenplum OS Settings |
| #****************************************************************************** |
| OS_OPENFILES=65535 |
| #****************************************************************************** |
| # General Variables |
| #****************************************************************************** |
| HOSTFILE=/etc/hosts |
| PG_PID=postmaster.pid |
| PG_OPT=postmaster.opts |
| PG_CONF=postgresql.conf |
| PG_HBA=pg_hba.conf |
| GP_TEMP_DIRECTORIES_FILE="gp_temporary_files_directories" |
| if [ x"$TRUSTED_SHELL" = x"" ]; then TRUSTED_SHELL="$SSH"; fi |
| if [ x"$TRUSTED_COPY" = x"" ]; then TRUSTED_COPY="$SCP"; fi |
| PG_CONF_ADD_FILE=$WORKDIR/postgresql_conf_gp_additions |
| RECOVER_FLAG=/tmp/active_recovery_in_progress |
| SCHEMA_FILE=cdb_schema.sql |
| DEFAULTDB=template0 |
| |
| CONFIG_TABLE="(SELECT dbid, content, role, preferred_role, mode, status, |
| hostname, address, port, fselocation as datadir, |
| replication_port, san_mounts |
| FROM gp_segment_configuration |
| JOIN pg_filespace_entry ON (dbid = fsedbid) |
| JOIN pg_filespace fs ON (fs.oid = fsefsoid) |
| WHERE fsname = 'pg_system')" |
| |
| GP_PG_VIEW="(SELECT dbid, role = 'p' as isprimary, content, status = 'u' as valid, |
| preferred_role = 'p' as definedprimary FROM gp_segment_configuration)" |
| |
| ACTIVITY_TABLE=pg_stat_activity |
| GP_INITDB_VER_TABLE=gp_version_at_initdb |
| CLASS_TABLE=pg_class |
| EXTERNAL_TABLE=pg_exttable |
| SCHEMA_TABLE=pg_namespace |
| ATTRIBUTE_TABLE=pg_attribute |
| INHERIT_TABLE=pg_inherits |
| INDEX_TABLE=pg_indexes |
| TYPE_TABLE=pg_type |
| CONSTRAINT_TABLE=pg_constraint |
| RULES_TABLE=pg_rules |
| PG_SIZE_FUNC=pg_relation_size |
| DISTRIB_TABLE=gp_distribution_policy |
| CHILD_TABLE_ID="_c_d_" |
| DEFAULT_CHK_PT_SEG=8 |
| #DEFAULT_IP_ALLOW="0.0.0.0/0" |
| DEFAULT_QD_MAX_CONNECT=250 |
| QE_CONNECT_FACTOR=3 |
| # DEFAULT_BUFFERS sets the default shared_buffers unless overridden by '-b'. |
| # It applies to the master db and segment dbs. Specify either the number of |
| # buffers (without suffix) or the amount of memory to use for buffers (with |
| # case-insensitive suffix 'kB', 'MB' or 'GB'). |
| DEFAULT_BUFFERS=128000kB |
| DEBUG_LEVEL=0 |
| BATCH_DEFAULT=60 |
| WAIT_LIMIT=1800 |
| WARN_MARK="<<<<<" |
| IDX_TYPE_ARRAY=(btree bitmap hash) |
| #****************************************************************************** |
| # Functions |
| #****************************************************************************** |
| |
| IN_ARRAY () { |
| for v in $2; do |
| if [ x"$1" == x"$v" ]; then |
| return 1 |
| fi |
| done |
| return 0 |
| } |
| |
| CHK_DB_QD_SET () { |
| if [ ! $MASTER_DATA_DIRECTORY ]; then |
| ERROR_EXIT "[FATAL]:-MASTER_DATA_DIRECTORY parameter not set, update user start-up file [i.e. .bashrc]." 2 |
| fi |
| } |
| |
| VERSION_INFO () { |
| VERSION=`$HEAD -10 $0|$GREP -i Version: | $CUT -d# -f2|$CUT -d- -f2|$TR -d '\t'` |
| STATUS=`$HEAD -10 $0|$GREP -i Status: | $CUT -d# -f2|$CUT -d- -f2|$TR -d '\t'` |
| UPDATE=`$HEAD -10 $0|$GREP -i Updated:| $CUT -d# -f2|$CUT -d- -f2|$TR -d '\t'` |
| CHK_SUM=`$CKSUM $0|$AWK '{print $1" "$2}'` |
| $ECHO "`basename $0` Version = $VERSION" |
| $ECHO "`basename $0` Status = $STATUS" |
| $ECHO "`basename $0` Update = $UPDATE" |
| $ECHO "`basename $0` Check sum = $CHK_SUM" |
| exit 0 |
| } |
| |
| LOG_MSG () { |
| TIME=`$DATE +%H":"%M":"%S` |
| CUR_DATE=`$DATE +%Y%m%d` |
| DISPLAY_TXT=0 |
| #Check to see if we need to update value of EXIT_STATUS |
| if [ `$ECHO $1|$AWK -F"]" '{print $1}'|$TR -d '\133'|$GREP -c "WARN"` -eq 1 ];then |
| EXIT_STATUS=1 |
| fi |
| if [ `$ECHO $1|$AWK -F"]" '{print $1}'|$TR -d '\133'|$GREP -c "FATAL"` -eq 1 ];then |
| EXIT_STATUS=2 |
| fi |
| WARN=`$ECHO $1|$AWK -F"]" '{print $1}'|$TR -d '\133'|$GREP -c "WARN"` |
| if [ x"$WARN" == x"" ]; then |
| WARN=0 |
| fi |
| if [ $WARN -eq 1 ];then |
| EXIT_STATUS=1 |
| fi |
| FATAL=`$ECHO $1|$AWK -F"]" '{print $1}'|$TR -d '\133'|$GREP -c "FATAL"` |
| if [ x"$FATAL" == x"" ]; then |
| FATAL=0 |
| fi |
| if [ $FATAL -eq 1 ];then |
| EXIT_STATUS=2 |
| fi |
| if [ x"" == x"$DEBUG_LEVEL" ];then |
| DEBUG_LEVEL=1 |
| fi |
| if [ $# -eq 2 ];then |
| DISPLAY_TXT=1 |
| fi |
| if [ $VERBOSE ]; then |
| if [ $DEBUG_LEVEL -eq 1 ] || [ $DISPLAY_TXT -eq 1 ];then |
| $ECHO "${CUR_DATE}:${TIME}:${PROG_PIDNAME}:${CALL_HOST}:${USER_NAME}-$1" | $TEE -a $LOG_FILE |
| else |
| $ECHO "${CUR_DATE}:${TIME}:${PROG_PIDNAME}:${CALL_HOST}:${USER_NAME}-$1" >> $LOG_FILE |
| fi |
| else |
| $ECHO "${CUR_DATE}:${TIME}:${PROG_PIDNAME}:${CALL_HOST}:${USER_NAME}-$1" >> $LOG_FILE |
| fi |
| } |
| |
| POSTGRES_VERSION_CHK() { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| HOST=$1;shift |
| |
| CURRENT_VERSION=`$EXPORT_GPHOME; $EXPORT_LIB_PATH; $GPHOME/bin/postgres --gp-version` |
| VERSION_MATCH=0 |
| |
| VER=`$TRUSTED_SHELL $HOST "$EXPORT_GPHOME; $EXPORT_LIB_PATH; $GPHOME/bin/postgres --gp-version"` |
| if [ $? -ne 0 ] ; then |
| LOG_MSG "[WARN]:- Failed to obtain postgres version on $HOST" 1 |
| EXIT_STATUS=1 |
| VERSION_MATCH=0 |
| fi |
| LOG_MSG "[INFO]:- Current postgres version = $CURRENT_VERSION" |
| LOG_MSG "[INFO]:- postgres version on $HOST = $VER" |
| |
| if [ x"$VER" != x"$CURRENT_VERSION" ] ; then |
| LOG_MSG "[WARN]:-Postgres version does not match. [$CURRENT_VERSION != $VER]" 1 |
| VERSION_MATCH=0 |
| EXIT_STATUS=1 |
| else |
| VERSION_MATCH=1 |
| fi |
| |
| |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| |
| } |
| |
| ERROR_EXIT () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| TIME=`$DATE +%H":"%M":"%S` |
| CUR_DATE=`$DATE +%Y%m%d` |
| $ECHO "${CUR_DATE}:${TIME}:${PROG_NAME}:${CALL_HOST}:${USER_NAME}-$1 Script Exiting!" >> $LOG_FILE |
| $ECHO "${CUR_DATE}:${TIME}:${PROG_NAME}:${CALL_HOST}:${USER_NAME}-$1 Script Exiting!" |
| DEBUG_LEVEL=1 |
| if [ $BACKOUT_FILE ]; then |
| if [ -s $BACKOUT_FILE ]; then |
| LOG_MSG "[WARN]:-Script has left Greenplum Database in an incomplete state" |
| LOG_MSG "[WARN]:-Run command /bin/bash $BACKOUT_FILE to remove these changes" |
| BACKOUT_COMMAND "if [ x$MASTER_HOSTNAME != x\`$HOSTNAME\` ];then $ECHO \"[FATAL]:-Not on original master host $MASTER_HOSTNAME, backout script exiting!\";exit 2;fi" |
| $ECHO "$RM -f $BACKOUT_FILE" >> $BACKOUT_FILE |
| fi |
| fi |
| exit $2 |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| READ_CHK () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| NROWS=`env PGOPTIONS="-c gp_session_role=utility" $PSQL -A -t -p $MASTER_PORT -d "$DEFAULTDB" -c" select * from $CONFIG_TABLE a where port<0;"` |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ];then |
| READ_COUNT=0 |
| #Could not connect to database so set read count to zero |
| LOG_MSG "[WARN]:-Could not obtain read count from database" |
| EXIT_STATUS=1 |
| else |
| if [ x"" == x"$NROWS" ];then |
| READ_COUNT=0 |
| else |
| READ_COUNT=`$ECHO $NROWS|$WC -l` |
| fi |
| LOG_MSG "[INFO]:-Obtained -ve port read count $READ_COUNT" |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| ERROR_CHK () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ $# -ne 3 ];then |
| INITIAL_LEVEL=$DEBUG_LEVEL |
| DEBUG_LEVEL=1 |
| LOG_MSG "[WARN]:-Incorrect # parameters supplied to $FUNCNAME" |
| DEBUG_LEVEL=$INITIAL_LEVEL |
| return;fi |
| RETVAL=$1;shift |
| MSG_TXT=$1;shift |
| ACTION=$1 #1=issue warn, 2=fatal |
| if [ $RETVAL -eq 0 ];then |
| LOG_MSG "[INFO]:-Successfully completed $MSG_TXT" |
| else |
| if [ $ACTION -eq 1 ];then |
| INITIAL_LEVEL=$DEBUG_LEVEL |
| DEBUG_LEVEL=1 |
| LOG_MSG "[WARN]:-Issue with $MSG_TXT" |
| EXIT_STATUS=1 |
| DEBUG_LEVEL=$INITIAL_LEVEL |
| else |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| ERROR_EXIT "[FATAL]:-Failed to complete $MSG_TXT " 2 |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| ED_PG_CONF () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| ED_TMP_FILE=/tmp/ed_text.$$ |
| APPEND=0 |
| FILENAME=$1;shift |
| SEARCH_TXT=$1;shift |
| SUB_TXT="$1";shift |
| KEEP_PREV=$1;shift |
| ED_HOST=$1 |
| if [ x"" == x"$ED_HOST" ]; then |
| if [ `$GREP -c "${SEARCH_TXT}[ ]*=" $FILENAME` -gt 1 ]; then |
| LOG_MSG "[INFO]:-Found more than 1 instance of $SEARCH_TXT in $FILENAME, will append" 1 |
| APPEND=1 |
| fi |
| if [ `$GREP -c "${SEARCH_TXT}[ ]*=" $FILENAME` -eq 0 ] || [ $APPEND -eq 1 ]; then |
| $ECHO $SUB_TXT >> $FILENAME |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[WARN]:-Failed to append line $SUB_TXT to $FILENAME" 1 |
| else |
| LOG_MSG "[INFO]:-Appended line $SUB_TXT to $FILENAME" |
| fi |
| else |
| if [ $KEEP_PREV -eq 0 ];then |
| ed $FILENAME << _EOF_ > /dev/null 2>&1 |
| 1 |
| /${SEARCH_TXT} |
| . |
| i |
| $SUB_TXT # |
| . |
| .,.+1j |
| . |
| w |
| q |
| _EOF_ |
| else |
| ed $FILENAME << _EOF_ > /dev/null 2>&1 |
| 1 |
| /${SEARCH_TXT} |
| . |
| d |
| . |
| -1 |
| a |
| $SUB_TXT |
| . |
| w |
| q |
| _EOF_ |
| fi |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[WARN]:-Failed to replace $SEARCH_TXT in $FILENAME" |
| ERROR_EXIT=1 |
| else |
| LOG_MSG "[INFO]:-Replaced line in $FILENAME" |
| fi |
| fi |
| else |
| if [ `$TRUSTED_SHELL $ED_HOST "$GREP -c \"${SEARCH_TXT}\" $FILENAME"` -gt 1 ]; then |
| LOG_MSG "[INFO]:-Found more than 1 instance of $SEARCH_TXT in $FILENAME on $ED_HOST, will append" 1 |
| APPEND=1 |
| fi |
| if [ `$TRUSTED_SHELL $ED_HOST "$GREP -c \"${SEARCH_TXT}\" $FILENAME"` -eq 0 ] || [ $APPEND -eq 1 ]; then |
| $TRUSTED_SHELL $ED_HOST "$ECHO \"$SUB_TXT\" >> $FILENAME" |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[WARN]:-Failed to append line $SUB_TXT to $FILENAME on $ED_HOST" |
| ERROR_EXIT=1 |
| else |
| LOG_MSG "[INFO]:-Appended line $SUB_TXT to $FILENAME on $ED_HOST" 1 |
| fi |
| else |
| $ECHO 1 > $ED_TMP_FILE |
| $ECHO "/${SEARCH_TXT}" >> $ED_TMP_FILE |
| $ECHO . >> $ED_TMP_FILE |
| if [ $KEEP_PREV -eq 0 ];then |
| $ECHO i >> $ED_TMP_FILE |
| $ECHO "$SUB_TXT #" >> $ED_TMP_FILE |
| $ECHO . >> $ED_TMP_FILE |
| $ECHO ".,.+1j" >> $ED_TMP_FILE |
| $ECHO . >> $ED_TMP_FILE |
| else |
| $ECHO d >> $ED_TMP_FILE |
| $ECHO . >> $ED_TMP_FILE |
| $ECHO -1 >> $ED_TMP_FILE |
| $ECHO a >> $ED_TMP_FILE |
| $ECHO "$SUB_TXT" >> $ED_TMP_FILE |
| $ECHO . >> $ED_TMP_FILE |
| fi |
| $ECHO w >> $ED_TMP_FILE |
| $ECHO q >> $ED_TMP_FILE |
| #$SCP $ED_TMP_FILE ${ED_HOST}:/tmp > /dev/null 2>&1 |
| $CAT $ED_TMP_FILE | $TRUSTED_SHELL ${ED_HOST} $DD of=$ED_TMP_FILE > /dev/null 2>&1 |
| $TRUSTED_SHELL $ED_HOST "ed $FILENAME < $ED_TMP_FILE" > /dev/null 2>&1 |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[WARN]:-Failed to insert $SUB_TXT in $FILENAME on $ED_HOST" |
| ERROR_EXIT=1 |
| else |
| LOG_MSG "[INFO]:-Replaced line in $FILENAME on $ED_HOST" |
| fi |
| $TRUSTED_SHELL $ED_HOST "$RM -f $ED_TMP_FILE" |
| $RM -f $ED_TMP_FILE |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| CHK_EXTERNAL () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| EXTERNAL=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select 1 from $EXTERNAL_TABLE where reloid in (select oid from $CLASS_TABLE where relname='$TABLENAME' and relnamespace in (select oid from $SCHEMA_TABLE where nspname='$SCHEMA_NAME'));"|$WC -l` |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| |
| # Specifies the regular expressions used to parse a qualified table name. |
| declare -r TABLE_IDENTIFIER_PATTERN='((")((([^"]{1,})|""){1,})")|([^".]{1,})' |
| declare -r QUALIFIED_TABLE_IDENTIFIER_PATTERN="^((${TABLE_IDENTIFIER_PATTERN})\\.){0,1}(${TABLE_IDENTIFIER_PATTERN})$" |
| |
| GET_TABLE_IDENTIFIER () { |
| # ----------------------------------------------------------------- |
| # Parses a properly quoted, fully-qualified SQL table name into |
| # the schema and table name parts. If a part is quoted, the quotes |
| # are removed; if a part is not quoted, the part is lower-cased. |
| # |
| # The schema name, if any, is returned in ${SQL_NAME[0]}, the |
| # "quoted" version in ${SQL_NAME[2]}; the table name is returned |
| # in ${SQL_NAME[1]}, the "quoted" version in ${SQL_NAME[3]}. |
| # |
| # Quoted identifiers can contain any character, except the |
| # character with code zero. (To include a double quote, write two |
| # double quotes.) |
| # ----------------------------------------------------------------- |
| if PARSE_TABLE_IDENTIFIER "${1}" ; then |
| # Get schema name; may be omitted |
| if [ "${BASH_REMATCH[2]}" ] ; then |
| if [ "${BASH_REMATCH[4]}" ] ; then |
| # Quoted name; undouble quotes but otherwise take literally |
| SQL_NAME[0]="${BASH_REMATCH[5]//\"\"/\"}" |
| SQL_NAME[2]="\"${BASH_REMATCH[5]}\"" |
| else |
| # Unquoted name; make lower-case |
| if [ "$OS_TYPE" == "sunos" ] ; then |
| SQL_NAME[0]=$($ECHO "${BASH_REMATCH[2]}" | $MBTR '[:upper:]' '[:lower:]') |
| else |
| SQL_NAME[0]=$($ECHO "${BASH_REMATCH[2]}" | $TR '[:upper:]' '[:lower:]') |
| fi |
| SQL_NAME[2]="${SQL_NAME[0]}" |
| fi |
| else |
| SQL_NAME[0]= |
| fi |
| # Get table name |
| if [ "${BASH_REMATCH[11]}" ] ; then |
| # Quoted name; undouble quotes but otherwise take literally |
| SQL_NAME[1]="${BASH_REMATCH[12]//\"\"/\"}" |
| SQL_NAME[3]="\"${BASH_REMATCH[12]}\"" |
| else |
| # Unquoted name; make lower-case |
| if [ "$OS_TYPE" == "sunos" ] ; then |
| SQL_NAME[1]=$($ECHO "${BASH_REMATCH[9]}" | $MBTR '[:upper:]' '[:lower:]') |
| else |
| SQL_NAME[1]=$($ECHO "${BASH_REMATCH[9]}" | $TR '[:upper:]' '[:lower:]') |
| fi |
| SQL_NAME[3]="${SQL_NAME[1]}" |
| fi |
| else |
| SQL_NAME=('' '' '' '') |
| fi |
| } |
| |
| # Determine if the bash regular expression operator '=~' is supported. |
| # If so, define the version of PARSE_TABLE_IDENTIFER using the operator; |
| # otherwise, use the sed-based version. |
| if $BASH -c '[[ "string" =~ string ]]' 2>/dev/null ; then |
| eval 'PARSE_TABLE_IDENTIFIER () { |
| [[ "${1}" =~ ${QUALIFIED_TABLE_IDENTIFIER_PATTERN} ]] |
| }' |
| else |
| # Determine the option, if any, for sed to enable support of the regular |
| # expression used to parse the qualified table identifier. |
| for reOption in "-r" "-E" ""; do |
| reTest=$($ECHO "\"Mixed Case\".\"TableName\"" | $SED ${reOption} -e "s/${QUALIFIED_TABLE_IDENTIFIER_PATTERN}/\\9/" 2>/dev/null) |
| if [ $? -eq 0 ] && [ "${reTest}" == "\"TableName\"" ] ; then |
| break |
| fi |
| reOption= |
| done |
| unset reTest |
| if [ ! "${reOption}" ] ; then |
| ERROR_EXIT "[FATAL]:-$SED lacks support for the regular expression used to parse qualified table identifiers" 2 |
| fi |
| |
| # The PARSE_TABLE_IDENTIFIER function provides a functional replacement for a |
| # [[ "${1}" =~ ${QUALIFIED_TABLE_IDENTIFIER} ]] statement that could be used |
| # in the GET_TABLE_IDENTIFIER function in newer versions of BASH. Once support |
| # for "old" BASH is dropped, the call to this function should be replaced with |
| # the BASH regular expression pattern matching expression above. (Attempts to |
| # conditionally use the =~ operator fail BASH syntax checking.) |
| PARSE_TABLE_IDENTIFIER () { |
| local nl=$'\\\n' |
| local nullTag=$'~\t~' |
| names="$($ECHO "${1}" | $SED ${reOption} -n -e " |
| p |
| h |
| # Process the schema portion of the name |
| s/${QUALIFIED_TABLE_IDENTIFIER_PATTERN}/${nl}\\1${nl}\\2${nl}\\3${nl}\\4${nl}\\5${nl}\\6${nl}\\7${nl}\\8/ |
| x |
| # Reduce to table portion of the name (must have) |
| s/${QUALIFIED_TABLE_IDENTIFIER_PATTERN}/\\9/ |
| t haveTable |
| q |
| :haveTable |
| s/(${TABLE_IDENTIFIER_PATTERN})$/\\1${nl}\\2${nl}\\3${nl}\\4${nl}\\5${nl}\\6${nl}\\7${nl}/ |
| H |
| g |
| # Word splitting eliminates adjacent separators; provide a "null" value |
| :setNulls |
| s/\\n\\n/${nl}${nullTag}${nl}/g |
| t setNulls |
| p |
| ")" |
| local oldIFS="${IFS}" |
| IFS=$'\n' |
| BASH_REMATCH=(${names}) |
| IFS="${oldIFS}" |
| if [ "${#BASH_REMATCH[@]}" -eq 1 ] |
| then |
| # No table name appeared (only original string is in ${names} |
| BASH_REMATCH=() |
| return 1 |
| else |
| # Reduce the "null" value to an actual empty string |
| local i |
| for (( i=0; i <"${#BASH_REMATCH[@]}"; i++ )); do |
| [ "${BASH_REMATCH[$i]}" == "${nullTag}" ] && BASH_REMATCH[$i]="" |
| done |
| fi |
| return 0 |
| } |
| |
| fi |
| |
| CHK_EXISTS_TABLE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| TABLENAME="$1" |
| MASTER_PORT=$2 |
| QD_DBNAME=$3 |
| if [ $# -ne 3 ];then |
| ERROR_EXIT "[FATAL]:-Incorrect number of parameters passed expected 3 got $#" 2;fi |
| DB_THERE=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$DEFAULTDB" -c"select 1 from pg_database where datname='$QD_DBNAME';" |$WC -l` |
| if [ $DB_THERE -eq 0 ];then |
| ERROR_EXIT "[FATAL]:-Database $QD_DBNAME does not exist" 2 |
| fi |
| LOG_MSG "[INFO]:-Checking for table $TABLENAME in database $QD_DBNAME" |
| GET_TABLE_IDENTIFIER "$TABLENAME" |
| SCHEMA_NAME="${SQL_NAME[0]}" |
| QUOTED_SCHEMA_NAME="${SQL_NAME[2]}" |
| TABLENAME="${SQL_NAME[1]}" |
| QUOTED_TABLENAME="${SQL_NAME[3]}" |
| if [ "${SCHEMA_NAME}" ];then |
| TMP_OUT=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select 1 from pg_class where relname='$TABLENAME' and relnamespace in (select oid from pg_namespace where nspname='$SCHEMA_NAME');"` |
| TAB_COUNT=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select 1 from pg_class where relname='$TABLENAME' and relnamespace in (select oid from pg_namespace where nspname='$SCHEMA_NAME');" |$WC -l` |
| if [ $TAB_COUNT -eq 1 ];then |
| LOG_MSG "[INFO]:-Found table ${QUOTED_SCHEMA_NAME}.${QUOTED_TABLENAME} in database $QD_DBNAME" |
| CHK_EXTERNAL |
| PARTITIONED=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select relhassubclass from pg_class where relname='$TABLENAME' and relnamespace in (select oid from pg_namespace where nspname='$SCHEMA_NAME');"` |
| fi |
| else |
| TMP_OUT=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select 1 from pg_class where relname='$TABLENAME';"` |
| TAB_COUNT=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select 1 from pg_class where relname='$TABLENAME';" |$WC -l` |
| if [ $TAB_COUNT -eq 1 ];then |
| PARTITIONED=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select relhassubclass from pg_class where relname='$TABLENAME';"` |
| SCHEMA_NAME=`$EXPORT_LIB_PATH;$PSQL -A -t -q -p $MASTER_PORT -d "$QD_DBNAME" -c"select nspname from pg_namespace where oid in(select relnamespace from pg_class where relname='$TABLENAME');"` |
| CHK_EXTERNAL |
| fi |
| fi |
| # $EXPORT_LIB_PATH;$PSQL -q -p $MASTER_PORT -d "$QD_DBNAME" -c"\d $TABLENAME;" -o /dev/null |
| if [ $TAB_COUNT -eq 0 ] || [ $TAB_COUNT -gt 1 ];then |
| EXISTS=1 |
| else |
| EXISTS=0 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| EVENT_MAIL () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| case $OS_TYPE in |
| sunos ) MAIL=/bin/mailx ;; |
| *) MAIL=`findCmdInPath mail` ;; |
| esac |
| MAIL_SUBJECT=$1;shift |
| MAIL_MESSAGE=$1 |
| if [ ! -f $MAILFILE ] && [ ! -f $HMAILFILE ] ;then |
| LOG_MSG "[WARN]:-No $MAILFILE" 1 |
| LOG_MSG "[WARN]:-or $HMAILFILE" 1 |
| LOG_MSG "[WARN]:-Unable to send email notification" 1 |
| LOG_MSG "[INFO]:-To enable email notification, create $MAILFILE" 1 |
| LOG_MSG "[INFO]:-or $HMAILFILE containing required email addresses" 1 |
| EXIT_STATUS=1 |
| else |
| if [ -f $HMAILFILE ];then MAILFILE=$HMAILFILE;fi |
| for MAIL_ADDRESS in `$CAT $MAILFILE | $GREP -v "^#"` |
| do |
| LOG_MSG "[INFO]:-Sending mail to $MAIL_ADDRESS using file $MAILFILE" 1 |
| $ECHO "$MAIL_MESSAGE"|$MAIL -s "$MAIL_SUBJECT" $MAIL_ADDRESS |
| ERROR_CHK $? "send email to $MAIL_ADDRESS" 1 |
| done |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| POSTGRES_PORT_CHK () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_PG_PID_ACTIVE $1 $2 |
| if [ $PID -ne 0 ];then |
| ERROR_EXIT "[FATAL]:-Host $2 has an active database process on port = $1" 2 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| CREATE_SPREAD_MIRROR_ARRAY () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| ((MAX_ARRAY=${#QE_PRIMARY_ARRAY[@]}-1)) |
| |
| # Current host and subnet we are working on |
| CURRENT_HOST=0 |
| CURRENT_SUBNET=0 |
| |
| # Destination host and subnet |
| DEST_HOST=0 |
| DEST_SUBNET=0 |
| |
| if [ x"$NUM_MHOST_NODE" != x"" ] && [ $NUM_MHOST_NODE -gt 0 ] ; then |
| ((DIRS_PER_SUBNET=$NUM_DATADIR/$NUM_MHOST_NODE)) |
| else |
| DIRS_PER_SUBNET=$NUM_DATADIR |
| fi |
| |
| ((MAX_SUBNET=$NUM_DATADIR/$DIRS_PER_SUBNET)) |
| ((MAX_HOST=${#QE_PRIMARY_ARRAY[@]}/$NUM_DATADIR)) |
| |
| SEGS_PROCESSED=0 |
| SEGS_PROCESSED_HOST=0 |
| |
| |
| # The following is heavily dependent on sort order of primary array. This sort |
| # order will be affected by hostnames so something non-standard will cause |
| # strange behaviour. This isn't new (just recording this fact for future generations) |
| # and can be worked around with a mapping file to gpinitsystem (-I option). |
| # The right way to do this would require us to connect to remote hosts, determine |
| # what subnet we are on for that hostname and then build the array that way. We *will* |
| # do this once this is in python (or anything other than BASH) |
| LOG_MSG "[INFO]:-Building spread mirror array type $MULTI_TXT, please wait..." 1 |
| for QE_LINE in ${QE_PRIMARY_ARRAY[@]} |
| do |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $NOLINE_ECHO ".\c";fi |
| |
| if [ $(($SEGS_PROCESSED%$NUM_DATADIR)) -eq 0 ] ; then |
| # A new host group is starting |
| if [ $SEGS_PROCESSED -ne 0 ] ; then ((CURRENT_HOST=$CURRENT_HOST+1)); fi |
| # Start the mirroring on the next host |
| ((DEST_HOST=$CURRENT_HOST+1)) |
| # Always subnet "0" to start |
| CURRENT_SUBNET=0 |
| DEST_SUBNET=1 |
| # Make sure we loop back when needed |
| if [ $DEST_HOST -ge $MAX_HOST ] ; then DEST_HOST=0; fi |
| SEGS_PROCESSED_HOST=0 |
| else |
| # Continue with current host |
| # move dest host to the next one (This is spread mirroring) |
| ((DEST_HOST=$DEST_HOST+1)) |
| # Make sure we look back when needed |
| if [ $DEST_HOST -ge $MAX_HOST ] ; then DEST_HOST=0; fi |
| # Get what subnet we are on, we may have moved to next |
| ((CURRENT_SUBNET=($SEGS_PROCESSED_HOST+1)/$DIRS_PER_SUBNET)) |
| ((DEST_SUBNET=$CURRENT_SUBNET+1)) |
| # Handle looping over |
| if [ $DEST_SUBNET -ge $MAX_SUBNET ] ; then DEST_SUBNET=0; fi |
| # Increment the number of segments we've processed for this host |
| ((SEGS_PROCESSED_HOST=$SEGS_PROCESSED_HOST+1)) |
| fi |
| |
| # Handle the case where it's a single hostname (thus a single subnet) |
| # This case will mainly be for QA testing |
| if [ $NUM_DATADIR -eq $DIRS_PER_SUBNET ] ; then DEST_SUBNET=0; fi |
| |
| # Handle possible loop |
| if [ $DEST_SUBNET -ge $MAX_SUBNET ] ; then DEST_SUBNET=0; fi |
| |
| # Calculate the index based on host and subnet number |
| ((PRIM_SEG_INDEX=($DEST_HOST*$NUM_DATADIR)+($DEST_SUBNET*$DIRS_PER_SUBNET))) |
| |
| QE_M_NAME=`$ECHO ${QE_PRIMARY_ARRAY[$PRIM_SEG_INDEX]}|$AWK -F"~" '{print $1}'` |
| GP_M_DIR=${MIRROR_DATA_DIRECTORY[$SEGS_PROCESSED%$NUM_DATADIR]} |
| P_PORT=`$ECHO $QE_LINE|$AWK -F"~" '{print $2}'` |
| P_REPL_PORT=`$ECHO $QE_LINE|$AWK -F"~" '{print $6}'` |
| ((GP_M_PORT=$P_PORT+$MIRROR_OFFSET)) |
| ((M_REPL_PORT=$P_REPL_PORT+$MIRROR_REPLICATION_PORT_OFFSET)) |
| M_CONTENT=`$ECHO $QE_LINE|$AWK -F"~" '{print $5}'` |
| M_SEG=`$ECHO $QE_LINE|$AWK -F"~" '{print $3}'|$AWK -F"/" '{print $NF}'` |
| QE_MIRROR_ARRAY=(${QE_MIRROR_ARRAY[@]} ${QE_M_NAME}~${GP_M_PORT}~${GP_M_DIR}/${M_SEG}~${DBID_COUNT}~${M_CONTENT}~${M_REPL_PORT}) |
| POSTGRES_PORT_CHK $GP_M_PORT $QE_M_NAME |
| ((DBID_COUNT=$DBID_COUNT+1)) |
| ((SEGS_PROCESSED=$SEGS_PROCESSED+1)) |
| done |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $ECHO;fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_MAX_LEN () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| LOG_MSG "[INFO]:-Formatting output, please wait..." 1 |
| GET_MASTER_PORT $MASTER_DATA_DIRECTORY |
| LEN_ARRAY=(`$EXPORT_LIB_PATH;env PGOPTIONS="-c gp_session_role=utility" $PSQL -F" " -A -t -q -p $MASTER_PORT -d "$DEFAULTDB" -c"select max(length(hostname))+1, max(length(port))+1, max(length(datadir))+1, max(length(content))+1, max(length(dbid)) from $CONFIG_TABLE a where content<>-1;"`) |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| CREATE_GROUP_MIRROR_ARRAY () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| LOG_MSG "[INFO]:-Building group mirror array type $MULTI_TXT, please wait..." 1 |
| PRI_HOST_COUNT=`$ECHO ${QE_PRIMARY_ARRAY[@]}|$TR ' ' '\n'|$AWK -F"~" '{print $1}'|$SORT -u|$WC -l` |
| if [ $MULTI_HOME -eq 1 ] && [ $REMOTE_HOST_COUNT -eq 1 ];then |
| PRI_HOST_COUNT=1 |
| fi |
| |
| if [ x"$NUM_MHOST_NODE" != x"" ] && [ $NUM_MHOST_NODE -gt 0 ] ; then |
| ((DIRS_PER_SUBNET=$NUM_DATADIR/$NUM_MHOST_NODE)) |
| else |
| DIRS_PER_SUBNET=$NUM_DATADIR |
| fi |
| ((MAX_SUBNET=$NUM_DATADIR/$DIRS_PER_SUBNET)) |
| ((MAX_HOST=${#QE_PRIMARY_ARRAY[@]}/$NUM_DATADIR)) |
| |
| # Current host we are working on |
| CURRENT_HOST=0 |
| |
| # Destination host and subnet |
| DEST_HOST=0 |
| DEST_SUBNET=0 |
| |
| PRIMARY_ARRAY_LENGTH=${#QE_PRIMARY_ARRAY[@]} |
| PRIMARY_INDEX=0 |
| |
| for QE_LINE in ${QE_PRIMARY_ARRAY[@]} |
| do |
| if [ $(($PRIMARY_INDEX%$NUM_DATADIR)) -eq 0 ] ; then |
| if [ $PRIMARY_INDEX -ne 0 ] ; then ((CURRENT_HOST=$CURRENT_HOST+1)); fi |
| ((DEST_HOST=$CURRENT_HOST+1)) |
| if [ $DEST_HOST -ge $MAX_HOST ] ; then DEST_HOST=0; fi |
| DEST_SUBNET=1 |
| else |
| if [ $(($PRIMARY_INDEX%$DIRS_PER_SUBNET)) -eq 0 ] ; then |
| ((DEST_SUBNET=$DEST_SUBNET+1)) |
| fi |
| fi |
| |
| # Handle possible loop |
| if [ $DEST_SUBNET -ge $MAX_SUBNET ] ; then DEST_SUBNET=0; fi |
| |
| ((MIRROR_INDEX=($DEST_HOST*$NUM_DATADIR)+($DEST_SUBNET*$DIRS_PER_SUBNET))) |
| |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $NOLINE_ECHO ".\c";fi |
| |
| QE_M_NAME=`$ECHO ${QE_PRIMARY_ARRAY[$MIRROR_INDEX]}|$AWK -F"~" '{print $1}'` |
| GP_M_DIR=${MIRROR_DATA_DIRECTORY[$PRIMARY_INDEX%$NUM_DATADIR]}/`$ECHO $QE_LINE|$AWK -F"~" '{print $3}'|$AWK -F"/" '{print $NF}'` |
| |
| M_CONTENT=`$ECHO $QE_LINE|$AWK -F"~" '{print $5}'` |
| P_PORT=`$ECHO $QE_LINE|$AWK -F"~" '{print $2}'` |
| P_REPL_PORT=`$ECHO $QE_LINE|$AWK -F"~" '{print $6}'` |
| GP_M_PORT=$(($P_PORT+$MIRROR_OFFSET)) |
| M_REPL_PORT=$(($P_REPL_PORT+$MIRROR_REPLICATION_PORT_OFFSET)) |
| |
| QE_MIRROR_ARRAY=(${QE_MIRROR_ARRAY[@]} ${QE_M_NAME}~${GP_M_PORT}~${GP_M_DIR}~${DBID_COUNT}~${M_CONTENT}~${M_REPL_PORT}) |
| POSTGRES_PORT_CHK $GP_M_PORT $QE_M_NAME |
| |
| DBID_COUNT=$(($DBID_COUNT+1)) |
| PRIMARY_INDEX=$((PRIMARY_INDEX+1)) |
| done |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $ECHO;fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_REPLY () { |
| $ECHO "$1 Yy/Nn>" |
| read REPLY |
| if [ -z $REPLY ]; then |
| LOG_MSG "[WARN]:-User abort requested, Script Exits!" 1 |
| exit 1 |
| fi |
| if [ $REPLY != Y ] && [ $REPLY != y ]; then |
| LOG_MSG "[WARN]:-User abort requested, Script Exits!" 1 |
| exit 1 |
| fi |
| } |
| |
| CHK_MULTI_HOME () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_QE_DETAILS |
| MULTI_ARRAY=() |
| J=0 |
| if [ x"" == x"$1" ];then |
| #Select two hosts to test as we do not want to do the whole array |
| LOG_MSG "[INFO]:-Obtaining GPDB array type, [Brief], please wait..." 1 |
| while [ $J -lt 2 ] |
| do |
| QE_HOST=`$ECHO ${QE_ARRAY[$J]}|$AWK -F"|" '{print $1}'` |
| REMOTE_HOSTNAME=`$TRUSTED_SHELL $QE_HOST "$HOSTNAME"` |
| MULTI_ARRAY=(${MULTI_ARRAY[@]} ${QE_HOST}:$REMOTE_HOSTNAME) |
| ((J=$J+1)) |
| done |
| else |
| LOG_MSG "[INFO]:-Obtaining GPDB array type, [Full], please wait..." 1 |
| for QE_LINE in ${QE_ARRAY[@]} |
| do |
| QE_HOST=`$ECHO $QE_LINE|$AWK -F"|" '{print $1}'` |
| REMOTE_HOSTNAME=`$TRUSTED_SHELL $QE_HOST "$HOSTNAME"` |
| MULTI_ARRAY=(${MULTI_ARRAY[@]} ${QE_HOST}:$REMOTE_HOSTNAME) |
| done |
| fi |
| SEG_HOST_COUNT=`$ECHO ${MULTI_ARRAY[@]}|$TR ' ' '\n'|$AWK -F"~" '{print $1}'|$SORT -u|wc -l` |
| REMOTE_HOST_COUNT=`$ECHO ${MULTI_ARRAY[@]}|$TR ' ' '\n'|$AWK -F"~" '{print $2}'|$SORT -u|wc -l` |
| if [ $SEG_HOST_COUNT -eq $REMOTE_HOST_COUNT ];then |
| LOG_MSG "[INFO]:-Non multi-home configuration" |
| MULTI_HOME=0 |
| MULTI_TXT="Standard" |
| else |
| LOG_MSG "[INFO]:-Multi-home configuration" |
| MULTI_HOME=1 |
| MULTI_TXT="Multi-home" |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_DISTRIB_COLS () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ $# -ne 3 ];then |
| ERROR_EXIT "[FATAL]:-Incorrect # parameters supplied, got $# expected 3" 2;fi |
| T_NAME=$1 |
| if [ `$ECHO $1|$GREP -c "\."` -eq 1 ];then |
| T_NAME=`$ECHO $1|$CUT -d"." -f2` |
| S_NAME=`$ECHO $1|$CUT -d"." -f1` |
| DISTRIB_COLS=`${EXPORT_LIB_PATH};$PSQL -p $2 -d "$3" -A -t -c"select attrnums from $DISTRIB_TABLE where localoid in (select oid from pg_class where relname='${T_NAME}' and relnamespace in (select oid from pg_namespace where nspname='${S_NAME}'));"` |
| if [ x"" == x"$DISTRIB_COLS" ];then |
| DISTRIB_COLS='';fi |
| else |
| LOG_MSG "[WARN]:-Incorrect table name sent to function, should be schema.tablename" 1 |
| ERROR_EXIT "[FATAL]:-Error in $FUNCNAME parameters" 2 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_TABLE_TYPE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ $# -ne 3 ];then |
| ERROR_EXIT "[FATAL]:-Incorrect # parameters supplied, got $# expected 3" 2;fi |
| T_NAME=$1 |
| if [ `$ECHO $1|$GREP -c "\."` -eq 1 ];then |
| T_NAME=`$ECHO $1|$CUT -d"." -f2` |
| S_NAME=`$ECHO $1|$CUT -d"." -f1` |
| TAB_TYPE=`${EXPORT_LIB_PATH};$PSQL -p $2 -d "$3" -A -t -c"select 1 from pg_depend where objid in (select oid from pg_class where relname='${T_NAME}' and relnamespace in (select oid from pg_namespace where nspname='${S_NAME}')) and refobjid not in (select relnamespace from pg_class where relname='${T_NAME}' and relnamespace in (select oid from pg_namespace where nspname='${S_NAME}'));"|$WC -l` |
| if [ $TAB_TYPE -eq 1 ];then |
| TAB_TYPE_TXT="Child table" |
| TAB_PARENT_NAME=(`${EXPORT_LIB_PATH};$PSQL -p $2 -d "$3" -R" " -A -t -c"select relname from pg_class where oid in (select refobjid from pg_depend where objid in (select oid from pg_class where relname='${T_NAME}' and relnamespace in (select oid from pg_namespace where nspname='${S_NAME}')) and refobjid not in (select relnamespace from pg_class where relname='${T_NAME}' and relnamespace in (select oid from pg_namespace where nspname='${S_NAME}')));"`) |
| else |
| TAB_TYPE_TXT="Not child table" |
| fi |
| else |
| LOG_MSG "[WARN]:-Incorrect table name sent to function, should be schema.tablename" 1 |
| ERROR_EXIT "[FATAL]:-Error in $FUNCNAME parameters" 2 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| CHK_FILE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| FILENAME=$1 |
| FILE_HOST=$2 |
| if [ x"" == x"$FILE_HOST" ];then |
| LOG_MSG "[INFO]:-Checking file $FILENAME" |
| if [ ! -s $FILENAME ] || [ ! -r $FILENAME ] |
| then |
| EXISTS=1 |
| else |
| EXISTS=0 |
| fi |
| else |
| EXISTS=`$TRUSTED_SHELL $FILE_HOST "if [ ! -s $FILENAME ] || [ ! -r $FILENAME ];then $ECHO 1;else $ECHO 0;fi"` |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ];then |
| LOG_MSG "[WARN]:-Failed to obtain details of $FILENAME on $FILE_HOST" |
| EXIT_STATUS=1 |
| EXISTS=1 |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| CHK_DIR () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| DIR_NAME=$1;shift |
| DIR_HOST=$1 |
| if [ x"" == x"$DIR_HOST" ];then |
| EXISTS=`if [ -d $DIR_NAME ];then $ECHO 0;else $ECHO 1;fi` |
| else |
| EXISTS=`$TRUSTED_SHELL $DIR_HOST "if [ -d $DIR_NAME ];then $ECHO 0;else $ECHO 1;fi"` |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ];then |
| LOG_MSG "[WARN]:-Failed to obtain details of $DIR_NAME on $DIR_HOST" 1 |
| EXIT_STATUS=1 |
| EXISTS=1 |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| CHK_WRITE_DIR () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| DIR_NAME=$1;shift |
| DIR_HOST=$1;shift |
| NOEXIT=$1 |
| LOG_MSG "[INFO]:-Checking write access to $DIR_NAME on $DIR_HOST" |
| $TRUSTED_SHELL $DIR_HOST "$TOUCH ${DIR_NAME}/tmp_file_test" |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ];then |
| if [ x"" == x"$NOEXIT" ];then |
| ERROR_EXIT "[FATAL]:-Cannot write to $DIR_NAME on $DIR_HOST" 2 |
| else |
| LOG_MSG "[FATAL]:-Cannot write to $DIR_NAME on $DIR_HOST" 1 |
| fi |
| else |
| $TRUSTED_SHELL $DIR_HOST "$RM -f ${DIR_NAME}/tmp_file_test" |
| LOG_MSG "[INFO]:-Write test passed on $DIR_HOST $DIR_NAME directory" |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| GET_MASTER_PORT () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| MASTER_DATA_DIRECTORY=$1 |
| if [ x"" == x"$MASTER_DATA_DIRECTORY" ];then |
| ERROR_EXIT "[FATAL]:-MASTER_DATA_DIRECTORY variable not set" 2;fi |
| if [ ! -d $MASTER_DATA_DIRECTORY ]; then |
| ERROR_EXIT "[FATAL]:-No $MASTER_DATA_DIRECTORY directory" 2 |
| fi |
| if [ -r $MASTER_DATA_DIRECTORY/$PG_CONF ];then |
| MASTER_PORT=`$AWK 'split($0,a,"#")>0 && split(a[1],b,"=")>1 {print b[1] " " b[2]}' $MASTER_DATA_DIRECTORY/$PG_CONF | $AWK '$1=="port" {print $2}' | $TAIL -1` |
| if [ x"" == x"$MASTER_PORT" ] ; then |
| #look for include files |
| for INC_FILE in `$AWK '/^[ ]*include /{print $2}' $MASTER_DATA_DIRECTORY/$PG_CONF | $TR -d "'\""` ; do |
| if [[ $INC_FILE == /* ]] ; then |
| GET_MASTER_PORT_RECUR "$INC_FILE" 1 |
| else |
| GET_MASTER_PORT_RECUR "$MASTER_DATA_DIRECTORY/$INC_FILE" 1 |
| fi |
| done |
| if [ x"" == x"$MASTER_PORT" ] ; then |
| ERROR_EXIT "[FATAL]:-Failed to obtain master port number from $MASTER_DATA_DIRECTORY/$PG_CONF" 2 |
| fi |
| fi |
| else |
| ERROR_EXIT "[FATAL]:-Do not have read access to $MASTER_DATA_DIRECTORY/$PG_CONF" 2 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_MASTER_PORT_RECUR () { |
| INCLUDED_FILE=$1 |
| RECUR=$2 |
| if [ $RECUR -le 10 ] ; then |
| MASTER_PORT=`$AWK 'split($0,a,"#")>0 && split(a[1],b,"=")>1 {print b[1] " " b[2]}' $INCLUDED_FILE | $AWK '$1=="port" {print $2}' | $TAIL -1` |
| if [ x"" == x"$MASTER_PORT" ] ; then |
| #look for include files |
| let CURR_DEPTH=$RECUR+1 |
| for INC_FILE in `$AWK '/^[ ]*include /{print $2}' $INC_FILE | $TR -d "'\""` ; do |
| if [[ $INC_FILE == /* ]] ; then |
| GET_MASTER_PORT_RECUR "$INC_FILE" $CURR_DEPTH |
| else |
| GET_MASTER_PORT_RECUR "$MASTER_DATA_DIRECTORY/$INC_FILE" $CURR_DEPTH |
| fi |
| if [ x"" != x"$MASTER_PORT" ] ; then |
| break |
| fi |
| done |
| fi |
| else |
| ERROR_EXIT "[FATAL]:-Could not open configuration file \"$INCLUDED_FILE\": maximum nesting depth exceeded" |
| fi |
| } |
| |
| CHK_ON_PASSIVE_STANDBY () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GPSYNC_COUNT=0 |
| CHK_DB_QD_SET |
| GET_MASTER_PORT $MASTER_DATA_DIRECTORY |
| GET_PG_PID_ACTIVE $MASTER_PORT |
| if [ -f $MASTER_DATA_DIRECTORY/postmaster.opts ];then |
| GPSYNC_COUNT=`$GREP -c gpsync $MASTER_DATA_DIRECTORY/postmaster.opts` |
| fi |
| if [ $PID -ne 0 ] && [ $GPSYNC_COUNT -ne 0 ];then |
| LOG_MSG "[FATAL]:-Cannot run this script on a passive standby instance" 1 |
| LOG_MSG "[FATAL]:-where there is a conflict with the current value of" 1 |
| LOG_MSG "[FATAL]:-the MASTER_DATA_DIRECTORY environment variable setting." 1 |
| ERROR_EXIT "[FATAL]:-Unable to process requested command" 2 |
| fi |
| if [ $GPSYNC_COUNT -ne 0 ];then |
| LOG_MSG "[FATAL]:-Cannot run this script on the standby instance" 1 |
| LOG_MSG "[FATAL]:-Status indicates that standby instance processs not running" 1 |
| LOG_MSG "[FATAL]:-Check standby process status via gpstate -f on Master instance" 1 |
| ERROR_EXIT "[FATAL]:-Unable to process requested command" 2 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_CIDRADDR () { |
| # MPP-15889 |
| # assuming argument is an ip address, return the address |
| # with a /32 or /128 cidr suffix based on whether or not the |
| # address contains a : |
| |
| if [ `echo $1 | grep -c :` -gt 0 ]; then |
| echo $1/128 |
| else |
| echo $1/32 |
| fi |
| } |
| |
| BUILD_MASTER_PG_HBA_FILE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ $# -eq 0 ];then ERROR_EXIT "[FATAL]:-Passed zero parameters, expected at least 1" 2;fi |
| GP_DIR=$1 |
| LOG_MSG "[INFO]:-Clearing values in Master $PG_HBA" |
| $GREP "^#" ${GP_DIR}/$PG_HBA > $TMP_PG_HBA |
| $MV $TMP_PG_HBA ${GP_DIR}/$PG_HBA |
| LOG_MSG "[INFO]:-Setting local access" |
| $ECHO "local all $USER_NAME $PG_METHOD" >> ${GP_DIR}/$PG_HBA |
| #$ECHO "local all all $PG_METHOD" >> ${GP_DIR}/$PG_HBA |
| LOG_MSG "[INFO]:-Setting local host access" |
| $ECHO "host all $USER_NAME 127.0.0.1/28 trust" >> ${GP_DIR}/$PG_HBA |
| for ADDR in "${MASTER_IP_ADDRESS_ALL[@]}" |
| do |
| # MPP-15889 |
| CIDRADDR=$(GET_CIDRADDR $ADDR) |
| $ECHO "host all $USER_NAME $CIDRADDR trust" >> ${GP_DIR}/$PG_HBA |
| done |
| for ADDR in "${STANDBY_IP_ADDRESS_ALL[@]}" |
| do |
| # MPP-15889 |
| CIDRADDR=$(GET_CIDRADDR $ADDR) |
| $ECHO "host all $USER_NAME $CIDRADDR trust" >> ${GP_DIR}/$PG_HBA |
| done |
| |
| # Add all local IPV6 addresses |
| for ADDR in "${MASTER_IPV6_LOCAL_ADDRESS_ALL[@]}" |
| do |
| # MPP-15889 |
| CIDRADDR=$(GET_CIDRADDR $ADDR) |
| $ECHO "host all $USER_NAME $CIDRADDR trust" >> ${GP_DIR}/$PG_HBA |
| done |
| LOG_MSG "[INFO]:-Complete Master $PG_HBA configuration" |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| BUILD_PERFMON() { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GP_DIR=$1 |
| $MKDIR -p $GP_DIR/gpperfmon/conf $GP_DIR/gpperfmon/logs $GP_DIR/gpperfmon/data |
| $CAT <<_EOF_ >> $GP_DIR/gpperfmon/conf/gpperfmon.conf |
| [GPMMON] |
| # quantum specifies the time in seconds between updates from |
| # performance monitor agents on all segments. Valid values |
| # are 10, 15, 20, 30, or 60 |
| quantum = 15 |
| |
| # min_query_time specifies the minimum query run time |
| # in seconds for statistics collection. The monitor logs all |
| # queries that run longer than this value in the queries_history |
| # table. For queries with shorter run times, no historical |
| # data is collected. |
| min_query_time = 20 |
| |
| # Specifies the minimum iterator run time in seconds for |
| # statistics collection. The monitor logs all iterators that |
| # run longer than this value in the iterators_history table. |
| # For iterators with shorter run times, no data is collected. |
| # Minimum value is 10 seconds. |
| min_detailed_query_time = 60 |
| |
| # This should be a percentage between 0 and 100 and should be |
| # less than the error_disk_space_percentage. If a filesystem’s |
| # disk space used percentage equals or exceeds this value a |
| # warning will be logged and a warning email/snmp trap may be |
| # sent. If this configuration is set to 0 or not specified, no |
| # warnings are sent. |
| #warning_disk_space_percentage = 80 |
| |
| # This should be a percentage between 0 and 100 and should be |
| # greater than the warning_disk_space_percentage. If a |
| # filesystem’s disk space used percentage equals or exceeds |
| # this value an error will be logged and a error email/snmp |
| # trap may be sent. If this configuration is set to 0 or not |
| # specified, no errors are sent. |
| #error_disk_space_percentage = 90 |
| |
| #This is the interval in minutes that limits the number of |
| #error/warning messages that are sent. The minimum value for |
| #this configuration is 1. Setting this to 0 or not specifying |
| #this configuration results in it getting set to the minimum. |
| disk_space_interval = 60 |
| |
| #This is the maximum number of error/warning messages that |
| #will be sent in the disk_space_interval. The maximum value |
| #for this configuration is 50. The minimum value for this |
| #configuration is 1. Setting this configuration to greater |
| #than 50 or not specifying this configuration results in it |
| #getting set to the maximum. |
| max_disk_space_messages_per_interval = 10 |
| |
| |
| log_location = $GP_DIR/gpperfmon/logs |
| _EOF_ |
| } |
| |
| CHK_DB_RUNNING () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ $# -eq 1 ];then |
| CHK_DISPATCH_ACCESS=1 |
| else |
| CHK_DISPATCH_ACCESS=0 |
| fi |
| if [ ! -d $MASTER_DATA_DIRECTORY ]; then |
| ERROR_EXIT "[FATAL]:-No Master $MASTER_DATA_DIRECTORY directory" 2 |
| fi |
| if [ ! -f $MASTER_DATA_DIRECTORY/$PG_PID ]; then |
| LOG_MSG "[FATAL]:-No $MASTER_DATA_DIRECTORY/$PG_PID file" 1 |
| ERROR_EXIT "[FATAL]:-Run gpstart to start the Greenplum database." 2 |
| fi |
| GET_MASTER_PORT $MASTER_DATA_DIRECTORY |
| export $EXPORT_LIB_PATH;env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"SELECT d.datname as \"Name\", |
| r.rolname as \"Owner\", |
| pg_catalog.pg_encoding_to_char(d.encoding) as \"Encoding\" |
| FROM pg_catalog.pg_database d |
| JOIN pg_catalog.pg_authid r ON d.datdba = r.oid |
| ORDER BY 1;" >> $LOG_FILE 2>&1 |
| if [ $? -ne 0 ];then |
| LOG_MSG "[FATAL]:-Have a postmaster.pid file for master instance on port $MASTER_PORT" 1 |
| LOG_MSG "[FATAL]:-However, error reported on test psql access to master instance" 1 |
| LOG_MSG "[INFO]:-Check ps output for a postmaster process on the above port" 1 |
| LOG_MSG "[INFO]:-Check the master postgres logfile for errors and also the utility log file" 1 |
| ERROR_EXIT "[FATAL]:-Unable to continue" 2 |
| fi |
| if [ $CHK_DISPATCH_ACCESS -eq 1 ];then |
| #Check if in admin mode |
| export $EXPORT_LIB_PATH;$PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"\l" >> $LOG_FILE 2>&1 |
| if [ $? -ne 0 ];then |
| LOG_MSG "[WARN]:-Can access the Master instance in admin mode, but dispatch access failed" 1 |
| LOG_MSG "[INFO]:-This could mean that the Master instance is in admin mode only" 1 |
| LOG_MSG "[INFO]:-Run gpstop -m to shutdown Master instance from admin mode, and restart" 1 |
| LOG_MSG "[INFO]:-the Greenplum database using gpstart" 1 |
| EXIT_STATUS=1 |
| else |
| EXIT_STATUS=0 |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_QD_DB_NAME () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_MASTER_PORT $MASTER_DATA_DIRECTORY |
| CHK_DB_RUNNING |
| #Check if we have PGDATABASE environment variable set, if so see if that database exists |
| if [ x"" != x"$PGDATABASE" ];then |
| LOG_MSG "[INFO]:-PGDATABASE set, checking for this database" |
| QD_DBNAME_THERE=`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select 1 from pg_database where datname='${PGDATABASE}';"|$WC -l` |
| ERROR_CHK $? "check for $PGDATABASE" 2 |
| if [ $QD_DBNAME_THERE -eq 1 ];then |
| QD_DBNAME=$PGDATABASE |
| else |
| QD_DBNAME_THERE="" |
| fi |
| fi |
| if [ x"" = x"$QD_DBNAME_THERE" ];then |
| LOG_MSG "[INFO]:-Checking for a non-system database" |
| QD_DBNAME=`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"$GPLISTDATABASEQTY " 2>/dev/null|$GREP -v postgres|$GREP -v template0|$HEAD -1|$CUT -d"|" -f1` |
| ERROR_CHK $? "obtain database name" 2 |
| fi |
| MASTER_DIR_CHK=`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select 1 from ${CONFIG_TABLE} a;"|$WC -l` |
| if [ $MASTER_DIR_CHK -eq 0 ];then |
| ERROR_EXIT "[FATAL]:-MASTER_DATA_DIRECTORY value of $MASTER_DATA_DIRECTORY is incorrect" 2;fi |
| if [ x"" == x"$QD_DBNAME" ]; then |
| LOG_MSG "[INFO]:-Unable to obtain a non-system database name, setting value to "$DEFAULTDB"" |
| QD_DBNAME="$DEFAULTDB" |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_STANDBY_COUNT () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_QD_DB_NAME |
| STANDBY_COUNT=`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -q -p $MASTER_PORT -d "$QD_DBNAME" -A -t -c"select 1 from $CONFIG_TABLE a where content=-1 and dbid<>1 ;"|$WC -l` |
| ERROR_CHK $? "obtain standby master host count" 1 |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_STANDBY_DETAILS () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_QD_DB_NAME |
| STANDBY_ARRAY=(`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -q -p $MASTER_PORT -d "$QD_DBNAME" -A -t -c"select hostname, datadir, port, mode, status, preferred_role, role from $CONFIG_TABLE a where content=-1 and dbid<>1"`) > /dev/null 2>&1 |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[INFO]:-Unable to obtain standby master details, error code $RETVAL returned" 1 |
| EXIT_STATUS=1 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_TRANS_READ () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| TRANS_STATE=`${EXPORT_LIB_PATH};$PSQL -q -p $MASTER_PORT -d "$QD_DBNAME" -A -t -c"show transaction_read_only;"|$AWK '{print $NF}'` |
| ERROR_CHK $? "obtain transaction state" 1 |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_QE_DETAILS () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_QD_DB_NAME |
| if [ x"" == x"$PGUSER" ];then |
| DBUSER=$USER |
| else |
| DBUSER=$PGUSER |
| fi |
| |
| if [ $# -eq 0 ];then |
| QE_ARRAY=(`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -q -p $MASTER_PORT -U $DBUSER -d "$QD_DBNAME" -A -t -c"select a.hostname, a.datadir, a.port, b.valid, b.definedprimary from $CONFIG_TABLE a, $GP_PG_VIEW b where a.dbid=b.dbid and a.content<>-1 order by b.dbid;"`) > /dev/null 2>&1 |
| else |
| QE_ARRAY=(`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -q -p $MASTER_PORT -U $DBUSER -d "$QD_DBNAME" -A -t -c"select a.hostname, a.datadir, a.port, b.valid, b.definedprimary from $CONFIG_TABLE a, $GP_PG_VIEW b where a.dbid=b.dbid and a.content<>-1 order by a.port;"`) > /dev/null 2>&1 |
| fi |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[WARN]:-Unable to obtain segment instance host details from Master db, error code $RETVAL returned" 1 |
| EXIT_STATUS=1 |
| fi |
| QE_ARRAY_COUNT=${#QE_ARRAY[@]} |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_DB_LIST () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_MASTER_PORT $MASTER_DATA_DIRECTORY |
| DB_ARRAY=(`env PGOPTIONS="-c gp_session_role=utility" $PSQL -q -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select datname from pg_database where datname not in ('template1', 'template0', 'postgres');"`) |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| CHK_MIRRORS_CONFIGURED () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| MIRROR_COUNT=`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select count(dbid)/count(distinct(content)) from $CONFIG_TABLE a where content<>-1;"` |
| ERROR_CHK $? "obtain mirror count from master instance" 2 |
| LOG_MSG "[INFO]:-Obtained $MIRROR_COUNT as check value" |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_MIRROR_TYPE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| CHK_MIRRORS_CONFIGURED |
| if [ $MIRROR_COUNT -eq 1 ];then |
| MIR_TYPE="No Mirror";MIR_TYPE_NUM=0 |
| else |
| SEP_COUNT=`${EXPORT_LIB_PATH};$PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select count(distinct hostname)/(select count(distinct hostname) from $CONFIG_TABLE a where preferred_role = 'p' and content<>-1) from $CONFIG_TABLE a where content<>-1;"` |
| if [ $SEP_COUNT -eq 2 ];then |
| SEP_TEXT="[Separate array]" |
| else |
| SEP_TEXT="[Shared array]" |
| fi |
| #Get number of primary hosts |
| NUM_SEG_HOSTS=`${EXPORT_LIB_PATH};$PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select count(distinct(hostname)) from $CONFIG_TABLE a where content<>-1;"` |
| #Get the primary and mirror hostnames for the first segment instance host |
| FIRST_PRI_MIR_ARRAY=(`${EXPORT_LIB_PATH};$PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select hostname, content from $CONFIG_TABLE a where content>-1 and content<(select max(port)-min(port)+1 from $CONFIG_TABLE a where content<>-1 and preferred_role='p') order by content,dbid;"|$TR '\n' ' '`) |
| ((SEG_PER_HOST=${#FIRST_PRI_MIR_ARRAY[@]}/2)) |
| CHK_MULTI_HOME |
| if [ $MULTI_HOME -eq 0 ];then |
| if [ `$ECHO ${FIRST_PRI_MIR_ARRAY[@]}|$TR ' ' '\n'|$AWK -F"|" '{print $1}'|$SORT -u|$WC -l` -eq 2 ] || [ $NUM_SEG_HOSTS -eq 1 ];then |
| MIR_TYPE="Group [Single-home] $SEP_TEXT";MIR_TYPE_NUM=1 |
| else |
| MIR_TYPE="Spread [Single-home] $SEP_TEXT";MIR_TYPE_NUM=2 |
| fi |
| else |
| J=0 |
| MIR_H_NAME_ARRAY=() |
| while [ $J -lt $SEG_PER_HOST ] |
| do |
| MIR_HOST=`$ECHO ${FIRST_PRI_MIR_ARRAY[@]}|$TR ' ' '\n'|$GREP "|${J}$"|$AWK -F"|" '{print $1}'|$TAIL -1` |
| PRI_HOST=`$ECHO ${FIRST_PRI_MIR_ARRAY[@]}|$TR ' ' '\n'|$GREP "|${J}$"|$AWK -F"|" '{print $1}'|$HEAD -1` |
| #MIR_H_HOST=`$ECHO ${MULTI_ARRAY[@]}|$TR ' ' '\n'|$GREP "${MIR_HOST}~"|$SORT -u|$AWK -F"~" '{print $2}'` |
| MIR_H_CONFIG_HOST=`${EXPORT_LIB_PATH};$PSQL -p $MASTER_PORT -d "$DEFAULTDB" -A -t -c"select hostname from $CONFIG_TABLE a where hostname<>'${PRI_HOST}' and content=${J};"` |
| MIR_H_HOST=`$TRUSTED_SHELL $MIR_H_CONFIG_HOST "$HOSTNAME"|$AWK '{print $1}'` |
| #MIR_HOST_VAL=`$TRUSTED_SHELL $MIR_HOST "$HOSTNAME"` |
| MIR_H_NAME_ARRAY=(${MIR_H_NAME_ARRAY[@]} $MIR_H_HOST) |
| #MIR_H_NAME_ARRAY=(${MIR_H_NAME_ARRAY[@]} $MIR_HOST_VAL) |
| ((J=$J+1)) |
| done |
| UNIQ_COUNT=`$ECHO ${MIR_H_NAME_ARRAY[@]}|$TR ' ' '\n'|$SORT -u|$WC -l` |
| if [ $UNIQ_COUNT -eq 1 ];then |
| MIR_TYPE="Group [Multi-home] $SEP_TEXT";MIR_TYPE_NUM=3 |
| else |
| MIR_TYPE="Spread [Multi-home] $SEP_TEXT";MIR_TYPE_NUM=4;fi |
| |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_QE_PRIMARY_DETAILS () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_QD_DB_NAME |
| QE_PRIMARY_ARRAY=(`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -q -p $MASTER_PORT -d "$QD_DBNAME" -A -t -c"select a.hostname, a.datadir, a.port, b.valid, b.isprimary from $CONFIG_TABLE a, $GP_PG_VIEW b where a.dbid=b.dbid and a.content<>-1 and a.preferred_role = 'p' order by a.content;" 2>/dev/null`) > /dev/null 2>&1 |
| |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[WARN]:-Unable to obtain segment instance primary host details from Master db, error code $RETVAL returned" 1 |
| EXIT_STATUS=1 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_QE_MIRROR_DETAILS () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| GET_QD_DB_NAME |
| QE_MIRROR_ARRAY=(`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -q -p $MASTER_PORT -d "$QD_DBNAME" -A -t -c"select a.hostname, a.datadir, a.port, b.valid, b.isprimary from $CONFIG_TABLE a, $GP_PG_VIEW b where a.dbid=b.dbid and a.content<>-1 and a.preferred_role='m' order by a.content;" 2>/dev/null`) > /dev/null 2>&1 |
| |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[WARN]:-Unable to obtain segment instance mirror host details from Master db, error code $RETVAL returned" 1 |
| EXIT_STATUS=1 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| GET_PG_PID_ACTIVE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| # Expects port number and hostname for remote checking |
| PORT=$1;shift |
| HOST=$1 |
| PG_LOCK_FILE="/tmp/.s.PGSQL.${PORT}.lock" |
| PG_LOCK_NETSTAT="" |
| if [ x"" == x"$HOST" ];then |
| #See if we have a netstat entry for this local host |
| PORT_ARRAY=(`$NETSTAT -an 2>/dev/null |$GREP ".s.PGSQL.${PORT}"|$AWK '{print $NF}'|$AWK -F"." '{print $NF}'|$SORT -u`) |
| for P_CHK in ${PORT_ARRAY[@]} |
| do |
| if [ $P_CHK -eq $PORT ];then PG_LOCK_NETSTAT=$PORT;fi |
| done |
| #PG_LOCK_NETSTAT=`$NETSTAT -an 2>/dev/null |$GREP ".s.PGSQL.${PORT}"|$AWK '{print $NF}'|$HEAD -1` |
| #See if we have a lock file in /tmp |
| if [ -f ${PG_LOCK_FILE} ];then |
| PG_LOCK_TMP=1 |
| else |
| PG_LOCK_TMP=0 |
| fi |
| if [ x"" == x"$PG_LOCK_NETSTAT" ] && [ $PG_LOCK_TMP -eq 0 ];then |
| PID=0 |
| LOG_MSG "[INFO]:-No socket connection or lock file in /tmp found for port=${PORT}" |
| else |
| #Now check the failure combinations |
| if [ $PG_LOCK_TMP -eq 0 ] && [ x"" != x"$PG_LOCK_NETSTAT" ];then |
| #Have a process but no lock file |
| LOG_MSG "[WARN]:-No lock file $PG_LOCK_FILE but process running on port $PORT" 1 |
| PID=1 |
| EXIT_STATUS=1 |
| fi |
| if [ $PG_LOCK_TMP -eq 1 ] && [ x"" == x"$PG_LOCK_NETSTAT" ];then |
| #Have a lock file but no process |
| if [ -r ${PG_LOCK_FILE} ];then |
| PID=`$CAT ${PG_LOCK_FILE}|$HEAD -1|$AWK '{print $1}'` |
| else |
| LOG_MSG "[WARN]:-Unable to access ${PG_LOCK_FILE}" 1 |
| PID=1 |
| fi |
| LOG_MSG "[WARN]:-Have lock file $PG_LOCK_FILE but no process running on port $PORT" 1 |
| EXIT_STATUS=1 |
| fi |
| if [ $PG_LOCK_TMP -eq 1 ] && [ x"" != x"$PG_LOCK_NETSTAT" ];then |
| #Have both a lock file and a netstat process |
| if [ -r ${PG_LOCK_FILE} ];then |
| PID=`$CAT ${PG_LOCK_FILE}|$HEAD -1|$AWK '{print $1}'` |
| else |
| LOG_MSG "[WARN]:-Unable to access ${PG_LOCK_FILE}" 1 |
| PID=1 |
| EXIT_STATUS=1 |
| fi |
| LOG_MSG "[INFO]:-Have lock file $PG_LOCK_FILE and a process running on port $PORT" |
| fi |
| fi |
| else |
| PING_HOST $HOST 1 |
| if [ $RETVAL -ne 0 ];then |
| PID=0 |
| EXIT_STATUS=1 |
| else |
| PORT_ARRAY=(`$TRUSTED_SHELL $HOST "$NETSTAT -an 2>/dev/null |$GREP ".s.PGSQL.${PORT}" 2>/dev/null"|$AWK '{print $NF}'|$AWK -F"." '{print $NF}'|$SORT -u`) |
| for P_CHK in ${PORT_ARRAY[@]} |
| do |
| if [ $P_CHK -eq $PORT ];then PG_LOCK_NETSTAT=$PORT;fi |
| done |
| #PG_LOCK_NETSTAT=`$TRUSTED_SHELL $HOST "$NETSTAT -an 2>/dev/null |$GREP ".s.PGSQL.${PORT}" 2>/dev/null"|$AWK '{print $NF}'|$HEAD -1` |
| PG_LOCK_TMP=`$TRUSTED_SHELL $HOST "$LS ${PG_LOCK_FILE} 2>/dev/null"|$WC -l` |
| if [ x"" == x"$PG_LOCK_NETSTAT" ] && [ $PG_LOCK_TMP -eq 0 ];then |
| PID=0 |
| LOG_MSG "[INFO]:-No socket connection or lock file $PG_LOCK_FILE found for port=${PORT}" |
| else |
| #Now check the failure combinations |
| if [ $PG_LOCK_TMP -eq 0 ] && [ x"" != x"$PG_LOCK_NETSTAT" ];then |
| #Have a process but no lock file |
| LOG_MSG "[WARN]:-No lock file $PG_LOCK_FILE but process running on port $PORT on $HOST" 1 |
| PID=1 |
| EXIT_STATUS=1 |
| fi |
| if [ $PG_LOCK_TMP -eq 1 ] && [ x"" == x"$PG_LOCK_NETSTAT" ];then |
| #Have a lock file but no process |
| CAN_READ=`$TRUSTED_SHELL $HOST "if [ -r ${PG_LOCK_FILE} ];then echo 1;else echo 0;fi"` |
| if [ $CAN_READ -eq 1 ];then |
| PID=`$TRUSTED_SHELL $HOST "$CAT ${PG_LOCK_FILE}|$HEAD -1 2>/dev/null"|$AWK '{print $1}'` |
| else |
| LOG_MSG "[WARN]:-Unable to access ${PG_LOCK_FILE} on $HOST" 1 |
| fi |
| LOG_MSG "[WARN]:-Have lock file $PG_LOCK_FILE but no process running on port $PORT on $HOST" 1 |
| PID=1 |
| EXIT_STATUS=1 |
| fi |
| if [ $PG_LOCK_TMP -eq 1 ] && [ x"" != x"$PG_LOCK_NETSTAT" ];then |
| #Have both a lock file and a netstat process |
| CAN_READ=`$TRUSTED_SHELL $HOST "if [ -r ${PG_LOCK_FILE} ];then echo 1;else echo 0;fi"` |
| if [ $CAN_READ -eq 1 ];then |
| PID=`$TRUSTED_SHELL $HOST "$CAT ${PG_LOCK_FILE}|$HEAD -1 2>/dev/null"|$AWK '{print $1}'` |
| else |
| LOG_MSG "[WARN]:-Unable to access ${PG_LOCK_FILE} on $HOST" 1 |
| EXIT_STATUS=1 |
| fi |
| LOG_MSG "[INFO]:-Have lock file $PG_LOCK_FILE and a process running on port $PORT on $HOST" |
| fi |
| fi |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| RUN_COMMAND () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| COMMAND="$1" |
| LOG_MSG "[INFO]:-Commencing local $COMMAND" |
| $COMMAND >> $LOG_FILE 2>&1 |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| ERROR_EXIT "[FATAL]:- Command $COMMAND failed with error status $RETVAL, see log file $LOG_FILE for more detail" 2 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| RUN_COMMAND_REMOTE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| HOST=$1 |
| COMMAND=$2 |
| LOG_MSG "[INFO]:-Commencing remote $TRUSTED_SHELL $HOST $COMMAND" |
| $TRUSTED_SHELL $HOST $COMMAND >> $LOG_FILE 2>&1 |
| RETVAL=$? |
| if [ $RETVAL -ne 0 ]; then |
| LOG_MSG "[FATAL]:- Command $COMMAND on $HOST failed with error status $RETVAL" 2 |
| else |
| LOG_MSG "[INFO]:-Completed $TRUSTED_SHELL $HOST $COMMAND" |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| return $RETVAL |
| } |
| |
| BACKOUT_COMMAND () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| COMMAND=$1 |
| if [ ! -f $BACKOUT_FILE ]; then |
| $ECHO $COMMAND > $BACKOUT_FILE |
| else |
| $CAT $BACKOUT_FILE > /tmp/backout_file.tmp.$$ |
| $ECHO $COMMAND > $BACKOUT_FILE |
| $CAT /tmp/backout_file.tmp.$$ >> $BACKOUT_FILE |
| $RM -f /tmp/backout_file.tmp.$$ |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| PING_HOST () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| TARGET_HOST=$1;shift |
| PING_EXIT=$1 |
| if [ x"" == x"$PING_EXIT" ];then PING_EXIT=0;fi |
| case $OS_TYPE in |
| darwin ) |
| $PING $PING_TIME $TARGET_HOST > /dev/null 2>&1 || $PING6 $PING_TIME $TARGET_HOST > /dev/null 2>&1 ;; |
| linux ) |
| $PING $TARGET_HOST $PING_TIME > /dev/null 2>&1 || $PING6 $TARGET_HOST $PING_TIME > /dev/null 2>&1 ;; |
| * ) |
| $PING $TARGET_HOST $PING_TIME > /dev/null 2>&1 |
| esac |
| RETVAL=$? |
| case $RETVAL in |
| 0) LOG_MSG "[INFO]:-$TARGET_HOST contact established" ;; |
| 1) if [ $PING_EXIT -eq 0 ];then |
| ERROR_EXIT "[FATAL]:-Unable to contact $TARGET_HOST" 2 |
| else |
| LOG_MSG "[WARN]:-Unable to contact $TARGET_HOST" 1 |
| fi ;; |
| 2) if [ $PING_EXIT -eq 0 ];then |
| ERROR_EXIT "[FATAL]:-Unknown host $TARGET_HOST" 2 |
| else |
| LOG_MSG "[WARN]:-Unknown host $TARGET_HOST" 1 |
| fi ;; |
| esac |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| return $RETVAL |
| } |
| |
| STANDBY_CATALOG_UPDATE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| MASTER_STANDBY_HOSTNAME=$1;shift |
| MASTER_STANDBY_DATA_DIRECTORY=$1;shift |
| MASTER_STANDBY_PORT=$1 |
| STANDBY_HOST_COUNT=`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -A -t -d "$QD_DBNAME" -c"select distinct hostname from $CONFIG_TABLE a where hostname='${MASTER_STANDBY_HOSTNAME}';"|$WC -l` |
| ERROR_CHK $? "obtain standby host count" 2 |
| LOG_MSG "[INFO]:-Creating new gp_segment_configuration record for ${MASTER_STANDBY_HOSTNAME}" |
| MAX_DB_ID=`${EXPORT_LIB_PATH};env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -A -t -d "$QD_DBNAME" -c"select max(dbid)+1 from $CONFIG_TABLE a;"` |
| ERROR_CHK $? "obtain max dbid from gp_configuration" 2 |
| $EXPORT_LIB_PATH;env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -A -t -d "$QD_DBNAME" -c"insert into gp_segment_configuration (dbid, content, role, preferred_role, mode, status, hostname, address, port) values (${MAX_DB_ID},-1,'m', 'm', 'u', 's', '${MASTER_STANDBY_HOSTNAME}','${MASTER_STANDBY_HOSTNAME}',${MASTER_STANDBY_PORT});" |
| $EXPORT_LIB_PATH;env PGOPTIONS="-c gp_session_role=utility" $PSQL -p $MASTER_PORT -A -t -d "$QD_DBNAME" -c"insert into pg_filespace_entry (fsefsoid, fsedbid, fselocation) values (3052, ${MAX_DB_ID},'${MASTER_STANDBY_DATA_DIRECTORY}');" |
| ERROR_CHK $? "add standby host gp_configuration record" 2 |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| PARALLEL_SETUP () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| PARALLEL_STATUS_FILE=$1 |
| $TOUCH $PARALLEL_STATUS_FILE |
| export PARALLEL_STATUS_FILE=$PARALLEL_STATUS_FILE |
| LOG_MSG "[INFO]:-Spawning parallel processes batch [1], please wait..." 1 |
| BATCH_COUNT=0 |
| INST_COUNT=0 |
| BATCH_DONE=1 |
| BATCH_TOTAL=0 |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| PARALLEL_COUNT () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ $# -ne 2 ];then ERROR_EXIT "[FATAL]:-Incorrect number of parameters passed to $FUNCNAME" 2;fi |
| BATCH_LIMIT=$1 |
| BATCH_DEFAULT=$2 |
| ((INST_COUNT=$INST_COUNT+1)) |
| ((BATCH_COUNT=$BATCH_COUNT+1)) |
| ((BATCH_TOTAL=$BATCH_TOTAL+1)) |
| if [ $BATCH_COUNT -eq $BATCH_DEFAULT ] || [ $BATCH_LIMIT -eq $BATCH_TOTAL ];then |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $ECHO;fi |
| PARALLEL_WAIT |
| ((BATCH_DONE=$BATCH_DONE+1)) |
| BATCH_COUNT=0 |
| if [ $BATCH_LIMIT -ne $BATCH_TOTAL ];then |
| LOG_MSG "[INFO]:-Spawning parallel processes batch [$BATCH_DONE], please wait..." 1 |
| fi |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| PARALLEL_WAIT () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| LOG_MSG "[INFO]:-Waiting for parallel processes batch [$BATCH_DONE], please wait..." 1 |
| SLEEP_COUNT=0 |
| while [ `$WC -l $PARALLEL_STATUS_FILE|$AWK '{print $1}'` -ne $INST_COUNT ] |
| do |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $NOLINE_ECHO ".\c";fi |
| $SLEEP 1 |
| ((SLEEP_COUNT=$SLEEP_COUNT+1)) |
| if [ $WAIT_LIMIT -lt $SLEEP_COUNT ];then |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $NOLINE_ECHO ".\c";fi |
| LOG_MSG "[FATAL]:-Failed to process this batch of segments within $WAIT_LIMIT seconds" 1 |
| LOG_MSG "[INFO]:-Review contents of $LOG_FILE" 1 |
| ERROR_EXIT "[FATAL]:-Process timeout failure" 2 |
| fi |
| done |
| if [ $DEBUG_LEVEL -eq 0 ] && [ x"" != x"$VERBOSE" ];then $ECHO;fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| PARALLEL_SUMMARY_STATUS_REPORT () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| REPORT_FAIL=0 |
| if [ -f $1 ];then |
| KILLED_COUNT=`$GREP -c "KILLED:" $PARALLEL_STATUS_FILE` |
| COMPLETED_COUNT=`$GREP -c "COMPLETED:" $PARALLEL_STATUS_FILE` |
| FAILED_COUNT=`$GREP -c "FAILED:" $PARALLEL_STATUS_FILE` |
| ((TOTAL_FAILED_COUNT=$KILLED_COUNT+$FAILED_COUNT)) |
| LOG_MSG "[INFO]:------------------------------------------------" 1 |
| LOG_MSG "[INFO]:-Parallel process exit status" 1 |
| LOG_MSG "[INFO]:------------------------------------------------" 1 |
| LOG_MSG "[INFO]:-Total processes marked as completed = $COMPLETED_COUNT" 1 |
| if [ $KILLED_COUNT -ne 0 ];then |
| LOG_MSG "[WARN]:-Total processes marked as killed = $KILLED_COUNT $WARN_MARK" 1 |
| REPORT_FAIL=1 |
| else |
| LOG_MSG "[INFO]:-Total processes marked as killed = 0" 1 |
| fi |
| if [ $FAILED_COUNT -ne 0 ];then |
| LOG_MSG "[WARN]:-Total processes marked as failed = $FAILED_COUNT $WARN_MARK" 1 |
| REPORT_FAIL=1 |
| else |
| LOG_MSG "[INFO]:-Total processes marked as failed = 0" 1 |
| fi |
| LOG_MSG "[INFO]:------------------------------------------------" 1 |
| else |
| LOG_MSG "[WARN]:-Could not locate status file $1" 1 |
| REPORT_FAIL=1 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| RESET_BATCH_VALUE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| LOG_MSG "[INFO]:-Batch value being re-configured from $BATCH_DEFAULT to $BATCH_LIMIT" 1 |
| SAVE_BATCH=$BATCH_DEFAULT |
| BATCH_DEFAULT=$BATCH_LIMIT |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| RESTORE_BATCH_VALUE () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ x"" != x"$SAVE_BATCH" ];then |
| BATCH_DEFAULT=$SAVE_BATCH |
| SAVE_BATCH="" |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| CHK_GPDB_ID () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ -f ${INITDB} ];then |
| PERMISSION=`ls -al ${INITDB}|$AWK '{print $1}'` |
| MASTER_INITDB_ID=`ls -al ${INITDB}|$AWK '{print $3}'` |
| INIT_CHAR=`$ECHO $MASTER_INITDB_ID|$TR -d '\n'|$WC -c|$TR -d ' '` |
| MASTER_INITDB_GROUPID=`ls -al ${INITDB}|$AWK '{print $4}'` |
| GROUP_INIT_CHAR=`$ECHO $MASTER_INITDB_ID|$TR -d '\n'|$WC -c|$TR -d ' '` |
| GPDB_ID=`id|$TR '(' ' '|$TR ')' ' '|$AWK '{print $2}'` |
| GPDB_GROUPID=`id|$TR '(' ' '|$TR ')' ' '|$AWK '{print $4}'` |
| |
| |
| USER_EXECUTE=`$ECHO $PERMISSION | $SED -e 's/...\(.\)....../\1/g'` |
| GROUP_EXECUTE=`$ECHO $PERMISSION | $SED -e 's/......\(.\).../\1/g'` |
| |
| if [ `$ECHO $GPDB_ID|$TR -d '\n'|$WC -c` -gt $INIT_CHAR ];then |
| GPDB_ID_CHK=`$ECHO $GPDB_ID|$CUT -c1-$INIT_CHAR` |
| else |
| GPDB_ID_CHK=$GPDB_ID |
| fi |
| |
| if [ `$ECHO $GPDB_GROUPID|$TR -d '\n'|$WC -c` -gt $GROUP_INIT_CHAR ];then |
| GPDB_GROUPID_CHK=`$ECHO $GPDB_GROUPID|$CUT -c1-$GROUP_INIT_CHAR` |
| else |
| GPDB_GROUPID_CHK=$GPDB_GROUPID |
| fi |
| |
| if [ x$GPDB_ID_CHK == x$MASTER_INITDB_ID ] && [ x"x" == x"$USER_EXECUTE" ];then |
| LOG_MSG "[INFO]:-Current user id of $GPDB_ID, matches initdb id of $MASTER_INITDB_ID" |
| elif [ x$GPDB_GROUPID_CHK == x$MASTER_INITDB_GROUPID ] && [ x"x" == x"$GROUP_EXECUTE" ] ; then |
| LOG_MSG "[INFO]:-Current group id of $GPDB_GROUPID, matches initdb group id of $MASTER_INITDB_GROUPID" |
| else |
| LOG_MSG "[WARN]:-File permission mismatch. The $GPDB_ID_CHK owns the Greenplum Database installation directory." |
| LOG_MSG "[WARN]:-You are currently logged in as $MASTER_INITDB_ID and may not have sufficient" |
| LOG_MSG "[WARN]:-permissions to run the Greenplum binaries and management utilities." |
| fi |
| |
| if [ x"" != x"$USER" ];then |
| if [ `$ECHO $USER|$TR -d '\n'|$WC -c` -gt $INIT_CHAR ];then |
| USER_CHK=`$ECHO $USER|$CUT -c1-$INIT_CHAR` |
| else |
| USER_CHK=$USER |
| fi |
| if [ x$GPDB_ID_CHK != x$USER_CHK ];then |
| LOG_MSG "[WARN]:-\$USER mismatch, id returns $GPDB_ID, \$USER returns $USER" 1 |
| LOG_MSG "[WARN]:-The GPDB super user account that owns the initdb binary should run these utilities" 1 |
| LOG_MSG "[WARN]:-This may cause problems when these utilities are run as $USER" 1 |
| fi |
| else |
| LOG_MSG "[INFO]:-Environment variable \$USER unset, will set to $GPDB_ID" 1 |
| export USER=$GPDB_ID |
| fi |
| if [ x"" != x"$LOGNAME" ];then |
| if [ `$ECHO $LOGNAME|$TR -d '\n'|$WC -c` -gt $INIT_CHAR ];then |
| LOGNAME_CHK=`$ECHO $LOGNAME|$CUT -c1-$INIT_CHAR` |
| else |
| LOGNAME_CHK=$LOGNAME |
| fi |
| if [ x$GPDB_ID_CHK != x$LOGNAME_CHK ];then |
| LOG_MSG "[WARN]:-\$LOGNAME mismatch, id returns $GPDB_ID_CHK, \$LOGNAME returns $LOGNAME_CHK" 1 |
| LOG_MSG "[WARN]:-The GPDB super user account that owns the initdb binary should run these utilities" 1 |
| LOG_MSG "[WARN]:-This may cause problems when these utilities are run as $LOGNAME" 1 |
| fi |
| else |
| LOG_MSG "[INFO]:-Environment variable \$LOGNAME unset, will set to $GPDB_ID" 1 |
| export LOGNAME=$GPDB_ID |
| fi |
| else |
| LOG_MSG "[WARN]:-No initdb file, unable to verify id" 1 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| PARSE_PERMISSIONS () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| #Expect 3 parameters schema.tablename port database |
| if [ $# -ne 3 ];then |
| ERROR_EXIT "[FATAL]:-Got $# parameters, expected 3" 2 |
| fi |
| T_NAME=$1;shift |
| PORT=$1;shift |
| DB=$1 |
| #Check to ensure that we have schema_name.tablename |
| if [ `$ECHO $T_NAME|grep -c "."` -ne 1 ];then |
| ERROR_EXIT "[FATAL]:-Schema name not supplied" 2 |
| else |
| SCHEMA_NAME=`$ECHO $T_NAME|$AWK -F"." '{print $1}'` |
| TABLENAME=`$ECHO $T_NAME|$AWK -F"." '{print $2}'` |
| fi |
| #Get relacl information |
| PERM_COUNT=0 |
| for PERM_LINE in `$PSQL -p $PORT -d "$DB" -A -t -c "select relacl from pg_class where relname='${TABLENAME}' and relnamespace in (select oid from pg_namespace where nspname='$SCHEMA_NAME');"|$TR -d '{'|$TR -d '}'|$TR ',' '\n'|$GREP -v "${USER}="|$TR '/' '\n'|$GREP -v "${USER}" ` |
| do |
| DB_ACCOUNTNAME=`$ECHO $PERM_LINE|$AWK -F"=" '{print $1}'` |
| if [ x"" != x"$DB_ACCOUNTNAME" ];then |
| PERM_ALLOW=`$ECHO $PERM_LINE|$AWK -F"=" '{print $2}'` |
| if [ `$ECHO $PERM_ALLOW|$GREP -c "r"` -eq 1 ];then PERM_TEXT="$PERM_TEXT select";fi |
| if [ `$ECHO $PERM_ALLOW|$GREP -c "w"` -eq 1 ];then PERM_TEXT="$PERM_TEXT update";fi |
| if [ `$ECHO $PERM_ALLOW|$GREP -c "d"` -eq 1 ];then PERM_TEXT="$PERM_TEXT delete";fi |
| if [ `$ECHO $PERM_ALLOW|$GREP -c "a"` -eq 1 ];then PERM_TEXT="$PERM_TEXT insert";fi |
| if [ `$ECHO $PERM_ALLOW|$GREP -c "R"` -eq 1 ];then PERM_TEXT="$PERM_TEXT rule";fi |
| if [ `$ECHO $PERM_ALLOW|$GREP -c "x"` -eq 1 ];then PERM_TEXT="$PERM_TEXT references";fi |
| if [ `$ECHO $PERM_ALLOW|$GREP -c "t"` -eq 1 ];then PERM_TEXT="$PERM_TEXT trigger";fi |
| PERM_TEXT=`$ECHO $PERM_TEXT|$TR ' ' ','` |
| PERM_ARRAY[$PERM_COUNT]="grant $PERM_TEXT on ~ to $DB_ACCOUNTNAME;" |
| PERM_TEXT='' |
| ((PERM_COUNT=$PERM_COUNT+1)) |
| fi |
| done |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| |
| CHK_START_ERROR_TXT () { |
| LOG_MSG "[INFO]:-Start Function $FUNCNAME" |
| if [ $DISPLAY_ERROR -eq 1 ];then |
| LOG_MSG "[INFO]:-*********************************************************************************" 1 |
| LOG_MSG "[WARN]:-There are $INVALID_COUNT segment(s) marked as invalid" 1 |
| LOG_MSG "[INFO]:-The GPDB gp_fault_action parameter is set to continue in the event of failure" 1 |
| LOG_MSG "[INFO]:-To recover from this current invalid state, review usage of gprecoverseg" 1 |
| LOG_MSG "[INFO]:-management utility, which will recover failed segment instance databases" 1 |
| LOG_MSG "[WARN]:-As gp_fault_action is set to continue, recovery will need to shutdown the" 1 |
| LOG_MSG "[WARN]:-GPDB database to ensure a consistent recovery can be completed" 1 |
| LOG_MSG "[INFO]:-*********************************************************************************" 1 |
| EXIT_STATUS=1 |
| fi |
| LOG_MSG "[INFO]:-End Function $FUNCNAME" |
| } |
| |
| |
| UPDATE_MPP () { |
| LOG_MSG "[INFO][$INST_COUNT]:-Start Function $FUNCNAME" |
| U_DB=$DEFAULTDB |
| U_PT=$1 |
| U_MPPNAME="$2" |
| U_NUMSEG=$3 |
| U_DBID=$4 |
| U_CONTENT=$5 |
| TYPE=$6 |
| U_HOST=$7 |
| U_DIR=$8 |
| LOG_MSG "[INFO][$INST_COUNT]:-Making dbid file @ $U_HOST:$U_DIR = $U_DBID" |
| MAKE_DBID_FILE $U_DBID $U_HOST $U_DIR |
| LOG_MSG "[INFO][$INST_COUNT]:-Successfully updated GPDB system table" |
| LOG_MSG "[INFO][$INST_COUNT]:-End Function $FUNCNAME" |
| } |
| |
| #****************************************************************************** |
| # Main Section |
| #****************************************************************************** |
| #****************************************************************************** |
| # Setup logging directory |
| #****************************************************************************** |
| CUR_DATE=`$DATE +%Y%m%d` |
| DEFLOGDIR=$HOME/hawqAdminLogs |
| if [ ! -d $DEFLOGDIR ]; then |
| mkdir $DEFLOGDIR |
| fi |
| LOG_FILE=$DEFLOGDIR/${PROG_NAME}_${CUR_DATE}.log |
| |
| if [ $# -ne 0 ]; then |
| if [ "$1" == "-v" ]; then |
| VERSION_INFO |
| fi |
| fi |
| #Set up OS type for scripts to change command lines |
| OS_TYPE=`uname -s|tr '[A-Z]' '[a-z]'` |
| case $OS_TYPE in |
| sunos ) IFCONFIG_TXT="-a inet" |
| IPV6_ADDR_LIST_CMD="$IFCONFIG -a6" |
| PS_TXT="-ef" |
| LIB_TYPE="LD_LIBRARY_PATH" |
| ZCAT=gzcat |
| # MPP-15890 |
| PG_METHOD=ident |
| HOST_ARCH_TYPE="uname -i" |
| NOLINE_ECHO=/usr/bin/echo |
| DEFAULT_LOCALE_SETTING=en_US.UTF-8 |
| MAIL=/bin/mailx |
| PING_TIME="1" |
| GTAR=`findCmdInPath gtar` |
| DF=`findCmdInPath df` |
| # Multi-byte tr needed on Solaris to handle [:upper:], [:lower:], etc. |
| MBTR=/usr/xpg4/bin/tr |
| DU_TXT="-s" ;; |
| linux ) IFCONFIG_TXT="" |
| IPV6_ADDR_LIST_CMD="`findCmdInPath ip` -6 address show" |
| PS_TXT="ax" |
| LIB_TYPE="LD_LIBRARY_PATH" |
| PG_METHOD="ident" |
| HOST_ARCH_TYPE="uname -i" |
| NOLINE_ECHO="$ECHO -e" |
| DEFAULT_LOCALE_SETTING=en_US.utf8 |
| PING6=`findCmdInPath ping6` |
| PING_TIME="-c 1" |
| GTAR=`findCmdInPath tar` |
| DF="`findCmdInPath df` -P" |
| ID=`whoami` |
| DU_TXT="-c" ;; |
| darwin ) IFCONFIG_TXT="" |
| IPV6_ADDR_LIST_CMD="$IFCONFIG -a inet6" |
| PS_TXT="ax" |
| LIB_TYPE="DYLD_LIBRARY_PATH" |
| # Darwin zcat wants to append ".Z" to the end of the file name; use "gunzip -c" instead |
| ZCAT="`findCmdInPath gunzip` -c" |
| PG_METHOD="ident" |
| HOST_ARCH_TYPE="uname -m" |
| NOLINE_ECHO=$ECHO |
| DEFAULT_LOCALE_SETTING=en_US.utf-8 |
| PING6=`findCmdInPath ping6` |
| PING_TIME="-c 1" |
| GTAR=`findCmdInPath gnutar` |
| DF="`findCmdInPath df` -P" |
| DU_TXT="-c" ;; |
| freebsd ) IFCONFIG_TXT="" |
| PS_TXT="ax" |
| LIB_TYPE="LD_LIBRARY_PATH" |
| PG_METHOD="ident" |
| HOST_ARCH_TYPE="uname -m" |
| NOLINE_ECHO="$ECHO -e" |
| DEFAULT_LOCALE_SETTING=en_US.utf8 |
| PING_TIME="-c 1" |
| GTAR=`findCmdInPath gtar` |
| DF="`findCmdInPath df` -P" |
| DU_TXT="-c" ;; |
| * ) echo unknown ;; |
| esac |
| |
| |
| GP_LIBRARY_PATH=`$DIRNAME \`$DIRNAME $INITDB\``/lib |
| SHARE_PATH=`$DIRNAME \`$DIRNAME $INITDB\``/share |
| SCRIPTS_DIR=`$DIRNAME \` $DIRNAME $INITDB\``/bin |
| |
| |
| ## |
| # we setup some EXPORT foo='blah' commands for when we dispatch to segments and standby master |
| ## |
| EXPORT_GPHOME='export GPHOME='$GPHOME |
| if [ x"$LIB_TYPE" == x"LD_LIBRARY_PATH" ]; then |
| EXPORT_LIB_PATH="export LD_LIBRARY_PATH=$LD_LIBRARY_PATH" |
| else |
| EXPORT_LIB_PATH="export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH" |
| fi |