//
// Simple demonstration lock client.
// Just acquires a lock, sleeps a few seconds, and releases.
// This works fine even with a broken lock server.
//

#include "amisc.h"
#include "async.h"
#include "arpc.h"
#include "dns.h"
#include "lock_client.h"

static void
usage ()
{
  fprintf(stderr, "Usage: lock_demo lock-server-host lock-server-port\n");
  exit (1);
}

void
test3()
{
  exit(0);
}

// done sleeping, now release the lock.
// we cannot exit right away, since we might not be  done
// sending the release RPC to the lock server. so sleep
// again for a bit before exiting.
void
test2(lock_client *lc, str name)
{
  printf("Releasing the lock.\n");
  lc->release(name);
  delaycb(1, wrap(&test3));
}

// the server has granted the lock.
void
test1(lock_client *lc, str name)
{
  printf("Got the lock. Sleeping...\n");

  // delaycb() returns right away, but arranges to
  // call test2(lc, name) 5 seconds from now.
  delaycb(5, wrap(&test2, lc, name));
}

void
test(lock_client *lc)
{
  printf("Asking for the lock...\n");

  // acquire the lock named "thelock".
  // acquire() returns right away, but arranges to
  // call test1(lc, "thelock") when a grant RPC
  // arrives from the server.
  lc->acquire("thelock", wrap(&test1, lc, "thelock"));
}

// dns_hostbyname() has found lock server's host name.
void
got_bs(char *port, ptr<hostent> h, int err)
{
  if(!h || err != 0){
    fprintf(stderr, "could not resolve lock server host name\n");
    exit(1);
  }

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

  lock_client *lc = New lock_client(sin);

  test(lc);
}

int
main (int argc, char **argv)
{
  setprogname (argv[0]);
  if (argc != 3 || !isdigit(argv[2][0]))
    usage ();

  srandom(getpid());

  // translate lock server's host name to an IP address.
  // dns_hostbyname() returns right away, but arranges
  // to call got_bs(argv[2]) when it finds out the IP address.
  dns_hostbyname(argv[1],
                 wrap(&got_bs, argv[2]),
                 true, true);

  amain ();
}
