/*******************************************
 * Copyright(c) 2000-2003 Mikio Hirabayashi
 *******************************************/


#include "xdepot.h"
#include <new>
#include <cstdlib>

extern "C" {
#include <pthread.h>
}

using namespace qdbm;



/*************************************************************************************************
 * Depot_error
 *************************************************************************************************/


Depot_error::Depot_error() throw() : DBM_error(){
  this->ecode = DP_EMISC;
}


Depot_error::Depot_error(int ecode) throw() : DBM_error(){
  this->ecode = ecode;
}


Depot_error::Depot_error(const Depot_error& de) throw() : DBM_error(de){
  this->ecode = de.ecode;
}


Depot_error::~Depot_error() throw(){
  return;
}


Depot_error& Depot_error::operator=(const Depot_error& de) throw(){
  this->ecode = de.ecode;
  return *this;
}


Depot_error& Depot_error::operator=(int ecode) throw(){
  this->ecode = ecode;
  return *this;
}


bool Depot_error::operator==(const Depot_error &de) const throw(){
  return ecode == de.ecode;
}


bool Depot_error::operator!=(const Depot_error &de) const throw(){
  return ecode != de.ecode;
}


bool Depot_error::operator==(int ecode) const throw(){
  return this->ecode == ecode;
}


bool Depot_error::operator!=(int ecode) const throw(){
  return this->ecode != ecode;
}


int Depot_error::code() const throw(){
  return ecode;
}


const char* Depot_error::message() const throw(){
  return dperrmsg(ecode);
}



/*************************************************************************************************
 * Depot
 *************************************************************************************************/


namespace {
  pthread_mutex_t mutex;
  class Init {
  public:
    Init(){
      pthread_mutex_init(&mutex, NULL);
    }
    ~Init(){
      pthread_mutex_destroy(&mutex);
    }
  };
  Init init;
}


const char* Depot::version() throw(){
  return dpversion;
}


void Depot::remove(const char* name) throw(Depot_error){
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpremove(name)){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


Depot::Depot(const char* name, int omode, int bnum) throw(Depot_error) : ADBM(){
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!(depot = dpopen(name, omode, bnum))){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


Depot::~Depot() throw(){
  if(!depot) return;
  pthread_mutex_lock(&mutex);
  dpclose(depot);
  pthread_mutex_unlock(&mutex);
  depot = 0;
}


void Depot::close() throw(Depot_error){
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpclose(depot)){
    depot = 0;
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  depot = 0;
}


void Depot::put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode)
  throw(Depot_error){
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpput(depot, kbuf, ksiz, vbuf, vsiz, dmode)){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


void Depot::out(const char* kbuf, int ksiz) throw(Depot_error){
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpout(depot, kbuf, ksiz)){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


char* Depot::get(const char* kbuf, int ksiz, int start, int max, int* sp) throw(Depot_error){
  char* vbuf;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!(vbuf = dpget(depot, kbuf, ksiz, start, max, sp))){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vbuf;
}


int Depot::vsiz(const char* kbuf, int ksiz) throw(Depot_error){
  int vsiz;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if((vsiz = dpvsiz(depot, kbuf, ksiz)) == -1){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vsiz;
}


void Depot::iterinit() throw(Depot_error){
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpiterinit(depot)){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


char* Depot::iternext(int* sp) throw(Depot_error){
  char* vbuf;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!(vbuf = dpiternext(depot, sp))){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vbuf;
}


void Depot::setalign(int align) throw(Depot_error){
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpsetalign(depot, align)){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


void Depot::sync() throw(Depot_error){
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpsync(depot)){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


void Depot::optimize(int bnum) throw(Depot_error){
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!dpoptimize(depot, bnum)){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


char* Depot::name() throw(Depot_error){
  char* buf;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  if(!(buf = dpname(depot))){
    pthread_mutex_unlock(&mutex);
    throw Depot_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return buf;
}


int Depot::fsiz() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dpfsiz(depot);
  pthread_mutex_unlock(&mutex);
  return rv;
}


int Depot::bnum() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dpbnum(depot);
  pthread_mutex_unlock(&mutex);
  return rv;
}


int Depot::busenum() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dpbusenum(depot);
  pthread_mutex_unlock(&mutex);
  return rv;
}


int Depot::rnum() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dprnum(depot);
  pthread_mutex_unlock(&mutex);
  return rv;
}


bool Depot::writable() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dpwritable(depot);
  pthread_mutex_unlock(&mutex);
  return rv ? true : false;
}


bool Depot::fatalerror() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dpfatalerror(depot);
  pthread_mutex_unlock(&mutex);
  return rv ? true : false;
}


int Depot::inode() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dpinode(depot);
  pthread_mutex_unlock(&mutex);
  return rv;
}


int Depot::fdesc() throw(Depot_error){
  int rv;
  if(!depot) throw Depot_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Depot_error();
  rv = dpfdesc(depot);
  pthread_mutex_unlock(&mutex);
  return rv;
}


void Depot::storerec(const Datum& key, const Datum& val, bool replace) throw(Depot_error){
  put(key.ptr(), key.size(), val.ptr(), val.size(), replace ? DP_DOVER : DP_DKEEP);
}


void Depot::deleterec(const Datum& key) throw(Depot_error){
  out(key.ptr(), key.size());
}


Datum* Depot::fetchrec(const Datum& key) throw(Depot_error){
  char* vbuf;
  int vsiz;
  Datum* res = new Datum();
  vbuf = get(key.ptr(), key.size(), 0, -1, &vsiz);
  res->cjack(vbuf, vsiz);
  return res;
}


Datum* Depot::firstkey() throw(Depot_error){
  iterinit();
  return nextkey();
}


Datum* Depot::nextkey() throw(Depot_error){
  char* kbuf;
  int ksiz;
  Datum* res = new Datum();
  kbuf = iternext(&ksiz);
  res->cjack(kbuf, ksiz);
  return res;
}


bool Depot::error() throw(Depot_error){
  return fatalerror();
}


void Depot::clearerror() throw(Depot_error){
  if(!depot) throw Depot_error();
}


Depot::Depot(const Depot& depot) throw(Depot_error){
  throw Depot_error();
}


Depot& Depot::operator=(const Depot& depot) throw(Depot_error){
  throw Depot_error();
}



/* END OF FILE */
