[Gllug] Delayed data feed
Robert McKay
robert at mckay.com
Thu Jan 13 02:02:54 UTC 2011
On Wed, Jan 12, 2011 at 5:32 PM, Robert McKay <robert at mckay.com> wrote:
> On Wed, Jan 12, 2011 at 4:33 PM, - Tethys <tethys at gmail.com> wrote:
>
>> Does anyone know of a simple delay utility that consumes data from
>> stdin and outputs it on stdout a fixed time later? What I want to be
>> able to do is:
>>
>> mkdata | delay 30 | send_data_to_customer
>>
>> That will send the (time sensitive) output of mkdata to the customer
>> with a 30 second delay. The amount of data I'm talking about isn't so
>> large that I need to worry about memory usage, and buffering it in RAM
>> will work just fine. I can write it myself, but I'd rather not
>> reinvent the wheel if someone's already done it.
>>
>
> You could pipe it through a series of netcats such that the latency along
> the path is 30 seconds. 50 roundtrips to japan should do it. ;-)
>
> It's sortof an interesting problem as to do it properly you really need to
> timestamp every read().
>
> You could perhaps create artificial latency using netem perhaps making the
> nc idea almost practical.
>
> Here's some crappy perl I made that may work. I think.
>
>
A better version that exits on EOF properly.
#!/usr/bin/perl -w
#
# A simple latency pipe. Configure $delay to suit your needs.
# reads from STDIN, adds latency, writes to STDOUT
#
# Usage: something | this.pl
#
# Test it:
#
# while true; do
# sleep $(( $RANDOM%5 ));
# date +%s;
# done | ./this.pl | perl -ane ' $now = `date +%s`;\
# chomp($now); print "now ($now) - then ($F[0]) = ", $now - $F[0], "\n"; '
use strict;
use IO::Select;
use IO::Handle;
# how long to delay reads
my $delay = 30;
my $bufsize = 1024;
my @chunks = ();
my $reading = 1;
my $chunk;
my $out = IO::Handle->new();
$out->fdopen(fileno(\*STDOUT),"w");
my $s = IO::Select->new();
$s->add(\*STDIN);
while( ($reading)||(scalar(@chunks)>0) )
{
if ($s->can_read(0.01) )
{
if (sysread(STDIN, $chunk, $bufsize)!=0)
{
push @chunks, { time=>time(), chunk=>$chunk };
}
else
{
# a read event happened, but read returned 0 bytes. this means EOF
$reading = 0;
}
}
if (my $test = shift(@chunks))
{
if ($test->{time} <= (time()-$delay) )
{
print $out $test->{chunk};
$out->flush();
} else { unshift(@chunks, $test); }
}
}
rm at rat:~$ dd if=/dev/urandom of=test.file count=10000 bs=1024
10000+0 records in
10000+0 records out
rm at rat:~$ time perl latency.pl < test.file > test.file2
real 0m30.266s
user 0m12.490s
sys 0m2.510s
rm at rat:~$ md5sum test.file test.file2
43a8d122da31ed1c852bd3e7bd50cc32 test.file
43a8d122da31ed1c852bd3e7bd50cc32 test.file2
rm at rat:~$ while true; do sleep $(( $RANDOM%5 )); date +%s; done | ./
latency.pl | perl -ane ' $now = `date +%s`; chomp($now); print "now ($now) -
then ($F[0]) = ", $now - $F[0], "\n"; '
now (1294885976) - then (1294885946) = 30
now (1294885979) - then (1294885949) = 30
now (1294885981) - then (1294885951) = 30
now (1294885982) - then (1294885952) = 30
now (1294885982) - then (1294885952) = 30
now (1294885986) - then (1294885956) = 30
^C
rm at rat:~$
there's also Kosta's python solution from the last time;
http://lists.gllug.org.uk/pipermail/gllug/2010-April/083052.html
Rob
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.lug.org.uk/pipermail/gllug/attachments/20110113/15d9375d/attachment.html>
-------------- next part --------------
--
Gllug mailing list - Gllug at gllug.org.uk
http://lists.gllug.org.uk/mailman/listinfo/gllug
More information about the GLLUG
mailing list