From 5df79c53745fde5d6c3340a2979b1429cd5892c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Sat, 8 Oct 2011 20:30:28 +0200 Subject: Initial import of htcd system 1.0 Signed-off-by: Henrik Rydberg --- src/hdb/db.cc | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 src/hdb/db.cc (limited to 'src/hdb/db.cc') diff --git a/src/hdb/db.cc b/src/hdb/db.cc new file mode 100644 index 0000000..0cc9827 --- /dev/null +++ b/src/hdb/db.cc @@ -0,0 +1,276 @@ +/************************************************************************* + * + * HTCd - Copyright (C) 1998-2006 Henrik Rydberg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +filemap* dbmap::flist; +mutex_t dbmap::mutex; +opmap dbmap::M; + +/////////////////////////////////////////////////////////////////////// + +dbmap::dbmap(): + wok(0),fatal(0),index(0), + compname(),file(0),tmap(),recs() +{ + minor=0; + major=0; +} + +dbmap::~dbmap() +{ + Close(); +} + +/////////////////////////////////////////////////////////////////////// + +void dbmap::remap_tabs() +{ + fatal=head()->fatal.get(); + tmap.clear(); + for(int i=0;itabs[i]),i); +} + +void dbmap::remap_recs() +{ + major=head()->major.get(); + recs.clear(); + int p=file->recs(); + while(file->size(p)) { + record_t* rec=(record_t*)file->at(p); + if(rec->caps.get()) + recs.push_back(idx_t(rec->at(index),rec)); + p+=rec->mem.get(); + } + recs.sort(CompOperator(compname)); +} + +int dbmap::remap() +{ + int state=0; + if(fatal!=head()->fatal.get()) { remap_tabs(); state|=4; } + if(major!=head()->major.get()) { remap_recs(); state|=2; } + if(minor!=head()->minor.get()) { minor=head()->minor.get(); state|=1; } + return state; +} + +/////////////////////////////////////////////////////////////////////// + +void Open(const mstring& path,int update=0,int prot=0600) throw(merror_t); +void Saveas(const mstring& path,int prot=0600) throw(merror_t); +void Close(); + +void dbmap::Open(const mstring& path,int update,int prot) throw(merror_t) +{ + Close(); + wok=update?1:0; + { + MLOCK(mutex); + for(filemap* p=flist;p;p=p->next) + if(p->Pathname()==path&&p->writable()==wok) { (file=p)->pushref(); break; } + if(!file) { + filemap* fm=new filemap(flist); + try { fm->open(path,wok,prot); fm->check(); file=flist=fm; } + catch(...) { delete fm; wok=0; throw; } + } + } + index=head()->index.get(); + compname=head()->compname; + remap_tabs(); + remap_recs(); + minor=head()->minor.get(); +} + +void dbmap::Saveas(const mstring& path,int prot) throw(merror_t) +{ + file->save(path,prot); +} + +void dbmap::Close() +{ + wok=0; + minor=0; + major=0; + fatal=0; + index=0; + compname.clear(); + recs.clear(); + tmap.clear(); + if(file) { + MLOCK(mutex); + if(file->reference()) file->popref(); + else { + if(flist==file) flist=file->next; + else for(filemap* p=flist;p;p=p->next) + if(p->next==file) { p->next=file->next; break; } + delete file; + } + file=0; + } +} + +void dbmap::Sync() +{ + MLOCK(mutex); + for(filemap* p=flist;p;p=p->next) { + if(p->writable()) p->sync(); + } +} + +/////////////////////////////////////////////////////////////////////// + +void dbmap::SetTable(int col,const sref& name) throw(merror_t) +{ + check(); + if(!wok) THROW("db: cannot set table - readonly"); + if(col<0||col>=Tables()) THROW("db: bad column"); + HEADLOCK(file); + head()->set(col,name); + remap(); +} + +void dbmap::InsertTable(int col,const sref& name) throw(merror_t) +{ + check(); + if(!wok) THROW("db: cannot insert table - readonly"); + if(Tables()+1>file->maxtabs) THROW("db: too many tables"); + if(col<0||col>Tables()) THROW("db: bad column"); + { + HEADLOCK(file); + head()->insert(col,name); + int p=file->recs(); + while(file->size(p)) { + record_t* rec=(record_t*)file->at(p); + if(rec->caps.get()) rec->insert(col); + p+=rec->mem.get(); + } + head()->major.add(1); + } + index=head()->index.get(); + compname=head()->compname; + remap(); +} + +void dbmap::RemTable(int col) throw(merror_t) +{ + check(); + if(!wok) THROW("db: cannot remove table - readonly"); + if(col<0||col>=Tables()) THROW("db: bad column"); + if(col==head()->index.get()) THROW("db: cannot remove index table"); + { + HEADLOCK(file); + head()->remove(col); + int p=file->recs(); + while(file->size(p)) { + record_t* rec=(record_t*)file->at(p); + if(rec->caps.get()) rec->remove(col); + p+=rec->mem.get(); + } + head()->major.add(1); + } + index=head()->index.get(); + compname=head()->compname; + remap(); +} + +/////////////////////////////////////////////////////////////////////// + +void dbmap::Get(int row,spile& list) throw(merror_t) +{ + check(); + if(row<0||row>=recs.size()) THROW("db: not a valid record"); + list.resize(Tables()); + recs[row].rec->get(list); +} + +void dbmap::Set(int row,int col,const sref& s) throw(merror_t) +{ + check(); + if(!wok) THROW("db: cannot set - readonly"); + if(row<0||row>=recs.size()) THROW("db: not a valid record"); + if(col==index) THROW("db: cannot set index"); + HEADLOCK(file); + record_t* rec=recs[row].rec; + int dim=rec->setreq(col,s); + if(dim>rec->caps.get()) { + rec=new(file->add(dim)) record_t(*rec); + file->rem(recs[row].rec); + recs[row].rec=rec; + head()->major.add(1); + major++; + } + rec->set(col,s); + head()->minor.add(1); + minor++; +} + +void dbmap::Set(int row,const spile& list) throw(merror_t) +{ + check(); + if(!wok) THROW("db: cannot set - readonly"); + if(row<0||row>=recs.size()) THROW("db: not a valid record"); + if(list.size()!=Tables()) + THROW("db: wrong number of tables - "<at(index)!=list[index]) THROW("db: cannot set index"); + int dim=record_t::req(list); + if(dim>rec->caps.get()) { + rec=new(file->add(dim)) record_t(*rec); + file->rem(recs[row].rec); + recs[row].rec=rec; + head()->major.add(1); + major++; + } + rec->set(list); + head()->minor.add(1); + minor++; +} + +/////////////////////////////////////////////////////////////////////// + +void dbmap::Rem(int row) throw(merror_t) +{ + if(!wok) THROW("db: cannot delete - readonly"); + if(row<0||row>=recs.size()) THROW("db: not a valid record"); + HEADLOCK(file); + file->rem(recs[row].rec); + recs.erase(recs.begin()+row); + head()->major.add(1); + major++; +} + +int dbmap::Insert(const spile& list,int unique) throw(merror_t) +{ + check(); + if(!wok) THROW("db: cannot insert - readonly"); + if(index!=head()->index.get()) + THROW("db: can only insert under normal order"); + HEADLOCK(file); + remap(); + int row=recs.get(list[index]); + if(row<0) { + record_t* rec=new(file->add(record_t::req(list))) record_t(list); + row=recs.add(rec->at(index),rec); + head()->major.add(1); + major++; + } + return row; +} -- cgit v1.2.3