// extent client interface.

#ifndef extent_client_h
#define extent_client_h

#include <string>
#include "extent_protocol.h"
#include "rpc.h"

typedef struct data_unit {
	std::string  buf;
	bool dirty;
};

typedef struct attr_unit {
	extent_protocol::attr attr;
	bool dirty;
};

class extent_client {
 private:
  rpcc cl;
  struct sockaddr_in dst;

	//the two caches
	std::map<extent_protocol::extentid_t, data_unit *> * data_cache; 
	std::map<extent_protocol::extentid_t, attr_unit *>  * attr_cache;

	std::list<extent_protocol::extentid_t> * remove_attr;
	std::list<extent_protocol::extentid_t> * remove_data;

	extent_protocol::status get_cache_data(extent_protocol::extentid_t eid, std::string & buf);
	extent_protocol::status get_cache_attr(extent_protocol::extentid_t eid, extent_protocol::attr & buf);
	extent_protocol::status put_cache_data(extent_protocol::extentid_t eid, std::string buf);
	extent_protocol::status put_cache_attr(extent_protocol::extentid_t eid, extent_protocol::attr buf);
	extent_protocol::status do_remove(extent_protocol::extentid_t eid);
	
	pthread_mutex_t cache_mutex;
	
	
	//REPAIR: get rid of the need to use these on client and server 
	int get_content_position(std::string full_value);
	std::string read_name(unsigned int start, std::string str, unsigned int & after);
	unsigned long long read_nr(unsigned int start, std::string str, unsigned int & after);

 public:
  extent_client(struct sockaddr_in dst);
  extent_protocol::status flush(extent_protocol::extentid_t eid);

  extent_protocol::status get(extent_protocol::extentid_t eid, 
			      std::string &buf);
  extent_protocol::status getattr(extent_protocol::extentid_t eid, 
				  extent_protocol::attr &a);
  extent_protocol::status setattr(extent_protocol::extentid_t eid, extent_protocol::attr &a);
  //put overwrites
  extent_protocol::status put(extent_protocol::extentid_t eid, std::string buf);
  extent_protocol::status remove(extent_protocol::extentid_t eid);
  extent_protocol::status print_map();

};

#endif 

