/*
 * nasd_cheops_mgr_srpc.c
 */
/*
 * SRPC Callbacks and Mechanisms for Cheops Manager
 */
/*
 * Copyright (c) 1996,1997,1998,1999 Carnegie Mellon University.
 * All rights reserved.
 *
 * Author: Khalil Amiri, CMU SCS/ECE, July 18 1997
 *
 * Permission to use, copy, modify and distribute this software and
 * its documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 *
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 *
 * Carnegie Mellon requests users of this software to return to
 *
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 *
 * any improvements or extensions that they make and grant Carnegie Mellon the
 * rights to redistribute these changes.
 */

/*
 * cheops storage manager interface
 */

#include <nasd/nasd_options.h>

#if NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_SRPC

# include <nasd/nasd_types.h>
# include <nasd/nasd_cheops_types.h>
# include <nasd/nasd_itypes.h>
# include <nasd/nasd_general.h>
# include <nasd/nasd_cheops_common.h>
# include <nasd/nasd_cheops_mgr.h>
# include <nasd/nasd_cheops_mgr_common.h>
# include <nasd/nasd_cheops_mgr_structs.h>
# include <nasd/nasd_cheops_mgr_internal.h>
# include <nasd/nasd_srpc.h>
# include <nasd/nasd_types_marshall.h>
# include <nasd/nasd_cheops_types_marshall.h>
# include <nasd/nasd_cheops_mgr_sstub.h>

/* debugging */
# define NASD_CHEOPS_OP_DEBUG           1

# define DOBEGIN(_opname_) {                                            \
  nasd_cheops_mgr_begin_rpc();                                          \
}
# define DORETURN(_opname_) {                                           \
  nasd_cheops_mgr_end_rpc();                                            \
  return 0;                                                             \
}

/*
 * RPC Callbacks
 */

nasd_srpc_status_t
nasd_cheops_null_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_res_otw_t                         out_res_otw)
{
  nasd_res_t res;

  DOBEGIN(null);

  res.nasd_status = NASD_SUCCESS;
  nasd_res_t_marshall(&res, out_res_otw);
#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n","nasd_cheops_NULL_cm");
#endif /* CHEOPS_OP_DEBUG */

  DORETURN(null);
}

nasd_srpc_status_t
nasd_cheops_bs_create_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_bs_cr_args_otw_t       in_args_otw,
  nasd_cheops_bs_cr_res_otw_t        out_res_otw)
{
  nasd_cookie_t                in_cookie;
  nasd_cheops_bs_cr_args_t args;
  nasd_cheops_bs_cr_res_t res;
	int rc=0;                   
	nasd_cheops_qos_req_t qos_req; /* XXX default qos struct */

  DOBEGIN(bs_create);

  nasd_cheops_bs_cr_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, 0,
                                    NASD_CHEOPS_OP_BS_CREATE); 
  if (rc) {
    res.out_nasd_status = NASD_AUTHCHECK_FAILED;
  } else {
    bzero((char *)&res.out_bs_handle, sizeof(nasd_cheops_bs_handle_t));
    rc = nasd_cheops_bs_create(NASD_FALSE, &qos_req, &res.out_bs_handle); 
    res.out_nasd_status = rc;
  }

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s (new id=0x%"
   NASD_ID_FMT ")\n",
	 "nasd_cheops_BS_CREATE_cm", res.out_bs_handle.bsid);
#endif /* CHEOPS_OP_DEBUG */

  nasd_cheops_bs_cr_res_t_marshall(&res, out_res_otw);

  DORETURN(bs_create);
}

nasd_srpc_status_t
nasd_cheops_bs_qos_create_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_bs_cr_args_otw_t       in_args_otw,
  nasd_cheops_bs_cr_res_otw_t        out_res_otw)
{
  nasd_cookie_t in_cookie;
  int  failures = 0;
	int  rc=0;                   
  nasd_cheops_bs_qc_args_t args;
  nasd_cheops_bs_qc_res_t res;

  DOBEGIN(bs_qos_create);

  nasd_cheops_bs_qc_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, 0,
                                     NASD_CHEOPS_OP_BS_CREATE); 
  if (rc) {
    res.out_nasd_status = NASD_AUTHCHECK_FAILED;
  } else {
    bzero((char *)&res.out_bs_handle, sizeof(nasd_cheops_bs_handle_t));
    rc = nasd_cheops_bs_create(NASD_TRUE, &args.in_qos_req,
                               &res.out_bs_handle);
    res.out_nasd_status = rc;
  } 

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n",
   "nasd_cheops_BS_QOSCREATE_cm");
#endif /* CHEOPS_OP_DEBUG */

  nasd_cheops_bs_qc_res_t_marshall(&res, out_res_otw);

  DORETURN(bs_qos_create);
}

nasd_srpc_status_t
nasd_cheops_bs_lookup_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_bs_lu_args_otw_t       in_args_otw,
  nasd_cheops_bs_lu_res_otw_t        out_res_otw)
{
  int rc;
  nasd_cheops_bs_lu_args_t args;
  nasd_cheops_bs_lu_res_t res;
  nasd_cookie_t in_cookie;
  nasd_identifier_t in_bsid;

  DOBEGIN(bs_lookup);

  nasd_cheops_bs_lu_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;
  in_bsid = args.in_bsid;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, in_bsid,
                                    NASD_CHEOPS_OP_BS_LOOKUP);
  if (rc) {
    res.out_nasd_status = NASD_AUTHCHECK_FAILED;
  } else {
    rc = nasd_cheops_bs_lookup(in_bsid, &res.out_bs_handle); 
    res.out_nasd_status = rc;
  }

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s(rc=%d)\n",
   "nasd_cheops_BS_LOOKUP_cm",rc);
#endif /* CHEOPS_OP_DEBUG */

  nasd_cheops_bs_lu_res_t_marshall(&res, out_res_otw);

  DORETURN(bs_lookup);
}

nasd_srpc_status_t
nasd_cheops_bs_remove_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_bs_rm_args_otw_t       in_args_otw,
  nasd_cheops_bs_rm_res_otw_t        out_res_otw)
{
  nasd_cheops_bs_rm_args_t args;
  nasd_cheops_bs_rm_res_t res;
  nasd_cookie_t in_cookie;
  nasd_identifier_t in_bsid;
  int  rc;

  DOBEGIN(bs_remove);

	nasd_cheops_bs_rm_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;
  in_bsid = args.in_bsid;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, in_bsid,
                                    NASD_CHEOPS_OP_BS_REMOVE);
  if (rc) {
    res.out_nasd_status = NASD_AUTHCHECK_FAILED;
  } else {
    rc = nasd_cheops_bs_remove(in_bsid); 
    res.out_nasd_status = rc;
  }

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n",
   "nasd_cheops_BS_REMOVE_cm");
#endif /* CHEOPS_OP_DEBUG */

  nasd_cheops_bs_rm_res_t_marshall(&res, out_res_otw);

  DORETURN(bs_remove);
}

nasd_srpc_status_t
nasd_cheops_bs_getattr_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_bs_ga_args_otw_t      in_args_otw,
  nads_cheops_bs_ga_res_otw_t       out_res_otw)
{
  nasd_cheops_bs_ga_args_t args;
  nads_cheops_bs_ga_res_t res;
  nasd_cookie_t in_cookie;
  nasd_identifier_t in_bsid;
  int rc=0;

  DOBEGIN(bs_getattr);

	nasd_cheops_bs_ga_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;
  in_bsid = args.in_bsid;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, in_bsid,
                                    NASD_CHEOPS_OP_BS_GETATTR);
	if (rc) {
	  res.out_nasd_status = NASD_AUTHCHECK_FAILED;
	} else {
    rc = nasd_cheops_bs_getattr(in_bsid, &res.out_attr); 
    res.out_nasd_status = rc;
	}

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n",
   "nasd_cheops_BS_GETATTR_cm");
#endif /* CHEOPS_OP_DEBUG */

  nads_cheops_bs_ga_res_t_marshall(&res, out_res_otw);
  DORETURN(bs_getattr);
}

nasd_srpc_status_t
nasd_cheops_bs_setattr_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_bs_sa_args_otw_t      in_args_otw,
  nads_cheops_bs_sa_res_otw_t       out_res_otw)
{
  nasd_cheops_bs_sa_args_t args;
  nads_cheops_bs_sa_res_t res;
  nasd_cookie_t in_cookie;
  nasd_identifier_t in_bsid;
  nasd_attribute_t in_attr;
  int rc=0;

  DOBEGIN(bs_setattr);

	nasd_cheops_bs_sa_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;
  in_bsid = args.in_bsid;
  in_attr = args.in_attr;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, in_bsid,
                                    NASD_CHEOPS_OP_BS_SETATTR);
	if (rc) {
	  res.out_nasd_status = NASD_AUTHCHECK_FAILED;
	} else {
    rc = nasd_cheops_bs_setattr(in_bsid, in_attr); 
    res.out_nasd_status = rc;
	}

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n",
   "nasd_cheops_BS_SETATTR_cm");
#endif /* CHEOPS_OP_DEBUG */

  nads_cheops_bs_sa_res_t_marshall(&res, out_res_otw);

  DORETURN(bs_setattr);
}

nasd_srpc_status_t
nasd_cheops_bs_refresh_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_bs_re_args_otw_t      in_args_otw,
  nasd_cheops_bs_re_res_otw_t       out_res_otw)
{
  nasd_cheops_bs_re_args_t args;
  nasd_cheops_bs_re_res_t res;
  nasd_cookie_t in_cookie;
  nasd_identifier_t in_bsid;
  int  rc;

  DOBEGIN(bs_refresh);

	nasd_cheops_bs_re_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;
  in_bsid = args.in_bsid;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, in_bsid,
                                    NASD_CHEOPS_OP_BS_LOOKUP);
  if (rc) {
    res.out_nasd_status = NASD_AUTHCHECK_FAILED;
  } else {
    bzero((char *)&res.out_bs_handle, sizeof(nasd_cheops_bs_handle_t));
    rc = nasd_cheops_bs_lookup(in_bsid, &res.out_bs_handle); 
    res.out_nasd_status = rc;
  }

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n",
   "nasd_cheops_BS_REFRESH_cm");
#endif /* CHEOPS_OP_DEBUG */

  nasd_cheops_bs_re_res_t_marshall(&res, out_res_otw);

  DORETURN(bs_refresh);
}

nasd_srpc_status_t
nasd_cheops_dr_lookup_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_dr_lu_args_otw_t       in_args_otw, 
  nasd_cheops_dr_lu_res_otw_t        out_res_otw)
{
  nasd_cheops_dr_lu_args_t args;
  nasd_cheops_dr_lu_res_t res;
  nasd_cookie_t in_cookie;
  nasd_disk_ident_t in_drive_id;
  int rc=0;

  DOBEGIN(dr_lookup);

  nasd_cheops_dr_lu_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;
  in_drive_id = args.in_drive_id;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie,
                                    in_drive_id, NASD_CHEOPS_OP_DR_LOOKUP);
  if (rc) {
    res.out_nasd_status = NASD_AUTHCHECK_FAILED;
  } else {
    bzero((char *)&res.out_dr_info, sizeof(nasd_cheops_cl_dinfo_t));
    rc = nasd_cheops_dr_lookup(in_drive_id, &res.out_dr_info); 
    res.out_nasd_status = rc;
  }

#if NASD_CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n",
   "nasd_cheops_DR_LOOKUP_cm");
#endif /* CHEOPS_OP_DEBUG */

  nasd_cheops_dr_lu_res_t_marshall(&res, out_res_otw);

  DORETURN(dr_lookup);
}

nasd_srpc_status_t
nasd_cheops_mgr_lookup_cm_server(
  nasd_srpc_listener_t                  *listener,
  nasd_srpc_conn_t                      *conn,
  nasd_srpc_server_call_t               *call,
  nasd_cheops_mgr_lookup_args_otw_t      in_args_otw,
  nasd_cheops_mgr_lu_res_otw_t       out_res_otw)
{
  nasd_cheops_mgr_lookup_args_t args;
  nasd_cheops_mgr_lu_res_t res;
  nasd_cookie_t in_cookie;
  nasd_identifier_t in_bsid;
  int rc=0;

  DOBEGIN(mgr_lookup);

  nasd_cheops_mgr_lookup_args_t_unmarshall(in_args_otw, &args);
  in_cookie = args.in_cookie;
  in_bsid = args.in_bsid;

  rc = nasd_cheops_mgr_check_cookie(listener, conn, call, in_cookie, in_bsid,
                                    NASD_CHEOPS_OP_MGR_LOOKUP);
  if (rc) {
    res.out_nasd_status = NASD_AUTHCHECK_FAILED;
  } else {
    bzero((char *)&res.out_mgr_info, sizeof(nasd_cheops_mgr_info_t));
    rc = nasd_cheops_mgr_lookup(in_bsid, &res.out_mgr_info); 
    res.out_nasd_status = rc;
  }

#if CHEOPS_OP_DEBUG > 0
  (cheops_Msg "Cheops storage manager: Handled %s\n",
   "nasd_cheops_MGR_LOOKUP_cm");
#endif /* CHEOPS_OP_DEBUG */

  nasd_cheops_mgr_lu_res_t_marshall(&res, out_res_otw);

  DORETURN(mgr_lookup);
}

/*
 * RPC Mechanism
 */

nasd_srpc_listener_t *nasd_cheops_mgr_listener;
int nasd_cheops_mgr_srpc_started = 0;
nasd_threadgroup_t nasd_cheops_mgr_listening_group;

void
nasd_cheops_mgr_srpc_kill_listener_group(
  void  *ignored)
{
  nasd_status_t rc;

  rc = nasd_destroy_threadgroup(&nasd_cheops_mgr_listening_group);
  if (rc) {
    nasd_printf("CHEOPS MGR: WARNING: got 0x%x (%s) destroying "
                "nasd_cheops_mgr_listening_group\n",
                rc, nasd_error_string(rc));
  }
}

nasd_status_t
nasd_cheops_mgr_rpc_specific_init(void)
{
  nasd_status_t rc;

  rc = nasd_init_threadgroup(&nasd_cheops_mgr_listening_group);
  if (!rc) {
    rc = nasd_shutdown_proc(nasd_cheops_mgr_shutdown_list,
                            nasd_cheops_mgr_srpc_kill_listener_group, NULL);
    if (rc)
      nasd_cheops_mgr_srpc_kill_listener_group(NULL);
    else {
      nasd_cheops_mgr_listener = NULL;
      rc = nasd_srpc_init();
      if (rc == NASD_SUCCESS)
        nasd_cheops_mgr_srpc_started = 1;
    }
  }
  return rc;
}

nasd_status_t
nasd_cheops_mgr_rpc_specific_startup(void)
{
  return NASD_SUCCESS;
}

void
nasd_cheops_mgr_rpc_specific_stop(void)
{
  nasd_status_t rc;

  if (nasd_cheops_mgr_listener) {
    rc = nasd_srpc_listener_destroy(nasd_cheops_mgr_listener);
    if (rc)
      nasd_printf("CHEOPS MGR: got 0x%x (%s) destroying mgr listener\n",
                  rc, nasd_error_string(rc));
    nasd_cheops_mgr_listener = NULL;    /* XXX ouch */
  }
  if (nasd_cheops_mgr_srpc_started) {
    NASD_THREADGROUP_WAIT_START(&nasd_cheops_mgr_listening_group);
    NASD_THREADGROUP_WAIT_STOP(&nasd_cheops_mgr_listening_group);
    nasd_cheops_mgr_srpc_started = 0;
    nasd_srpc_shutdown();
  }
}

nasd_status_t
nasd_cheops_mgr_rpc_specific_listen(
  int          service_threads,
  nasd_uint16  ipport)
{
  nasd_status_t rc;

  rc = nasd_srpc_listener_start(&nasd_cheops_mgr_listener, service_threads,
                                ipport, nasd_cheops_mgr_demux);
  if (!rc) {
    NASD_THREADGROUP_STARTED(&nasd_cheops_mgr_listening_group);
    NASD_THREADGROUP_RUNNING(&nasd_cheops_mgr_listening_group);
    rc = nasd_srpc_listener_wait(nasd_cheops_mgr_listener);
    NASD_THREADGROUP_DONE(&nasd_cheops_mgr_listening_group);
  }

  return rc;
}

nasd_status_t
nasd_cheops_mgr_rpc_specific_set_stacksize(
  int  stacksize)
{
  return NASD_OP_NOT_SUPPORTED;
}
#endif /* NASD_RPC_PACKAGE == NASD_RPC_PACKAGE_DCE */

/* Local Variables:  */
/* indent-tabs-mode: nil */
/* tab-width: 2 */
/* End: */
