00001
00002
00003
00004
00009 #include "header.h"
00010 #include "handler.h"
00011 #include "store.h"
00012 #include "field.h"
00013 #include "persist.h"
00014 #include "format.h"
00015
00016 #include "mk4io.h"
00017
00018 #if !q4_INLINE
00019 #include "store.inl"
00020 #endif
00021
00023
00024 c4_Dependencies::c4_Dependencies() {
00025 _refs.SetSize(0, 3);
00026 }
00027
00028 c4_Dependencies::~c4_Dependencies(){}
00029
00030 void c4_Dependencies::Add(c4_Sequence *seq_) {
00031 for (int i = 0; i < _refs.GetSize(); ++i)
00032 d4_assert(_refs.GetAt(i) != seq_);
00033
00034 _refs.Add(seq_);
00035 }
00036
00037 bool c4_Dependencies::Remove(c4_Sequence *seq_) {
00038 int n = _refs.GetSize() - 1;
00039 d4_assert(n >= 0);
00040
00041 for (int i = 0; i <= n; ++i)
00042 if (_refs.GetAt(i) == seq_) {
00043 _refs.SetAt(i, _refs.GetAt(n));
00044 _refs.SetSize(n);
00045 return n > 0;
00046 }
00047
00048 d4_assert(0);
00049 return true;
00050 }
00051
00053
00054 c4_Notifier::~c4_Notifier() {
00055 if (_type > kNone && _origin->GetDependencies()) {
00056 c4_PtrArray &refs = _origin->GetDependencies()->_refs;
00057
00058 for (int i = 0; i < refs.GetSize(); ++i) {
00059 c4_Sequence *seq = (c4_Sequence*)refs.GetAt(i);
00060 d4_assert(seq != 0);
00061
00062 seq->PostChange(*this);
00063
00064 if (_chain && _chain->_origin == seq) {
00065 c4_Notifier *next = _chain->_next;
00066 _chain->_next = 0;
00067
00068 delete _chain;
00069
00070 _chain = next;
00071 }
00072 }
00073 }
00074
00075 d4_assert(!_chain);
00076 d4_assert(!_next);
00077 }
00078
00079 void c4_Notifier::StartSetAt(int index_, c4_Cursor &cursor_) {
00080 _type = kSetAt;
00081 _index = index_;
00082 _cursor = &cursor_;
00083
00084 Notify();
00085 }
00086
00087 void c4_Notifier::StartInsertAt(int i_, c4_Cursor &cursor_, int n_) {
00088 _type = kInsertAt;
00089 _index = i_;
00090 _cursor = &cursor_;
00091 _count = n_;
00092
00093 Notify();
00094 }
00095
00096 void c4_Notifier::StartRemoveAt(int index_, int count_) {
00097 _type = kRemoveAt;
00098 _index = index_;
00099 _count = count_;
00100
00101 Notify();
00102 }
00103
00104 void c4_Notifier::StartMove(int from_, int to_) {
00105 _type = kMove;
00106 _index = from_;
00107 _count = to_;
00108
00109 Notify();
00110 }
00111
00112 void c4_Notifier::StartSet(int i_, int propId_, const c4_Bytes &buf_) {
00113 _type = kSet;
00114 _index = i_;
00115 _propId = propId_;
00116 _bytes = &buf_;
00117
00118 Notify();
00119 }
00120
00121 void c4_Notifier::Notify() {
00122 d4_assert(_origin->GetDependencies() != 0);
00123 c4_PtrArray &refs = _origin->GetDependencies()->_refs;
00124
00125 int n = refs.GetSize();
00126 d4_assert(n > 0);
00127
00128 c4_Notifier **rover = &_chain;
00129
00130 for (int i = 0; i < n; ++i) {
00131 c4_Sequence *seq = (c4_Sequence*)refs.GetAt(i);
00132 d4_assert(seq != 0);
00133
00134 c4_Notifier *ptr = seq->PreChange(*this);
00135 if (ptr) {
00136 d4_assert(ptr->_origin == seq);
00137
00138 d4_assert(! *rover);
00139 *rover = ptr;
00140 rover = &ptr->_next;
00141 }
00142 }
00143 }
00144
00146
00186 c4_Storage::c4_Storage() {
00187
00188 Initialize(*d4_new c4_Strategy, true, 0);
00189 }
00190
00191 c4_Storage::c4_Storage(c4_Strategy &strategy_, bool owned_, int mode_) {
00192 Initialize(strategy_, owned_, mode_);
00193 Persist()->LoadAll();
00194 }
00195
00196 c4_Storage::c4_Storage(const char *fname_, int mode_) {
00197 c4_FileStrategy *strat = d4_new c4_FileStrategy;
00198 strat->DataOpen(fname_, mode_);
00199
00200 Initialize(*strat, true, mode_);
00201 if (strat->IsValid())
00202 Persist()->LoadAll();
00203 }
00204
00205 c4_Storage::c4_Storage(const c4_View &root_) {
00206 if (root_.Persist() != 0)
00207
00208 *(c4_View*)this = root_;
00209 else
00210
00211 Initialize(*d4_new c4_Strategy, true, 0);
00212 }
00213
00214 c4_Storage::~c4_Storage() {
00215
00216
00217 }
00218
00219 void c4_Storage::Initialize(c4_Strategy &strategy_, bool owned_, int mode_) {
00220 c4_Persist *pers = d4_new c4_Persist(strategy_, owned_, mode_);
00221 c4_HandlerSeq *seq = d4_new c4_HandlerSeq(pers);
00222 seq->DefineRoot();
00223 *(c4_View*)this = seq;
00224 pers->SetRoot(seq);
00225 }
00226
00228 c4_ViewRef c4_Storage::View(const char *name_) {
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 c4_ViewProp prop(name_);
00245 int n = AddProperty(prop);
00246 d4_assert(n >= 0);
00247
00248
00249 return NthProperty(n)(GetAt(0));
00250 }
00251
00253 c4_View c4_Storage::GetAs(const char *description_) {
00254 d4_assert(description_ != 0);
00255
00256
00257
00258 const char *q = strchr(description_, '[');
00259 if (q != 0) {
00260 c4_String vname(description_, q - description_);
00261 const char *d = Description(vname);
00262 if (d != 0) {
00263 c4_String desc(d);
00264 if (("[" + desc + "]").CompareNoCase(q) == 0)
00265 return View(vname);
00266 }
00267 }
00268
00269 c4_Field *field = d4_new c4_Field(description_);
00270 d4_assert(field != 0);
00271
00272 d4_assert(! *description_);
00273
00274 c4_String name = field->Name();
00275 d4_assert(!name.IsEmpty());
00276
00277 c4_Field &curr = Persist()->Root().Definition();
00278
00279 c4_String newField = "," + field->Description();
00280 bool keep = newField.Find('[') >= 0;
00281
00282 c4_String newDef;
00283
00284
00285 for (int i = 0; i < curr.NumSubFields(); ++i) {
00286 c4_Field &of = curr.SubField(i);
00287 if (of.Name().CompareNoCase(name) == 0) {
00288 if (field->IsRepeating())
00289 newDef += newField;
00290
00291
00292 newField.Empty();
00293 continue;
00294 }
00295
00296 newDef += "," + of.Description();
00297 }
00298
00299 if (keep)
00300
00301 newDef += newField;
00302
00303
00304 delete field;
00305
00306 const char *p = newDef;
00307 SetStructure(*p ? ++p: p);
00308
00309 if (!keep)
00310
00311 return c4_View();
00312
00313 return View(name);
00314 }
00315
00317 void c4_Storage::SetStructure(const char *description_) {
00318 d4_assert(description_ != 0);
00319
00320 if (description_ != Description()) {
00321 c4_String s = "[" + c4_String(description_) + "]";
00322 description_ = s;
00323
00324 c4_Field *field = d4_new c4_Field(description_);
00325 d4_assert(! *description_);
00326
00327 d4_assert(field != 0);
00328 Persist()->Root().Restructure(*field, false);
00329 }
00330 }
00331
00333 c4_Strategy &c4_Storage::Strategy()const {
00334 return Persist()->Strategy();
00335 }
00336
00338 const char *c4_Storage::Description(const char *name_) {
00339 if (name_ == 0 || *name_ == 0)
00340 return c4_View::Description();
00341
00342 c4_View v = View(name_);
00343 return v.Description();
00344 }
00345
00347 bool c4_Storage::SetAside(c4_Storage &aside_) {
00348 c4_Persist *pers = Persist();
00349 bool f = pers->SetAside(aside_);
00350
00351 *(c4_View*)this = &pers->Root();
00352 return f;
00353 }
00354
00356 c4_Storage *c4_Storage::GetAside()const {
00357 return Persist()->GetAside();
00358 }
00359
00361 bool c4_Storage::Commit(bool full_) {
00362 return Strategy().IsValid() && Persist()->Commit(full_);
00363 }
00364
00369 bool c4_Storage::Rollback(bool full_) {
00370 c4_Persist *pers = Persist();
00371 bool f = Strategy().IsValid() && pers->Rollback(full_);
00372
00373 *(c4_View*)this = &pers->Root();
00374 return f;
00375 }
00376
00378 bool c4_Storage::AutoCommit(bool flag_) {
00379 return Persist()->AutoCommit(flag_);
00380 }
00381
00383 bool c4_Storage::LoadFrom(c4_Stream &stream_) {
00384 c4_HandlerSeq *newRoot = c4_Persist::Load(&stream_);
00385 if (newRoot == 0)
00386 return false;
00387
00388
00389
00390 c4_View temp(newRoot);
00391
00392 SetSize(0);
00393 SetStructure(temp.Description());
00394 InsertAt(0, temp);
00395
00396 return true;
00397 }
00398
00400 void c4_Storage::SaveTo(c4_Stream &stream_) {
00401 c4_Persist::Save(&stream_, Persist()->Root());
00402 }
00403
00404 t4_i32 c4_Storage::FreeSpace(t4_i32 *bytes_) {
00405 return Persist()->FreeBytes(bytes_);
00406 }
00407
00409
00410 c4_DerivedSeq::c4_DerivedSeq(c4_Sequence &seq_): _seq(seq_) {
00411 _seq.Attach(this);
00412 }
00413
00414 c4_DerivedSeq::~c4_DerivedSeq() {
00415 _seq.Detach(this);
00416 }
00417
00418 int c4_DerivedSeq::RemapIndex(int index_, const c4_Sequence *seq_)const {
00419 return seq_ == this ? index_ : _seq.RemapIndex(index_, seq_);
00420 }
00421
00422 int c4_DerivedSeq::NumRows()const {
00423 return _seq.NumRows();
00424 }
00425
00426 int c4_DerivedSeq::NumHandlers()const {
00427 return _seq.NumHandlers();
00428 }
00429
00430 c4_Handler &c4_DerivedSeq::NthHandler(int colNum_)const {
00431 return _seq.NthHandler(colNum_);
00432 }
00433
00434 const c4_Sequence *c4_DerivedSeq::HandlerContext(int colNum_)const {
00435 return _seq.HandlerContext(colNum_);
00436 }
00437
00438 int c4_DerivedSeq::AddHandler(c4_Handler *handler_) {
00439 return _seq.AddHandler(handler_);
00440 }
00441
00442 c4_Handler *c4_DerivedSeq::CreateHandler(const c4_Property &prop_) {
00443 return _seq.CreateHandler(prop_);
00444 }
00445
00446 void c4_DerivedSeq::SetNumRows(int size_) {
00447 _seq.SetNumRows(size_);
00448 }
00449
00450 c4_Notifier *c4_DerivedSeq::PreChange(c4_Notifier &nf_) {
00451 if (!GetDependencies())
00452 return 0;
00453
00454 c4_Notifier *chg = d4_new c4_Notifier(this);
00455
00456 switch (nf_._type) {
00457 case c4_Notifier::kSetAt: chg->StartSetAt(nf_._index, *nf_._cursor);
00458 break;
00459
00460 case c4_Notifier::kSet: chg->StartSet(nf_._index, nf_._propId, *nf_._bytes)
00461 ;
00462 break;
00463
00464 case c4_Notifier::kInsertAt: chg->StartInsertAt(nf_._index, *nf_._cursor,
00465 nf_._count);
00466 break;
00467
00468 case c4_Notifier::kRemoveAt: chg->StartRemoveAt(nf_._index, nf_._count);
00469 break;
00470
00471 case c4_Notifier::kMove: chg->StartMove(nf_._index, nf_._count);
00472 break;
00473 }
00474
00475 return chg;
00476 }
00477
00479
00480 c4_StreamStrategy::c4_StreamStrategy(t4_i32 buflen_): _stream(0), _buffer
00481 (d4_new t4_byte[buflen_]), _buflen(buflen_), _position(0) {
00482 _mapStart = _buffer;
00483 _dataSize = buflen_;
00484 }
00485
00486 c4_StreamStrategy::c4_StreamStrategy(c4_Stream *stream_): _stream(stream_),
00487 _buffer(0), _buflen(0), _position(0){}
00488
00489 c4_StreamStrategy::~c4_StreamStrategy() {
00490 _mapStart = 0;
00491 _dataSize = 0;
00492
00493 if (_buffer != 0)
00494 delete [] _buffer;
00495 }
00496
00497 bool c4_StreamStrategy::IsValid()const {
00498 return true;
00499 }
00500
00501 int c4_StreamStrategy::DataRead(t4_i32 pos_, void *buffer_, int length_) {
00502 if (_buffer != 0) {
00503 d4_assert(pos_ <= _buflen);
00504 _position = pos_ + _baseOffset;
00505
00506 if (length_ > _buflen - _position)
00507 length_ = _buflen - _position;
00508 if (length_ > 0)
00509 memcpy(buffer_, _buffer + _position, length_);
00510 } else {
00511 d4_assert(_position == pos_ + _baseOffset);
00512 length_ = _stream != 0 ? _stream->Read(buffer_, length_): 0;
00513 }
00514
00515 _position += length_;
00516 return length_;
00517 }
00518
00519 void c4_StreamStrategy::DataWrite(t4_i32 pos_, const void *buffer_, int length_)
00520 {
00521 if (_buffer != 0) {
00522 d4_assert(pos_ <= _buflen);
00523 _position = pos_ + _baseOffset;
00524
00525 int n = length_;
00526 if (n > _buflen - _position)
00527 n = _buflen - _position;
00528 if (n > 0)
00529 memcpy(_buffer + _position, buffer_, n);
00530 } else {
00531 d4_assert(_position == pos_ + _baseOffset);
00532 if (_stream != 0 && !_stream->Write(buffer_, length_))
00533 ++_failure;
00534 }
00535
00536 _position += length_;
00537 }
00538
00539 t4_i32 c4_StreamStrategy::FileSize() {
00540 return _position;
00541 }
00542