/*
 * nasd_edrfs_core.c
 *
 * Core functionality for NASD EDRFS.
 *
 * Author: Jim Zelenka
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1997,1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#include <nasd/nasd_options.h>
#include <nasd/nasd_types.h>
#include <nasd/nasd_freelist.h>
#include <nasd/nasd_itypes.h>
#include <nasd/nasd_mem.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_timeout.h>
#include <nasd/nasd_edrfs_server_internal.h>

#include <nasd/nasd_pipe.h>

/*
 * Server-global shutdown.
 */
nasd_shutdown_list_t *nasd_edrfs_shutdown = NULL;

nasd_freelist_t *nasd_edrfs_createpair_freelist = NULL;
#define NASD_MAX_FREE_CREATEPAIR 64
#define NASD_CREATEPAIR_INC       2
#define NASD_CREATEPAIR_INITIAL  16

nasd_freelist_t *nasd_edrfs_setattrpair_freelist = NULL;
#define NASD_MAX_FREE_SETATTRPAIR 64
#define NASD_SETATTRPAIR_INC       2
#define NASD_SETATTRPAIR_INITIAL  16

nasd_freelist_t *nasd_edrfs_infopage_freelist = NULL;
#define NASD_MAX_FREE_INFOPAGE 32
#define NASD_INFOPAGE_INC       2
#define NASD_INFOPAGE_INITIAL  16

nasd_freelist_t *nasd_edrfs_lookupstuff_freelist = NULL;
#define NASD_MAX_FREE_LOOKUPSTUFF 32
#define NASD_LOOKUPSTUFF_INC       2
#define NASD_LOOKUPSTUFF_INITIAL  16

int nasd_edrfs_fm_initted_drive_client = 0;

nasd_status_t
nasd_edrfs_really_shutdown()
{
  nasd_status_t rc;
  int e;

  nasd_printf("EDRFS: really shutting down\n");

  /* synchronize any dirty data here (currently, there isn't any) */

  /* now get rid of clean dirs on the LRU */
  nasd_edrfs_server_dir_cleanup();

  nasd_printf("EDRFS: shutdown drives\n");

  nasd_edrfs_shutdown_drives();

  nasd_printf("EDRFS: begin automatic shutdown\n");

  e = 0;
  rc = nasd_shutdown_list_shutdown(nasd_edrfs_shutdown,
    NASD_SHUTDOWN_ANNOUNCE_NONE);
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_shutdown_list_shutdown()\n",
      rc, nasd_error_string(rc));
    e = 1;
  }

  nasd_printf("EDRFS: automatic shutdown complete\n");

  nasd_shutdown_cleanup();

  if (nasd_edrfs_fm_initted_drive_client) {
    nasd_cl_p_shutdown();
    nasd_edrfs_fm_initted_drive_client = 0;
  }
  nasd_printf("EDRFS: shutdown complete\n");

  return(NASD_SUCCESS);
}

void
nasd_edrfs_shutdown_timeoutsys(
  void  *ignored)
{
  nasd_timeout_shutdown();
}

nasd_status_t
nasd_edrfs_init()
{
  nasd_status_t rc;

  NASD_ASSERT(sizeof(nasd_edrfs_dirpage_t) == 8192);
  NASD_ASSERT(sizeof(nasd_edrfs_dirdata_t) == 64);
  NASD_ASSERT(sizeof(nasd_edrfs_dirheader_t) == 64);

  nasd_edrfs_fm_initted_drive_client = 0;

  rc = nasd_cl_p_init();
  if (rc) {
    nasd_printf("EDRFS: got 0x%x (%s) when initializing client library",
      rc, nasd_error_string(rc));
    return(rc);
  }
  nasd_edrfs_fm_initted_drive_client = 1;

  rc = nasd_shutdown_sys_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_shutdown_sys_init()\n",
      rc, nasd_error_string(rc));
    return(rc);
  }

  rc = nasd_shutdown_list_init(&nasd_edrfs_shutdown);
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_shutdown_list_init()\n",
      rc, nasd_error_string(rc));
    return(rc);
  }

  rc = nasd_timeout_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_timeout_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }
  rc = nasd_shutdown_proc(nasd_edrfs_shutdown, nasd_edrfs_shutdown_timeoutsys,
    NULL);
  if (rc) {
    nasd_edrfs_shutdown_timeoutsys(NULL);
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_createpair_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_createpair_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_setattrpair_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_setattrpair_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_infopage_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_infopage_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_lookupstuff_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_lookupstuff_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_name_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_name_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_server_dir_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_server_dir_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_drsys_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_drsys_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  rc = nasd_edrfs_rpc_init();
  if (rc) {
    nasd_printf("ERROR: got 0x%x (%s) from nasd_edrfs_rpc_init()\n",
      rc, nasd_error_string(rc));
    nasd_edrfs_really_shutdown();
    return(rc);
  }

  return(NASD_SUCCESS);
}

nasd_edrfs_createpair_t *
nasd_edrfs_get_createpair()
{
  nasd_edrfs_createpair_t *cp;

  NASD_FREELIST_GET(nasd_edrfs_createpair_freelist,cp,next,(nasd_edrfs_createpair_t *));
  return(cp);
}

void
nasd_edrfs_free_createpair(
  nasd_edrfs_createpair_t  *cp)
{
  NASD_FREELIST_FREE(nasd_edrfs_createpair_freelist,cp,next);
}

nasd_status_t
nasd_edrfs_createpair_init()
{
  nasd_status_t rc;

  NASD_FREELIST_CREATE(nasd_edrfs_createpair_freelist, NASD_MAX_FREE_CREATEPAIR,
    NASD_CREATEPAIR_INC, sizeof(nasd_edrfs_createpair_t));
  if (nasd_edrfs_createpair_freelist == NULL) {
    return(NASD_NO_MEM);
  }
  rc = nasd_shutdown_proc(nasd_edrfs_shutdown, nasd_edrfs_createpair_shutdown,
    NULL);
  if (rc) {
    nasd_edrfs_createpair_shutdown(NULL);
    return(rc);
  }
  NASD_FREELIST_PRIME(nasd_edrfs_createpair_freelist,
    NASD_CREATEPAIR_INITIAL,next, (nasd_edrfs_createpair_t *));
  return(NASD_SUCCESS);
}

void
nasd_edrfs_createpair_shutdown(
  void  *ignored)
{
  NASD_FREELIST_DESTROY(nasd_edrfs_createpair_freelist,next,(nasd_edrfs_createpair_t *));
}

nasd_edrfs_setattrpair_t *
nasd_edrfs_get_setattrpair()
{
  nasd_edrfs_setattrpair_t *cp;

  NASD_FREELIST_GET(nasd_edrfs_setattrpair_freelist,cp,next,(nasd_edrfs_setattrpair_t *));
  return(cp);
}

void
nasd_edrfs_free_setattrpair(
  nasd_edrfs_setattrpair_t  *cp)
{
  NASD_FREELIST_FREE(nasd_edrfs_setattrpair_freelist,cp,next);
}

nasd_status_t
nasd_edrfs_setattrpair_init()
{
  nasd_status_t rc;

  NASD_FREELIST_CREATE(nasd_edrfs_setattrpair_freelist, NASD_MAX_FREE_SETATTRPAIR,
    NASD_SETATTRPAIR_INC, sizeof(nasd_edrfs_setattrpair_t));
  if (nasd_edrfs_setattrpair_freelist == NULL) {
    return(NASD_NO_MEM);
  }
  rc = nasd_shutdown_proc(nasd_edrfs_shutdown, nasd_edrfs_setattrpair_shutdown,
    NULL);
  if (rc) {
    nasd_edrfs_setattrpair_shutdown(NULL);
    return(rc);
  }
  NASD_FREELIST_PRIME(nasd_edrfs_setattrpair_freelist,
    NASD_SETATTRPAIR_INITIAL,next, (nasd_edrfs_setattrpair_t *));
  return(NASD_SUCCESS);
}

void
nasd_edrfs_setattrpair_shutdown(
  void  *ignored)
{
  NASD_FREELIST_DESTROY(nasd_edrfs_setattrpair_freelist,next,(nasd_edrfs_setattrpair_t *));
}

nasd_edrfs_infopage_t *
nasd_edrfs_get_infopage()
{
  nasd_edrfs_infopage_t *cp;

  NASD_FREELIST_GET(nasd_edrfs_infopage_freelist,cp,next,(nasd_edrfs_infopage_t *));
  return(cp);
}

void
nasd_edrfs_free_infopage(
  nasd_edrfs_infopage_t  *cp)
{
  NASD_FREELIST_FREE(nasd_edrfs_infopage_freelist,cp,next);
}

nasd_status_t
nasd_edrfs_infopage_init()
{
  nasd_status_t rc;

  NASD_FREELIST_CREATE(nasd_edrfs_infopage_freelist, NASD_MAX_FREE_INFOPAGE,
    NASD_INFOPAGE_INC, sizeof(nasd_edrfs_infopage_t));
  if (nasd_edrfs_infopage_freelist == NULL) {
    return(NASD_NO_MEM);
  }
  rc = nasd_shutdown_proc(nasd_edrfs_shutdown, nasd_edrfs_infopage_shutdown,
    NULL);
  if (rc) {
    nasd_edrfs_infopage_shutdown(NULL);
    return(rc);
  }
  NASD_FREELIST_PRIME(nasd_edrfs_infopage_freelist,
    NASD_INFOPAGE_INITIAL,next, (nasd_edrfs_infopage_t *));
  return(NASD_SUCCESS);
}

void
nasd_edrfs_infopage_shutdown(
  void  *ignored)
{
  NASD_FREELIST_DESTROY(nasd_edrfs_infopage_freelist,next,(nasd_edrfs_infopage_t *));
}

nasd_edrfs_lookupstuff_t *
nasd_edrfs_get_lookupstuff()
{
  nasd_edrfs_lookupstuff_t *cp;

  NASD_FREELIST_GET(nasd_edrfs_lookupstuff_freelist,cp,next,(nasd_edrfs_lookupstuff_t *));
  return(cp);
}

void
nasd_edrfs_free_lookupstuff(
  nasd_edrfs_lookupstuff_t  *cp)
{
  NASD_FREELIST_FREE(nasd_edrfs_lookupstuff_freelist,cp,next);
}

nasd_status_t
nasd_edrfs_lookupstuff_init()
{
  nasd_status_t rc;

  NASD_FREELIST_CREATE(nasd_edrfs_lookupstuff_freelist, NASD_MAX_FREE_LOOKUPSTUFF,
    NASD_LOOKUPSTUFF_INC, sizeof(nasd_edrfs_lookupstuff_t));
  if (nasd_edrfs_lookupstuff_freelist == NULL) {
    return(NASD_NO_MEM);
  }
  rc = nasd_shutdown_proc(nasd_edrfs_shutdown, nasd_edrfs_lookupstuff_shutdown,
    NULL);
  if (rc) {
    nasd_edrfs_lookupstuff_shutdown(NULL);
    return(rc);
  }
  NASD_FREELIST_PRIME(nasd_edrfs_lookupstuff_freelist,
    NASD_LOOKUPSTUFF_INITIAL,next, (nasd_edrfs_lookupstuff_t *));
  return(NASD_SUCCESS);
}

void
nasd_edrfs_lookupstuff_shutdown(
  void  *ignored)
{
  NASD_FREELIST_DESTROY(nasd_edrfs_lookupstuff_freelist,next,(nasd_edrfs_lookupstuff_t *));
}

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