You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
3.8 KiB
C++

//
// WordMeta.cc
//
// Part of the ht://Dig package <http://www.htdig.org/>
// Copyright (c) 1999-2004 The ht://Dig Group
// For copyright details, see the file COPYING in your distribution
// or the GNU Library General Public License (LGPL) version 2 or later
// <http://www.gnu.org/copyleft/lgpl.html>
//
// $Id: WordMeta.cc,v 1.4 2004/05/28 13:15:28 lha Exp $
//
#ifdef HAVE_CONFIG_H
#include "htconfig.h"
#endif /* HAVE_CONFIG_H */
#include <fcntl.h>
extern "C" {
#include "db_int.h"
#include "db_page.h"
#include "db_shash.h"
#include "lock.h"
#include "mp.h"
}
#include "WordMeta.h"
#include "WordListOne.h"
#define WORD_META_SERIAL_SIZE (WORD_META_SERIAL_FILE + 1)
class WordLock {
public:
WordLock() { lock.off = LOCK_INVALID; }
DB_LOCK lock;
};
//
// Total size of structure must *NOT* be over 256 bytes.
//
typedef struct _WordMetaInfo {
DBMETA meta;
unsigned int serials[WORD_META_SERIAL_SIZE];
} WordMetaInfo;
class WordMetaImp
{
public:
WordMetaImp() {
mpf = 0;
pgno = PGNO_INVALID;
info = 0;
}
DB_MPOOLFILE *mpf;
db_pgno_t pgno;
WordMetaInfo *info;
};
WordMeta::~WordMeta()
{
delete imp;
delete db;
}
int WordMeta::Initialize(WordList* nwords)
{
words = nwords;
db = new WordDB(nwords->GetContext()->GetDBInfo());
imp = new WordMetaImp();
return OK;
}
int WordMeta::Open()
{
const String& filename = words->Filename();
int flags = words->Flags();
db->set_pagesize(words->Pagesize());
if(db->Open(filename, "meta", DB_BTREE, flags, 0666, WORD_DB_DICT) != 0)
return NOTOK;
imp->mpf = db->db->mpf;
int ret;
String kpgno("pgno");
if((ret = db->Get(0, kpgno, imp->pgno, 0)) != 0 && ret != DB_NOTFOUND)
return NOTOK;
/*
* First time thru, create the meta page and initialize it.
*/
if(ret == DB_NOTFOUND) {
if(CDB_memp_fget(imp->mpf, &imp->pgno, DB_MPOOL_NEW, (void**)&imp->info) != 0)
return NOTOK;
memset((char*)imp->info, '\0', sizeof(WordMetaInfo));
imp->info->meta.type = P_INVALID;
imp->info->meta.pgno = imp->pgno;
if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
return NOTOK;
if(db->Put(0, kpgno, imp->pgno, 0) != 0)
return NOTOK;
}
return OK;
}
int WordMeta::Close()
{
return db->Close() == 0 ? OK : NOTOK;
}
int WordMeta::Serial(int what, unsigned int& serial)
{
serial = WORD_META_SERIAL_INVALID;
if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
return NOTOK;
serial = ++imp->info->serials[what];
if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
return NOTOK;
return OK;
}
int WordMeta::GetSerial(int what, unsigned int& serial)
{
serial = WORD_META_SERIAL_INVALID;
if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
return NOTOK;
serial = imp->info->serials[what];
if(CDB_memp_fput(imp->mpf, (void*)imp->info, 0) != 0)
return NOTOK;
return OK;
}
int WordMeta::SetSerial(int what, unsigned int serial)
{
if(CDB_memp_fget(imp->mpf, &imp->pgno, 0, (void**)&imp->info) != 0)
return NOTOK;
imp->info->serials[what] = serial;
if(CDB_memp_fput(imp->mpf, (void*)imp->info, DB_MPOOL_DIRTY) != 0)
return NOTOK;
return OK;
}
int WordMeta::Lock(const String& resource, WordLock*& lock)
{
lock = new WordLock;
DB_ENV* dbenv = words->GetContext()->GetDBInfo().dbenv;
u_int32_t id;
if(CDB_lock_id(dbenv, &id) != 0) {
delete lock;
lock = 0;
return NOTOK;
}
DBT obj;
obj.size = resource.length();
obj.data = (void*)resource.get();
if(CDB_lock_get(dbenv, id, 0, &obj, DB_LOCK_WRITE, &lock->lock) != 0) {
delete lock;
lock = 0;
return NOTOK;
}
return OK;
}
int WordMeta::Unlock(const String& resource, WordLock*& lock)
{
DB_ENV* dbenv = words->GetContext()->GetDBInfo().dbenv;
int ret = CDB_lock_put(dbenv, &lock->lock);
delete lock;
lock = 0;
return ret == 0 ? OK : NOTOK;
}