diff options
-rwxr-xr-x | p2ptbl | 158 | ||||
-rwxr-xr-x | p2ptbl-recv | 12 |
2 files changed, 170 insertions, 0 deletions
@@ -0,0 +1,158 @@ +#!/bin/sh -e + +init () { + [ -n "$1" ] || printArgs + mkdir -p "$(dirname $1)" + [ -f "$1" ] || cat >"$1" </dev/null +} + +get () { + [ -n "$2" ] || printArgs + grep "^$2"$'\t' "$1" | cut -f3- +} + +show () { + cut -f1,3- "$1" +} + +filter () { + tbl="$1" + shift 1 + cut -f1,2 "$tbl" \ + | while read key version; do + echo -e "$key\t$(($version+$RANDOM))" + done > "$tbl".ver + cut -f1,3- "$tbl" \ + | "$@" \ + | join -t$'\t' "$tbl".ver - \ + > "$tbl"~ + mv "$tbl"~ "$tbl" + rm "$tbl".ver +} + +update () { + [ -n "$2" -a -n "$3" ] || printArgs + oldversion=$(grep "^$2"$'\t' "$1" | cut -f2) + tmpfile="$1.update" + echo -e "$2\t$(($oldversion + 1 + $RANDOM))\t$3" > "$tmpfile" + merge "$1" "$tmpfile" + if [ -n "$4" ]; then + # broadcast update + gzip <"$tmpfile" >"$tmpfile.gz" + hbbpc $4 p2ptbl/$(basename "$1") - <"$tmpfile.gz" + rm "$tmpfile.gz" + fi + rm "$tmpfile" +} + +merge () { + # we use sort instead of merge here to be robust in case the rows + # are not sorted + sort "$1" "$2" \ + | { + oldkey="" + oldversion=0 + oldval="" + while read key version val; do + if [ "$key" == "$oldkey" ]; then + if [ "$version" -gt "$oldversion" ]; then + oldversion="$version" + oldval="$val" + fi + else + [ -n "$oldkey" ] && echo -e "$oldkey\t$oldversion\t$oldval" + oldkey="$key" + oldversion="$version" + oldval="$val" + fi + done + [ -n "$oldkey" ] && echo -e "$oldkey\t$oldversion\t$oldval" + } > "$1~" + mv "$1~" "$1" +} + +gossip() { + tgts="$2" + if="$3" + [ "$tgts" -gt 0 -a -n "$if" ] 2>/dev/null || printArgs + + # binary search over number of sent lines until size is maximized + # and below target size + lc=$(wc -l <"$1") + [ $lc == 0 ] && return + shuf -v seed=$RANDOM <"$1" >"$1.gossip" + while [ $lc -ge 1 ]; do + head -n$lc "$1.gossip" | gzip >"$1.gossip.gz" + if [ $tgts -ge $(wc -c <"$1.gossip.gz") ]; then + hbbpc $if p2ptbl/$(basename "$1") - <"$1.gossip.gz" + rm "$1.gossip" "$1.gossip.gz" + return; + fi + lc=$(($lc / 2)) + done + rm "$1.gossip" "$1.gossip.gz" + echo "$1 has rows bigger then requested packet size" + exit 1 +} + +printArgs () { + echo -e >&2 "Usage: +$0 init table +$0 get table key +$0 show table +$0 update table key value [interface] +$0 filter table program [args] +$0 merge table foreign-table +$0 gossip table target-size interface" + exit 1 +} + +checkTable () { + [ -n "$1" ] || printArgs; + [ -f "$1" ] || { + echo >&2 "$1 is no P2P table"; + printArgs; + } +} + +lockTable () { + checkTable "$2" + exec 666<"$2" + flock "$1" 666 +} + +case "$1" in + init) + init "$2" + ;; + get) + lockTable -s "$2" + get "$2" "$3" + ;; + show) + lockTable -s "$2" + show "$2" + ;; + filter) + tbl="$2" + shift 2 + lockTable -x "$tbl" + filter "$tbl" "$@" + ;; + update) + lockTable -s "$2" + update "$2" "$3" "$4" "$5" + ;; + merge) + lockTable -x "$2" + checkTable "$3" + merge "$2" "$3" + ;; + gossip) + lockTable -s "$2" + gossip "$2" "$3" "$4" + ;; + *) + printArgs + ;; +esac
\ No newline at end of file diff --git a/p2ptbl-recv b/p2ptbl-recv new file mode 100755 index 0000000..f10fa39 --- /dev/null +++ b/p2ptbl-recv @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +tbldir=/tmp/p2ptbl +tbl=$tbldir/$(basename $0) + +[ -f $tbl ] || p2ptbl init $tbl + +gunzip > $tbl.recv +p2ptbl merge $tbl $tbl.recv +rm $tbl.recv
\ No newline at end of file |