#!/bin/bash - this is a sourced file but this header helps vim # $HeadURL$ $LastChangedRevision$ COMPATIBILITY_TEST_SQL="(release_distro_compatibilities.distro_pkgtype isnull or release_distro_compatibilities.distro_pkgtype == hosts.pkgtype) and (release_distro_compatibilities.distro isnull or release_distro_compatibilities.distro == hosts.distro) and (release_distro_compatibilities.distro_release isnull or release_distro_compatibilities.distro_release == hosts.release) and (release_distro_compatibilities.distro_port isnull or release_distro_compatibilities.distro_port == hosts.port) and extendeds.repo == release_distro_compatibilities.repo and sections.repo == release_distro_compatibilities.repo and sections.release == release_distro_compatibilities.release" init() { local ERRSTACK_REF="$1"; shift local DIR ade_inherit CODE_SCHEMA_CONFORMANCY || return $? ade_write_sql "$ERRSTACK_REF" ".read $(paa-config paa_share_prefix)/sql/paa-$CODE_SCHEMA_CONFORMANCY.sql" || return $? init_deb "$ERRSTACK_REF" || return $? init_rpm "$ERRSTACK_REF" || return $? # Sanity checks and derivations DIR=$PAA_STATE_PREFIX # Guts if [ -d $DIR ] && [ "X$(ls $DIR)" != X ]; then save_old_dir_contents "$ERRSTACK_REF" mv $DIR || return $? elif [ -d $DIR ]; then : elif [ -e $DIR ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$DIR: exists but is not an empty directory" return $ADE_FAIL fi return $ADE_OK } repo() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO SPECIFIED_REPOTYPE SPECIFIED_PKGTYPE SPECIFIED_IS_DISTRO local REPOPATH MIRROR_CMD MIRROR_DIR FREEZE_DIR INDIRECT_DIR URL ORIGIN LABEL SIGNER local DB_REPOPATH DB_MIRROR_CMD DB_MIRROR_DIR DB_FREEZE_DIR DB_INDIRECT_DIR DB_URL DB_ORIGIN DB_LABEL DB_SIGNER local COUNT PROGNAME ade_inherit SEPARATOR || return $? # Argument processing [ $# = 4 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 SPECIFIED_PKGTYPE=$2 SPECIFIED_REPOTYPE=$3 SPECIFIED_IS_DISTRO=$4 ade_debug "$ERRSTACK_REF" 10 "repo: SPECIFIED_REPO=$SPECIFIED_REPO, SPECIFIED_REPOTYPE=$SPECIFIED_REPOTYPE, SPECIFIED_PKGTYPE=$SPECIFIED_PKGTYPE, SPECIFIED_IS_DISTRO=$SPECIFIED_IS_DISTRO" # Sanity checks and derivations ade_get_progname "$ERRSTACK_REF" PROGNAME MATCH_FLAG=false # Stash in a temp table; it will make database stuff simpler. ade_write_sql "$ERRSTACK_REF" "create temp table newrepos (repo text, status text, pid text, pkgtype text, repotype text, is_distro text);" || return $? ade_write_sql "$ERRSTACK_REF" "insert into newrepos values ('$SPECIFIED_REPO', 'non-existent', null, '$SPECIFIED_PKGTYPE', '$SPECIFIED_REPOTYPE', '$SPECIFIED_IS_DISTRO');" || return $? # Main loop list_possible_repos "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_debug "$ERRSTACK_REF" 10 "repo: REPO=$REPO" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_repo_attributes "$ERRSTACK_REF" $REPO STATUS PID REPOTYPE REPOPATH || return $? ade_debug "$ERRSTACK_REF" 10 "repo: STATUS=$STATUS, PID=$PID, REPOTYPE=$REPOTYPE, REPOPATH=$REPOPATH" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = non-existent ]; then ade_info "$ERRSTACK_REF" "$REPO: defining ..." elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: already defined!" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: fostering and resuming defining ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "insert or replace into repos (repo, status, pid, pkgtype, repotype, config_gz, repoed_ts) values ('$SPECIFIED_REPO', 'updating', $$, NULL, NULL, NULL, strftime('%s','now'));" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true # Guts ade_write_sql "$ERRSTACK_REF" "update repos set pkgtype = '$SPECIFIED_PKGTYPE', repotype = '$SPECIFIED_REPOTYPE', is_distro = '$SPECIFIED_IS_DISTRO' where repo == '$SPECIFIED_REPO';" || return $? ade_register_temp_file "$ERRSTACK_REF" /tmp/$PROGNAME.$$.$SPECIFIED_REPO || return $? generate_config_template "$ERRSTACK_REF" $SPECIFIED_REPO $SPECIFIED_IS_DISTRO $SPECIFIED_PKGTYPE $SPECIFIED_REPOTYPE > /tmp/$PROGNAME.$$.$SPECIFIED_REPO || return $? ade_debug "$ERRSTACK_REF" 10 "repo: calling import_repo_config to load generated file ..." import_repo_config "$ERRSTACK_REF" $SPECIFIED_REPO /tmp/$PROGNAME.$$.$SPECIFIED_REPO || return $? rm -f /tmp/$PROGNAME.$$.$SPECIFIED_REPO ade_deregister_temp_file "$ERRSTACK_REF" /tmp/$PROGNAME.$$.$SPECIFIED_REPO # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "update repos set status = 'pending', pid = NULL, repoed_ts = strftime('%s','now') where repo == '$SPECIFIED_REPO';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing defined" return $ADE_FAIL fi return $ADE_OK } editrepo() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local REPO STATUS PKGTYPE local TUPLES TUPLE FILENAME COMPILED_FLAG TUPLES_FD MATCH_FLAG CONTINUE_FLAG PROGNAME ade_inherit SEPARATOR || return $? # Argument processing [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 # Sanity checks and derivations ade_get_progname "$ERRSTACK_REF" PROGNAME MATCH_FLAG=false # The 'vi' below is long. We don't want to be in a transaction then. But we do want to be able # to restore how things where before. So we save records into a temporary table. Here we clone # the table structure but not the content. ade_write_sql "$ERRSTACK_REF" "create temp table old_repos as select * from repos where 0 == 1;" || return $? # Main loop # Note: in this function, cleaning up temp files on error is just too complicated. We leave it # to ade_gep() to take care of for us. ade_write_sql "$ERRSTACK_REF" "select repo,status,coalesce(pid,'NULL') as pid,coalesce(pkgtype,'NULL') as pkgtype from (select * from repos union select newrepos.* from (select '$SPECIFIED_REPO' as repo, 'non-existent' as status, NULL as pid, NULL as pkgtype, NULL as repotype, NULL as is_distro, NULL as config_gz, NULL as repoed_ts where repo != 'ALL-REPOS') as newrepos left outer join repos on newrepos.repo == repos.repo where repos.repo isnull) as repos order by repo;" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge (nothing) ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO STATUS PID PKGTYPE || return $? ade_blank_sql_null "$ERRSTACK_REF" || return $? ade_debug "$ERRSTACK_REF" 10 "editrepo: REPO=$REPO, STATUS=$STATUS, PID=$PID, PKGTYPE=$PKGTYPE" # Skips CONTINUE_FLAG=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then break elif [ $SPECIFIED_REPO = $REPO ]; then break fi CONTINUE_FLAG=true done ! $CONTINUE_FLAG || continue CONTINUE_FLAG=false for SETJMP in SETJMP; do if [ $STATUS = non-existent ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: not defined!" return $ADE_FAIL elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO: editing ..." break elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: fostering and resuming editing ..." break fi CONTINUE_FLAG=true done ! $CONTINUE_FLAG || continue # Per-loop sanity checks and derivations MATCH_FLAG=true FILENAME=/tmp/$PROGNAME.$$.$REPO.sh # Lock (keep locked except on long things and stuff we want to not roll back) ade_write_sql "$ERRSTACK_REF" "begin transaction;" || return $? ade_write_sql "$ERRSTACK_REF" "insert into old_repos select * from repos where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "update repos set status = 'updating', pid = $$, repoed_ts = strftime('%s','now') where repo == '$REPO';" || return $? # Guts # Export, copy (to detect changes) and edit ade_debug "$ERRSTACK_REF" 10 "editrepo: exporting config to $FILENAME ..." ade_register_temp_file "$ERRSTACK_REF" $FILENAME || return $? export_repo_config "$ERRSTACK_REF" $REPO $FILENAME || return $? ade_register_temp_file "$ERRSTACK_REF" $FILENAME.orig || return $? cp $FILENAME $FILENAME.orig # Call editor (with unlocking/locking around) ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? ade_debug "$ERRSTACK_REF" 10 "editrepo: calling editor ..." ${EDITOR:-vi} $FILENAME ade_write_sql "$ERRSTACK_REF" "begin transaction;" || return $? # If no changes then undo committed changes. (Note if status was # updating ('cos it got killed) then we recompile regardless of # whether file changed or not.) if [ $STATUS != updating ] && cmp -s $FILENAME.orig $FILENAME; then ade_info "$ERRSTACK_REF" "$REPO: no changes detected" rm -f $FILENAME $FILENAME.orig ade_deregister_temp_file "$ERRSTACK_REF" $FILENAME $FILENAME.orig || return $? ade_write_sql "$ERRSTACK_REF" "replace into repos select * from old_repos;" || return $? ade_write_sql "$ERRSTACK_REF" "delete from old_repos;" ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue fi # Config has changed; save it and checkpoint it. ade_debug "$ERRSTACK_REF" 10 "editrepo: importing (changed) config from $FILENAME ..." import_repo_config "$ERRSTACK_REF" $REPO $FILENAME || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? ade_write_sql "$ERRSTACK_REF" "begin transaction;" || return $? # Compile config. ade_info "$ERRSTACK_REF" "$REPO: changes detected; recompiling configuration ..." ade_debug "$ERRSTACK_REF" 10 "editrepo: purging extended info in preparation for regenerating ..." ade_write_sql "$ERRSTACK_REF" "delete from ports where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from sections where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from compatibilities where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from releases where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from extendeds where repo == '$REPO';" || return $? compile_config "$ERRSTACK_REF" $REPO $FILENAME COMPILED_FLAG || return $? ade_debug "$ERRSTACK_REF" 10 "editrepo: COMPILED_FLAG=$COMPILED_FLAG" rm -f $FILENAME ade_deregister_temp_file "$ERRSTACK_REF" $FILENAME || return $? rm -f $FILENAME.orig ade_deregister_temp_file "$ERRSTACK_REF" $FILENAME.orig || return $? # Delay ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? sleep_if_sleep_defined "$ERRSTACK_REF" || return $? ade_write_sql "$ERRSTACK_REF" "begin transaction;" || return $? # Unlock if $COMPILED_FLAG; then STATUS="available" else STATUS="pending" fi ade_write_sql "$ERRSTACK_REF" "update repos set status = '$STATUS', pid = NULL, repoed_ts = strftime('%s','now') where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from old_repos;" ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing edited" return $ADE_FAIL fi return $ADE_OK } unrepo() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local REPO STATUS PID REPOTYPE REPOPATH local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG PROGNAME ade_inherit SEPARATOR || return $? # Argument processing [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 # Sanity checks and derivations ade_get_progname "$ERRSTACK_REF" PROGNAME [ $SPECIFIED_REPO != ALL-REPOS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-REPOS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } MATCH_FLAG=false ## list_possible_repos wants temp table 'newrepos' to exist, even though this function ## doesn't use it (yet). #ade_write_sql "$ERRSTACK_REF" "create temp table newrepos (repo text, status text, pid text, pkgtype text, repotype text, is_distro text);" || return $? # Main loop list_existing_repos "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_debug "$ERRSTACK_REF" 10 "unrepo: REPO=$REPO" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_repo_attributes "$ERRSTACK_REF" $REPO STATUS PID REPOTYPE REPOPATH || return $? ade_debug "$ERRSTACK_REF" 10 "unrepo: STATUS=$STATUS, PID=$PID, REPOTYPE=$REPOTYPE, REPOPATH=$REPOPATH" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = non-existent ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: not defined!" return $ADE_FAIL elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO: undefining ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: fostering and resuming undefining ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "update repos set status = 'deleting', pid = $$, repoed_ts = strftime('%s','now') where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true # Guts # Local managed repositories are about the one thing that can't be # recreated. So deletion must be manual. if [ $REPOTYPE != owned ]; then : elif [ "X$REPOPATH" != X ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: you should remove the directory ($REPOPATH) for this repository yourself" else ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: you should remove the directory (with which $PROGNAME has not yet been acquainted) for this repository yourself" fi ade_write_sql "$ERRSTACK_REF" "delete from controls where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from extendeds where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from sections where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from ports where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from compatibilities where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "delete from releases where repo == '$REPO';" || return $? # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "delete from repos where repo == '$REPO';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing undefined" return $ADE_FAIL fi return $ADE_OK } listrepos() { local ERRSTACK_REF="$1"; shift local REPO STATUS PID PKGTYPE REPOTYPE IS_DISTRO REPOED_TS local CONFIG_COMPILED_DATE REPOED_DATE local TUPLES TUPLE FMTSTR VERBOSELEVEL ade_inherit REPO_FMTSTR STATUS_FMTSTR PID_FMTSTR PKGTYPE_FMTSTR LOGICAL_FMTSTR REPOTYPE_FMTSTR DATE_FMTSTR SEPARATOR || return $? # Defaults for options # Process options # Process arguments # (Args are left untouched for the filter code at the end of this function.) # Sanity checks and derivations FMTSTR="$REPO_FMTSTR $STATUS_FMTSTR $PID_FMTSTR $PKGTYPE_FMTSTR $REPOTYPE_FMTSTR $LOGICAL_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "repo" "status" "pid" "pkgtype" "repotype" "distro?" "last modified" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" # Main loop ade_write_sql "$ERRSTACK_REF" "select repo, status, coalesce(pid,'NULL'), pkgtype, repotype, is_distro, coalesce(repoed_ts,'NULL') from repos order by repo;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO STATUS PID PKGTYPE REPOTYPE IS_DISTRO REPOED_TS || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO STATUS PID PKGTYPE REPOTYPE IS_DISTRO REPOED_TS || return $? ade_debug "$ERRSTACK_REF" 10 "listrepos: REPO=$REPO, STATUS=$STATUS, PID=$PID, PKGTYPE=$PKGTYPE, REPOTYPE=$REPOTYPE, IS_DISTRO=$IS_DISTRO, REPOED_TS=$REPOED_TS" # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. REPOED_DATE= [ "X$REPOED_TS" = X ] || REPOED_DATE=$(date -d @$REPOED_TS) [[ $STATUS =~ ^(available|pending)$ ]] || [ -d /proc/$PID ] || { STATUS=orphaned; PID=; } # Display printf "$FMTSTR" "$REPO" "$STATUS" "$PID" "$PKGTYPE" "$REPOTYPE" "$IS_DISTRO" "$REPOED_DATE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" echo return $ADE_OK } mirror() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local REPO STATUS PID MIRRORED_TS REPOTYPE MIRROR_DIR REPOPATH MIRROR_CMD || return $? local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG local EXPANDED_MIRROR_DIR ade_inherit SEPARATOR || return $? # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 # Sanity checks and derivations MATCH_FLAG=false # Main loop list_possible_mirrors "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_debug "$ERRSTACK_REF" 10 "mirror: REPO=$REPO" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_mirror_attributes "$ERRSTACK_REF" $REPO STATUS PID MIRRORED_TS REPOTYPE MIRROR_DIR REPOPATH MIRROR_CMD || return $? ade_debug "$ERRSTACK_REF" 10 "mirror: STATUS=$STATUS, PID=$PID, MIRRORED_TS=$MIRRORED_TS, REPOTYPE=$REPOTYPE, MIRROR_DIR=$MIRROR_DIR, REPOPATH=$REPOPATH, MIRROR_CMD=$MIRROR_CMD" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $REPOTYPE = mirrored -o $REPOTYPE = owned ]; then : elif [ $SPECIFIED_REPO = "ALL-REPOS" ]; then # accessed repos can't be mirrored. If the user asked to # mirror 'ALL-REPOS', then just silently ignore them. SKIP=true break # we already know we'll skip this repo, skip further applicability tests. elif [ $SPECIFIED_REPO = $REPO ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: wrong repo type!" fi if [ $STATUS = "non-existent" ]; then ade_info "$ERRSTACK_REF" "$REPO: mirroring ..." elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO: re-mirroring ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: fostering and resuming mirroring ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "insert or replace into mirrors (repo, status, pid, mirrored_ts) values ('$REPO', 'updating', $$, strftime('%s','now'));" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true detokenise "$ERRSTACK_REF" "$MIRROR_DIR" EXPANDED_MIRROR_DIR REPO=$REPO || return $? write_test_dir "$ERRSTACK_REF" "$EXPANDED_MIRROR_DIR" || return $? # Guts ade_debug "$ERRSTACK_REF" 10 "mirror: calling [$MIRROR_CMD] ..." ( cd $EXPANDED_MIRROR_DIR && eval "$MIRROR_CMD" ) || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "mirror command ($MIRROR_CMD) failed"; return $ADE_FAIL; } # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "update mirrors set status = 'available', pid = NULL, mirrored_ts = strftime('%s','now') where repo == '$REPO';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing mirrored" return $ADE_FAIL fi return $ADE_OK } unmirror() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local REPO STATUS PID MIRROR_DIR local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG STATUS PID MIRRORED_TS REPOTYPE MIRROR_DIR REPOPATH MIRROR_CMD local EXPANDED_MIRROR_DIR ade_inherit SEPARATOR || return $? # Option processing # Argument processing [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 # Sanity checks and derivations [ $SPECIFIED_REPO != ALL-REPOS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-REPOS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } # Main loop list_existing_mirrors "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_debug "$ERRSTACK_REF" 10 "unmirror: REPO=$REPO" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_mirror_attributes "$ERRSTACK_REF" $REPO STATUS PID MIRRORED_TS REPOTYPE MIRROR_DIR REPOPATH MIRROR_CMD || return $? ade_debug "$ERRSTACK_REF" 10 "mirror: STATUS=$STATUS, PID=$PID, MIRRORED_TS=$MIRRORED_TS, REPOTYPE=$REPOTYPE, MIRROR_DIR=$MIRROR_DIR, REPOPATH=$REPOPATH, MIRROR_CMD=$MIRROR_CMD" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then SKIP=true break # we already know we'll skip this repo, skip further applicability tests. elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO: unmirroring ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: fostering and resuming unmirroring ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "update mirrors set status = 'deleting', pid = $$, mirrored_ts = strftime('%s','now') where repo == '$REPO';" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true detokenise "$ERRSTACK_REF" "$MIRROR_DIR" EXPANDED_MIRROR_DIR REPO=$REPO || return $? # Guts rm -fr "$EXPANDED_MIRROR_DIR/" # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "delete from mirrors where repo == '$REPO';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing unmirrored" return $ADE_FAIL fi return $ADE_OK } listmirrors() { local ERRSTACK_REF="$1"; shift local FMTSTR MIRRORED_DATE REPO STATUS PID MIRRORED_TS local TUPLES TUPLE STAR VERBOSELEVEL ade_inherit REPO_FMTSTR STATUS_FMTSTR PID_FMTSTR DATE_FMTSTR SEPARATOR || return $? # Defaults for options # Process options # Process arguments # (Args are left untouched for the filter code at the end of this function.) # Sanity checks and derivations FMTSTR="$REPO_FMTSTR $STATUS_FMTSTR $PID_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "mirror" "status" "pid" "last changed" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" # Main loop ade_write_sql "$ERRSTACK_REF" "select repo, status, coalesce(pid,'NULL'), mirrored_ts from mirrors order by repo;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO STATUS PID MIRRORED_TS || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO STATUS PID MIRRORED_TS || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. MIRRORED_DATE= [ "X$MIRRORED_TS" = X ] || MIRRORED_DATE=$(date -d @$MIRRORED_TS) [[ $STATUS =~ ^(available|pending)$ ]] || [ -d /proc/$PID ] || { STATUS=orphaned; PID=; } # Display printf "$FMTSTR" "$REPO" "$STATUS" "$PID" "$MIRRORED_DATE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" echo return $ADE_OK } freeze() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local REPO PKGTYPE STATUS MIRROR_DIR FREEZE_DIR INDIRECT_DIR FREEZE local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG local EXPANDED_MIRROR_DIR EXPANDED_FREEZE_DIR ade_inherit SEPARATOR || return $? # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 # Sanity checks and derivations MATCH_FLAG=false # Main loop list_possible_freezes "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO FREEZE || return $? ade_debug "$ERRSTACK_REF" 10 "freeze: REPO=$REPO, FREEZE=$FREEZE" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_freeze_attributes "$ERRSTACK_REF" $REPO $FREEZE STATUS PID FROZEN_TS MIRROR_DIR FREEZE_DIR || return $? ade_debug "$ERRSTACK_REF" 10 "freeze: STATUS=$STATUS, PID=$PID, FROZEN_TS=$FROZEN_TS, MIRROR_DIR=$MIRROR_DIR, FREEZE_DIR=$FREEZE_DIR" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then ade_info "$ERRSTACK_REF" "$REPO.$FREEZE: freezing ..." elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$FREEZE: already frozen!" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$FREEZE: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$FREEZE: fostering and resuming freezing ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "insert or replace into freezes (repo, freeze, status, pid, frozen_ts) VALUES ('$REPO', $FREEZE, 'updating', $$, strftime('%s','now'));" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true detokenise "$ERRSTACK_REF" "$MIRROR_DIR" EXPANDED_MIRROR_DIR REPO=$REPO || return $? detokenise "$ERRSTACK_REF" "$FREEZE_DIR" EXPANDED_FREEZE_DIR REPO=$REPO FREEZE=$FREEZE || return $? # Guts mkdir -p $EXPANDED_FREEZE_DIR rsync -a --delete --chmod=u=rw,go=r,D+x $EXPANDED_MIRROR_DIR/ $EXPANDED_FREEZE_DIR/ # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "update freezes set status = 'available', pid = NULL, frozen_ts = strftime('%s','now') where repo == '$REPO' and freeze == $FREEZE;" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing frozen" return $ADE_FAIL fi return $ADE_OK } unfreeze() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO SPECIFIED_FREEZE local REPO FREEZE local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG PREVIOUS_REPO ade_inherit SEPARATOR || return $? # Option processing # Argument processing [ $# = 2 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 SPECIFIED_FREEZE=$2 # Sanity checks and derivations [ $SPECIFIED_REPO != ALL-REPOS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-REPOS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } [ $SPECIFIED_FREEZE != ALL-FREEZES ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-FREEZES is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } [ $SPECIFIED_FREEZE != OLD-FREEZES ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "OLD-FREEZES is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } MATCH_FLAG=false # We're going to track the newest freeze PREVIOUS_REPO=no_repo_with_this_name # Main loop list_existing_freezes "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO FREEZE || return $? ade_debug "$ERRSTACK_REF" 10 "unmirror: REPO=$REPO, FREEZE=$FREEZE" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_freeze_attributes "$ERRSTACK_REF" $REPO $FREEZE STATUS PID FROZEN_TS MIRROR_DIR FREEZE_DIR || return $? ade_debug "$ERRSTACK_REF" 10 "mirror: STATUS=$STATUS, PID=$PID, FROZEN_TS=$FROZEN_TS, MIRROR_DIR=$MIRROR_DIR, FREEZE_DIR=$FREEZE_DIR" if [ $REPO = $PREVIOUS_REPO ]; then NEWEST_FREEZE_FLAG=false else NEWEST_FREEZE_FLAG=true fi PREVIOUS_REPO=$REPO # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $SPECIFIED_FREEZE = "ALL-FREEZES" ]; then : elif [ $SPECIFIED_FREEZE = "NEWEST-FREEZE" ] && $NEWEST_FREEZE_FLAG; then : elif [ $SPECIFIED_FREEZE = "OLD-FREEZES" ] && ! $NEWEST_FREEZE_FLAG; then : elif [ $SPECIFIED_FREEZE = $FREEZE ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then SKIP=true break # we already know we'll skip this repo, skip further applicability tests. elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO.$FREEZE: unfreezing ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$FREEZE: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$FREEZE: fostering and resuming unfreezing ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "update freezes set status = 'deleting', pid = $$, frozen_ts = strftime('%s','now') where repo == '$REPO' and freeze == $FREEZE;" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true detokenise "$ERRSTACK_REF" "$FREEZE_DIR" EXPANDED_FREEZE_DIR REPO=$REPO FREEZE=$FREEZE || return $? # Guts rm -fr "$EXPANDED_FREEZE_DIR/" # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "delete from freezes where repo == '$REPO' and freeze == $FREEZE;" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing unfrozen" return $ADE_FAIL fi return $ADE_OK } listfreezes() { local ERRSTACK_REF="$1"; shift local REPO FREEZE STATUS PID FROZEN_TS local FMTSTR THING FROZENDATE local TUPLES TUPLE STAR VERBOSELEVEL ade_inherit REPO_FMTSTR FREEZE_FMTSTR STATUS_FMTSTR PID_FMTSTR DATE_FMTSTR SEPARATOR || return $? # Defaults for options # Process options # Process arguments # (Args are left untouched for the filter code at the end of this function.) # Sanity checks and derivations ade_get_verboselevel "$ERRSTACK_REF" VERBOSELEVEL || return $? FMTSTR="$REPO_FMTSTR $FREEZE_FMTSTR $STATUS_FMTSTR $PID_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "repo" "freeze" "status" "pid" "last changed" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" # Main loop ade_write_sql "$ERRSTACK_REF" "select repo, freeze, status, coalesce(pid,'NULL'), frozen_ts from freezes order by repo, freeze;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO FREEZE STATUS PID FROZEN_TS || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO FREEZE STATUS PID FROZEN_TS || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. FROZEN_DATE= [ "X$FROZEN_TS" = X ] || FROZEN_DATE=$(date -d @$FROZEN_TS) [[ $STATUS =~ ^(available|pending)$ ]] || [ -d /proc/$PID ] || { STATUS=orphaned; PID=; } # Display printf "$FMTSTR" "$REPO" "$FREEZE" "$STATUS" "$PID" "$FROZEN_DATE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" echo return $ADE_OK } host() { local ERRSTACK_REF="$1"; shift local SPECIFIED_HOST SPECIFIED_PKGTYPE SPECIFIED_DISTRO SPECIFIED_RELEASE SPECIFIED_PORT local DERIVED_HOST DERIVED_PKGTYPE DERIVED_DISTRO DERIVED_RELEASE DERIVED_PORT local HOST PKGTYPE DISTRO RELEASE PORT local COUNT HOSTED_TS ade_inherit SEPARATOR THIS_HOST || return $? # Argument processing [ \( $# = 1 -a "X$1" = "XTHIS-HOST" \) -o \( $# = 5 -a "X$1" != "XTHIS-HOST" \) ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_HOST=$1 SPECIFIED_PKGTYPE=$2 SPECIFIED_DISTRO=$3 SPECIFIED_RELEASE=$4 SPECIFIED_PORT=$5 # Sanity checks and derivations if [ "X$SPECIFIED_HOST" = "XTHIS-HOST" ]; then DERIVED_HOST=$THIS_HOST # We could use facter, check /etc/redhat-release & /etc/debian_version or # count output lines from 'rpm -qa' & 'dpkg -l'. if [ -f /etc/redhat-release -a ! -f /etc/debian_version ]; then DERIVED_PKGTYPE=rpm DERIVED_PORT=$(uname -m) ade_validate_command "$ERRSTACK_REF" lsb_release || return $? DERIVED_RELEASE=$(lsb_release -sr) elif [ ! -f /etc/redhat-release -a -f /etc/debian_version ]; then DERIVED_PKGTYPE=deb DERIVED_PORT=$(dpkg-architecture -qDEB_BUILD_ARCH) ade_validate_command "$ERRSTACK_REF" lsb_release || return $? DERIVED_RELEASE=$(lsb_release -sc) else ade_error "$ERRSTACK_REF" PAA_ERR_MISC "can't identify pkgtype" return $ADE_FAIL fi DERIVED_DISTRO=$(lsb_release -si) DERIVED_DISTRO=${DERIVED_DISTRO,,} else DERIVED_HOST=$SPECIFIED_HOST DERIVED_PKGTYPE=$SPECIFIED_PKGTYPE DERIVED_DISTRO=$SPECIFIED_DISTRO DERIVED_RELEASE=$SPECIFIED_RELEASE DERIVED_PORT=$SPECIFIED_PORT fi MATCH_FLAG=false ade_debug "$ERRSTACK_REF" 10 "host: DERIVED_HOST=$DERIVED_HOST, DERIVED_PKGTYPE=$DERIVED_PKGTYPE, DERIVED_DISTRO=$DERIVED_DISTRO, DERIVED_RELEASE=$DERIVED_RELEASE, DERIVED_PORT=$DERIVED_PORT" # Stash in a temp table; it will make database stuff simpler. ade_write_sql "$ERRSTACK_REF" "create temp table newhosts (host text, status text, pid text, pkgtype text, distro text, release text, port text, hosted_ts text);" || return $? ade_write_sql "$ERRSTACK_REF" "insert into newhosts values ('$DERIVED_HOST', 'non-existent', null, '$DERIVED_PKGTYPE', '$DERIVED_DISTRO', '$DERIVED_RELEASE', '$DERIVED_PORT', null);" || return $? # Main loop list_possible_hosts "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" HOST || return $? ade_debug "$ERRSTACK_REF" 10 "repo: HOST=$HOST" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_host_attributes "$ERRSTACK_REF" $HOST STATUS PID PKGTYPE DISTRO RELEASE PORT HOSTED_TS || return $? ade_debug "$ERRSTACK_REF" 10 "repo: STATUS=$STATUS, PID=$PID, PKGTYPE=$PKGTYPE, DISTRO=$DISTRO, RELEASE=$RELEASE, PORT=$PORT, HOSTED_TS=$HOSTED_TS" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $DERIVED_HOST = $HOST ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = non-existent ]; then ade_info "$ERRSTACK_REF" "$HOST: defining ..." elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$HOST: already defined!" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$HOST: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$HOST: fostering and resuming defining ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "insert or replace into hosts (host, status, pid, pkgtype, distro, release, port, hosted_ts) VALUES ('$DERIVED_HOST', 'updating', $$, NULL, NULL, NULL, NULL, strftime('%s','now'));" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true # Guts ade_write_sql "$ERRSTACK_REF" "update hosts set pkgtype = '$DERIVED_PKGTYPE', distro = '$DERIVED_DISTRO', release = '$DERIVED_RELEASE', port = '$DERIVED_PORT' where host == '$DERIVED_HOST';" || return $? # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "update hosts set status = 'available', pid = NULL, hosted_ts = strftime('%s','now') where host == '$DERIVED_HOST';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing defined" return $ADE_FAIL fi return $ADE_OK } unhost() { local ERRSTACK_REF="$1"; shift local SPECIFIED_HOST local HOST local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG ade_inherit SEPARATOR THIS_HOST || return $? # Argument processing [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_HOST=$1 # Sanity checks and derivations [ $SPECIFIED_HOST != "ALL-HOSTS" ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-HOSTS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } MATCH_FLAG=false if [ "X$SPECIFIED_HOST" = "XTHIS-HOST" ]; then DERIVED_HOST=$THIS_HOST else DERIVED_HOST=$SPECIFIED_HOST fi ## list_possible_hosts wants temp table 'newhosts' to exist, even though this function ## doesn't use it (yet). #ade_write_sql "$ERRSTACK_REF" "create temp table newhosts (host text, status text, pid text, pkgtype text, distro text, release text, port text, hosted_ts text);" || return $? # Main loop list_existing_hosts "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" HOST || return $? ade_debug "$ERRSTACK_REF" 10 "unrepo: HOST=$HOST" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_host_attributes "$ERRSTACK_REF" $HOST STATUS PID PKGTYPE DISTRO RELEASE PORT HOSTED_TS || return $? ade_debug "$ERRSTACK_REF" 10 "unrepo: STATUS=$STATUS, PID=$PID, PKGTYPE=$PKGTYPE, DISTRO=$DISTRO, RELEASE=$RELEASE, PORT=$PORT, HOSTED_TS=$HOSTED_TS" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_HOST = "ALL-HOSTS" ]; then : elif [ $SPECIFIED_HOST = $HOST ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = non-existent ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$HOST: not defined!" return $ADE_FAIL elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$HOST: undefining ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$HOST: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$HOST: fostering and resuming undefining ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "update hosts set status = 'deleting', pid = $$, hosted_ts = strftime('%s','now') where host == '$HOST';" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true # Guts # # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "delete from hosts where host == '$HOST';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing unhosted" return $ADE_FAIL fi return $ADE_OK } listhosts() { local ERRSTACK_REF="$1"; shift local FMTSTR HOST STATUS PID HOSTED_TS DISTRO RELEASE PORT local TUPLES TUPLE STAR VERBOSELEVEL ade_inherit HOST_FMTSTR STATUS_FMTSTR PKGTYPE_FMTSTR DISTRO_FMTSTR RELEASE_FMTSTR PORT_FMTSTR DATE_FMTSTR SEPARATOR || return $? # Defaults for options # Process options # Process arguments # (Args are left untouched for the filter code at the end of this function.) # Sanity checks and derivations ade_get_verboselevel "$ERRSTACK_REF" VERBOSELEVEL || return $? FMTSTR="$HOST_FMTSTR $STATUS_FMTSTR $PID_FMTSTR $PKGTYPE_FMTSTR $DISTRO_FMTSTR $RELEASE_FMTSTR $PORT_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "host" "status" "pid" "pkgtype" "distro" "release" "port" "last changed" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" # Main loop ade_write_sql "$ERRSTACK_REF" "select host, status, coalesce(pid,'NULL'), pkgtype, distro, release, port, hosted_ts from hosts order by host;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" HOST STATUS PID PKGTYPE DISTRO RELEASE PORT HOSTED_TS || return $? ade_blank_sql_null "$ERRSTACK_REF" HOST STATUS PID PKGTYPE DISTRO RELEASE PORT HOSTED_TS || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. HOSTED_DATE= [ "X$HOSTED_TS" = X ] || HOSTED_DATE=$(date -d @$HOSTED_TS) [[ $STATUS =~ ^(available|pending)$ ]] || [ -d /proc/$PID ] || { STATUS=orphaned; PID=; } # Display printf "$FMTSTR" "$HOST" "$STATUS" "$PID" "$PKGTYPE" "$DISTRO" "$RELEASE" "$PORT" "$HOSTED_DATE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" echo return $ADE_OK } indirect() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO SPECIFIED_HOST local REPO HOST FREEZE FREEZE_DIR INDIRECT_DIR INDIRECTED_TS local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG local NEWEST_FREEZE_FLAG PREVIOUS_REPO PREVIOUS_HOST local EXPANDED_INDIRECT_DIR EXPANDED_FREEZE_DIR SYMLINK_TARGET ade_inherit SEPARATOR || return $? # Defaults for options # Process options # Process arguments [ $# = 3 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 SPECIFIED_HOST=$2 SPECIFIED_FREEZE=$3 # Sanity checks and derivations MATCH_FLAG=false ## We're going to track the newest freeze PREVIOUS_REPO=no_repo_with_this_name PREVIOUS_HOST=no_host_with_this_name # Main loop list_possible_indirects "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO HOST FREEZE || return $? ade_debug "$ERRSTACK_REF" 10 "indirect: REPO=$REPO, HOST=$HOST, FREEZE=$FREEZE" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? # The primary keys of an indirect are just the repo and the host, but get_indirect_attributes() # is the one get_*_attributes() function that needs to be passed on additional parameter # besides the primary key fields; it is passed also the freeze ID. get_indirect_attributes "$ERRSTACK_REF" $REPO $HOST $FREEZE STATUS PID INDIRECTED_TS FREEZE_DIR INDIRECT_DIR || return $? ade_debug "$ERRSTACK_REF" 10 "indirect: STATUS=$STATUS, PID=$PID, INDIRECTED_TS=$INDIRECTED_TS, FREEZE_DIR=$FREEZE_DIR, INDIRECT_DIR=$INDIRECT_DIR" if [ $REPO = $PREVIOUS_REPO -a $HOST = $PREVIOUS_HOST ]; then NEWEST_FREEZE_FLAG=false else NEWEST_FREEZE_FLAG=true fi PREVIOUS_REPO=$REPO PREVIOUS_HOST=$HOST ade_debug "$ERRSTACK_REF" 10 "indirect: NEWEST_FREEZE_FLAG=$NEWEST_FREEZE_FLAG" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_HOST = "ALL-HOSTS" ]; then : elif [ $SPECIFIED_HOST = $HOST ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $SPECIFIED_FREEZE = "NEWEST-FREEZE" ] && $NEWEST_FREEZE_FLAG; then : elif [ $SPECIFIED_FREEZE != "NEWEST-FREEZE" ] && [ $SPECIFIED_FREEZE = $FREEZE ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then ade_info "$ERRSTACK_REF" "$REPO.$HOST: indirecting ..." elif [[ $STATUS =~ ^(available|pending)$ ]]; then # Something that is already indirected can be reindirected without complaint (presumably # made to point to a newer freeze). ade_info "$ERRSTACK_REF" "$REPO.$HOST: indirecting ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: fostering and resuming indirecting ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "insert or replace into indirects (repo, host, status, pid, freeze, indirected_ts) values ('$REPO', '$HOST', 'updating', $$, NULL, strftime('%s','now'));" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true detokenise "$ERRSTACK_REF" "$INDIRECT_DIR" EXPANDED_INDIRECT_DIR REPO=$REPO HOST=$HOST || return $? detokenise "$ERRSTACK_REF" "$FREEZE_DIR" EXPANDED_FREEZE_DIR REPO=$REPO FREEZE=$FREEZE || return $? # Guts if [ -h $EXPANDED_INDIRECT_DIR ]; then rm -f $EXPANDED_INDIRECT_DIR elif [ -e $EXPANDED_INDIRECT_DIR ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$EXPANDED_INDIRECT_DIR: exists and is not a symlink" return $ADE_FAIL fi mkdir -p $(dirname $EXPANDED_INDIRECT_DIR) convert_abssymlink_to_relsymlink "$ERRSTACK_REF" $EXPANDED_INDIRECT_DIR $EXPANDED_FREEZE_DIR SYMLINK_TARGET || return $? ln -s $SYMLINK_TARGET $EXPANDED_INDIRECT_DIR ade_write_sql "$ERRSTACK_REF" "update indirects set freeze = $FREEZE where repo == '$REPO' and host == '$HOST';" || return $? # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "update indirects set status = 'available', pid = NULL, indirected_ts = strftime('%s','now') where repo == '$REPO' and host == '$HOST';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing indirected" return $ADE_FAIL fi return $ADE_OK } unindirect() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO SPECIFIED_HOST local REPO FREEZE_DIR INDIRECT_DIR local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG local EXPANDED_INDIRECT_DIR local FREEZE ade_inherit SEPARATOR || return $? # Option processing # Argument processing [ $# = 2 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 SPECIFIED_HOST=$2 # Sanity checks and derivations [ $SPECIFIED_REPO != ALL-REPOS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-REPOS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } [ $SPECIFIED_HOST != ALL-HOSTS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-HOSTS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } # Main loop list_existing_indirects "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # list_possible_indirects() has returned tuples containing the freeze, but we don't need that here. ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO HOST FREEZE || return $? ade_debug "$ERRSTACK_REF" 10 "unindirect: REPO=$REPO, HOST=$HOST" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_indirect_attributes "$ERRSTACK_REF" $REPO $HOST $FREEZE STATUS PID INDIRECTED_TS FREEZE_DIR INDIRECT_DIR || return $? ade_debug "$ERRSTACK_REF" 10 "unindirect: STATUS=$STATUS, PID=$PID, INDIRECTED_TS=$INDIRECTED_TS, FREEZE_DIR=$FREEZE_DIR, INDIRECT_DIR=$INDIRECT_DIR" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_HOST = "ALL-HOSTS" ]; then : elif [ $SPECIFIED_HOST = $HOST ]; then : else SKIP=true break # we already know we'll skip this host, skip further applicability tests. fi if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then SKIP=true break # we already know we'll skip this repo, skip further applicability tests. elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO.$HOST: unindirecting ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: fostering and resuming unindirecting ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "update indirects set status = 'deleting', pid = $$, indirected_ts = strftime('%s','now') where repo == '$REPO' and host == '$HOST';" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true detokenise "$ERRSTACK_REF" "$INDIRECT_DIR" EXPANDED_INDIRECT_DIR REPO=$REPO HOST=$HOST || return $? # Guts if [ -h $EXPANDED_INDIRECT_DIR ]; then rm -f $EXPANDED_INDIRECT_DIR elif [ -e $EXPANDED_INDIRECT_DIR ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$EXPANDED_INDIRECT_DIR: exists and is not a symlink" return $ADE_FAIL fi # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "delete from indirects where repo == '$REPO' and host == '$HOST';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing unindirected" return $ADE_FAIL fi return $ADE_OK } listindirects() { local ERRSTACK_REF="$1"; shift local REPO HOST STATUS PID FREEZE INDIRECTED_TS local FMTSTR THING FREEZEDATE INDIRECTED_DATE local TUPLES TUPLE STAR VERBOSELEVEL ade_inherit REPO_FMTSTR HOST_FMTSTR STATUS_FMTSTR PID_FMTSTR FREEZE_FMTSTR DATE_FMTSTR SEPARATOR || return $? # Defaults for options # Process options # Process arguments # (Args are left untouched for the filter code at the end of this function.) # Sanity checks and derivations ade_get_verboselevel "$ERRSTACK_REF" VERBOSELEVEL || return $? FMTSTR="$REPO_FMTSTR $HOST_FMTSTR $STATUS_FMTSTR $PID_FMTSTR $FREEZE_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "repo" "host" "status" "pid" "freeze" "last changed" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" # Main loop ade_write_sql "$ERRSTACK_REF" "select repo, host, status, pid, freeze, indirected_ts from indirects order by repo, host;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO HOST STATUS PID FREEZE INDIRECTED_TS || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO HOST STATUS PID FREEZE INDIRECTED_TS || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. INDIRECTED_DATE= [ "X$INDIRECTED_TS" = X ] || INDIRECTED_DATE=$(date -d @$INDIRECTED_TS) [[ $STATUS =~ ^(available|pending)$ ]] || [ -d /proc/$PID ] || { STATUS=orphaned; PID=; } # Display printf "$FMTSTR" "$REPO" "$HOST" "$STATUS" "$PID" "$FREEZE" "$INDIRECTED_DATE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" echo return $ADE_OK } share() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO SPECIFIED_HOST local REPO HOST STATUS PID SHARED_TS INDIRECT_DIR URL local TUPLES TUPLE MATCH_FLAG SKIP local URL_PATHCMPNT EXPANDED_URL_PATHCMPNT EXPANDED_INDIRECT_DIR ade_inherit SEPARATOR || return $? # Defaults for options # Process options # Process arguments [ $# = 2 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 SPECIFIED_HOST=$2 # Sanity checks and derivations MATCH_FLAG=false # Main loop list_possible_shares "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO HOST || return $? ade_debug "$ERRSTACK_REF" 10 "share: REPO=$REPO, HOST=$HOST" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_share_attributes "$ERRSTACK_REF" $REPO $HOST STATUS PID SHARED_TS INDIRECT_DIR URL ade_debug "$ERRSTACK_REF" 10 "share: STATUS=$STATUS, PID=$PID, SHARED_TS=$SHARED_TS, INDIRECT_DIR=$INDIRECT_DIR, URL=$URL" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_HOST = "ALL-HOSTS" ]; then : elif [ $SPECIFIED_HOST = $HOST ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then ade_info "$ERRSTACK_REF" "$REPO.$HOST: sharing ..." elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: already shared!" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: fostering and resuming sharing ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "insert or replace into shares (repo, host, status, pid, shared_ts) VALUES ('$REPO', '$HOST', 'updating', $$, strftime('%s','now'));" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true URL_PATHCMPNT=/${URL#http://*/} detokenise "$ERRSTACK_REF" $URL_PATHCMPNT EXPANDED_URL_PATHCMPNT REPO=$REPO HOST=$HOST || return $? detokenise "$ERRSTACK_REF" "$INDIRECT_DIR" EXPANDED_INDIRECT_DIR REPO=$REPO HOST=$HOST || return $? # Guts mkdir -p $PAA_STATE_PREFIX { echo " Alias $EXPANDED_URL_PATHCMPNT \"$EXPANDED_INDIRECT_DIR/\"" echo " " echo " Options Indexes FollowSymLinks MultiViews" echo " AllowOverride None" echo " Order allow,deny" echo " Allow from all" echo " " } > $PAA_STATE_PREFIX/$REPO.$HOST.conf # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "update shares set status = 'available', pid = NULL, shared_ts = strftime('%s','now') where repo == '$REPO' and host == '$HOST';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing shared" return $ADE_FAIL fi # Reload apache. reload_apache "$ERRSTACK_REF" || return $? return $ADE_OK } unshare() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO SPECIFIED_HOST local REPO HOST local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG ade_inherit PAA_STATE_PREFIX SEPARATOR || return $? # Option processing # Argument processing [ $# = 2 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 SPECIFIED_HOST=$2 # Sanity checks and derivations [ $SPECIFIED_REPO != ALL-REPOS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-REPOS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } [ $SPECIFIED_HOST != ALL-HOSTS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-HOSTS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } # Main loop list_existing_shares "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO HOST || return $? ade_debug "$ERRSTACK_REF" 10 "unshare: REPO=$REPO, HOST=$HOST" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_share_attributes "$ERRSTACK_REF" $REPO $HOST STATUS PID SHARED_TS INDIRECT_DIR URL ade_debug "$ERRSTACK_REF" 10 "unshare: STATUS=$STATUS, PID=$PID, SHARED_TS=$SHARED_TS, INDIRECT_DIR=$INDIRECT_DIR, URL=$URL" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_HOST = "ALL-HOSTS" ]; then : elif [ $SPECIFIED_HOST = $HOST ]; then : else SKIP=true break # we already know we'll skip this host, skip further applicability tests. fi if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then SKIP=true break # we already know we'll skip this repo, skip further applicability tests. elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO.$HOST: unsharing ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO.$HOST: fostering and resuming unsharing ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "update shares set status = 'deleting', pid = $$, shared_ts = strftime('%s','now') where repo == '$REPO' and host == '$HOST';" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true detokenise "$ERRSTACK_REF" "$INDIRECT_DIR" EXPANDED_INDIRECT_DIR REPO=$REPO HOST=$HOST || return $? # Guts rm -f $PAA_STATE_PREFIX/$REPO.$HOST.conf # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "delete from shares where repo == '$REPO' and host == '$HOST';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing unshared" return $ADE_FAIL fi # Reload apache. reload_apache "$ERRSTACK_REF" || return $? return $ADE_OK } listshares() { local ERRSTACK_REF="$1"; shift local REPO HOST STATUS PID SHARED_TS local FMTSTR local TUPLES TUPLE STAR VERBOSELEVEL ade_inherit REPO_FMTSTR HOST_FMTSTR STATUS_FMTSTR PID_FMTSTR DATE_FMTSTR SEPARATOR || return $? # Defaults for options # Process options # Process arguments # (Args are left untouched for the filter code at the end of this function.) # Sanity checks and derivations ade_get_verboselevel "$ERRSTACK_REF" VERBOSELEVEL || return $? FMTSTR="$REPO_FMTSTR $HOST_FMTSTR $STATUS_FMTSTR $PID_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "repo" "host" "status" "pid" "last changed" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" # Main loop ade_write_sql "$ERRSTACK_REF" "select repo, host, status, coalesce(pid,'NULL'), shared_ts from shares order by repo, host;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO HOST STATUS PID SHARED_TS || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO HOST STATUS PID SHARED_TS || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. SHARED_DATE= [ "X$SHARED_TS" = X ] || SHARED_DATE=$(date -d @$SHARED_TS) [[ $STATUS =~ ^(available|pending)$ ]] || [ -d /proc/$PID ] || { STATUS=orphaned; PID=; } # Display printf "$FMTSTR" "$REPO" "$HOST" "$STATUS" "$PID" "$SHARED_DATE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" echo return $ADE_OK } access() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local HOST REPO PKGTYPE RELEASE PORT SECTIONS URL local TUPLES TUPLE MATCH_FLAG CONTINUE_FLAG ade_inherit SEPARATOR THIS_HOST || return $? # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 # Sanity checks and derivations MATCH_FLAG=false # Main loop list_possible_accesses "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_debug "$ERRSTACK_REF" 10 "access: REPO=$REPO" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_access_attributes "$ERRSTACK_REF" $REPO STATUS PID ACCESSED_TS RELEASE PORT PKGTYPE URL SECTIONS || return $? ade_debug "$ERRSTACK_REF" 10 "access: STATUS=$STATUS, PID=$PID, ACCESSED_TS=$ACCESSED_TS, RELEASE=$RELEASE, PORT=$PORT, PKGTYPE=$PKGTYPE, URL=$URL, SECTIONS=$SECTIONS" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then ade_info "$ERRSTACK_REF" "$REPO: accessing ..." elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: already accessed!" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: fostering and resuming accessing ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "insert or replace into accesses (repo, status, pid, host, accessed_ts) VALUES ('$REPO', 'updating', $$, NULL, strftime('%s','now'));" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true # Guts ade_write_sql "$ERRSTACK_REF" "update accesses set host = '$THIS_HOST' where repo == '$REPO';" || return $? access_$PKGTYPE "$ERRSTACK_REF" "$REPO" "$RELEASE" "$PORT" "$SECTIONS" "$URL" || return $? # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "update accesses set status = 'available', pid = NULL, accessed_ts = strftime('%s','now') where repo == '$REPO';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing accessed" return $ADE_FAIL fi return $ADE_OK } unaccess() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local REPO HOST PKGTYPE local TUPLES TUPLE MATCH_TYPE CONTINUE_FLAG ade_inherit SEPARATOR THIS_HOST || return $? # Option processing # Argument processing [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_REPO=$1 # Sanity checks and derivations [ $SPECIFIED_REPO != ALL-REPOS ] || [ $FORCE_FLAG = true ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "ALL-REPOS is dangerous (do you need to use '--force'?)"; return $ADE_FAIL; } MATCH_FLAG=false # Main loop list_existing_accesses "$ERRSTACK_REF" TUPLES || return $? ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_debug "$ERRSTACK_REF" 10 "unaccess: REPO=$REPO" # Lock (status reading to status changing must be atomic, else contention issues!) ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_access_attributes "$ERRSTACK_REF" $REPO STATUS PID ACCESSED_TS RELEASE PORT PKGTYPE URL SECTIONS || return $? ade_debug "$ERRSTACK_REF" 10 "unaccess: STATUS=$STATUS, PID=$PID, ACCESSED_TS=$ACCESSED_TS, RELEASE=$RELEASE, PORT=$PORT, PKGTYPE=$PKGTYPE, URL=$URL, SECTIONS=$SECTIONS" # Determine skip SKIP=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then : elif [ $SPECIFIED_REPO = $REPO ]; then : else SKIP=true break # we already know we'll skip this repo, skip further applicability tests. fi if [ $STATUS = "non-existent" ]; then SKIP=true break # we already know we'll skip this repo, skip further applicability tests. elif [[ $STATUS =~ ^(available|pending)$ ]]; then ade_info "$ERRSTACK_REF" "$REPO: unaccessing ..." elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ -d /proc/$PID ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: locked ($PID is working on this)" return $ADE_FAIL elif ! [[ $STATUS =~ ^(available|pending)$ ]] && [ ! -d /proc/$PID ]; then ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: fostering and resuming unaccessing ..." fi done # If skipping, release exclusivity lock and skip if $SKIP; then ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? continue # Else mark operation in progress, release exclusivity lock (and continue into doing work) else ade_write_sql "$ERRSTACK_REF" "update accesses set status = 'deleting', pid = $$, accessed_ts = strftime('%s','now') where repo == '$REPO' and host == '$THIS_HOST';" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? fi # Per-loop sanity checks and derivations MATCH_FLAG=true # Guts unaccess_$PKGTYPE "$ERRSTACK_REF" || return $? # Delay sleep_if_sleep_defined "$ERRSTACK_REF" || return $? # Unlock (no atomic locking needed, since current status already ensures nobody else # will be working on this record). ade_write_sql "$ERRSTACK_REF" "delete from accesses where repo == '$REPO' and host == '$THIS_HOST';" || return $? done ade_close_filehandle "$ERRSTACK_REF" TUPLES_FD || return $? # Handle nothing mirrored. if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing unaccessed" return $ADE_FAIL fi return $ADE_OK } listaccesses() { local ERRSTACK_REF="$1"; shift local REPO STATUS PID ACCESSED_TS local FMTSTR local TUPLES TUPLE STAR VERBOSELEVEL ade_inherit REPO_FMTSTR STATUS_FMTSTR PID_FMTSTR DATE_FMTSTR SEPARATOR || return $? # Defaults for options # Process options # Process arguments # (Args are left untouched for the filter code at the end of this function.) # Sanity checks and derivations ade_get_verboselevel "$ERRSTACK_REF" VERBOSELEVEL || return $? FMTSTR="$REPO_FMTSTR $STATUS_FMTSTR $PID_FMTSTR $DATE_FMTSTR\n" printf "$FMTSTR" "repo" "status" "pid" "last changed" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" "$UNDERLINE" # Main loop ade_write_sql "$ERRSTACK_REF" "select repo, status, coalesce(pid,'NULL'), accessed_ts from accesses order by repo;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO STATUS PID ACCESSED_TS || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO STATUS PID ACCESSED_TS || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. ACCESSED_DATE= [ "X$ACCESSED_TS" = X ] || ACCESSED_DATE=$(date -d @$ACCESSED_TS) [[ $STATUS =~ ^(available|pending)$ ]] || [ -d /proc/$PID ] || { STATUS=orphaned; PID=; } # Display printf "$FMTSTR" "$REPO" "$STATUS" "$PID" "$ACCESSED_DATE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" echo return $ADE_OK } insert() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO SPECIFIED_RELEASES SPECIFIED_RELEASE SPECIFIED_SECTION local PKGTYPE NAME ARCH VERSION SRCFILE FILE local SPECIFIED_RELEASE ade_inherit SEPARATOR || return $? # Process arguments [ $# -ge 3 ] || ade_msg_usage "$ERRSTACK_REF" # paa insert ,... [
] ... SPECIFIED_REPO=$1 SPECIFIED_RELEASES=${2//,/ } shift 2 # Sanity checks and derivations ade_write_sql "$ERRSTACK_REF" "select pkgtype from repos where repo == '$SPECIFIED_REPO' and status == 'available';" PKGTYPE || return $? [ "X$PKGTYPE" != X ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "no such repository"; return $ADE_FAIL; } if [ $PKGTYPE = deb ]; then [ $# -ge 2 ] || ade_msg_usage "$ERRSTACK_REF" SPECIFIED_SECTION=$1 shift elif [ $PKGTYPE = rpm ]; then SPECIFIED_SECTION="universal-section" fi if [ "X$SPECIFIED_RELEASES" = "XALL-RELEASES" ]; then ade_write_sql "$ERRSTACK_REF" "select release from releases where repo == '$SPECIFIED_REPO';" SPECIFIED_RELEASES || return $? fi ade_debug "$ERRSTACK_REF" 10 "insert: SPECIFIED_REPO=$SPECIFIED_REPO, SPECIFIED_RELEASES=\"$SPECIFIED_RELEASES\", SPECIFIED_SECTION=$SPECIFIED_SECTION" # Lock ade_write_sql "$ERRSTACK_REF" "begin transaction;" || return $? # Collect info about each file into files table and about the desired insertions. for SPECIFIED_FILE in "$@"; do [ -r $SPECIFIED_FILE ] || { ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$SPECIFIED_FILE: not accessible"; return $ADE_FAIL; } FILE=$(basename $SPECIFIED_FILE) DIR=$(dirname $SPECIFIED_FILE) PKGTYPE=${SPECIFIED_FILE##*.} # Lock ade_info "$ERRSTACK_REF" "$FILE: analysing ..." ade_write_sql "$ERRSTACK_REF" "insert or replace into files (file, status, pid, pkgtype, name, arch, version, dir, filed_ts) values ('$FILE', 'updating', $$, NULL, NULL, NULL, NULL, NULL, strftime('%s','now'));" || return $? # Collect and save info ade_debug "$ERRSTACK_REF" 10 "insert: NAME=$NAME (should not be set yet, as we pass the reference to analyse_$PKGTYPE())" analyse_$PKGTYPE "$ERRSTACK_REF" $SPECIFIED_FILE NAME ARCH VERSION || return $? ade_debug "$ERRSTACK_REF" 10 "insert: NAME=$NAME (should be set now, as analyse_$PKGTYPE() should have set it)" ade_write_sql "$ERRSTACK_REF" "update files set pkgtype = '$PKGTYPE', name = '$NAME', arch = '$ARCH', version = '$VERSION', dir = '$DIR' where file == '$FILE';" || return $? # Unlock ade_write_sql "$ERRSTACK_REF" "update files set status = 'available', pid = NULL, filed_ts = strftime('%s','now') where file == '$FILE';" || return $? done # For each requested release, check if it is possible to insert each file # into that the requested repo/release/section for SPECIFIED_RELEASE in $SPECIFIED_RELEASES; do ade_write_sql "$ERRSTACK_REF" "select desired.*,files.*,coalesce(port,'NULL'),coalesce(layout,'NULL'),coalesce(path,'NULL') from (select '$SPECIFIED_REPO' as repo,'$SPECIFIED_RELEASE' as release, '$SPECIFIED_SECTION' as section) as desired,files left outer join port_file_compatibilities on desired.repo == port_file_compatibilities.repo and desired.release == port_file_compatibilities.release and desired.section == port_file_compatibilities.section and files.arch == port_file_compatibilities.arch and files.pkgtype == port_file_compatibilities.pkgtype left outer join releases on desired.repo == releases.repo and desired.release == releases.release left outer join extendeds on desired.repo == extendeds.repo;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO RELEASE SECTION FILE STATUS PID PKGTYPE NAME ARCH VERSION DIR FILED_TS PORT LAYOUT REPOPATH || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO RELEASE SECTION FILE STATUS PID PKGTYPE NAME ARCH VERSION DIR FILED_TS PORT LAYOUT REPOPATH || return $? ade_debug "$ERRSTACK_REF" 10 "insert: REPO=$REPO, RELEASE=$RELEASE, SECTION=$SECTION, FILE=$FILE, STATUS=$STATUS, PID=$PID, PKGTYPE=$PKGTYPE, NAME=$NAME, ARCH=$ARCH, VERSION=$VERSION, DIR=$DIR, FILED_TS=$FILED_TS, PORT=$PORT, LAYOUT=$LAYOUT, REPOPATH=$REPOPATH" # Skips (more of a sanity check really) if [ "X$PORT" = X -o "X$LAYOUT" = X ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "$REPO: will not accept $FILE into release $RELEASE section $SECTION" return $ADE_FAIL fi # Per-loop sanity checks and derivations detokenise "$ERRSTACK_REF" $LAYOUT EXPANDED_LAYOUT RELEASE=$RELEASE PORT=$PORT SECTION=$SECTION || return $? # Lock ade_write_sql "$ERRSTACK_REF" "insert or replace into controls (repo,release,port,name,version,status,pid,file,dir,controlled_ts) values ('$SPECIFIED_REPO','$SPECIFIED_RELEASE','$PORT','$NAME','$VERSION','updating',$$,NULL,NULL,strftime('%s','now'));" || return $? # Guts mkdir -p $REPOPATH/$EXPANDED_LAYOUT cp $DIR/$FILE $REPOPATH/$EXPANDED_LAYOUT/$FILE ade_write_sql "$ERRSTACK_REF" "update controls set file = '$FILE', dir = '$EXPANDED_LAYOUT', section = '$SECTION' where repo == '$SPECIFIED_REPO' and release == '$SPECIFIED_RELEASE' and port == '$PORT' and name == '$NAME' and version == '$VERSION';" || return $? # Unlock ade_write_sql "$ERRSTACK_REF" "update controls set status = 'pending', pid = NULL, controlled_ts = strftime('%s','now') where repo == '$SPECIFIED_REPO' and release == '$SPECIFIED_RELEASE' and port == '$PORT' and name == '$NAME' and version == '$VERSION';" || return $? done <<<"$TUPLES" done # Unlock ade_write_sql "$ERRSTACK_REF" "delete from files;" || return $? ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? return $ADE_OK } control() { local ERRSTACK_REF="$1"; shift local SPECIFIED_REPO local REPO RELEASE PORT SECTION PKGTYPE local RELEASES PORTS SECTIONS COUNT local TUPLES TUPLE MATCH_FLAG CONTROLLED_TS local CONTROL_REPO_NEEDED_FLAG CONTROL_RELEASE_NEEDED_FLAG CONTROL_PORT_NEEDED_FLAG CONTROL_SECTION_NEEDED_FLAG local TUPLES_FD RELEASES_FD PORTS_FD SECTIONS_FD local FULLPATH FILE DIR TUPLES TUPLE PROGNAME ade_inherit SEPARATOR LOGNAME || return $? # Process arguments [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" # paa control SPECIFIED_REPO=$1 # Sanity checks and derivations ade_get_progname "$ERRSTACK_REF" PROGNAME MATCH_FLAG=false # gpg-agent will call pinentry and that will require write access to the terminal. If the terminal # has running 'su - ' then the terminal permissions will not allow pinentry to work. if [ ! -w $(tty) ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "terminal permissions issue (hint: do you need to log in as yourself instead of su-ing from root?)" return $ADE_FAIL fi if ! pgrep -u $LOGNAME gpg-agent > /dev/null; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "it looks like gpg-agent is not running (hint: do you need to run 'gpg-agent --daemon'?)" return $ADE_FAIL fi # Check that all files in the controls table which are already marked available are # available and delete references to non-existent files. We need # "extendeds.path || '/' || controls.dir || '/' || controls.file as fullpath" # to work out if the file exists; we need "controls.dir as dir, controls.file as file" in order to # delete the entry. ade_write_sql "$ERRSTACK_REF" "select extendeds.path || '/' || controls.dir || '/' || controls.file as fullpath, controls.dir as dir, controls.file as file from extendeds,controls where extendeds.repo == '$SPECIFIED_REPO' and extendeds.repo == controls.repo and controls.status == 'available' order by fullpath;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" FULLPATH DIR FILE || return $? ade_blank_sql_null "$ERRSTACK_REF" FULLPATH DIR FILE || return $? [ ! -f "$FULLPATH" ] || continue ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "$FULLPATH: non-existent; removing references to this file ..." ade_write_sql "$ERRSTACK_REF" "delete from controls where controls.dir == '$DIR' and controls.file == '$FILE';" || return $? done <<<"$TUPLES" # Main loop ade_write_sql "$ERRSTACK_REF" "select repo,pkgtype from repos where repotype == 'owned' and status == 'available' order by repo;" TUPLES || return $? # We need to read those tuples of line by line, which a 'for TUPLE in $TUPLES' loop won't do, so we *must* # use a 'while read TUPLE' loop, but that will leave the code in the body of the loop thinking that tty is # not a terminal and that screws up gpg, which we'll call in the body of the loop. Therefore we use the # exec try to get a handle on TUPLES and then we can do a 'while read -u HANDLE TUPLE' loop, which will not # affect the loop body's stdin. ade_open_string_for_reading "$ERRSTACK_REF" TUPLES_FD "$TUPLES" || return $? while read -u $TUPLES_FD TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO PKGTYPE || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO PKGTYPE || return $? ade_debug "$ERRSTACK_REF" 10 "mirror: REPO=$REPO, PKGTYPE=$PKGTYPE" # Skips CONTINUE_FLAG=false for SETJMP in SETJMP; do if [ $SPECIFIED_REPO = "ALL-REPOS" ]; then break elif [ $SPECIFIED_REPO = $REPO ]; then break fi CONTINUE_FLAG=true done ! $CONTINUE_FLAG || continue # Per-loop sanity checks and derivations MATCH_FLAG=true # Lock ade_write_sql "$ERRSTACK_REF" "begin transaction;" || return $? # Guts # For each release, for each port within that release, for each section within that # port, now compare what we want against what is possible and regenerate control files # accordingly. CONTROL_REPO_NEEDED_FLAG=false ade_write_sql "$ERRSTACK_REF" "select release from releases where repo == '$SPECIFIED_REPO' order by release;" RELEASES || return $? ade_open_string_for_reading "$ERRSTACK_REF" RELEASES_FD "$RELEASES" || return $? while read -u $RELEASES_FD RELEASE; do # Workaround for "no rows produces one line of output" bug. [ "X$RELEASE" != X ] || break ade_debug "$ERRSTACK_REF" 10 "control: SPECIFIED_REPO=$SPECIFIED_REPO, RELEASE=$RELEASE" CONTROL_RELEASE_NEEDED_FLAG=false ade_write_sql "$ERRSTACK_REF" "select port from ports where repo == '$SPECIFIED_REPO' and release == '$RELEASE' order by port;" PORTS || return $? ade_open_string_for_reading "$ERRSTACK_REF" PORTS_FD "$PORTS" || return $? while read -u $PORTS_FD PORT; do # Workaround for "no rows produces one line of output" bug. [ "X$PORT" != X ] || break ade_debug "$ERRSTACK_REF" 10 "control: SPECIFIED_REPO=$SPECIFIED_REPO, RELEASE=$RELEASE, PORT=$PORT" CONTROL_PORT_NEEDED_FLAG=false ade_write_sql "$ERRSTACK_REF" "select section from sections where repo == '$SPECIFIED_REPO' and release == '$RELEASE' order by section;" SECTIONS || return $? ade_open_string_for_reading "$ERRSTACK_REF" SECTIONS_FD "$SECTIONS" || return $? while read -u $SECTIONS_FD SECTION; do # Workaround for "no rows produces one line of output" bug. [ "X$SECTION" != X ] || break ade_debug "$ERRSTACK_REF" 10 "control: SPECIFIED_REPO=$SPECIFIED_REPO, RELEASE=$RELEASE, PORT=$PORT, SECTION=$SECTION" CONTROL_SECTION_NEEDED_FLAG=false # Which files are to be inserted in this repo/release/port/section? ade_write_sql "$ERRSTACK_REF" "select count(*) from controls where repo == '$SPECIFIED_REPO' and release == '$RELEASE' and port == '$PORT' and section == '$SECTION' and status == 'pending';" COUNT || return $? ade_debug "$ERRSTACK_REF" 10 "control: COUNT=$COUNT" [ $COUNT = 0 ] || CONTROL_SECTION_NEEDED_FLAG=true if $CONTROL_SECTION_NEEDED_FLAG || $FORCE_FLAG; then # This info message is only for debs; it looks silly for rpms, which # don't use sections. [ $PKGTYPE != deb ] || ade_info "$ERRSTACK_REF" "$SPECIFIED_REPO: generating control files specific to release $RELEASE, port $PORT, section $SECTION ..." control_section_$PKGTYPE "$ERRSTACK_REF" $SPECIFIED_REPO $RELEASE $PORT $SECTION || return $? CONTROL_PORT_NEEDED_FLAG=true fi done ade_close_filehandle "$ERRSTACK_REF" SECTIONS_FD || return $? if $CONTROL_PORT_NEEDED_FLAG || $FORCE_FLAG; then ade_info "$ERRSTACK_REF" "$SPECIFIED_REPO: generating control files specific to release $RELEASE, port $PORT ..." control_port_$PKGTYPE "$ERRSTACK_REF" $SPECIFIED_REPO $RELEASE $PORT || return $? CONTROL_RELEASE_NEEDED_FLAG=true fi done ade_close_filehandle "$ERRSTACK_REF" PORTS_FD || return $? if $CONTROL_RELEASE_NEEDED_FLAG || $FORCE_FLAG; then ade_info "$ERRSTACK_REF" "$SPECIFIED_REPO: generating control files specific to release $RELEASE ..." control_release_$PKGTYPE "$ERRSTACK_REF" $SPECIFIED_REPO $RELEASE || return $? CONTROL_REPO_NEEDED_FLAG=true fi done ade_close_filehandle "$ERRSTACK_REF" RELEASES_FD || return $? if $CONTROL_REPO_NEEDED_FLAG || $FORCE_FLAG; then ade_info "$ERRSTACK_REF" "$SPECIFIED_REPO: generating other control files ..." control_repo_$PKGTYPE "$ERRSTACK_REF" $SPECIFIED_REPO || return $? ade_write_sql "$ERRSTACK_REF" "update controls set status = 'available', pid = NULL, controlled_ts = strftime('%s','now') where repo == '$SPECIFIED_REPO';" || return $? else ade_warning "$ERRSTACK_REF" PAA_ERR_MISC "no recently inserted packages to process (do you want to run '$PROGNAME --force control $SPECIFIED_REPO'?)" fi # Unlock ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? done if ! $MATCH_FLAG; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "nothing controlled" return $ADE_FAIL fi return $ADE_OK } # Undocumented debugging functions editdb() { local ERRSTACK_REF="$1"; shift local DUMP PREEDIT_MD5SUM POSTEDIT_MD5SUM DB_SCHEMA_CONFORMANCY PROGNAME ade_inherit DB_FILE SEPARATOR EXCLUSIVE_TIMEOUT || return $? # Process arguments [ $# = 0 ] || ade_msg_usage "$ERRSTACK_REF" # paa editdb ... ... # Sanity checks and derivations ade_get_progname "$ERRSTACK_REF" PROGNAME # Guts ade_debug "$ERRSTACK_REF" 10 "editdb: dumping ..." get_db_schema_conformancy "$ERRSTACK_REF" DB_SCHEMA_CONFORMANCY || return $? # Don't use ade_write_sql() to run '.dump' because we'll relay the output # line by line, which can be quite slow. Instead we invoke a new sqlite3 shell below. # Same goes for loading, further below. ade_register_temp_file "$ERRSTACK_REF" /tmp/$PROGNAME.$$.sql || return $? { # Dump doesn't dump user_version; if this is not loaded, then a cosmetically # altered dump is not reloadable. echo "pragma user_version = $DB_SCHEMA_CONFORMANCY;" if ! $SQLITE_CMD $DB_FILE ".dump"; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "invalid SQL; your edits have been left in /tmp/$PROGNAME.$$.sql" return $ADE_FAIL fi } > /tmp/$PROGNAME.$$.sql PREEDIT_MD5SUM=$(md5sum /tmp/$PROGNAME.$$.sql) ade_debug "$ERRSTACK_REF" 10 "editdb: invoking editor ..." ${EDITOR:-vi} /tmp/$PROGNAME.$$.sql POSTEDIT_MD5SUM=$(md5sum /tmp/$PROGNAME.$$.sql) # If no changes made do nothing if [ "X$PREEDIT_MD5SUM" = "X$POSTEDIT_MD5SUM" ]; then ade_debug "$ERRSTACK_REF" 10 "editdb: no changes detected; returning early ..." rm -f /tmp/$PROGNAME.$$.sql ade_deregister_temp_file "$ERRSTACK_REF" /tmp/$PROGNAME.$$.sql return $ADE_OK fi # Check changed dump can be loaded ade_debug "$ERRSTACK_REF" 10 "editdb: changes detected; checking loadable ..." TMP_DB_FILE=${DB_FILE%.sqlite}.$$.new.sqlite # Don't use 'while read LINE; do ade_write_sql($LINE)' to load because we'll # inject the modified dump line by line, which can be quite slow. Instead we invoke a # new sqlite3 shell below. Same goes for dumping, above. ade_register_temp_file "$ERRSTACK_REF" ${DB_FILE%.sqlite}.$$.new.sqlite || return $? if ! $SQLITE_CMD $TMP_DB_FILE < /tmp/$PROGNAME.$$.sql; then ade_debug "$ERRSTACK_REF" 10 "editdb: not loadable; processing error ..." rm -f $TMP_DB_FILE ade_deregister_temp_file "$ERRSTACK_REF" $TMP_DB_FILE || return $? # Deregister without delete so error message may tell user where to find saved file ade_deregister_temp_file "$ERRSTACK_REF" /tmp/$PROGNAME.$$.sql ade_error "$ERRSTACK_REF" PAA_ERR_MISC "invalid SQL; your edits have been left in /tmp/$PROGNAME.$$.sql" return $ADE_FAIL fi # Close connection to database and slide new database into place ade_debug "$ERRSTACK_REF" 10 "editdb: loadable; stopping database and sliding in to place ..." ade_disconnect_sqlite || return $? # We could just return at this point but, given that paa() will shut the database down, # it is actually easiest if we start it up again (then paa() doesn't need to *decide* # if it needs to shut it down. ade_connect_sqlite "$ERRSTACK_REF" "$SEPARATOR" "$EXCLUSIVE_TIMEOUT" || return $? mv $TMP_DB_FILE $DB_FILE ade_deregister_temp_file "$ERRSTACK_REF" $TMP_DB_FILE return $ADE_OK } showtbl() { local ERRSTACK_REF="$1"; shift local SPECIFIED_TABLE # Process arguments [ $# = 1 ] || ade_msg_usage "$ERRSTACK_REF" # paa showtbl SPECIFIED_TABLE=$1 # Sanity checks and derivations # Guts # This function cannot use ade_write_sql() because that absolutely # requires headers off and list mode (so much so that it must be made to # restore those settings if we were to tamper with them here and we *do* # need to set them here). $SQLITE_CMD -header -column $DB_FILE "select * from $SPECIFIED_TABLE;" return $ADE_OK } upgrade() { local ERRSTACK_REF="$1"; shift local SPECIFIED_TABLE ade_inherit RCDIR # Process arguments [ $# = 0 ] || ade_msg_usage "$ERRSTACK_REF" # paa upgrade # Sanity checks and derivations # Guts # Dropping stuff, re-creating stuff, re-inserting stuff are all painful under # foreign key constraints. Disable them. This must be done before beginning # a transaction else it's a no-op. ade_write_sql "$ERRSTACK_REF" "pragma foreign_keys = off;" || return $? # Lock everybody else out! ade_write_sql "$ERRSTACK_REF" "begin exclusive transaction;" || return $? get_db_schema_conformancy "$ERRSTACK_REF" DB_SCHEMA_CONFORMANCY || return $? if [ $DB_SCHEMA_CONFORMANCY = $CODE_SCHEMA_CONFORMANCY ]; then ade_error "$ERRSTACK_REF" PAA_ERR_MISC "no upgrade necessary" return $ADE_FAIL fi # Back up database before starting. save_old_dir_contents "$ERRSTACK_REF" cp $RCDIR || return $? # Loop applying updates. while [ $DB_SCHEMA_CONFORMANCY != $CODE_SCHEMA_CONFORMANCY ]; do # Determine name of upgrade function. UPGRADE_FUNCTION=upgrade_from_${DB_SCHEMA_CONFORMANCY}_to_$((DB_SCHEMA_CONFORMANCY+1)) [ "X$(type -t $UPGRADE_FUNCTION)" = Xfunction ] || ade_internal "$ERRSTACK_REF" "upgrade: $UPGRADE_FUNCTION: no such function" # Apply upgrade. ade_info "$ERRSTACK_REF" "upgrading from database schema conformancy level $DB_SCHEMA_CONFORMANCY to $((DB_SCHEMA_CONFORMANCY+1)) ..." $UPGRADE_FUNCTION "$ERRSTACK_REF" || ade_internal "$ERRSTACK_REF" "upgrade: $UPGRADE_FUNCTION: failed" # Refresh old and new schema conformancy values. OLD_DB_SCHEMA_CONFORMANCY=$DB_SCHEMA_CONFORMANCY get_db_schema_conformancy "$ERRSTACK_REF" DB_SCHEMA_CONFORMANCY || return $? # Check the upgrade function bumped the database schema conformancy. if [ $OLD_DB_SCHEMA_CONFORMANCY = $DB_SCHEMA_CONFORMANCY ]; then ade_internal "$ERRSTACK_REF" "upgrade: $UPGRADE_FUNCTION: didn't raise database schema conformancy" fi done ade_write_sql "$ERRSTACK_REF" "end transaction;" || return $? ade_write_sql "$ERRSTACK_REF" "pragma foreign_keys = on;" || return $? return $ADE_OK } listobsolete() { local ERRSTACK_REF="$1"; shift local SPECIFIED_TABLE PROGNAME ade_inherit RCDIR # Process arguments [ $# = 0 ] || ade_msg_usage "$ERRSTACK_REF" # Sanity checks and derivations ade_get_progname "$ERRSTACK_REF" PROGNAME # Guts FMTSTR="$REPO_FMTSTR\n" ade_register_temp_file "$ERRSTACK_REF" /tmp/$PROGNAME.$$.obsolete-resources || return $? # Concatenate the list of mirrored repos, the list of accesses repos and the list of 'owned' # repos (no table references owned repos, so we just have to trust they're not obsolete). # Dedupe that list (that's the 'select distinct repo ... from ...'). Cross that with the # list of repos and look for repos that don't have an entry in that first list (meaning # list the repos that are neither owned, nor referenced in mirrors, nor referenced in # accesses). ade_write_sql "$ERRSTACK_REF" "select all_repos.repo from repos as all_repos left outer join (select distinct repo as repo from (select repo from mirrors union select repo from accesses union select repo from repos where repotype == 'owned')) as repos_in_use on all_repos.repo == repos_in_use.repo where repos_in_use.repo is null;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. # Display printf "$FMTSTR" "$REPO" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" > /tmp/$PROGNAME.$$.obsolete-resources if [ $(stat -c %s /tmp/$PROGNAME.$$.obsolete-resources) != 0 ]; then echo "obsolete repos" echo "==============" echo printf "$FMTSTR" "repo" printf "$FMTSTR" "$UNDERLINE" cat /tmp/$PROGNAME.$$.obsolete-resources echo fi FMTSTR="$REPO_FMTSTR\n" ade_write_sql "$ERRSTACK_REF" "select mirrors.repo from mirrors left outer join freezes on mirrors.repo == freezes.repo where freezes.repo is null order by mirrors.repo;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. # Display printf "$FMTSTR" "$REPO" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" > /tmp/$PROGNAME.$$.obsolete-resources if [ $(stat -c %s /tmp/$PROGNAME.$$.obsolete-resources) != 0 ]; then echo "obsolete mirrors" echo "================" echo printf "$FMTSTR" "repo" printf "$FMTSTR" "$UNDERLINE" cat /tmp/$PROGNAME.$$.obsolete-resources echo fi FMTSTR="$REPO_FMTSTR $FREEZE_FMTSTR\n" ade_write_sql "$ERRSTACK_REF" "select freezes.repo,freezes.freeze from freezes left outer join indirects on freezes.repo == indirects.repo and freezes.freeze == indirects.freeze where indirects.freeze is null order by freezes.repo,freezes.freeze;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO FREEZE || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO FREEZE || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. # Display printf "$FMTSTR" "$REPO" "$FREEZE" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" > /tmp/$PROGNAME.$$.obsolete-resources if [ $(stat -c %s /tmp/$PROGNAME.$$.obsolete-resources) != 0 ]; then echo "obsolete freezes" echo "================" echo printf "$FMTSTR" "repo" "freeze" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" cat /tmp/$PROGNAME.$$.obsolete-resources echo fi FMTSTR="$REPO_FMTSTR $HOST_FMTSTR\n" ade_write_sql "$ERRSTACK_REF" "select indirects.repo, indirects.host from indirects left outer join shares on indirects.repo == shares.repo and indirects.host == shares.host where shares.repo is null order by indirects.repo, indirects.host;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" REPO HOST || return $? ade_blank_sql_null "$ERRSTACK_REF" REPO HOST || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. # Display printf "$FMTSTR" "$REPO" "$HOST" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" > /tmp/$PROGNAME.$$.obsolete-resources if [ $(stat -c %s /tmp/$PROGNAME.$$.obsolete-resources) != 0 ]; then echo "obsolete indirects" echo "==================" echo printf "$FMTSTR" "repo" "host" printf "$FMTSTR" "$UNDERLINE" "$UNDERLINE" cat /tmp/$PROGNAME.$$.obsolete-resources echo fi FMTSTR="$HOST_FMTSTR\n" ade_write_sql "$ERRSTACK_REF" "select hosts.host from hosts left outer join (select host from indirects union select host from accesses) as x on hosts.host == x.host where x.host is null order by hosts.host;" TUPLES || return $? while read TUPLE; do # Workaround for "no rows produces one line of output" bug. [ "X$TUPLE" != X ] || break # Unmunge ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" HOST || return $? ade_blank_sql_null "$ERRSTACK_REF" HOST || return $? # Skips (handled by egrep) # Lock (pointless for a list function) # Rewrite fields for human consumption, being careful not to reuse old values. # Display printf "$FMTSTR" "$HOST" # Unlock (we didn't lock) done <<<"$TUPLES" | ade_filter "$@" > /tmp/$PROGNAME.$$.obsolete-resources if [ $(stat -c %s /tmp/$PROGNAME.$$.obsolete-resources) != 0 ]; then echo "obsolete hosts" echo "==============" echo printf "$FMTSTR" "host" printf "$FMTSTR" "$UNDERLINE" cat /tmp/$PROGNAME.$$.obsolete-resources echo fi # Clean up rm -f /tmp/$PROGNAME.$$.obsolete-resources ade_deregister_temp_file "$ERRSTACK_REF" /tmp/$PROGNAME.$$.obsolete-resources return $ADE_OK } list_possible_hosts() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_hosts: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_hosts: TUPLES_REF=$TUPLES_REF" # Possible hosts are existing hosts and any that are about to be defined. ade_write_sql "$ERRSTACK_REF" "select host from hosts union select host from newhosts;" $TUPLES_REF || return $? return $ADE_OK } list_existing_hosts() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_existing_hosts: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_existing_hosts: TUPLES_REF=$TUPLES_REF" ade_write_sql "$ERRSTACK_REF" "select host from hosts;" $TUPLES_REF || return $? return $ADE_OK } list_possible_repos() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_repos: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_repos: TUPLES_REF=$TUPLES_REF" # Possible repos are existing repos and any that are about to be defined. ade_write_sql "$ERRSTACK_REF" "select repo from repos union select repo from newrepos;" $TUPLES_REF || return $? return $ADE_OK } list_existing_repos() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_existing_repos: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_existing_repos: TUPLES_REF=$TUPLES_REF" ade_write_sql "$ERRSTACK_REF" "select repo from repos order by repo;" $TUPLES_REF || return $? return $ADE_OK } list_possible_mirrors() { local ERRSTACK_REF="$1"; shift local MIRRORS_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_mirrors: $#: invalid argument count" MIRRORS_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_mirrors: MIRRORS_REF=$MIRRORS_REF" # Possible mirrors are existing mirrors and repos which have not been mirrored yet. This list # is actually just the list of defined repos. ade_write_sql "$ERRSTACK_REF" "select repo from repos;" $MIRRORS_REF || return $? return $ADE_OK } list_existing_mirrors() { local ERRSTACK_REF="$1"; shift local MIRRORS_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_existing_mirrors: $#: invalid argument count" MIRRORS_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_existing_mirrors: MIRRORS_REF=$MIRRORS_REF" ade_write_sql "$ERRSTACK_REF" "select repo from mirrors;" $MIRRORS_REF || return $? return $ADE_OK } list_possible_freezes() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_freezes: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_freezes: TUPLES_REF=$TUPLES_REF" # Possible freezes are orphaned freezes plus [all mirrors freshly frozen, excluding those that # we already noted are orphaned freezes]. ade_write_sql "$ERRSTACK_REF" "select freezes.repo,freeze from (select * from freezes where status != 'available' union select new_freezes.* from (select repo,strftime('%Y%m%d%H%M%S',mirrored_ts, 'unixepoch') as freeze,'non-existent' as status,NULL as pid,NULL as frozen_ts from mirrors) as new_freezes left outer join (select * from freezes where status != 'available') as orphaned_freezes on new_freezes.repo == orphaned_freezes.repo where orphaned_freezes.repo isnull) as freezes left outer join extendeds on freezes.repo == extendeds.repo;" $TUPLES_REF || return $? return $ADE_OK } list_existing_freezes() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_freezes: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_freezes: TUPLES_REF=$TUPLES_REF" ade_write_sql "$ERRSTACK_REF" "select repo,freeze from freezes;" $TUPLES_REF || return $? return $ADE_OK } list_possible_indirects() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_indirects: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_indirects: TUPLES_REF=$TUPLES_REF" # Possible indirects are all hosts crossed with all repos that have been frozen - subject to compatibility. # The 'order' is very important, since indirect() relies on the newest freeze coming first (within records # already ordered on repo and host) in order to process 'NEWEST-FREEZE' references. ade_write_sql "$ERRSTACK_REF" "select freezes.repo,host,freeze from freezes,hosts,release_distro_compatibilities where freezes.repo == release_distro_compatibilities.repo and (release_distro_compatibilities.pkgtype isnull or release_distro_compatibilities.pkgtype == hosts.pkgtype) and (release_distro_compatibilities.distro isnull or release_distro_compatibilities.distro == hosts.distro) and (release_distro_compatibilities.distro_release isnull or release_distro_compatibilities.distro_release == hosts.release) and release_distro_compatibilities.distro_port == hosts.port order by freezes.repo,host,freeze desc;" $TUPLES_REF || return $? return $ADE_OK } list_existing_indirects() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_existing_indirects: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_existing_indirects: TUPLES_REF=$TUPLES_REF" ade_write_sql "$ERRSTACK_REF" "select repo,host,freeze from indirects order by repo,host,freeze desc;" $TUPLES_REF || return $? return $ADE_OK } list_possible_shares() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_shares: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_shares: TUPLES_REF=$TUPLES_REF" # Possible shares are all orphaned shares plus [all indirects that don't related to orphaned shares]. ade_write_sql "$ERRSTACK_REF" "select shares.repo,shares.host from (select * from shares where status != 'available' union select new_shares.* from (select repo,host,'non-existent' as status,NULL as pid,NULL as shared_ts from indirects) as new_shares left outer join (select * from shares where status != 'available') as orphaned_shares on new_shares.repo == orphaned_shares.repo where orphaned_shares.repo isnull) as shares;" $TUPLES_REF || return $? return $ADE_OK } list_existing_shares() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_existing_shares: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_existing_shares: TUPLES_REF=$TUPLES_REF" ade_write_sql "$ERRSTACK_REF" "select repo, host from shares;" $TUPLES_REF || return $? return $ADE_OK } list_possible_accesses() { local ERRSTACK_REF="$1"; shift local TUPLES_REF ade_inherit THIS_HOST || return $? # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_possible_accesses: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_possible_accesses: TUPLES_REF=$TUPLES_REF" # Possible accesses are all compatible host/repo combinations - very similar to all possible # indirects. ade_write_sql "$ERRSTACK_REF" "select distinct repos.repo from repos,hosts,release_distro_compatibilities where repos.repo == release_distro_compatibilities.repo and (release_distro_compatibilities.pkgtype isnull or release_distro_compatibilities.pkgtype == hosts.pkgtype) and (release_distro_compatibilities.distro isnull or release_distro_compatibilities.distro == hosts.distro) and (release_distro_compatibilities.distro_release isnull or release_distro_compatibilities.distro_release == hosts.release) and release_distro_compatibilities.distro_port == hosts.port and hosts.host == '$THIS_HOST';" $TUPLES_REF || return $? return $ADE_OK } list_existing_accesses() { local ERRSTACK_REF="$1"; shift local TUPLES_REF # Defaults for options # Process options # Process arguments [ $# = 1 ] || ade_internal "$ERRSTACK_REF" "list_existing_accesses: $#: invalid argument count" TUPLES_REF=$1 ade_debug "$ERRSTACK_REF" 4 "list_existing_accesses: TUPLES_REF=$TUPLES_REF" ade_write_sql "$ERRSTACK_REF" "select repo from accesses;" $TUPLES_REF || return $? return $ADE_OK } get_repo_attributes() { local ERRSTACK_REF="$1"; shift local REPO STATUS_REF PID_REF REPOTYPE_REF REPOPATH_REF local EXISTS TUPLE # Process arguments [ $# = 5 ] || ade_internal "$ERRSTACK_REF" "get_repo_attributes: $#: invalid argument count" REPO=$1 STATUS_REF=$2 PID_REF=$3 REPOTYPE_REF=$4 REPOPATH_REF=$5 ade_debug "$ERRSTACK_REF" 10 "get_repo_attributes: REPO=$REPO, STATUS_REF=$STATUS_REF, PID_REF=$PID_REF, REPOTYPE_REF=$REPOTYPE_REF, REPOPATH_REF=$REPOPATH_REF" get_repo_exists "$ERRSTACK_REF" $REPO EXISTS || return $? if $EXISTS; then ade_write_sql "$ERRSTACK_REF" "select status, pid, repotype, path from repos left outer join extendeds on repos.repo == extendeds.repo where repos.repo == '$REPO';" TUPLE || return $? else ade_write_sql "$ERRSTACK_REF" "select status, pid, repotype, null as path from newrepos where repo == '$REPO';" TUPLE || return $? fi ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" $STATUS_REF $PID_REF $REPOTYPE_REF $REPOPATH_REF || return $? ade_blank_sql_null "$ERRSTACK_REF" $STATUS_REF $PID_REF $REPOTYPE_REF $REPOPATH_REF|| return $? return $ADE_OK } get_host_attributes() { local ERRSTACK_REF="$1"; shift local HOST STATUS_REF PID_REF HOSTTYPE_REF HOSTPATH_REF local EXISTS TUPLE # Process arguments [ $# = 8 ] || ade_internal "$ERRSTACK_REF" "get_host_attributes: $#: invalid argument count" HOST=$1 STATUS_REF=$2 PID_REF=$3 PKGTYPE_REF=$4 DISTRO_REF=$5 RELEASE_REF=$6 PORT_REF=$7 HOSTED_TS_REF=$8 ade_debug "$ERRSTACK_REF" 10 "get_host_attributes: HOST=$HOST, STATUS_REF=$STATUS_REF, PID_REF=$PID_REF, PKGTYPE_REF=$PKGTYPE_REF, DISTRO_REF=$DISTRO_REF, RELEASE_REF=$RELEASE_REF, PORT_REF=$PORT_REF, HOSTED_TS_REF=$HOSTED_TS_REF" get_host_exists "$ERRSTACK_REF" $HOST EXISTS || return $? if $EXISTS; then ade_write_sql "$ERRSTACK_REF" "select status, pid, pkgtype, distro, release, port, hosted_ts from hosts where host == '$HOST';" TUPLE || return $? else ade_write_sql "$ERRSTACK_REF" "select status, pid, pkgtype, distro, release, port, hosted_ts from newhosts where host == '$HOST';" TUPLE || return $? fi ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" $STATUS_REF $PID_REF $PKGTYPE_REF $DISTRO_REF $RELEASE_REF $PORT_REF $HOSTED_TS_REF || return $? ade_blank_sql_null "$ERRSTACK_REF" $STATUS_REF $PID_REF $PKGTYPE_REF $DISTRO_REF $RELEASE_REF $PORT_REF $HOSTED_TS_REF || return $? return $ADE_OK } get_mirror_attributes() { local ERRSTACK_REF="$1"; shift local REPO STATUS_REF PID_REF MIRRORED_TS_REF REPOTYPE_REF MIRROR_DIR_REF REPOPATH_REF MIRROR_CMD_REF local EXISTS TUPLE # Process arguments [ $# = 8 ] || ade_internal "$ERRSTACK_REF" "get_mirror_attributes: $#: invalid argument count" REPO=$1 STATUS_REF=$2 PID_REF=$3 MIRRORED_TS_REF=$4 REPOTYPE_REF=$5 MIRROR_DIR_REF=$6 REPOPATH_REF=$7 MIRROR_CMD_REF=$8 ade_debug "$ERRSTACK_REF" 10 "get_mirror_attributes: REPO=$REPO, STATUS_REF=$STATUS_REF, PID_REF=$PID_REF, MIRRORED_TS_REF=$MIRRORED_TS_REF, REPOTYPE_REF=$REPOTYPE_REF, MIRROR_DIR_REF=$MIRROR_DIR_REF, REPOPATH_REF=$REPOPATH_REF, MIRROR_CMD_REF=$MIRROR_CMD_REF" get_mirror_exists "$ERRSTACK_REF" $REPO EXISTS || return $? if $EXISTS; then ade_write_sql "$ERRSTACK_REF" "select mirrors.status, mirrors.pid, mirrored_ts, repotype, mirror_dir, path, mirror_cmd from repos,mirrors,extendeds where repos.repo == mirrors.repo and repos.repo == extendeds.repo and repos.repo == '$REPO';" TUPLE || return $? else ade_write_sql "$ERRSTACK_REF" "select 'non-existent' as status,null as pid,null as mirrored_ts, repotype, mirror_dir, path, mirror_cmd from repos,extendeds where repos.repo == extendeds.repo and repos.repo == '$REPO';" TUPLE || return $? fi ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" $STATUS_REF $PID_REF $MIRRORED_TS_REF $REPOTYPE_REF $MIRROR_DIR_REF $REPOPATH_REF $MIRROR_CMD_REF || return $? ade_blank_sql_null "$ERRSTACK_REF" $STATUS_REF $PID_REF $MIRRORED_TS_REF $REPOTYPE_REF $MIRROR_DIR_REF $REPOPATH_REF $MIRROR_CMD_REF || return $? return $ADE_OK } get_freeze_attributes() { local ERRSTACK_REF="$1"; shift local REPO FREEZE STATUS_REF PID_REF FROZEN_TS_REF MIRROR_DIR_REF FREEZE_DIR_REF local EXISTS TUPLE # Process arguments [ $# = 7 ] || ade_internal "$ERRSTACK_REF" "get_freeze_attributes: $#: invalid argument count" REPO=$1 FREEZE=$2 STATUS_REF=$3 PID_REF=$4 FROZEN_TS_REF=$5 MIRROR_DIR_REF=$6 FREEZE_DIR_REF=$7 ade_debug "$ERRSTACK_REF" 10 "get_freeze_attributes: REPO=$REPO, FREEZE=$FREEZE, STATUS_REF=$STATUS_REF, PID_REF=$PID_REF, FROZEN_TS_REF=$FROZEN_TS_REF, MIRROR_DIR_REF=$MIRROR_DIR_REF, FREEZE_DIR_REF=$FREEZE_DIR_REF" get_freeze_exists "$ERRSTACK_REF" $REPO $FREEZE EXISTS || return $? if $EXISTS; then ade_write_sql "$ERRSTACK_REF" "select freezes.status, freezes.pid, frozen_ts, mirror_dir, freeze_dir from repos,freezes,extendeds where repos.repo == freezes.repo and repos.repo == extendeds.repo and freezes.repo == '$REPO' and freezes.freeze == '$FREEZE';" TUPLE || return $? else ade_write_sql "$ERRSTACK_REF" "select 'non-existent' as status,null as pid,null as frozen_ts, mirror_dir, freeze_dir from repos,extendeds where repos.repo == extendeds.repo and repos.repo == '$REPO';" TUPLE || return $? fi ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" $STATUS_REF $PID_REF $FROZEN_TS_REF $MIRROR_DIR_REF $FREEZE_DIR_REF || return $? ade_blank_sql_null "$ERRSTACK_REF" $STATUS_REF $PID_REF $FROZEN_TS_REF $MIRROR_DIR_REF $FREEZE_DIR_REF || return $? return $ADE_OK } get_indirect_attributes() { local ERRSTACK_REF="$1"; shift local REPO HOST FREEZE STATUS_REF PID_REF INDIRECTED_TS_REF FREEZE_DIR_REF INDIRECT_DIR_REF local EXISTS TUPLE # Process arguments [ $# = 8 ] || ade_internal "$ERRSTACK_REF" "get_indirect_attributes: $#: invalid argument count" REPO=$1 HOST=$2 FREEZE=$3 STATUS_REF=$4 PID_REF=$5 INDIRECTED_TS_REF=$6 FREEZE_DIR_REF=$7 INDIRECT_DIR_REF=$8 ade_debug "$ERRSTACK_REF" 10 "get_indirect_attributes: REPO=$REPO, HOST=$HOST, FREEZE=$FREEZE, STATUS_REF=$STATUS_REF, PID_REF=$PID_REF, INDIRECTED_TS_REF=$INDIRECTED_TS_REF, FREEZE_DIR_REF=$FREEZE_DIR_REF, INDIRECT_DIR_REF=$INDIRECT_DIR_REF" get_indirect_exists "$ERRSTACK_REF" $REPO $HOST $FREEZE EXISTS || return $? if $EXISTS; then ade_write_sql "$ERRSTACK_REF" "select indirects.status, indirects.pid, indirected_ts, freeze_dir, indirect_dir from indirects,extendeds where indirects.repo == extendeds.repo and indirects.repo == '$REPO' and indirects.host == '$HOST' and indirects.freeze == '$FREEZE';" TUPLE || return $? else ade_write_sql "$ERRSTACK_REF" "select 'non-existent' as status,null as pid,null as indirected_ts, freeze_dir, indirect_dir from extendeds where extendeds.repo == '$REPO';" TUPLE || return $? fi ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" $STATUS_REF $PID_REF $INDIRECTED_TS_REF $FREEZE_REF $FREEZE_DIR_REF $INDIRECT_DIR_REF || return $? ade_blank_sql_null "$ERRSTACK_REF" $STATUS_REF $PID_REF $INDIRECTED_TS_REF $FREEZE_REF $FREEZE_DIR_REF $INDIRECT_DIR_REF || return $? return $ADE_OK } get_share_attributes() { local ERRSTACK_REF="$1"; shift local REPO HOST STATUS_REF PID_REF SHARED_TS_REF INDIRECT_DIR_REF URL_REF local EXISTS TUPLE # Process arguments [ $# = 7 ] || ade_internal "$ERRSTACK_REF" "get_share_attributes: $#: invalid argument count" REPO=$1 HOST=$2 STATUS_REF=$3 PID_REF=$4 SHARED_TS_REF=$5 INDIRECT_DIR_REF=$6 URL_REF=$7 ade_debug "$ERRSTACK_REF" 10 "get_share_attributes: REPO=$REPO, HOST=$HOST, STATUS_REF=$STATUS_REF, PID_REF=$PID_REF, SHARED_TS_REF=$SHARED_TS_REF, INDIRECT_DIR_REF=$INDIRECT_DIR_REF, URL_REF=$URL_REF" get_share_exists "$ERRSTACK_REF" $REPO $HOST EXISTS || return $? if $EXISTS; then ade_write_sql "$ERRSTACK_REF" "select shares.status, shares.pid, shared_ts, indirect_dir, url from shares,indirects,extendeds where shares.repo == extendeds.repo and shares.repo == indirects.repo and shares.host == indirects.host and shares.repo == '$REPO' and shares.host == '$HOST';" TUPLE || return $? else ade_write_sql "$ERRSTACK_REF" "select 'non-existent' as status,null as pid,null as shared_ts, indirect_dir, url from indirects,extendeds where indirects.repo == extendeds.repo and indirects.repo == '$REPO' and indirects.host == '$HOST';" TUPLE || return $? fi ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" $STATUS_REF $PID_REF $SHARED_TS_REF $INDIRECT_DIR_REF $URL_REF || return $? ade_blank_sql_null "$ERRSTACK_REF" $STATUS_REF $PID_REF $SHARED_TS_REF $INDIRECT_DIR_REF $URL_REF || return $? eval "ade_debug \"\$ERRSTACK_REF\" 10 \"get_share_attributes: REPO=\$REPO, HOST=\$HOST, STATUS=\$$STATUS_REF, PID=\$$PID_REF, SHARED_TS=\$$SHARED_TS_REF, INDIRECT_DIR=\$$INDIRECT_DIR_REF, URL=\$$URL_REF\"" return $ADE_OK } get_access_attributes() { local ERRSTACK_REF="$1"; shift local REPO STATUS_REF PID_REF ACCESSED_TS_REF RELEASE_REF PORT_REF PKGTYPE_REF URL_REF SECTIONS_REF local EXISTS TUPLE ade_inherit COMPATIBILITY_TEST_SQL THIS_HOST || return $? # Process arguments [ $# = 9 ] || ade_internal "$ERRSTACK_REF" "get_access_attributes: $#: invalid argument count" REPO=$1 STATUS_REF=$2 PID_REF=$3 ACCESSED_TS_REF=$4 RELEASE_REF=$5 PORT_REF=$6 PKGTYPE_REF=$7 URL_REF=$8 SECTIONS_REF=$9 ade_debug "$ERRSTACK_REF" 10 "get_access_attributes: REPO=$REPO, STATUS_REF=$STATUS_REF, PID_REF=$PID_REF, ACCESSED_TS_REF=$ACCESSED_TS_REF, RELEASE_REF=$RELEASE_REF, PORT_REF=$PORT_REF, PKGTYPE_REF=$PKGTYPE_REF, URL_REF=$URL_REF, SECTIONS_REF=$SECTIONS_REF" # Sanity checks and derivations get_access_exists "$ERRSTACK_REF" $REPO EXISTS || return $? if $EXISTS; then ade_write_sql "$ERRSTACK_REF" "select accesses.status as status, accesses.pid as pid, accessed_ts, release_distro_compatibilities.release, release_distro_compatibilities.distro_port as port, release_distro_compatibilities.pkgtype, url, group_concat(section,' ') as sections from accesses, extendeds, hosts, sections, release_distro_compatibilities where ($COMPATIBILITY_TEST_SQL) and hosts.host == accesses.host and extendeds.repo == accesses.repo and accesses.host == '$THIS_HOST' and accesses.repo == '$REPO' group by release_distro_compatibilities.repo,release_distro_compatibilities.release,hosts.host;" TUPLE || return $? else ade_write_sql "$ERRSTACK_REF" "select 'non-existent' as status,null as pid, null as accessed_ts, release_distro_compatibilities.release, release_distro_compatibilities.distro_port as port, release_distro_compatibilities.pkgtype, url, group_concat(section,' ') as sections from extendeds, hosts, sections, release_distro_compatibilities where ($COMPATIBILITY_TEST_SQL) and hosts.host == '$THIS_HOST' and extendeds.repo == '$REPO' group by release_distro_compatibilities.repo,release_distro_compatibilities.release,hosts.host;" TUPLE || return $? fi ade_split_string "$ERRSTACK_REF" "$TUPLE" "$SEPARATOR" $STATUS_REF $PID_REF $ACCESSED_TS_REF $RELEASE_REF $PORT_REF $PKGTYPE_REF $URL_REF $SECTIONS_REF || return $? ade_blank_sql_null "$ERRSTACK_REF" $STATUS_REF $PID_REF $ACCESSED_TS_REF $RELEASE_REF $PORT_REF $PKGTYPE_REF $URL_REF $SECTIONS_REF || return $? eval "ade_debug \"\$ERRSTACK_REF\" 10 \"get_access_attributes: REPO=\$REPO, THIS_HOST=\$THIS_HOST, STATUS=\$$STATUS_REF, PID=\$$PID_REF, ACCESSED_TS=\$$ACCESSED_TS_REF, RELEASE=\$$RELEASE_REF, PORT=\$$PORT_REF, PKGTYPE=\$$PKGTYPE_REF, URL=\$$URL_REF, SECTIONS=\$$SECTIONS_REF\"" return $ADE_OK } get_host_exists() { local ERRSTACK_REF="$1"; shift local HOST EXISTS_REF # Process arguments [ $# = 2 ] || ade_internal "$ERRSTACK_REF" "get_host_exists: $#: invalid argument count" HOST=$1 EXISTS_REF=$2 ade_write_sql "$ERRSTACK_REF" "select case count(*) when 0 then 'false' else 'true' end from hosts where host == '$HOST';" $EXISTS_REF || return $? return $ADE_OK } get_repo_exists() { local ERRSTACK_REF="$1"; shift local REPO EXISTS_REF # Process arguments [ $# = 2 ] || ade_internal "$ERRSTACK_REF" "get_repo_exists: $#: invalid argument count" REPO=$1 EXISTS_REF=$2 ade_write_sql "$ERRSTACK_REF" "select case count(*) when 0 then 'false' else 'true' end from repos where repo == '$REPO';" $EXISTS_REF || return $? return $ADE_OK } get_mirror_exists() { local ERRSTACK_REF="$1"; shift local REPO EXISTS_REF # Process arguments [ $# = 2 ] || ade_internal "$ERRSTACK_REF" "get_mirror_exists: $#: invalid argument count" REPO=$1 EXISTS_REF=$2 ade_write_sql "$ERRSTACK_REF" "select case count(*) when 0 then 'false' else 'true' end from mirrors where repo == '$REPO';" $EXISTS_REF || return $? return $ADE_OK } get_freeze_exists() { local ERRSTACK_REF="$1"; shift local REPO FREEZE EXISTS_REF # Process arguments [ $# = 3 ] || ade_internal "$ERRSTACK_REF" "get_freeze_exists: $#: invalid argument count" REPO=$1 FREEZE=$2 EXISTS_REF=$3 ade_write_sql "$ERRSTACK_REF" "select case count(*) when 0 then 'false' else 'true' end from freezes where repo == '$REPO' and freeze == '$FREEZE';" $EXISTS_REF || return $? return $ADE_OK } get_indirect_exists() { local ERRSTACK_REF="$1"; shift local REPO HOST FREEZE EXISTS_REF # Process arguments [ $# = 4 ] || ade_internal "$ERRSTACK_REF" "get_indirect_exists: $#: invalid argument count" REPO=$1 HOST=$2 FREEZE=$3 EXISTS_REF=$4 ade_write_sql "$ERRSTACK_REF" "select case count(*) when 0 then 'false' else 'true' end from indirects where repo == '$REPO' and host == '$HOST' and freeze == '$FREEZE';" $EXISTS_REF || return $? return $ADE_OK } get_share_exists() { local ERRSTACK_REF="$1"; shift local REPO HOST EXISTS_REF # Process arguments [ $# = 3 ] || ade_internal "$ERRSTACK_REF" "get_share_exists: $#: invalid argument count" REPO=$1 HOST=$2 EXISTS_REF=$3 ade_write_sql "$ERRSTACK_REF" "select case count(*) when 0 then 'false' else 'true' end from shares where repo == '$REPO' and host == '$HOST';" $EXISTS_REF || return $? return $ADE_OK } get_access_exists() { local ERRSTACK_REF="$1"; shift local REPO EXISTS_REF # Process arguments [ $# = 2 ] || ade_internal "$ERRSTACK_REF" "get_access_exists: $#: invalid argument count" REPO=$1 EXISTS_REF=$2 ade_write_sql "$ERRSTACK_REF" "select case count(*) when 0 then 'false' else 'true' end from accesses where repo == '$REPO';" $EXISTS_REF || return $? return $ADE_OK }