/*
 * nasd_edrfs_server_internal.h
 *
 * Internal structures and definitions for NASD EDRFS server.
 *
 * Authors: Jim Zelenka, Nat Lanza, Mathew Monroe
 */
/*
 * 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.
 */


#ifndef _NASD__NASD_EDRFS_SERVER_INTERNAL_H_
#define _NASD__NASD_EDRFS_SERVER_INTERNAL_H_

#include <nasd/nasd_types.h>
#include <nasd/nasd_drive_types.h>
#include <nasd/nasd_pdrive.h>
#include <nasd/nasd_edrfs_types.h>
#include <nasd/nasd_shutdown.h>
#include <nasd/nasd_pdrive_client.h>
#include <nasd/nasd_edrfs_mq.h>
#include <nasd/nasd_edrfs_internal.h>
#include <nasd/nasd_edrfs_dir.h>

typedef struct nasd_edrfs_attr_s          nasd_edrfs_attr_t;
typedef struct nasd_edrfs_core_dir_s      nasd_edrfs_core_dir_t;
typedef struct nasd_edrfs_core_dirpage_s  nasd_edrfs_core_dirpage_t;
typedef struct nasd_edrfs_createpair_s    nasd_edrfs_createpair_t;
typedef struct nasd_edrfs_diskdirent_s    nasd_edrfs_diskdirent_t;
typedef struct nasd_edrfs_drive_s         nasd_edrfs_drive_t;
typedef struct nasd_edrfs_infopage_s      nasd_edrfs_infopage_t;
typedef struct nasd_edrfs_lookupstuff_s   nasd_edrfs_lookupstuff_t;
typedef struct nasd_edrfs_objhash_s       nasd_edrfs_objhash_t;
typedef struct nasd_edrfs_setattrpair_s   nasd_edrfs_setattrpair_t;

#define NASD_EDRFS_NAMEHASH_BUCKETS 127

#if 1
#define NASD_EDRFS_OBJHASH_BUCKETS  127
#define nasd_edrfs_obj_hash(_nid_) NASD_ABS((int)((_nid_)%NASD_EDRFS_OBJHASH_BUCKETS))
#else
#define NASD_EDRFS_OBJHASH_BUCKETS  129
#define nasd_edrfs_obj_hash(_nid_) \
  (NASD_ABS(((((unsigned long)(_nid_))&0xfe00000000000000UL)>>57)|((((unsigned long)(_nid_))&0xffffffffUL)<<7))%NASD_EDRFS_OBJHASH_BUCKETS)
#endif

#define NASD_EDRFS_DIHASH_BUCKETS    16
#define NASD_EDRFS_DIHASH(_di_) ((_di_)&0xf)

#define NASD_EDRFS_MEMLIST_LEN 8

struct nasd_edrfs_drive_s {
  nasd_drive_handle_t      handle;
  int                      partnum;
  char                     drname[NASD_EDRFS_DRIVENAME_LEN];
  char                     pname[NASD_EDRFS_DRPATH_LEN];
  nasd_disk_ident_t        di;
  nasd_int32               portnum;
  nasd_uint32              net_addr;
  nasd_uint64              blocksize;
  nasd_edrfs_core_dir_t   *root;
  nasd_edrfs_drive_t      *next;
  nasd_edrfs_drive_t      *dinext; /* for dihash */
};

struct nasd_edrfs_diskdirent_s {
  char                        name[NASD_EDRFS_MAX_NAME_LEN];
  int                         slot;
  nasd_edrfs_core_dirpage_t  *page;
  nasd_edrfs_dirdata_t       *data;
  nasd_edrfs_attr_t          *attr;
  nasd_edrfs_core_dir_t      *dir;
  nasd_edrfs_diskdirent_t    *hnext;
  nasd_edrfs_diskdirent_t    *hprev;
  nasd_edrfs_diskdirent_t    *ihnext;
  nasd_edrfs_diskdirent_t    *ihprev;
};

struct nasd_edrfs_core_dir_s {
  nasd_identifier_t           nid;
  nasd_disk_ident_t           di;
  nasd_cookie_t               cookie;
  int                         refcnt;
  int                         deleted;
  int                         nentries;
  nasd_edrfs_drive_t         *drive;
  nasd_edrfs_core_dir_t      *lnext;
  nasd_edrfs_core_dir_t      *lprev;
  nasd_edrfs_core_dir_t      *dnext;
  nasd_edrfs_core_dir_t      *dprev;
  nasd_edrfs_core_dir_t      *hnext;
  nasd_edrfs_core_dir_t      *hprev;
  nasd_edrfs_attr_t          *attr;
  int                         isroot;
  NASD_DECLARE_MUTEX(lock)
  NASD_DECLARE_COND(cond)
  int                         busy;
  int                         ndirty;
  int                         npages;
  nasd_timespec_t             dirty_time;
  nasd_edrfs_diskdirent_t    *buckets[NASD_EDRFS_NAMEHASH_BUCKETS];
  nasd_edrfs_diskdirent_t    *idbuckets[NASD_EDRFS_OBJHASH_BUCKETS];
  nasd_edrfs_core_dirpage_t  *first_page;
  nasd_edrfs_core_dirpage_t  *last_page;
  int                         visited; /* debugging */
};

struct nasd_edrfs_core_dirpage_s {
  int                         dirty;
  nasd_offset_t               offset;
  nasd_edrfs_dirpage_t       *page;
  char                        raw_page[NASD_EDRFS_DIRPAGE_SIZE];
  nasd_edrfs_core_dirpage_t  *next;
  nasd_edrfs_core_dirpage_t  *prev;
};

struct nasd_edrfs_attr_s {
  nasd_p_getattr_dr_res_t     attr_res;
  nasd_edrfs_attributes_t     edrfsattr;
  int                         refcnt;
  nasd_edrfs_attr_t          *next;
};

#define NASD_EDRFS_ATTR_ATTR(_a_) ((_a_)->attr_res.out_attribute)

#if NASD_EDRFS_KEEP_CACHE_STATS > 0
#define NASD_EDRFS_CSINC(_stat_) \
  NASD_ATOMIC_INC64(&nasd_edrfs_cache_stats._stat_)
#endif /* NASD_EDRFS_KEEP_CACHE_STATS > 0 */

extern nasd_shutdown_list_t *nasd_edrfs_shutdown;

struct nasd_edrfs_createpair_s {
  nasd_p_create_dr_args_t         args;
  nasd_p_create_dr_res_t          res;
  nasd_cl_p_otw_buf_t             otw_buf;
  nasd_p_create_dr_args_otw_t     args_otw;
  nasd_p_create_dr_res_otw_t      res_otw;
  nasd_edrfs_attributes_t         edrfsattr;
  nasd_edrfs_attributes_t         new_edrfsattr;
  nasd_edrfs_createpair_t        *next;
};

struct nasd_edrfs_setattrpair_s {
  nasd_p_setattr_dr_args_t         sa_args;  
  nasd_p_setattr_dr_res_t          sa_res;
  nasd_p_getattr_dr_res_t          ga_res;
  nasd_edrfs_attributes_t          out_edrfsattr;
  nasd_edrfs_attributes_t          in_edrfsattr;
  nasd_cl_p_otw_buf_t              otw_buf;
  nasd_p_setattr_dr_args_otw_t     sa_args_otw;
  nasd_p_setattr_dr_res_otw_t      sa_res_otw;
  nasd_edrfs_setattrpair_t        *next;
};

struct nasd_edrfs_infopage_s {
  nasd_info_page_t        info_page;
  nasd_edrfs_infopage_t  *next;
};

struct nasd_edrfs_lookupstuff_s {
  nasd_edrfs_lookup_args_t   in_args;
  nasd_edrfs_lookup_res_t    out_res;
  nasd_edrfs_lookupstuff_t  *next;
};

NASD_DECLARE_EXTERN_MUTEX(nasd_edrfs_dircache_lock)

#define NASD_EDRFS_LOCK_DIRCACHE()   NASD_LOCK_MUTEX(nasd_edrfs_dircache_lock)
#define NASD_EDRFS_UNLOCK_DIRCACHE() NASD_UNLOCK_MUTEX(nasd_edrfs_dircache_lock)

#define NASD_EDRFS_LOCK_DIR(_d_,_dircache_lock_held_) { \
  if (_dircache_lock_held_ == 0) { \
    NASD_EDRFS_LOCK_DIRCACHE(); \
  } \
  NASD_LOCK_MUTEX((_d_)->lock); \
  if (_dircache_lock_held_ == 0) { \
    NASD_EDRFS_UNLOCK_DIRCACHE(); \
  } \
}

#define NASD_EDRFS_UNLOCK_DIR(_d_) { \
  NASD_UNLOCK_MUTEX((_d_)->lock); \
}

#if 0
#define nasd_edrfs_server_dir_hash_check(_verbose_) _nasd_edrfs_server_dir_hash_check(_verbose_)
#else
#define nasd_edrfs_server_dir_hash_check(_verbose_)
#endif

/*
 * from edrfs_core.c
 */
nasd_status_t nasd_edrfs_really_shutdown(void);
void nsad_edrfs_shutdown_timeoutsys(void *ignored);
nasd_status_t nasd_edrfs_init(void);
nasd_edrfs_createpair_t *nasd_edrfs_get_createpair(void);
void nasd_edrfs_free_createpair(nasd_edrfs_createpair_t *cp);
nasd_status_t nasd_edrfs_createpair_init(void);
void nasd_edrfs_createpair_shutdown(void *ignored);
nasd_edrfs_setattrpair_t *nasd_edrfs_get_setattrpair(void);
void nasd_edrfs_free_setattrpair(nasd_edrfs_setattrpair_t *cp);
nasd_status_t nasd_edrfs_setattrpair_init(void);
void nasd_edrfs_setattrpair_shutdown(void *ignored);
nasd_edrfs_infopage_t *nasd_edrfs_get_infopage(void);
void nasd_edrfs_free_infopage(nasd_edrfs_infopage_t *cp);
nasd_status_t nasd_edrfs_infopage_init(void);
void nasd_edrfs_infopage_shutdown(void *ignored);
nasd_edrfs_lookupstuff_t *nasd_edrfs_get_lookupstuff(void);
void nasd_edrfs_free_lookupstuff(nasd_edrfs_lookupstuff_t *cp);
nasd_status_t nasd_edrfs_lookupstuff_init(void);
void nasd_edrfs_lookupstuff_shutdown(void *ignored);

/*
 * from edrfs_dir.c
 */
extern nasd_edrfs_core_dirpage_t *nasd_edrfs_free_dirpages;
extern int nasd_edrfs_num_free_dirpages;
void nasd_edrfs_server_dir_cleanup(void);
void nasd_edrfs_server_dir_hash_ins(nasd_edrfs_core_dir_t *cd);
void _nasd_edrfs_server_dir_hash_check(int verbose);
nasd_status_t nasd_edrfs_server_dir_hash_lookup(nasd_edrfs_identifier_t edrfs_id,
  int force_load, nasd_edrfs_core_dir_t **out_dirp,
  nasd_edrfs_attr_t **out_attrp);
void nasd_edrfs_server_dir_dirty_page(nasd_edrfs_core_dir_t *dir,
  nasd_edrfs_core_dirpage_t *cdp);
nasd_status_t nasd_edrfs_server_dir_add_entry(nasd_edrfs_core_dir_t *dir,
  char *name, nasd_identifier_t nasdid, int type,
  nasd_edrfs_diskdirent_t **dep);
void nasd_edrfs_server_dir_release(nasd_edrfs_core_dir_t *dir);
void nasd_edrfs_server_dir_release_post_attribute(nasd_edrfs_core_dir_t *cd,
  nasd_edrfs_identifier_t in_identifier,
  nasd_edrfs_post_attribute_t *post_attribute);
void nasd_edrfs_server_dir_writer_loop(void *arg);
void nasd_edrfs_server_dir_writer_shutdown(void *ignored);
nasd_status_t nasd_edrfs_server_dir_init(void);
void nasd_edrfs_dealloc_coredir(nasd_edrfs_core_dir_t *cd,
  int dircache_lock_held);
void nasd_edrfs_ditch_coredir(nasd_edrfs_core_dir_t *cd,
  int dircache_lock_held);
nasd_edrfs_core_dir_t *nasd_edrfs_server_dir_get_coredir(int dircache_lock_held);
void nasd_edrfs_server_dir_mk_freepages(int npages);
nasd_status_t nasd_edrfs_load_dir(nasd_edrfs_core_dir_t *cd);
void nasd_edrfs_post_attribute(nasd_edrfs_core_dir_t *cd,
  nasd_edrfs_identifier_t in_identifier,
  nasd_edrfs_post_attribute_t *post_attribute);
nasd_status_t nasd_edrfs_lookup_post_attribute(
  nasd_edrfs_identifier_t in_identifier,
  nasd_edrfs_post_attribute_t *post_attribute);
nasd_status_t nasd_edrfs_server_dir_markerv(nasd_edrfs_core_dir_t *dir,
  nasd_edrfs_markerv_t *mvp);
nasd_status_t nasd_edrfs_server_dir_remove_entry(nasd_edrfs_core_dir_t *dir,
  nasd_edrfs_diskdirent_t *de);

/*
 * from edrfs_drive.c
 */
nasd_status_t nasd_edrfs_drsys_init(void);
nasd_status_t nasd_edrfs_mark_dirs_clean(void);
void nasd_edrfs_shutdown_drives(void);
nasd_status_t nasd_edrfs_add_mount(char *path, char *drive,
  char *drive_bind_name, int portnum, int partnum, nasd_uint32 net_addr);
nasd_status_t nasd_edrfs_mount_lookup(char *dirpath,
  nasd_list_len_t in_listlen, nasd_net_address_t out_drivelist[],
  nasd_list_len_t *out_listlen, nasd_edrfs_identifier_t *out_identifier);
nasd_status_t nasd_edrfs_server_dir_write_dirty(nasd_edrfs_core_dir_t *dir);
nasd_status_t nasd_edrfs_server_dir_load_attr(nasd_edrfs_core_dir_t *dir);
nasd_status_t nasd_edrfs_do_getattr(nasd_edrfs_drive_t *dr,
  nasd_identifier_t nasdid, nasd_p_getattr_dr_res_t *ga_res);
nasd_status_t nasd_edrfs_do_setattr(nasd_edrfs_drive_t *dr,
  nasd_p_setattr_dr_args_t *args, nasd_p_setattr_dr_res_t *res,
  nasd_cl_p_otw_buf_t *otw);
nasd_status_t nasd_edrfs_get_drive(nasd_edrfs_identifier_t in_identifier,
  nasd_edrfs_drive_t **drp);
nasd_status_t nasd_edrfs_do_create(nasd_edrfs_drive_t *dr,
  nasd_p_create_dr_args_t *cr_args, nasd_p_create_dr_res_t *cr_res,
  nasd_cl_p_otw_buf_t *otw);
nasd_status_t nasd_edrfs_do_remove(nasd_edrfs_drive_t *dr,
  nasd_identifier_t nasdid);

/*
 * from edrfs_name.c
 */
int nasd_edrfs_name_hash(char *str);
void nasd_edrfs_name_shutdown_freelist(void *arg);
void nasd_edrfs_attr_shutdown_freelist(void *arg);
nasd_status_t nasd_edrfs_name_init(void);
void nasd_edrfs_name_cleandir(nasd_edrfs_core_dir_t *dir);
nasd_status_t nasd_edrfs_name_hash_ins(nasd_edrfs_core_dir_t *dir,
  nasd_edrfs_diskdirent_t *de);
nasd_edrfs_diskdirent_t *nasd_edrfs_name_add(nasd_edrfs_core_dir_t *dir,
  nasd_edrfs_core_dirpage_t *page, int slot);
nasd_edrfs_diskdirent_t *nasd_edrfs_name_lookup(nasd_edrfs_core_dir_t *dir,
  char *name);
nasd_status_t nasd_edrfs_name_remove(nasd_edrfs_core_dir_t *dir,
  nasd_edrfs_diskdirent_t *de, int unhash_only);
nasd_edrfs_attr_t *nasd_edrfs_get_attr(void);
void nasd_edrfs_release_attr(nasd_edrfs_attr_t *attr);
void nasd_edrfs_debug_name_cache(nasd_edrfs_core_dir_t *dir);
nasd_status_t nasd_edrfs_valid_name(char *name);

/*
 * from edrfs_ops.c
 */
extern nasd_edrfs_cachestats_t nasd_edrfs_cache_stats;
void nasd_edrfs_begin_rpc(nasd_opstat_t *opstat);
void nasd_edrfs_end_rpc(nasd_opstat_t *opstat);
void nasd_edrfs_wait_shutdown_rpc(void);
void nasd_edrfs_shutdown_rpc(void *arg);
nasd_status_t nasd_edrfs_rpc_init(void);
nasd_status_t nasd_edrfs_startup_rpc(void);
void nasd_edrfs_stop_rpc(void);
nasd_status_t nasd_edrfs_rpc_listen(int service_threads, nasd_uint16 ipport);
nasd_status_t nasd_edrfs_rpc_set_stacksize(int stacksize);

/*
 * frame stubs
 */
nasd_status_t nasd_edrfs_do_drive_bind(char *drive_name,
  nasd_drive_handle_t *dhp);

/*
 * rpc-specific
 */
nasd_status_t nasd_edrfs_rpc_specific_init(void);
void nasd_edrfs_rpc_specific_stop(void);
nasd_status_t nasd_edrfs_rpc_specific_startup(void);
nasd_status_t nasd_edrfs_rpc_specific_listen(int service_threads,
  nasd_uint16  ipport);
nasd_status_t nasd_edrfs_rpc_specific_set_stacksize(int stacksize);

/*
 * message queue RPC stuff
 */
extern int nasd_edrfs_mq_ignore_eexist;
extern nasd_threadgroup_t nasd_edrfs_mq_listener_tg;
extern int nasd_edrfs_mq_mqid;
extern int nasd_edrfs_mq_service_threads;

nasd_status_t nasd_edrfs_mq_specific_init(void);
nasd_status_t nasd_edrfs_mq_specific_startup(void);
void nasd_edrfs_mq_specific_stop(void);
void nasd_edrfs_mq_specific_listen_stop(void);
nasd_status_t nasd_edrfs_mq_specific_listen(int service_threads);
nasd_status_t nasd_edrfs_mq_specific_set_stacksize(int stacksize);
void nasd_edrfs_mq_listen(nasd_threadarg_t ignored);

#endif /* !_NASD__NASD_EDRFS_SERVER_INTERNAL_H_ */

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