#!/bin/sh
# Utilities to process DB-related variables from WMC_CONFIG

# rebuild $HOST_DB_URLS as shell list (space-separated)
db_list() {
    [ -z "$HOST_DB_URLS" ] && printf >&2 "HOST_DB_URLS is empty \n" && return 1
    save_ifs="$IFS"; IFS=',' 
    set $(echo $HOST_DB_URLS); 
    echo "$@"
    IFS="$save_ifs"
}

# echoes the number of DBs
db_count() {
    [ -z "$HOST_DB_URLS" ] && echo 0 && return 1
	set $(db_list)
	echo $#
}

# echoes [0, N_DBs) list of integers, e.g. 0 1 2 3 if we have 4 DBs
db_irange() {
	local range=
	n_db=`db_count`
	if [ $n_db -gt 10 ]; then
		printf >&2 "Not implemented for db_count=$n_db\n" 
		return 1
	fi
	
	k=0
	while [ $k -lt $n_db ]; do
		if [ ".$range" = "." ]; then
			range=$k
		else
			range="$range $k"
		fi
		k=$(($k+1))
	done
	echo $range
	return 0
}

# db_nth <user|pass|host|name|url|auth> N
#	- echoes variable value for Nth DB 
#	- auth is complete authorization cmdline parameter, e.g. "-uhost_rw --password=*** -hwmc-05.yandex.ru -Dhost_05"
# indexes are zero-based, e.g. [0..3]; corresponds to Hash(hostName) % NumDBs
db_nth() {
	[ -z "$2" ] && { printf >&2 "Parameter missed: DB index [%s]\n" $2; return 1; }
	[ "$2" -ge 0 ] && [ "$2" -lt "$WMC_DB_COUNT" ] || { printf >&2 "Illegal DB index [%s]\n" $2; return 2; }
	
	case "$1" in
		user|pass|host|name|url|auth)
			eval db_nth_${1}_ $2
			return $?
			;;
		*)	
			printf >&2 "Illegal parameter [%s]\n" $1
			return 2
	esac
}

# db_all_cmdline
# @return cmdline parameters as separate lines
# Example:
# db_all_cmdline | while read cmd; do mysql $cmd -e 'do whatever here'; done
db_all_cmdline() {
	local x
	for x in $WMC_DB_IRANGE; do
		db_nth_auth_ $x
	done
	return 0
}


# db_hashstr "my.sample.com"
# @param host name
# @return print WMC_DB hash value of the string $1 (=sum of characters in the string)
# $(sum=0; for x in `echo -n $1 | od -An -td1`; do sum=$(($sum+$x)); done; echo $sum)
db_hashstr() {
    local x sum
	sum=0
    for x in `echo -n "$1" | od -An -td1`; do
        sum=$(($sum+$x))
    done
    echo $sum
}

# db_dbindex4host "my.sample.com"
# @param host name
# @return print DB index for the host name
db_dbindex4host() {
    local dbCount=$WMC_DB_COUNT
    echo $(($(db_hashstr $1) % $dbCount))
}

# db_filterhosts 3 < host_list > filtered_list
# @param db index
# Filter hosts containing in DB number $1 (from stdin to stdout)
# !!! SLOW !!! (~100x slower than Perl) Don't use for the long lists
db_filterhosts() {
    local dbCount=$WMC_DB_COUNT
    for word in `cat`; do
    	if [ $(($(db_hashstr $word) % $dbCount)) -eq $1 ]; then
    		echo $word
    	fi
    done
}


# ==============================================================================
# Unchecked, internal implementation. Not for direct use
# ==============================================================================
# unchecked, internal
db_nth_url_() {
	local k url
	k=0
	for url in $WMC_DB_URLS; do
		[ ".$k" = ".$1" ] && echo $url && return 0
		k=$(($k+1))
	done
	printf >&2 "Illegal DB index [%s]\n" $1
	return 2
}

# unchecked, internal
db_nth_name_() {
	local x
	eval x=\$$"HOST${1}_DB_NAME"
	echo $x
	return 0
}

# unchecked, internal
db_nth_host_() {
	local x
	eval x=\$$"HOST${1}_DB_HOST"
	echo $x
	return 0
}

# unchecked, internal
db_nth_user_() {
	local x
	eval x=\$$"HOST${1}_DB_USER"
	echo $x
	return 0
}

# unchecked, internal
db_nth_pass_() {
	local x
	eval x=\$$"HOST${1}_DB_PASSWORD"
	echo $x
	return 0
}

# Complete authorization command line. Unchecked, internal
db_nth_auth_() {
	local u p h d
	eval u=\$$"HOST${1}_DB_USER"
	eval p=\$$"HOST${1}_DB_PASSWORD"
	eval h=\$$"HOST${1}_DB_HOST"
	eval d=\$$"HOST${1}_DB_NAME"
	echo "--user=$u --password=$p --host=$h --database=$d"
	return 0
}

WMC_DB_URLS="$(db_list)"
WMC_DB_COUNT=$(db_count)
WMC_DB_IRANGE="$(db_irange)"


# ==============================================================================

# self-test aka POST
db_test_() {
	[ -z $WMC_CONFIG ] && printf >&2 "WMC_CONFIG not defined \n" && exit 2
	. $WMC_CONFIG || exit 1
	
	DB_URLS=`db_list`
	DB_COUNT=`db_count`

    printf "DB_URLS = $DB_URLS\n"
	printf "DB_COUNT = $DB_COUNT\n"
	
	for x in $DB_URLS; do echo $x; done
	
	DBs=`db_irange`
	for x in $DBs; do echo -n "$x,"; done
	echo	# \n
	
	printf "Negative test: " && \
	db_nth url   || printf >&2 "Error $? [%s]\n" 'db_nth url  '
    printf "Negative test: " && \
	db_nth url x || printf >&2 "Error $? [%s]\n" 'db_nth url x'
	db_nth url 0 || printf >&2 "Error $? [%s]\n" 'db_nth url 0'
	db_nth url 4 || printf >&2 "Error $? [%s]\n" 'db_nth url 4'
	
    printf "Negative test: " && \
	db_nth name 
    printf "Negative test: " && \
	db_nth name x
	db_nth name 1
	db_nth name 4
	
	db_nth host 0
	db_nth pass 0
	
	echo "mysql `db_nth auth 1` --no-auto-rehash -e 'show create table tbl_key_regions;'"
	mysql $(db_nth auth 1) --no-auto-rehash -e "show create table tbl_key_regions;"
	
	# Alternative notation
	printf "Negative test: " &&
	mysql `db_nth auth 6` --no-auto-rehash -e "show create table tbl_key_regions;"
	
    h1=`db_hashstr "www.lenta.ru"`; echo "db_hashstr 'www.lenta.ru' = $h1"
    h1=`db_hashstr "ru.wikipedia.org"`; echo "db_hashstr 'ru.wikipedia.org' = $h1"
    h1=`db_hashstr "www.some_very_long_and_stupid_host_name.com"`; echo "db_hashstr 'www.some_very_long_and_stupid_host_name.com' = $h1"
    
    d1=`db_dbindex4host "www.lenta.ru"`;        echo "DB Index for 'www.lenta.ru' is $d1"
    d1=`db_dbindex4host "ru.wikipedia.org"`;    echo "DB Index for 'ru.wikipedia.org' is $d1"
    d1=`db_dbindex4host "www.some_very_long_and_stupid_host_name.com"`;    echo "DB Index for 'www.some_very_long_and_stupid_host_name.com' is $d1"

    printf "Command line for the host=www.mail.ru (shall be 3):\n" &&
    echo "mysql `db_nth auth $(db_dbindex4host www.mail.ru) `"
    
    printf "Read host list from hosts.txt and write to hosts.1.txt" && \
    db_filterhosts 1 < hosts.txt > hosts.1.txt
}

#test_

