File:  [parser3project] / parser3 / src / include / Attic / pa_db_connection.h
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Wed Oct 24 09:03:42 2001 UTC (24 years, 8 months ago) by parser
Branches: MAIN
CVS tags: HEAD
hashfile pieced serialize. todo stamp

/** @file
	Parser: sql db decl.

	Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
	Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)

	$Id: pa_db_connection.h,v 1.4 2001/10/24 09:03:42 parser Exp $
*/

#ifndef PA_DB_CONNECTION_H
#define PA_DB_CONNECTION_H

#include "pa_config_includes.h"
#include "pa_pool.h"
#include "pa_db_manager.h"
#include "pa_globals.h"

#ifdef HAVE_DB_H
#	include <db.h>
#endif

// defines

#define PA_DB_ACCESS_METHOD DB_BTREE

// forwards

class Auto_transaction;
class DB_Cursor;

// class

/// DB connection. handy wrapper around low level <db.h> calls
class DB_Connection : public Pooled {
	friend Auto_transaction;
	friend DB_Cursor;
public:

	DB_Connection(Pool& pool, const String& afile_spec, DB_ENV& adbenv);
	
	//const String& url() { return ffile_spec; }

	void set_services(Pool *aservices_pool) {
		time_used=time(0); // they started to use at this time
		fservices_pool=aservices_pool;
	}
	bool expired(time_t older_dies) {
		return time_used<older_dies;
	}

	void close() {
		DB_manager->close_connection(ffile_spec, *this);
	}

	bool connected() { return db!=0; }
	void connect();
	void disconnect();	
	bool ping() { return !needs_recovery; }

	void put(const String& key, const String& data);
	String *get(const String& key);
	void _delete(const String& key);

	DB_Cursor cursor(const String *source);

private:

	DB_ENV& fdbenv;
	const String& ffile_spec; const char *file_spec_cstr;
	Pool *fservices_pool;
	DB *db;
	bool needs_recovery;
	DB_TXN *ftid;
	time_t time_used;

private: // transaction

	/// commits current transaction, restores previous transaction handle
	void commit_restore(DB_TXN *atid) { 
		if(ftid)
			check("txn_commit", &ffile_spec, txn_commit(ftid)); 

		ftid=atid;
	}
	
	/// rolls current transaction back, restores previous transaction handle
	void rollback_restore(DB_TXN *atid) {
		if(ftid)
			check("txn_abort", &ffile_spec, txn_abort(ftid));

		ftid=atid;
	}
	
	/// stars new current trunsaction @returns previous transaction handle
	DB_TXN *transaction_begin_save() {
		DB_TXN *result=ftid;
		check("txn_begin", &ffile_spec, ::txn_begin(fdbenv.tx_info, 0/*parent*/, &ftid));

		return result;
	}
	
private:

	void check(const char *operation, const String *source, int error);
	void *malloc(size_t size) { return fservices_pool->malloc(size); }
	void *calloc(size_t size) { return fservices_pool->calloc(size); }
	/// pass empty dbt, would fill it from string
	void key_string_to_dbt(const String& key_string, DBT& key_result);
	/// pass empty dbt, would fill it from string
	void key_dbt_to_string(const DBT& key_dbt, String& key_result);
	/// pass empty dbt, would fill it from string
	void data_string_to_dbt(const String& data_string, DBT& data_result);
	/// pass empty string, would fill it from dbt
	void data_dbt_to_string(const DBT& data_dbt, String& data_result);

};

///	Auto-object used for temporary changing DB_Connection::tid.
class Auto_transaction {
	DB_Connection& fconnection;
	bool marked_to_rollback;
	DB_TXN *saved_tid;
public:
	Auto_transaction(DB_Connection& aconnection) : 
		fconnection(aconnection), marked_to_rollback(false),
		saved_tid(aconnection.transaction_begin_save()) {
	}
	~Auto_transaction() { 
		if(marked_to_rollback)
			fconnection.rollback_restore(saved_tid);
		else
			fconnection.commit_restore(saved_tid);
	}
	void mark_to_rollback() {
		marked_to_rollback=true;
	}
};

/// DB cursor. handy wrapper around low level <db.h> calls
class DB_Cursor {
	friend DB_Connection;
private:
	DB_Cursor(DB_Connection& aconnection, const String *asource);
public:
	~DB_Cursor();
	/// pass empty strings to key&data, would fill them
	bool get(String& key, String& data, u_int32_t flags);
private:
	const String *fsource;
	DB_Connection& fconnection;
	DBC *cursor;
private:
	void check(const char *operation, const String *source, int error) {
		fconnection.check(operation, source, error);
	}
	/// pass empty string, would fill it from dbt
	void key_dbt_to_string(DBT& dbt, String& result) {
		fconnection.key_dbt_to_string(dbt, result);
	}
	/// pass empty string, would fill it from dbt
	void data_dbt_to_string(DBT& dbt, String& result) {
		fconnection.data_dbt_to_string(dbt, result);
	}
};

#endif

E-mail: