#!/bin/bash
cvmfs_test_name="Streaming cache manager"
cvmfs_test_autofs_on_startup=false
cvmfs_test_suites="quick"

CVMFS_TEST_690_HTTP_PID=
CVMFS_TEST_690_PRIVATE_MOUNTPOINT=
cleanup() {
  echo "running cleanup()"
  if [ ! -z $CVMFS_TEST_690_PRIVATE_MOUNTPOINT ]; then
    echo -n "umounting ${CVMFS_TEST_690_PRIVATE_MOUNTPOINT}... "
    remove_local_mount $CVMFS_TEST_690_PRIVATE_MOUNTPOINT && echo "done" || echo "fail"
  fi
  [ -z $CVMFS_TEST_690_HTTP_PID ] || sudo kill $CVMFS_TEST_690_HTTP_PID
}

cvmfs_run_test() {
  logfile=$1
  src_location=$2
  local repo_dir="/cvmfs/${CVMFS_TEST_REPO}"
  local scratch_dir="$(pwd)"

  echo "*** create a fresh repository named $CVMFS_TEST_REPO with user $CVMFS_TEST_USER"
  create_empty_repo $CVMFS_TEST_REPO $CVMFS_TEST_USER || return $?

  start_transaction $CVMFS_TEST_REPO                             || return $?
  mkdir -p ${repo_dir}/internal                                  || return 2
  mkdir -p ${repo_dir}/nested                                    || return 2
  touch ${repo_dir}/nested/.cvmfscatalog                         || return 2
  echo "Hello World" > ${repo_dir}/internal/small                || return 3
  cat /dev/urandom | head -c 2500 > ${repo_dir}/internal/bar     || return 4
  publish_repo $CVMFS_TEST_REPO -v                               || return 5

  start_transaction $CVMFS_TEST_REPO                                      || return $?
  echo "CVMFS_COMPRESSION_ALGORITHM=none" | \
    sudo tee -a /etc/cvmfs/repositories.d/${CVMFS_TEST_REPO}/server.conf
  mkdir -p ${repo_dir}/external                                           || return 6
  cat /dev/urandom | head -c $((1000*1000*25)) > ${repo_dir}/external/foo || return 7
  local external_md5=$(cat ${repo_dir}/external/foo | cvmfs_publish hash -a md5)
  echo "*** MD5 hash of ${repo_dir}/external/foo is $external_md5"
  if ! running_on_s3; then
    echo "CVMFS_EXTERNAL_DATA=true" | \
      sudo tee -a /etc/cvmfs/repositories.d/${CVMFS_TEST_REPO}/server.conf
  fi
  publish_repo $CVMFS_TEST_REPO -v                                        || return 9

  echo "*** Check catalog and data integrity"
  check_repository $CVMFS_TEST_REPO -i || return $?

  echo "*** Plant external file"
  if ! running_on_s3; then
    local chunk_list=$(get_xattr chunk_list /var/spool/cvmfs/${CVMFS_TEST_REPO}/rdonly/external/foo | tail -n +2)
    printf "$chunk_list\n"
    local nchunks=$(printf "$chunk_list\n" | wc -l)
    [ $nchunks -gt 1 ] || return 30
    mkdir /srv/cvmfs/${CVMFS_TEST_REPO}/data/external || return 31
    for c in $chunk_list; do
      local hash=$(echo $c | cut -d, -f1)
      cat /srv/cvmfs/${CVMFS_TEST_REPO}/data/${hash:0:2}/${hash:2}P >> \
        /srv/cvmfs/${CVMFS_TEST_REPO}/data/external/foo || return 32
    done
  fi

  echo "*** install a desaster cleanup"
  trap cleanup EXIT HUP INT TERM || return $?

  CVMFS_TEST_690_PRIVATE_MOUNTPOINT="$(pwd)/mountpoint"
  do_local_mount "$CVMFS_TEST_690_PRIVATE_MOUNTPOINT" \
                 "$CVMFS_TEST_REPO" \
                 "$(get_repo_url $CVMFS_TEST_REPO)" \
                 "" \
                 "CVMFS_STREAMING_CACHE=yes\nCVMFS_EXTERNAL_URL=http://localhost/cvmfs/${CVMFS_TEST_REPO}/data\nCVMFS_EXTERNAL_HTTP_PROXY=DIRECT" || return 10
  local talk_socket="$(get_cache_directory $CVMFS_TEST_690_PRIVATE_MOUNTPOINT)/$CVMFS_TEST_REPO/cvmfs_io.$CVMFS_TEST_REPO"
  local cache_instance=$(sudo cvmfs_talk -p $talk_socket cache instance)
  echo "$cache_instance"
  echo "$cache_instance" | grep Streaming || return 11

  ls -lah $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/ || return 20
  cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small || return 21
  sudo cvmfs_talk -p $talk_socket cache list | tee cache_list
  cat cache_list | grep small && return 22

  local is_external=$(get_xattr external_file $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo)
  running_on_s3 || [ x"$is_external" = "x1" ] || return 42
  md5sum $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo || return 43
  local verify_md5=$(cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo | cvmfs_publish hash -a md5)
  if [ "x$external_md5" != "x$verify_md5" ]; then
    echo "*** MD5 mismatch for $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo"
    return 49
  fi
  sudo cvmfs_talk -p $talk_socket cache list | tee cache_list
  cat cache_list | grep foo && return 44

  local size_md=$(stat --format=%s $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo)
  local size_cat=$(cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo | wc -c)
  echo "*** size of 'foo': $size_md / $size_cat"
  [ $size_md -eq $size_cat ] || return 45
  size_md=$(stat --format=%s $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small)
  size_cat=$(cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small | wc -c)
  echo "*** size of 'small': $size_md / $size_cat"
  [ $size_md -eq $size_cat ] || return 46
  size_md=$(stat --format=%s $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/bar)
  size_cat=$(cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/bar | wc -c)
  echo "*** size of 'bar': $size_md / $size_cat"
  [ $size_md -eq $size_cat ] || return 47

  sudo cvmfs_talk -p $talk_socket cache list
  sudo cvmfs_talk -p $talk_socket cache list catalogs

  cvmfs2 __RELOAD__ $(get_cache_directory $CVMFS_TEST_690_PRIVATE_MOUNTPOINT)/cvmfs.$CVMFS_TEST_REPO \
    --debug || return 50
  ls -lR $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/
  cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small || return 51
  md5sum $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo || return 52

  gcc -Wall -pthread -o openwaitprint ${src_location}/openwaitprint.c || return 60
  ./openwaitprint $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small > small &
  local pid_helper=$!

  cvmfs2 __RELOAD__ $(get_cache_directory $CVMFS_TEST_690_PRIVATE_MOUNTPOINT)/cvmfs.$CVMFS_TEST_REPO \
    --debug || return 61
  kill -USR1 $pid_helper
  wait $pid_helper || return 62
  diff small $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small || return 63

  echo "*** test forwarding of download errors"
  purge_disk_cache
  cvmfs2 __RELOAD__ $(get_cache_directory $CVMFS_TEST_690_PRIVATE_MOUNTPOINT)/cvmfs.$CVMFS_TEST_REPO \
    --debug || return 90
  sudo cvmfs_talk -p $talk_socket host set "http://localhost/cvmfs/${CVMFS_TEST_REPO}/data/nosuchurl"
  sudo cvmfs_talk -p $talk_socket external host set "http://localhost/cvmfs/${CVMFS_TEST_REPO}/data/nosuchurl"
  md5sum $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/external/foo && return 91
  sudo cvmfs_talk -p $talk_socket host set "http://localhost/cvmfs/${CVMFS_TEST_REPO}"
  sudo cvmfs_talk -p $talk_socket external host set "http://localhost/cvmfs/${CVMFS_TEST_REPO}/data"


  echo "*** ignore changing from streaming to non-streaming"
  local config=$(sudo cvmfs_talk -p $talk_socket parameters | \
    grep ^CVMFS_STREAMING_CACHE | awk '{print $NF}')
  echo "*** config is $config"
  echo "CVMFS_STREAMING_CACHE=no" >> $config
  ./openwaitprint $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small > small &
  pid_helper=$!
  cvmfs2 __RELOAD__ $(get_cache_directory $CVMFS_TEST_690_PRIVATE_MOUNTPOINT)/cvmfs.$CVMFS_TEST_REPO \
    --debug || return 70
  sudo cvmfs_talk -p $talk_socket parameters
  sudo cvmfs_talk -p $talk_socket cache instance
  kill -USR1 $pid_helper
  wait $pid_helper || return 71
  diff small $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small || return 72
  cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/bar > /dev/null || return 73
  ls -lR $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/ || return 74

  echo "*** ignore changing from non-streaming to streaming"
  remove_local_mount $CVMFS_TEST_690_PRIVATE_MOUNTPOINT || return 80
  do_local_mount "$CVMFS_TEST_690_PRIVATE_MOUNTPOINT" \
                 "$CVMFS_TEST_REPO" \
                 "$(get_repo_url $CVMFS_TEST_REPO)" \
                 "" \
                 "CVMFS_STREAMING_CACHE=no\nCVMFS_EXTERNAL_URL=http://localhost/cvmfs/${CVMFS_TEST_REPO}\nCVMFS_EXTERNAL_HTTP_PROXY=DIRECT" || return 81
  config=$(sudo cvmfs_talk -p $talk_socket parameters | \
    grep ^CVMFS_STREAMING_CACHE | awk '{print $NF}')
  echo "*** config is $config"
  echo "CVMFS_STREAMING_CACHE=yes" >> $config
  ./openwaitprint $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small > small &
  pid_helper=$!
  cvmfs2 __RELOAD__ $(get_cache_directory $CVMFS_TEST_690_PRIVATE_MOUNTPOINT)/cvmfs.$CVMFS_TEST_REPO \
    --debug || return 82
  sudo cvmfs_talk -p $talk_socket parameters
  sudo cvmfs_talk -p $talk_socket cache instance
  kill -USR1 $pid_helper
  wait $pid_helper || return 83
  diff small $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/small || return 84
  cat $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/internal/bar > /dev/null || return 85
  ls -lR $CVMFS_TEST_690_PRIVATE_MOUNTPOINT/ || return 86

  return 0
}
