//
// file server
// accepts NFS calls via dispatch()
// uses a class blockdb for storage
//

#ifndef FS_H
#define FS_H

#include "amisc.h"
#include "async.h"
#include "arpc.h"
#include "nfsserv.h"
#include "blockdbc.h"
#include "wmstr.h"

// #define FSLOCKS


class fs {
 public:
  fs(blockdbc *db);
  void dispatch(nfscall *);
  void new_root(char *fhname, callback<void, bool, nfs_fh3>::ref cb);
  static str fh2hex(nfs_fh3 fh);
  static nfs_fh3 hex2fh(str s);

 private:
  blockdbc *db;
  unsigned long long seq; // used to number new i-nodes &c
  static const int FHLEN = 8; // file handles are this many bytes long

  /*
   * Handler functions for incoming NFS RPCs
   */
  void nfs3_getattr(nfscall *nc);
  void nfs3_lookup(nfscall *nc);
  void nfs3_access(nfscall *nc);
  void nfs3_write(nfscall *nc);
  void nfs3_readdir(nfscall *nc);
  void nfs3_create(nfscall *nc);
  void nfs3_fsinfo(nfscall *nc);
  void nfs3_fsstat(nfscall *nc);
  void nfs3_read(nfscall *nc);
  void nfs3_setattr(nfscall *nc);
  void nfs3_remove(nfscall *nc);
  void nfs3_mkdir(nfscall *nc);

  /*
   * Call back functions needed to process NFS RPCs
   */
  void nfs3_getattr_cb(nfscall *nc, bool, fattr3);
  void nfs3_access_cb(nfscall *nc, bool, fattr3);
  void new_root_cb(nfs_fh3 fh, callback<void, bool, nfs_fh3>::ref cb, bool,
                   fattr3);

  /*
   * Utility functions
   */
  // Make up a (hopefully) unused filehandle into fh
  void new_fh(nfs_fh3 *fh);
  // Remove fh from block server
  void remove_fh(nfs_fh3 fh, callback<void, bool>::ref cb);
  // Put and get fattr3 for a filehandle
  void get_fh(nfs_fh3 fh, callback<void, bool, fattr3>::ref cb);
  void get_fh_cb(nfs_fh3, callback<void, bool, fattr3>::ref cb,
                 bool ok, str value);
  void put_fh(nfs_fh3 fh, fattr3 fa, callback<void, bool, fattr3>::ref cb);
  void put_fh_cb(callback<void, bool, fattr3>::ref cb, fattr3 fa, bool ok);
  void put_new_fh(nfs_fh3 fh, fattr3 fa, callback<void, bool, fattr3>::ref cb);

  uint64 fh2fileid(nfs_fh3 fh);
  wcc_data make_wcc(fattr3 before, fattr3 after);
  nfstime3 nfstime();
  nfs_fh3 s2fh(str s);
  str fh2s(nfs_fh3 fh);


};

#endif
