diff options
Diffstat (limited to 'wrap_rsync.sh')
-rwxr-xr-x | wrap_rsync.sh | 71 |
1 files changed, 30 insertions, 41 deletions
diff --git a/wrap_rsync.sh b/wrap_rsync.sh index fb420dc..60f7687 100755 --- a/wrap_rsync.sh +++ b/wrap_rsync.sh @@ -1,21 +1,23 @@ -#!/bin/bash - -set -x +#!/bin/bash -x # On container start, run an rsync to get a good copy of the tree. -# Once we have a copy, start xinetd to start serving. +# Then execute rsyncd; we will start serving once the sync completes. # Then keep syncing in the background every 30m. +# We keep the trees in a TMPFS, we need a million inodes and 1300MB of space. +mount -t tmpfs -o size=1300m,nr_inodes=1000000 tmpfs "${DEST_DIR}" +if [[ $? -ne 0 ]]; then + logger -t rsync "Init: Failed to create tmpfs: ${DEST_DIR}" + return 1 +fi + # Maintain 2 'partitions' of the tree. # "serving" - This copy is served to users and is not mutated. # "updating" - This copy is a shadow copy used for updates. # Create the two partitions on startup. -# We will swap between them at runtime. PARTITION1=$(mktemp -d -p "${DEST_DIR}" XXXXXX) PARTITION2=$(mktemp -d -p "${DEST_DIR}" XXXXXX) -# Our stateful copy. -UPDATES=${DEST_DIR}/stateful # Function sync syncs dest ("${2}") from source ("${1}") function sync() { @@ -46,62 +48,49 @@ function sync() { return 0 } -# Init will update the stateful tree copy. -# Then it will copy that to the stateless partition. +# Function init does a first sync, to populate the serving partition and +# setup symlinks, and begin serving data. +# "${1}" is the serving partition. "${2}" is the update partition function init() { - sync "${UPDATING}" "${SOURCE_MIRROR}" # this is synchronous. - sync "${UPDATING}" "${PARTITION1}" + sync "${1}" "${SOURCE_MIRROR}" # this is synchronous. - # We serve out of ${TMP_DIR}/serving - ln -s "${PARTITION1}" "${TMP_DIR}/serving" - # The second partition will be for stateless updates. - ln -s "${PARTITION2}" "${TMP_DIR}/update" + # We serve out of ${DEST_DIR}/serving + ln -s "${1}" "${DEST_DIR}/serving" + # Setup the update partition + ln -s "${2}" "${DEST_DIR}/update" - # Then launch xinetd; it will detech into the background and serve. - /etc/init.d/xinetd start + # Then launch rsyncd; it will detach into the background and serve from serving. + rsync --daemon --config="/opt/rsync/rsyncd.conf" + return 0 } -# function update syncs the UPDATING partition (stateful.) -# Then it syncs it into the ${TMP_DIR}/update partition (stateless.) -# Then we swap the two stateless partitions (via symlinks swapping.) +# Function update syncs the 'update' partition and, if successful, swaps the partitions. function update() { - update=$(readlink "${TMP_DIR}/update") - # Try to update our stateful tree copy. - if ! sync "${UPDATING}" "${SOURCE_MIRROR}"; then + update=$(readlink "${DEST_DIR}/update") + # If we fail to sync, just return false and avoid modifying the serving state. + if ! sync "${update}" "${SOURCE_MIRROR}"; then return 1 fi - # Try to update our stateless copy. - if ! sync "${update}" "${UPDATING}"; then - return 1 - fi - - # Quasi-atomic swap with symlinks. # Save the previous serving partition - old_serving=$(readlink "${TMP_DIR}/serving") + old_serving=$(readlink "${DEST_DIR}/serving") # Point the serving symlink at the update partition; now freshly updated. - mv -fT "${TMP_DIR}/update" "${TMP_DIR}/serving" + mv -fT "${DEST_DIR}/update" "${DEST_DIR}/serving" # Point the update partition at the old serving partition. - ln -sf "${old_serving}" "${TMP_DIR}/update" - - # Its plausible here that users may still be accessing the old_serving copy, so we don't delete it or anything. -} - -function health() { - /etc/init.d/xinetd status + ln -sf "${old_serving}" "${DEST_DIR}/update" } function serve() { while true do + # TODO(antarus): Add exponential backoff. sleep "${WAIT_TIME}" update - # If xinetd died, just suicide and docker will restart us. - health || exit 5 done } -init +# Partition1 starts as "serving", partition2 as "update" +init "${PARTITION1}" "${PARTITION2}" if [[ $? -ne 0 ]]; then exit 1 fi |