sub
new
{
my
$class
=
shift
;
my
$self
= {};
bless
$self
,
$class
;
$self
->_init(
@_
);
return
$self
;
}
sub
_init
{
my
$self
=
shift
;
my
%args
= (
@_
);
$self
->{
'status_file'
} =
$args
{
'status_file'
} or
die
"Unknown status file!"
;
return
0;
}
sub
start
{
my
$self
=
shift
;
my
$status_file
=
$self
->{
'status_file'
};
for
(
my
$port
= 3000; ;
$port
++)
{
unlink
(
$status_file
);
my
$fork_pid
=
fork
();
if
(!
defined
(
$fork_pid
))
{
die
"Fork was not successful!"
;
}
if
(!
$fork_pid
)
{
my
$server
=
Net::SeedServe->new(
'status_file'
=>
$status_file
,
'port'
=>
$port
,
);
eval
{
$server
->loop();
};
if
($@)
{
exit
(-1);
}
}
else
{
my
$text
;
while
(! (
defined
(
$text
) and
$text
=~ /\n\z/) )
{
while
(! -f
$status_file
)
{
usleep(5000);
}
usleep(5000);
$text
= io()->file(
$status_file
)->getline();
}
if
(
$text
eq
"Status:Success\tPort:$port\tPID:$fork_pid\n"
)
{
$self
->{
'port'
} =
$port
;
$self
->{
'server_pid'
} =
$fork_pid
;
return
+{
'port'
=>
$port
};
}
else
{
waitpid
(
$fork_pid
, 0);
}
}
}
}
sub
connect
{
my
$self
=
shift
;
my
$status_file
=
$self
->{
'status_file'
};
my
$text
= io()->file(
$status_file
)->getline();
if
(
$text
!~ /^Status:Success\tPort:(\d+)\tPID:(\d+)$/)
{
die
"Invalid status file."
;
}
my
$port
= $1;
$self
->{
'server_pid'
} = $2;
$self
->{
'port'
} =
$port
;
return
{
'port'
=>
$port
, };
}
sub
stop
{
my
$self
=
shift
;
my
$pid
=
$self
->{
'server_pid'
};
kill
(
"TERM"
,
$pid
);
waitpid
(
$pid
, 0);
}
sub
_ok_transact
{
my
$self
=
shift
;
my
$msg
=
shift
;
my
$port
=
$self
->{
'port'
};
my
$conn
= io(
"localhost:$port"
);
$conn
->
print
(
"$msg\n"
);
my
$response
=
$conn
->getline();
if
(
$response
eq
"OK\n"
)
{
return
0;
}
else
{
die
"Invalid response - $response."
;
}
}
sub
clear
{
my
$self
=
shift
;
return
$self
->_ok_transact(
"CLEAR"
);
}
sub
enqueue
{
my
$self
=
shift
;
my
$seeds
=
shift
;
if
(
grep
{
$_
!~ /^\d+$/ }
@$seeds
)
{
die
"Invalid seed."
;
}
return
$self
->_ok_transact(
"ENQUEUE "
.
join
(
""
,
map
{
"$_,"
}
@$seeds
));
}
1;