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


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

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

using namespace qdbm;



/*************************************************************************************************
 * Curia_error
 *************************************************************************************************/


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


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


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


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


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


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


bool Curia_error::operator==(const Curia_error &ce) const throw(){
  return ecode == ce.ecode;
}


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


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


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


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


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



/*************************************************************************************************
 * Curia
 *************************************************************************************************/


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


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


void Curia::remove(const char* name) throw(Curia_error){
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!crremove(name)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


Curia::Curia(const char* name, int omode, int bnum, int dnum) throw(Curia_error) : ADBM(){
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!(curia = cropen(name, omode, bnum, dnum))){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


Curia::~Curia() throw(){
  if(!curia) return;
  pthread_mutex_lock(&mutex);
  crclose(curia);
  pthread_mutex_unlock(&mutex);
  curia = 0;
}


void Curia::close() throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!crclose(curia)){
    curia = 0;
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  curia = 0;
}


void Curia::put(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode)
  throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!crput(curia, kbuf, ksiz, vbuf, vsiz, dmode)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


void Curia::out(const char* kbuf, int ksiz) throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!crout(curia, kbuf, ksiz)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


char* Curia::get(const char* kbuf, int ksiz, int start, int max, int* sp) throw(Curia_error){
  char* vbuf;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!(vbuf = crget(curia, kbuf, ksiz, start, max, sp))){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vbuf;
}


int Curia::vsiz(const char* kbuf, int ksiz) throw(Curia_error){
  int vsiz;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if((vsiz = crvsiz(curia, kbuf, ksiz)) == -1){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vsiz;
}


void Curia::iterinit() throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!criterinit(curia)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


char* Curia::iternext(int* sp) throw(Curia_error){
  char* vbuf;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!(vbuf = criternext(curia, sp))){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vbuf;
}


void Curia::setalign(int align) throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!crsetalign(curia, align)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


void Curia::sync() throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!crsync(curia)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


void Curia::optimize(int bnum) throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!croptimize(curia, bnum)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);

}


char* Curia::name() throw(Curia_error){
  char* buf;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!(buf = crname(curia))){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return buf;
}


int Curia::fsiz() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crfsiz(curia);
  pthread_mutex_unlock(&mutex);
  return rv;
}


int Curia::bnum() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crbnum(curia);
  pthread_mutex_unlock(&mutex);
  return rv;
}


int Curia::busenum() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crbusenum(curia);
  pthread_mutex_unlock(&mutex);
  return rv;
}


int Curia::rnum() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crrnum(curia);
  pthread_mutex_unlock(&mutex);
  return rv;
}


bool Curia::writable() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crwritable(curia);
  pthread_mutex_unlock(&mutex);
  return rv ? true : false;
}


bool Curia::fatalerror() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crfatalerror(curia);
  pthread_mutex_unlock(&mutex);
  return rv ? true : false;
}


int Curia::inode() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crinode(curia);
  pthread_mutex_unlock(&mutex);
  return rv;
}


void Curia::putlob(const char* kbuf, int ksiz, const char* vbuf, int vsiz, int dmode)
  throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, dmode)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


void Curia::outlob(const char* kbuf, int ksiz) throw(Curia_error){
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!croutlob(curia, kbuf, ksiz)){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
}


char* Curia::getlob(const char* kbuf, int ksiz, int start, int max, int* sp) throw(Curia_error){
  char* vbuf;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if(!(vbuf = crgetlob(curia, kbuf, ksiz, start, max, sp))){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vbuf;
}


int Curia::vsizlob(const char* kbuf, int ksiz) throw(Curia_error){
  int vsiz;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  if((vsiz = crvsizlob(curia, kbuf, ksiz)) == -1){
    pthread_mutex_unlock(&mutex);
    throw Curia_error(dpecode);
  }
  pthread_mutex_unlock(&mutex);
  return vsiz;
}


int Curia::rnumlob() throw(Curia_error){
  int rv;
  if(!curia) throw Curia_error();
  if(pthread_mutex_lock(&mutex) != 0) throw Curia_error();
  rv = crrnumlob(curia);
  pthread_mutex_unlock(&mutex);
  return rv;
}


void Curia::storerec(const Datum& key, const Datum& val, bool replace) throw(Curia_error){
  put(key.ptr(), key.size(), val.ptr(), val.size(), replace ? CR_DOVER : CR_DKEEP);
}


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


Datum* Curia::fetchrec(const Datum& key) throw(Curia_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* Curia::firstkey() throw(Curia_error){
  iterinit();
  return nextkey();
}


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


bool Curia::error() throw(Curia_error){
  return fatalerror();
}


void Curia::clearerror() throw(Curia_error){
  if(!curia) throw Curia_error();
}


Curia::Curia(const Curia& curia) throw(Curia_error){
  throw Curia_error();
}


Curia& Curia::operator=(const Curia& curia) throw(Curia_error){
  throw Curia_error();
}



/* END OF FILE */
