#  $HeadURL$ $LastChangedRevision$

#  Name of this package
package JS;

#  Packages required by this package
use strict;
no strict 'subs';                               #  Allow bare words, so &ade_err_error() calls look nicer.
use warnings;
use ADE;

#  Declare exports
BEGIN {
    use Exporter   ();
    our (@ISA, @EXPORT);
    @ISA         = qw(Exporter);
    @EXPORT      = qw(send_message read_message $js_msgqueue_key $js_msgqueue_type_jsd $js_msgqueue_type_jsm %js_defined_errors);
}
END { 
}       

#  Instantiate exported data
our($js_msgqueue_key);
our($js_msgqueue_type_jsd);
our($js_msgqueue_type_jsm);

#  Initialise exported data
$js_msgqueue_key = 87532;   #  basically a random number but the same in all js scripts.
$js_msgqueue_type_jsd = 1;
$js_msgqueue_type_jsm = 2;

#  Instantiate private data
my($max_msg_len);
my(%js_defined_errors);

#  Initialise private data 
$max_msg_len = 100 * 1024 * 1024;
%js_defined_errors = (
    js_err_misc            => { fmt => "%s" },
);
BEGIN {
    &ade_err_registerdefderrs(\%js_defined_errors);
}

sub send_message
{
    my($errstack_ref, $msgqueue_id, $sender_id, $recipient_id, $message_ref) = @_;
    my($serialised_message, %local_message);

    %local_message = %{$message_ref};
    $local_message{'sender-id'} = $sender_id;

    $serialised_message = Storable::freeze { %local_message };

    &ade_err_debug($errstack_ref, 10, "send_message: sending message ...");
    if (!msgsnd($msgqueue_id, pack("l! a*", $recipient_id, $serialised_message), 0)) {
        &ade_err_error($errstack_ref, js_err_misc, "msgsnd: failed");
        return($ade_err_fail);
    }

    return($ade_err_ok);
}

sub read_message
{
    my($errstack_ref, $msgqueue_id, $sender_id_ref, $recipient_id, $message_ref) = @_;
    my($rcvd_buf, $serialised_message, %local_message);

    &ade_err_debug($errstack_ref, 10, "read_message: awaiting message ...");
    if (!msgrcv($msgqueue_id, $rcvd_buf, $max_msg_len, $recipient_id, 0)) {
        #&ade_err_debug($errstack_ref, 10, "read_message: msgrcv() returned but there is no message; we assume it was interrupted");
        %{$message_ref} = ();
        return($ade_err_ok);
    }

    #&ade_err_debug($errstack_ref, 10, "read_message: msgrcv() returned with a message; unpacking ...");
    (undef, $serialised_message) = unpack("l! a*", $rcvd_buf);
    %local_message = %{ Storable::thaw($serialised_message) };

    ${$sender_id_ref} = $local_message{'sender-id'};
    delete $local_message{'sender-id'};
    %{$message_ref} = %local_message;

    return($ade_err_ok);
}
