/*
 * client-side RPC API for lock_server.
 */

#ifndef lock_client_h
#define lock_client_h 1

#include "amisc.h"
#include "async.h"
#include "arpc.h"
#include "list.h"
#include "ihash.h"
#include "lock_proto.h"

class lock_client {
public:
  lock_client(struct sockaddr_in sin);
  void acquire(str name, callback<void>::ref cb);
  void release(str name);

private:
  int fd;
  ptr<axprt> x;
  ptr<aclnt> c;
  ptr<asrv> sxx;
  struct sockaddr_in server;

  // remember the locks we're holding.
  struct lock {
    lock(str xname) : name(xname) { }
    ihash_entry<lock> hlink;
    str name;
  };
  ihash<const str, lock, &lock::name, &lock::hlink> locks;

  // list of callbacks waiting to acquire locks.
  struct qitem {
    qitem(str xname, callback<void>::ref xcb) : cb(xcb), name(xname) { }
    list_entry<qitem> llink;
    callback<void>::ref cb;
    str name;
  };
  list<qitem, &qitem::llink> queue;

  void acquire_cb1(bool *r, clnt_stat err);
  static void dispatch(lock_client *, svccb *);
  void grant(svccb *sbp);
  void release_cb(bool *r, clnt_stat err);
  void send_acquire(str name);
  void really_release(str name);
  str hex(str);
};

#endif lock_client_h
