#!/bin/sh

# Copyright (c) 2008-2011 Aleksey Cheusov <vle@gmx.net>
# All rights reserved.
#
# See LICENSE file

######################################################################

set -e
. /usr/pkg/bin/pipestatus

# usage: stage_upload_logs BUILD_ID
test $# -eq 1

# init
BUILD_ID="$1"

: ${DISTBB_CONF:=/usr/pkg/etc/distbb.conf}
. "$DISTBB_CONF"
. /usr/pkg/libexec/distbb/common

# main
######################################################################
cd $REPORT1_DIR

######################################################################
### graph of packages for paexec
verbose_print "Initial queue..."

/usr/pkg/libexec/distbb/gen_queue -f "$progress_fn" "$rebuild_PAe_fn" > "$queue_fn"
eval $WEIGH_PACKAGES_CMD -f "$queue_fn" "$pkg_src_summary_fn" > "$queue_fn.tmp"
cat "$queue_fn.tmp" >> "$queue_fn"
rm "$queue_fn.tmp"

verbose_print "done\n"

######################################################################
### main loop - building

postfilter (){
    # postprocessor for paexec's output.
    # It shows progress, success and failure messages,
    # redirects build logs to bulk_log/pkgpath directory,
    # recalculates counters in a queue file
    # removes unneeded bulk_log/pkgpath directories etc.
runawk \
   -v report1_dir=$REPORT1_DIR \
   -v packages_failed_fn=$packages_failed_fn.tmp \
   -v packages_failed_notavail_fn=$packages_failed_notavail_fn.tmp \
   -v progress_fn=$progress_fn \
   -v pkg_src_summary=$pkg_src_summary_fn \
   -e '
# input line format:
#    $1 - <SLAVE_HOST>
#    $2 - <TASK_NUMBER>

#use "xclose.awk"
#use "xsystem.awk"
#use "xgetline.awk"

BEGIN {
   while (xgetline0(pkg_src_summary)){
      if ($0 ~ /^PKGPATH=/) pkgpath = substr($0, 9)
      else if ($0 ~ /^PKGNAME=/) pkgname = substr($0, 9)
      else if (NF == 0) pkgnames [pkgpath] = pkgname
   }
}

function get_log_dir (pkgpath,            pkgname){
   pkgname = pkgnames [pkgpath]
   assert(pkgname != "", "bad pkgname=`" pkgname "`, this should not happen!")
   sub(/:.*/, "", pkgpath)  # remove options settings
   gsub(/\//, "_", pkgpath) # s|/|_|
   return report1_dir "/" pkgpath "_" pkgname
}

!($2 in pkgpaths) {
   # $3 - package name (PKGPATH)
   pkgpaths [$2] = $3
   run_on   [$2] = $1
   print "  started:", $3, "on", $1
   xsystem("mkdir -p " get_log_dir($3))

   next
}

$0 ~ /^[^ ]+ [0-9]+ (success|failure|fatal)$/ {
   status [$2] = $3
   next
}

status [$2] == "failure" && !($2 in failed_deps) {
   task_number = $2
   $1 = $2 = ""
   failed_deps [task_number] = $0
   next
}

{
   pkgpath = pkgpaths [$2]
   log_dir = get_log_dir(pkgpath)
   log_fn  = log_dir "/stage_" stage [$2] ".tmp"
}

$3 == "--**--**--" && $5 == "--**--**--" {
   if (stage [$2] != ""){
      xclose(log_fn)
   }
   stage [$2] = $4
   printf "" > (log_dir "/stage_" $4 ".tmp")

   # for detecting failed stage
   curr_stage_fn = (log_dir "/curr_stage.tmp")
   print $4 > curr_stage_fn
   xclose(curr_stage_fn)

   next
}

$0 ~ /^[^ ]+ [0-9]+  / {
   # normal log line
   sub(/^[^ ]+ [^ ]+  /, "")
   print > log_fn
   next
}

# end of task
{
   assert(NF == 2, "this should not happen")
   if (stage [$2] != "")
      xclose(log_fn)
}

function free_arrs (task){
   delete pkgpaths [task]
   delete run_on   [task]
   delete status [task]
   delete stage [task]
   delete failed_deps [task]
}

status [$2] == "fatal" {
   # fatal
   print "    FATAL:", pkgpath, "on", run_on [$2]
   xsystem("rm -rf " get_log_dir(pkgpaths [$2]))
   free_arrs($2)
   next
}

status [$2] == "success" {
   # succeeded
   print "    succeeded:", pkgpath, "on", run_on [$2]

   # removing log directory
   xsystem("rm -rf " log_dir)

   # free memory
   free_arrs($2)

   #
   print "success", pkgpath >> progress_fn
   xclose(progress_fn)

   #
   next
}

status [$2] == "failure" {
   # failed
   if (stage [$2] ~ /^(Available|Excluded)$/){
      print "    Not Available:", pkgpath, "on", run_on [$2]
      print pkgpath >> packages_failed_notavail_fn
      xclose(packages_failed_notavail_fn)
   }else{
      print "    F-A-I-L-E-D:", pkgpath, "on", run_on [$2]
      print pkgpath >> packages_failed_fn
      xclose(packages_failed_fn)
   }

   # indirectly failed
   cnt = split(failed_deps [$2], failed_pkgs)
   log_fn  = log_dir "/failed_deps.txt"
   printf "" > log_fn
   for (i=2; i <= cnt; ++i){
      fpkg = failed_pkgs [i]
      print fpkg > log_fn

      fpkg_logdir = get_log_dir(fpkg)
      xsystem("mkdir -p " fpkg_logdir)
      pkgp_log_fn = fpkg_logdir "/failed_because.txt"
      print pkgpath >> pkgp_log_fn
      xclose(pkgp_log_fn) # in order to not exceed system/awk limits...
   }
   xclose(log_fn)

   # free memory
   free_arrs($2)

   #
   print "failure", pkgpath >> progress_fn
   xclose(progress_fn) # to make stage "build" rerunable

   #
   next
}

{
   abort("this should not happen 2")
}
'
}

if is_true "$MASTER_MODE"; then
    SLAVES="-n '$SLAVES'"
    TRANSPORT="-t '$TRANSPORT'"
else
    SLAVES='-n +1' # building on localhost
    unset TRANSPORT || true
fi

verbose_print "Building\n"

env_for_slave="DISTBB_CONF=$DISTBB_CONF aux_reqd_deps_fn=$aux_reqd_deps_fn"

eval runpipe0 \
    paexec -s $PAEXEC_EXTRA_OPTS -EI -lr $TRANSPORT $SLAVES \
       -c "'env $env_for_slave /usr/pkg/libexec/distbb/wrapper $DISTBB_SLAVE'" \
       < "$queue_fn" '|' \
    postfilter

######################################################################
rmdir $REPORT1_DIR/* 2>/dev/null || true

if test -n "$DISTBB_DIFF"; then
    printf "%s\n" "$BUILD_ID" >> "$bb_history_fn"
    env LC_ALL=C uniq "$bb_history_fn" > "$bb_history_fn.tmp"
    mv "$bb_history_fn.tmp" "$bb_history_fn"
fi

echo "$(date -u '+%Y-%m-%d %H:%M') UTC" > $build_end_fn
