/* $Id: ccfs.C,v 1.3 2005/02/07 16:55:36 rtm Exp $ */

#include "amisc.h"
#include "async.h"
#include "arpc.h"
#include "dns.h"
#include "nfsserv.h"
#include "classfscli.h"
#include "blockdbc.h"
#include "fs.h"
#include "fsutil.h"

#define NAMESPACE "foo"

fs * g_fs;

static void
mounted (nfs_fh3 fh, int err)
{
  if(err == 0){
    printf("root file handle: %s\n",
           fsutil::fh2hex(fh).cstr());
    fflush(stdout);
  } else {
    fatal << "classfsd reports: " << strerror (err) << "\n";
  }
}

static void
usage ()
{
  fprintf(stderr, "Usage: ccfs dir-name blockdb-host blockdb-port [root-file-handle]\n");
  exit (1);
}

void
test_callback(bool ret)
{
  warn << "test: " << (ret ? "success\n" : "failure\n");
}


static void
got_root(str mntname, nfsserv_udp *nu, bool ok, nfs_fh3 fh)
{
  if(ok){
//     g_fs->test_dir(fh, wrap(test_callback));
    classmount (nu->getfd (), fh.data, mntname, wrap (mounted, fh));
  } else {
    fprintf(stderr, "ccfs: got_root failed\n");
    exit(1);
  }
}

// ask classfsd to make us an NFS server
ptr<nfsserv_udp> nfss_udp = New refcounted<nfsserv_udp>;
ptr<nfsserv_fixup> nfss = New refcounted<nfsserv_fixup> (nfss_udp);

// just lookup up block server's host name
void
got_bs(char *dirname, char *blockport, char *roothandle,
       ptr<hostent> h, int err)
{
  if(!h || err != 0){
    fprintf(stderr, "could not resolve block server host name\n");
    exit(1);
  }

  struct sockaddr_in sin;
  bzero(&sin, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_port = htons(atoi(blockport));
  sin.sin_addr = *(in_addr*)h->h_addr;

  // attach to the block server
  ref<tagged_blockdbc> db = New refcounted<tagged_blockdbc>(sin, NAMESPACE);
  // db->test();

  // attach to the block server
  ref<lock_client> lc = New refcounted<lock_client>(sin);

  // create a file server object
  fs *f = New fs(db, lc);
  g_fs = f;
  
  // get hold of NFS RPCs from classfs file system
  nfss->setcb (wrap (f, &fs::dispatch));

  // ask file server to create a new file system,
  // then once we know the root file handle,
  // tell classfsd about it.
  f->new_root(roothandle,
              wrap(got_root, dirname, nfss_udp));

#if 0
  lc->test();
#endif
}

int
main (int argc, char **argv)
{
  setprogname (argv[0]);
  if (argc != 4 && argc != 5)
    usage ();
  for(int i = 0; argv[3][i] != '\0'; i++)
    if(!isdigit(argv[3][i]))
      usage();

  srandom(getpid());

  // look up block server's host name
  dns_hostbyname(argv[2],
                 wrap(&got_bs, argv[1], argv[3], argc==5?argv[4]:0),
                 true, true);

  amain ();
}
