summaryrefslogtreecommitdiff
path: root/src/hdb/db.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/hdb/db.cc')
-rw-r--r--src/hdb/db.cc276
1 files changed, 276 insertions, 0 deletions
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 @@
1/*************************************************************************
2 *
3 * HTCd - Copyright (C) 1998-2006 Henrik Rydberg
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <hdb/db.h>
21#include <new>
22
23filemap* dbmap::flist;
24mutex_t dbmap::mutex;
25opmap dbmap::M;
26
27///////////////////////////////////////////////////////////////////////
28
29dbmap::dbmap():
30 wok(0),fatal(0),index(0),
31 compname(),file(0),tmap(),recs()
32{
33 minor=0;
34 major=0;
35}
36
37dbmap::~dbmap()
38{
39 Close();
40}
41
42///////////////////////////////////////////////////////////////////////
43
44void dbmap::remap_tabs()
45{
46 fatal=head()->fatal.get();
47 tmap.clear();
48 for(int i=0;i<Tables();i++) tmap.add(sref(head()->tabs[i]),i);
49}
50
51void dbmap::remap_recs()
52{
53 major=head()->major.get();
54 recs.clear();
55 int p=file->recs();
56 while(file->size(p)) {
57 record_t* rec=(record_t*)file->at(p);
58 if(rec->caps.get())
59 recs.push_back(idx_t(rec->at(index),rec));
60 p+=rec->mem.get();
61 }
62 recs.sort(CompOperator(compname));
63}
64
65int dbmap::remap()
66{
67 int state=0;
68 if(fatal!=head()->fatal.get()) { remap_tabs(); state|=4; }
69 if(major!=head()->major.get()) { remap_recs(); state|=2; }
70 if(minor!=head()->minor.get()) { minor=head()->minor.get(); state|=1; }
71 return state;
72}
73
74///////////////////////////////////////////////////////////////////////
75
76void Open(const mstring& path,int update=0,int prot=0600) throw(merror_t);
77void Saveas(const mstring& path,int prot=0600) throw(merror_t);
78void Close();
79
80void dbmap::Open(const mstring& path,int update,int prot) throw(merror_t)
81{
82 Close();
83 wok=update?1:0;
84 {
85 MLOCK(mutex);
86 for(filemap* p=flist;p;p=p->next)
87 if(p->Pathname()==path&&p->writable()==wok) { (file=p)->pushref(); break; }
88 if(!file) {
89 filemap* fm=new filemap(flist);
90 try { fm->open(path,wok,prot); fm->check(); file=flist=fm; }
91 catch(...) { delete fm; wok=0; throw; }
92 }
93 }
94 index=head()->index.get();
95 compname=head()->compname;
96 remap_tabs();
97 remap_recs();
98 minor=head()->minor.get();
99}
100
101void dbmap::Saveas(const mstring& path,int prot) throw(merror_t)
102{
103 file->save(path,prot);
104}
105
106void dbmap::Close()
107{
108 wok=0;
109 minor=0;
110 major=0;
111 fatal=0;
112 index=0;
113 compname.clear();
114 recs.clear();
115 tmap.clear();
116 if(file) {
117 MLOCK(mutex);
118 if(file->reference()) file->popref();
119 else {
120 if(flist==file) flist=file->next;
121 else for(filemap* p=flist;p;p=p->next)
122 if(p->next==file) { p->next=file->next; break; }
123 delete file;
124 }
125 file=0;
126 }
127}
128
129void dbmap::Sync()
130{
131 MLOCK(mutex);
132 for(filemap* p=flist;p;p=p->next) {
133 if(p->writable()) p->sync();
134 }
135}
136
137///////////////////////////////////////////////////////////////////////
138
139void dbmap::SetTable(int col,const sref& name) throw(merror_t)
140{
141 check();
142 if(!wok) THROW("db: cannot set table - readonly");
143 if(col<0||col>=Tables()) THROW("db: bad column");
144 HEADLOCK(file);
145 head()->set(col,name);
146 remap();
147}
148
149void dbmap::InsertTable(int col,const sref& name) throw(merror_t)
150{
151 check();
152 if(!wok) THROW("db: cannot insert table - readonly");
153 if(Tables()+1>file->maxtabs) THROW("db: too many tables");
154 if(col<0||col>Tables()) THROW("db: bad column");
155 {
156 HEADLOCK(file);
157 head()->insert(col,name);
158 int p=file->recs();
159 while(file->size(p)) {
160 record_t* rec=(record_t*)file->at(p);
161 if(rec->caps.get()) rec->insert(col);
162 p+=rec->mem.get();
163 }
164 head()->major.add(1);
165 }
166 index=head()->index.get();
167 compname=head()->compname;
168 remap();
169}
170
171void dbmap::RemTable(int col) throw(merror_t)
172{
173 check();
174 if(!wok) THROW("db: cannot remove table - readonly");
175 if(col<0||col>=Tables()) THROW("db: bad column");
176 if(col==head()->index.get()) THROW("db: cannot remove index table");
177 {
178 HEADLOCK(file);
179 head()->remove(col);
180 int p=file->recs();
181 while(file->size(p)) {
182 record_t* rec=(record_t*)file->at(p);
183 if(rec->caps.get()) rec->remove(col);
184 p+=rec->mem.get();
185 }
186 head()->major.add(1);
187 }
188 index=head()->index.get();
189 compname=head()->compname;
190 remap();
191}
192
193///////////////////////////////////////////////////////////////////////
194
195void dbmap::Get(int row,spile& list) throw(merror_t)
196{
197 check();
198 if(row<0||row>=recs.size()) THROW("db: not a valid record");
199 list.resize(Tables());
200 recs[row].rec->get(list);
201}
202
203void dbmap::Set(int row,int col,const sref& s) throw(merror_t)
204{
205 check();
206 if(!wok) THROW("db: cannot set - readonly");
207 if(row<0||row>=recs.size()) THROW("db: not a valid record");
208 if(col==index) THROW("db: cannot set index");
209 HEADLOCK(file);
210 record_t* rec=recs[row].rec;
211 int dim=rec->setreq(col,s);
212 if(dim>rec->caps.get()) {
213 rec=new(file->add(dim)) record_t(*rec);
214 file->rem(recs[row].rec);
215 recs[row].rec=rec;
216 head()->major.add(1);
217 major++;
218 }
219 rec->set(col,s);
220 head()->minor.add(1);
221 minor++;
222}
223
224void dbmap::Set(int row,const spile& list) throw(merror_t)
225{
226 check();
227 if(!wok) THROW("db: cannot set - readonly");
228 if(row<0||row>=recs.size()) THROW("db: not a valid record");
229 if(list.size()!=Tables())
230 THROW("db: wrong number of tables - "<<list.size()<<" should be "<<Tables());
231 HEADLOCK(file);
232 record_t* rec=recs[row].rec;
233 if(rec->at(index)!=list[index]) THROW("db: cannot set index");
234 int dim=record_t::req(list);
235 if(dim>rec->caps.get()) {
236 rec=new(file->add(dim)) record_t(*rec);
237 file->rem(recs[row].rec);
238 recs[row].rec=rec;
239 head()->major.add(1);
240 major++;
241 }
242 rec->set(list);
243 head()->minor.add(1);
244 minor++;
245}
246
247///////////////////////////////////////////////////////////////////////
248
249void dbmap::Rem(int row) throw(merror_t)
250{
251 if(!wok) THROW("db: cannot delete - readonly");
252 if(row<0||row>=recs.size()) THROW("db: not a valid record");
253 HEADLOCK(file);
254 file->rem(recs[row].rec);
255 recs.erase(recs.begin()+row);
256 head()->major.add(1);
257 major++;
258}
259
260int dbmap::Insert(const spile& list,int unique) throw(merror_t)
261{
262 check();
263 if(!wok) THROW("db: cannot insert - readonly");
264 if(index!=head()->index.get())
265 THROW("db: can only insert under normal order");
266 HEADLOCK(file);
267 remap();
268 int row=recs.get(list[index]);
269 if(row<0) {
270 record_t* rec=new(file->add(record_t::req(list))) record_t(list);
271 row=recs.add(rec->at(index),rec);
272 head()->major.add(1);
273 major++;
274 }
275 return row;
276}