/**
Copyright 2000 - 2003 LogicMatrix. All rights reserved.
This software is distributed under the LogicMatrix Free Software License. This software may be used for any purpose, personal or commercial. Redistributions in binary /source code form are permitted. Commercial redistribution of larger works derived from, or works which bundle this software requires a "Commercial Redistribution License" which can be purchased from LogicMatrix. Contact LogicMatrix for details
Redistributions qualify as Free and non-commercial under one of the following terms:
1) Redistributions are made at no charge beyond the reasonable cost of materials and delivery.
2) Redistributions in binary/source code form must reproduce this Copyright Notice,these license terms, and the disclaimer/limitation of liability set forth as below, in the documentation and/or other materials
provided with the distribution.
Disclaimer
==========
The Software is provided on an "AS IS" basis. No warranty is
provided that the Software is free of defects, or fit for a
particular purpose.
Limitation of Liability
=======================
LogicMatrix shall not be liable for any damages suffered by the Licensee or any third party resulting from use of the Software.
**/
/**
bdb_index.cpp
Purpose: provide an interface to BerkleyDB indexings services
Author: Vijay Mathew Pandyalakal
Date: 15/11/2003
Copyright: logicmatrix
**/
#include <string>
#include <vector>
using namespace std;
#include "db_cxx.h" // berkley db
#include "mydate.h"
using namespace openutils;
#include "dsql_m_structs.h"
#include "text.h"
#include "bdb_index.h"
using namespace dsqlm;
BdbIndex::BdbIndex(const char* db_name,bool unique) {
if(strlen(db_name) > 80) {
throw DsqlMException("Index file name too long");
}
strcpy(this->db_name,db_name);
this->unique = unique;
}
void BdbIndex::put(const char* key_str,const char* data_str) {
open();
int ret = 0;
Dbt key((char*)key_str, strlen(key_str));
Dbt data((char*)data_str, strlen(data_str));
char err_buff[101];
if(unique) {
ret = db->put(0, &key, &data, DB_NOOVERWRITE);
}else {
ret = db->put(0, &key, &data, 0);
}
if (ret == DB_KEYEXIST) {
sprintf(err_buff,"Duplicate entry in %s",db_name);
close();
throw DsqlMException(err_buff);
}else if(ret != 0) {
sprintf(err_buff,"Indexing failed in %s",db_name);
close();
throw DsqlMException(err_buff);
}
close();
}
void BdbIndex::get(const char* key_str) {
vct_datum.clear();
vct_keys.clear();
open();
int ret = 0;
// char err_buff[101];
Dbc *dbcp;
db->cursor(NULL, &dbcp, 0);
Dbt key_search((char*)key_str,strlen(key_str));
Dbt data_search;
key_search.set_ulen(0);
data_search.set_ulen(0);
if(dbcp->get(&key_search, &data_search, DB_SET) == 0) {
int sz = data_search.get_size();
char* data_string = new char[sz+1];
for(int i=0;i<sz;i++) {
data_string[i] = ((char*)(data_search.get_data()))[i];
}
data_string[i] = '\0';
long l = atol(data_string);
vct_datum.push_back(l);
delete[] data_string;
sz = key_search.get_size();
char* key_string = new char[sz+1];
for(i=0;i<sz;i++) {
key_string[i] = ((char*)(key_search.get_data()))[i];
}
key_string[i] = '\0';
string ks = key_string;
vct_keys.push_back(ks);
delete[] key_string;
if(!unique) {
while((dbcp->get(&key_search, &data_search, DB_NEXT_DUP)) == 0) {
sz = data_search.get_size();
data_string = new char[sz+1];
for(int i=0;i<sz;i++) {
data_string[i] = ((char*)(data_search.get_data()))[i];
}
data_string[i] = '\0';
l = atol(data_string);
vct_datum.push_back(l);
delete[] data_string;
sz = key_search.get_size();
char* key_string = new char[sz+1];
for(i=0;i<sz;i++) {
key_string[i] = ((char*)(key_search.get_data()))[i];
}
key_string[i] = '\0';
string ks = key_string;
vct_keys.push_back(ks);
delete[] key_string;
}
}
}
dbcp->close();
close();
}
void BdbIndex::getAll() {
open();
vct_keys.clear();
vct_datum.clear();
int ret = 0;
// char err_buff[101];
Dbc *dbcp;
db->cursor(NULL, &dbcp, 0);
Dbt key_search;
Dbt data_search;
key_search.set_ulen(0);
data_search.set_ulen(0);
while(dbcp->get(&key_search, &data_search, DB_NEXT) == 0) {
int sz = key_search.get_size();
char* key_string = new char[sz+1];
int i = 0;
for(i=0;i<sz;i++) {
key_string[i] = ((char*)(key_search.get_data()))[i];
}
key_string[i] = '\0';
sz = data_search.get_size();
char* data_string = new char[sz+1];
for(i=0;i<sz;i++) {
data_string[i] = ((char*)(data_search.get_data()))[i];
}
data_string[i] = '\0';
string ks = key_string;
string ds = data_string;
vct_keys.push_back(ks);
vct_datum.push_back(atol(ds.c_str()));
delete[] key_string;
delete[] data_string;
}
dbcp->close();
close();
}
long BdbIndex::getCursorSize() {
return (long)vct_datum.size();
}
string BdbIndex::getKey(long idx) {
if(idx < 0 || idx >= vct_keys.size()) {
throw DsqlMException("Invalid index");
}
return vct_keys[idx];
}
long BdbIndex::getData(long idx) {
if(idx < 0 || idx >= vct_datum.size()) {
throw DsqlMException("Invalid index");
}
return vct_datum[idx];
}
void BdbIndex::del(const char* key_str) {
int ret = 0;
open();
Text text;
string s = key_str;
s = text.trim(s);
// char err_buff[101];
Dbc *dbcp;
db->cursor(NULL, &dbcp, 0);
Dbt key_search((char*)s.c_str(),strlen(s.c_str()));
Dbt data_search;
if(dbcp->get(&key_search, &data_search, DB_SET) == 0) {
dbcp->del(0);
if(!unique) {
while((dbcp->get(&key_search, &data_search, DB_NEXT_DUP)) == 0) {
dbcp->del(0);
}
}
}
dbcp->close();
close();
}
void BdbIndex::del(const char* key_str,const char* data_str) {
int ret = 0;
open();
// char err_buff[101];
string s = key_str;
Text text;
s = text.trim(s);
Dbc *dbcp;
db->cursor(NULL, &dbcp, 0);
Dbt key_search((char*)s.c_str(),strlen(s.c_str()));
Dbt data_search((char*)data_str,strlen(data_str));
if(dbcp->get(&key_search, &data_search, DB_GET_BOTH) == 0) {
ret = dbcp->del(0);
}
dbcp->close();
close();
}
BdbIndex::~BdbIndex() {
close();
}
void BdbIndex::walkThru() {
/** debug **/
open();
int ret = 0;
char err_buff[101];
Dbc *dbcp;
db->cursor(NULL, &dbcp, 0);
Dbt key_search;
Dbt data_search;
//key_search.set_flags(DB_DBT_USERMEM);
key_search.set_ulen(0);
data_search.set_ulen(0);
while(dbcp->get(&key_search, &data_search, DB_NEXT) == 0) {
int sz = key_search.get_size();
char* key_string = new char[sz+1];
int i = 0;
for(i=0;i<sz;i++) {
key_string[i] = ((char*)(key_search.get_data()))[i];
}
key_string[i] = '\0';
sz = data_search.get_size();
char* data_string = new char[sz+1];
for(i=0;i<sz;i++) {
data_string[i] = ((char*)(data_search.get_data()))[i];
}
data_string[i] = '\0';
printf("%s:%s\n",key_string,data_string);
delete[] key_string;
delete[] data_string;
}
dbcp->close();
close();
/** end of debug **/
}
void BdbIndex::open() {
int ret = 0;
char err_buff[101];
db = new Db(0, 0);
db->set_pagesize(1024); /* Page size: 1K. */
db->set_cachesize(0, 32 * 1024, 0);
if(!unique) {
db->set_flags(DB_DUPSORT);
}
db->open(NULL, db_name, NULL, DB_BTREE, DB_CREATE, 0664);
}
void BdbIndex::close() {
if(db != 0) {
try {
db->close(0);
delete db;
}catch(...) { }
}
}