/*

Copyright (C) 2010-2018 Olaf Till <i7tiol@t-online.de>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; If not, see <http://www.gnu.org/licenses/>.

*/

// PKG_ADD: autoload ("network_set", "parallel_interface.oct");
// PKG_DEL: autoload ("network_set", "parallel_interface.oct", "remove");

#include <octave/oct.h>
#include <octave/dirfns.h>
#include <octave/oct-map.h>
#include <octave/oct-env.h>

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <unistd.h>

#include "parallel-gnutls.h"

DEFUN_DLD (network_set, args, ,
           "-*- texinfo -*-\n\
@deftypefn {Loadable Function} {} network_set (@var{connections}, @var{key}, @var{val})\n\
Set the property named by @var{key} to the value @var{val} for each machine specified by @var{connections}.\n\
\n\
This function can only be successfully called at the client\n\
machine. See @code{pconnect} for a description of the\n\
@var{connections} variable. @var{connections} can contain all\n\
connections of the network, a subset of them, or a single\n\
connection.\n\
\n\
Possible values of @var{key}: @code{'nlocaljobs'}: configured number\n\
of local processes on the machine (usable by functions for parallel\n\
execution); needs a non-negative integer in @var{val}, @code{0} means\n\
not specified.\n\
\n\
@seealso{pconnect, pserver, reval, psend, precv, sclose, parallel_generate_srp_data, select_sockets}\n\
@end deftypefn")
{
  std::string fname ("network_set");

  octave_value retval;

  if (args.length () != 3 ||
      args(0).type_id () != octave_parallel_connections::static_type_id ())
    {
      print_usage ();

      return retval;
    }

  const octave_base_value &rep = args(0).get_rep ();
  const octave_parallel_connections &cconns =
    dynamic_cast<const octave_parallel_connections&> (rep);
  octave_parallel_connections_rep *conns = cconns.get_rep ();
  int nconns = conns->get_connections ().numel ();

  if (conns->get_whole_network ()->is_closed ())
    {
      error ("%s: network is closed", fname.c_str ());

      return retval;
    }

  if (conns->is_server ())
    {
      error ("%s: 'network_set' can't be called at the server side",
             fname.c_str ());

      return retval;
    }

  std::string key;

  CHECK_ERROR (key = args(1).string_value (), retval,
               "%s: second argument must be a string", fname.c_str ());

  int arg;

  if (! key.compare ("nlocaljobs"))
    {
      CHECK_ERROR (arg = args(2).int_value (), retval,
                   "%s: argument for key 'nlocaljobs' could not be converted to a non-negative integer",
                   fname.c_str ());

      if (arg < 0)
        {
          error ("%s: argument for key 'nlocaljobs' could not be converted to a non-negative integer",
                 fname.c_str ());

          return retval;
        }
    }
  else
    {
      error ("%s: key '%s' not recognized", fname.c_str (), key.c_str ());

      return retval;
    }

  for (int i = 0; i < nconns; i++)
    conns->get_connections ()(i)->set_nlocaljobs (arg);

  return retval;
}

/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/
