#! /bin/sh

if [[ -z "${1}" ]] ; then
  echo "Usage $0 <YCSB_Version>"
  exit -1
fi
ycsb_version="${1}"

# Test with the latest version of each stable series
# (e.g., the second number should be even).
mongodb_versions="1.8.5 2.0.9 2.2.7 2.4.14 2.6.10 3.0.4"

# Directories
root=$(pwd)
dist="${root}/dist"
data="${root}/data"
logs="${root}/logs"
results="${root}/results.txt"
mkdir -p "${dist}" 
mkdir -p "${data}" 
mkdir -p "${logs}"

# Command to remove the previous run data but leave empty data files.
fsync="printjson(db.getSiblingDB('admin').runCommand({'fsync':1,'async':false,'lock':false}));"
compact="db.usertable.remove()"
compact="${compact};printjson(db.runCommand({'compact':'usertable','force':true}))"
compact="${compact};${fsync}"
shutdown="printjson(db.shutdownServer({timeoutSecs: 60}));"

# Download the YCSB distribution
if [[ ! -r "${dist}/${ycsb_version}.tar.gz" ]] ; then
  echo "Downloading YCSB ${ycsb_version} distribution."
  wget --quiet https://github.com/brianfrankcooper/YCSB/archive/${ycsb_version}.tar.gz
  if [[ ! -r "${ycsb_version}.tar.gz" ]] ; then
    echo ""
    echo "Could not download the YCSB version ${ycsb_version}."
    echo ""
    echo "Usage $0 <YCSB_Version>"
    exit -2
  fi
  mv "${ycsb_version}.tar.gz" "${dist}"
fi

echo "Unpacking the YCSB ${ycsb_version} distribution."
rm -rf "YCSB-${ycsb_version}" YCSB
tar xzf "${dist}/${ycsb_version}.tar.gz"
if [[ ! -d "YCSB-${ycsb_version}" ]] ; then
  echo ""
  echo "Could not find the YCSB distribution directory: YCSB-${ycsb_version}"
  echo ""
  echo "Usage $0 <YCSB_Version>"
  exit -3
fi
ln -s "YCSB-${ycsb_version}" YCSB
cd "YCSB-${ycsb_version}"

# Build YCSB
echo "Building the YCSB ${ycsb_version} distribution."
rm -f "${logs}/build.log" 
if ! mvn clean package >> "${logs}/build.log" 2>&1 ; then
  echo ""
  echo "Could not build the YCSB distribution."
  echo "  See ${logs}/build.log"
  echo "Usage $0 <YCSB_Version>"
  exit -3
fi

# Run the tests.
for mongodb_version in ${mongodb_versions} ; do

  # Start a standalone MongoDB instance.
  if [[ ! -r "${dist}/mongodb-linux-x86_64-${mongodb_version}.tgz" ]] ; then
    echo "Downloading MongoDB ${mongodb_version}."
    wget --quiet https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-${mongodb_version}.tgz
    if [[ ! -r "mongodb-linux-x86_64-${mongodb_version}.tgz" ]] ; then
      echo ""
      echo "Could not download the MongoDB version ${mongodb_version}."
      echo "  *** Skipping."
      continue
    fi
    mv "mongodb-linux-x86_64-${mongodb_version}.tgz" "${dist}"
  fi
  echo "Unpacking MongoDB ${mongodb_version}."
  rm -rf "${root}/mongodb-linux-x86_64-${mongodb_version}"
  tar --directory="${root}" -xzf "${dist}/mongodb-linux-x86_64-${mongodb_version}.tgz"
  if [[ ! -d "${root}/mongodb-linux-x86_64-${mongodb_version}/bin" ]] ; then
    echo ""
    echo "Could not find the MongoDB binaries: ${root}/mongodb-linux-x86_64-${mongodb_version}/bin."
    echo "  *** Skipping."
    continue
  fi
  mongo="${root}/mongodb-linux-x86_64-${mongodb_version}/bin/mongo"
  mongod="${root}/mongodb-linux-x86_64-${mongodb_version}/bin/mongod"

  # Make sure there is no MongoDB server already running.
  ${mongo} --eval "${shutdown}" localhost:27017/admin >> /dev/null 2>&1

  # Start the server
  echo "Starting MongoDB ${mongodb_version}. See ${logs}/mongod-${mongodb_version}.log"
  ${mongod} --dbpath "${data}" --logpath "${logs}/mongod-${mongodb_version}.log" --logappend --fork >> /dev/null 2>&1

  for workload in workloada workloadb workloadc workloadd workloade workloadf ; do
    for connections in 5 10; do
      let doubleConns=(connections+connections)
      for threads in ${connections} ${doubleConns} ; do
        for driver in mongodb-async mongodb ; do

          # Compatibility check.
          if [[ "${mongodb_version}" = "1.8.5" ]] && [[ "${driver}" = "mongodb" ]] ; then
            # MongoDB driver does not support 1.8.5
            continue
          fi
          
          # Remove all documents and compact (avoid re-disk allocation)."
          ${mongo} --eval "${compact}" localhost:27017/ycsb >> /dev/null 2>&1

          # Load the data set.
          now=$( date --utc "+%F %H:%M:%S" )
          printf "%s: %-9s: Load: %9s with %-13s thread=%3s conns=%2s" \
             "${now}" ${mongodb_version} ${workload} ${driver} ${threads} ${connections}
          
          let start=$( date --utc "+%s" )
          ./bin/ycsb load ${driver} -s -P workloads/${workload} -threads ${threads}            \
                 -p "mongodb.url=mongodb://localhost:27017/ycsb?w=1&maxPoolSize=${connections}&waitQueueMultiple=${threads}" \
                 >  ${logs}/${mongodb_version}-${workload}-${driver}-threads_${threads}-conns_${connections}-load.out \
                 2> ${logs}/${mongodb_version}-${workload}-${driver}-threads_${threads}-conns_${connections}-load.err
          let end=$( date --utc "+%s" )
          let delta=end-start
          printf " --> %10d seconds\n" ${delta}

          # Sync all of the writes to disk so they don't effect the operations run."
          ${mongo} --eval "${fsync}" localhost:27017/ycsb >> /dev/null 2>&1

          # Run the workload.
          now=$( date --utc "+%F %H:%M:%S" )
          printf "%s: %-9s:  Run: %9s with %-13s thread=%3s conns=%2s" \
             "${now}" ${mongodb_version} ${workload} ${driver} ${threads} ${connections}

          let start=$( date --utc "+%s" )
          ./bin/ycsb run ${driver} -s -P workloads/${workload} -threads ${threads}             \
                 -p "mongodb.url=mongodb://localhost:27017/ycsb?w=1&maxPoolSize=${connections}&waitQueueMultiple=${threads}" \
                 >  ${logs}/${mongodb_version}-${workload}-${driver}-threads_${threads}-conns_${connections}-run.out \
                 2> ${logs}/${mongodb_version}-${workload}-${driver}-threads_${threads}-conns_${connections}-run.err
          let end=$( date --utc "+%s" )
          let delta=end-start
          printf " --> %10d seconds\n" ${delta}
        done
      done
    done
  done

  # Shutdown the server
  echo "Stopping MongoDB ${mongodb_version}."
  ${mongo} --eval "${shutdown}" localhost:27017/admin >> /dev/null 2>&1
  rm -rf "${data}/*"
done






