/*
 * 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);
  void set_releasing_cb(callback<void,str,callback<void,void>::ref>::ptr cb);

private:
  int fd;
  ptr<axprt> x;
  ptr<aclnt> c;
  ptr<asrv> sxx;
  struct sockaddr_in server;
  callback<void, str, callback<void,void>::ref>::ptr releasing_cb;
  int last_id;

  struct lock 
  {
    lock(str xname) : name(xname) { }
    ihash_entry<lock> hlink;
    str name;
    bool acquired;
  };

  struct qitem 
  {
    qitem(str xname, callback<void>::ref xcb) : cb(xcb), name(xname) { }
    tailq_entry<qitem> llink;
    callback<void>::ref cb;
    str name;
    bool revoke;
    int id;
  };

  ihash<const str, lock, &lock::name, &lock::hlink> locks;
  tailq<qitem, &qitem::llink> queue;

  static void dispatch(lock_client *lc, svccb *sbp);
  void acquire_cb1(bool *r, clnt_stat err);
  void send_acquire(str name);
  void release_cb(bool *r, clnt_stat err);
  void really_release(str name);
  void call_releasing_cb(str name);
  void grant(svccb *sbp);
  void revoke(svccb *sbp);
  void process_lock_queue(str name);
  void dummy_cb();
  void print_lock_queue();
  void reacquire_lock_if_necessary(str name);
};


#endif lock_client_h

