summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xp2ptbl158
-rwxr-xr-xp2ptbl-recv12
2 files changed, 170 insertions, 0 deletions
diff --git a/p2ptbl b/p2ptbl
new file mode 100755
index 0000000..341cecd
--- /dev/null
+++ b/p2ptbl
@@ -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
contact: Jan Huwald // Impressum