#!/usr/bin/tclsh8.5
#
# $Id: be6b473313c09e70826fbb0afa7dd516d9be076e $
#

## The common defaults
set filters_init_file "/usr/local/libexec/nbsp/filters.init";
if {[file exists $filters_init_file] == 0} {
	puts "gribfilter-master disabled: $filters_init_file not found.";
	return 1;
}
source $filters_init_file;
unset filters_init_file;

if {$filters_init_status == 1} {
	return 1;
}
unset filters_init_status;

## Initialization of this filter.
set initfile [file join $common(libdir) "gribfilter.init"];
if {[file exists $initfile] == 0} {
        puts "gribfilter disabled: $initfile not found.";
        return 1;
}
source $initfile;

#
## variables of this filter
#
# gribfilter(slave,<type>,open) 0;
# gribfilter(slave,<type>,enable) 1;
# gribfilter(slave,<type>,F) (dynamically initialized before entering main)
#
foreach type $gribfilter(slave,types) { 
    set gribfilter(slave,$type,open) 0;
    set gribfilter(slave,$type,enable) 1;
}
set gribfilter(manager)		1;

proc main {argc argv} {

    global gribfilter;
    global errorInfo;

    cd $gribfilter(datadir);

    # gets returns -1 on eof. In addition the server explicitly
    # signals the filters to quit by sending a blankline
    # (gets returns 0 in this case, and finfo is "").

    while {[gets stdin finfo] >= 0} {
	if {$finfo == ""} {
	    log_msg "Received request to quit.";
	    break;
	}

	set status [catch {process $finfo} errmsg];
	if {$status == 1} {
	    log_msg "Error processing $finfo";
	    log_msg $errmsg;
	    log_msg $errorInfo;
	}

	# If there was a write error, the functions close the connections.
	# We check and try to reopen it.

	foreach type $gribfilter(slave,types) {
	    if {($gribfilter(slave,$type,enable) == 1) && \
		($gribfilter(slave,$type,open) == 0)} {
	        gribfilter_slave_open $type;
	    }
	}

	::nbsp::periodic::run
    }

    foreach type $gribfilter(slave,types) {
	gribfilter_slave_close $type;
    }
}

proc process {finfo} {

    global gribfilter;

    filterlib_get_rcvars rc $finfo -nobody;

    if {[regexp {^grib} $rc(nawips)] == 0} {
	return;
    }

    foreach type $gribfilter(slave,types) {
	if {[filterlib_uwildmat $gribfilter(slave,$type,ure) $rc(fname)] && \
	    ($gribfilter(slave,$type,enable) == 1)} {
	    gribfilter_slave_write $type $finfo;
	    break;
	}
    }
}

#
# The gribfilter_slave functions
#

proc gribfilter_slave_open {type} {

    global gribfilter;

    set status [catch {
	set gribfilter(slave,$type,F) [open "|$gribfilter(slave) -s" w];
	fconfigure $gribfilter(slave,$type,F) -buffering line;
    } errmsg];

    if {$status == 0} {
	set gribfilter(slave,$type,open) 1;
    } else {
	log_msg $errmsg
    }
}

proc gribfilter_slave_close {type} {

    global gribfilter;

    if {$gribfilter(slave,$type,open) == 0} {
	return;
    }

    set status [catch {close $gribfilter(slave,$type,F)} errmsg];
    set gribfilter(slave,$type,open) 0;
    if {$status != 0} {
	log_msg $errmsg;
    }
}

proc gribfilter_slave_write {type msg} {

    global gribfilter;
    global errorInfo;

    if {$gribfilter(slave,$type,open) == 0} {
	log_msg "Connection to slave $type is closed.";
	return;
    }

    set status [catch {puts $gribfilter(slave,$type,F) $msg} errmsg];
    if {$status == 0} {
	return;
    }

    # If there as a write error, close the connection and retry.
    gribfilter_slave_close $type;
    gribfilter_slave_open $type;
    if {$gribfilter(slave,$type,open) == 0} {
	log_msg $errmsg;
	return;
    }

    set status [catch {puts $gribfilter(slave,$type,F) $msg} errmsg];
    if {$status != 0} {
	log_msg $errmsg;
	log_msg $errorInfo;
	return;
    }
}

#
# Dynamic initialization
#
# Open the pipes. In case a connection cannot be establish, log an error
# and continue but disable that type.
foreach type $gribfilter(slave,types) { 
    gribfilter_slave_open $type;
    if {$gribfilter(slave,$type,open) == 0} {
	log_msg "Disabling the $type dispatching.";
	set gribfilter(slave,$type,enable) 0;
    }
}

# In work-crew mode only the master runs the scheduler
::nbsp::periodic::register \
    gribfilter_run_scheduler $gribfilter(schedule_run_period);

main $argc $argv;
