#!/bin/bash
set -e

# uh sorry... this is hideous but I already had it working in perl!
function uniquename_printf
{
	echo $1 | perl -e '
		sub pfile
		{
			my $format = shift;
			my $nr = shift;
			return sprintf "$format", $nr;
		}
		sub is_unique_file
		{
			my $format = shift;
			my $nr = shift;
			return ! (-e pfile($format, $nr));
		}
		sub is_next_unique_file
		{
			my $format = shift;
			my $nr = shift;
			if ($nr <= 0) {
				return is_unique_file($format, $nr);
			}
			return (is_unique_file($format, $nr) && 
				!is_unique_file($format, $nr-1)) 
		}
		sub uniquename_printf
		{
			my $format = shift;;
			my $nr = 0;
			my $jump = 0;
			while (!is_unique_file($nr)) {
				$nr = (1<<$jump++);
			}
			$jump--;
			while (!is_next_unique_file($format, $nr)) {
				if (is_unique_file($format, $nr)) {
					$nr -= (1<<$jump);
				} else {
					$nr += (1<<$jump);
				}
				$jump--;
			}
			return pfile($format, $nr);
		}
		my @in = <>;
		chomp @in;
		print uniquename_printf($in[0]);';
	echo
}

function uniqmkdir
{
	DIR=`uniquename_printf "$1"`
	mkdir "$DIR"
	echo "$DIR"
}
function archive_cmd_as
{
	SDIR=$1
	NAME=$2
	shift;
	shift;
	"$@" > $SDIR/$NAME
}
function archive_cmd
{
	SDIR=$1
	shift;
	archive_cmd_as $SDIR "$(basename $1)" "$@"
}

function archive_files
{
	SDIR=$1
	shift;
	for i in "$@"; do
		[ -e "$i" ] && cp --preserve=ownership "$i" $SDIR/
	done
}

function archive_proc_pid_files
{
	SDIR=$1
	shift;
	for FILE in "$@"; do 
		if ! [ -e /proc/self/$FILE ]; then 
			continue;
		fi
		find /proc/[0-9]*/ -name $FILE -maxdepth 1 \
		| xargs grep -a -H . > $SDIR/$FILE || true
	done 2> /dev/null
}

PERIOD=$1
NR_SAMPLES=$2

if [ -z "$PERIOD" ]; then
	echo no sample period given, defaulting to every 10 seconds
	PERIOD="10";
fi;
if [ -z "$NR_SAMPLES" ]; then
	echo no number of samples given, running forever
	NR_SAMPLES="-1";
fi;

BASE_DIR=`uniqmkdir vmlog-$(date +%s)-%05d`
SAMPLE_NR=0
while [ "$NR_SAMPLES" -eq "-1" ] || 
      [ $((NR_SAMPLES--)) -ne 0 ]; do
	if [ $((SAMPLE_NR++)) -ne 0 ]; then
		sleep $PERIOD;
	fi;
	SDIR=`uniqmkdir "$BASE_DIR/sample-%05d"`;
	echo vmlog sample number: $SAMPLE_NR

	archive_proc_pid_files $SDIR smaps maps oom_score oom_adj 
	archive_files 	       $SDIR /proc/{buddy,slab,mem,mem}info /proc/vmstat
	archive_cmd_as	       $SDIR proc-sys-vm grep . /proc/sys/vm/*
	archive_cmd	       $SDIR dmesg -c
	archive_cmd	       $SDIR date
done
