00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef GENERALDATA_H
00015 #define GENERALDATA_H
00016
00017
00018 #include <db_cxx.h>
00019
00020
00021 #include <qdatastream.h>
00022 #include <qdom.h>
00023 #include <qxml.h>
00024
00025
00026 #include <iostream>
00027 #include <string>
00028 #include <cassert>
00029 #include <iosfwd>
00030
00031 #include "trdb.h"
00032 #include "trapperdoc.h"
00033 #include "generalmaker.h"
00034 #include "generaldata.h"
00035
00036
00037 class TrapperDoc;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 class GeneralData
00081 {
00082 public:
00083 GeneralData();
00084 virtual ~GeneralData(){}
00085
00086 virtual void print_debug_info() { std::cerr<<"No debug info for class "<<uniqueName()<<endl;}
00087
00088
00089
00090
00091
00092
00093
00094 db_recno_t getRecno( );
00095
00096
00097 void setRecno( db_recno_t recno ) { m_recno = recno; }
00098
00099
00100
00101 virtual void readAttributes( const QXmlAttributes& attr )= 0;
00102
00103
00104 virtual void writeXml( std::ostream& stream )= 0;
00105
00106
00107
00108
00109 virtual void readDom( QDomElement & elem );
00110
00111
00112
00113
00114
00115 virtual void writeDom( QDomElement & elem );
00116
00117
00118
00119
00120
00121
00122 virtual void readStream( QDataStream & stream ) = 0;
00123
00124
00125
00126
00127
00128 virtual void writeStream( QDataStream & stream ) = 0;
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 virtual TrDb::IndexMap getIndexMap() = 0;
00142
00143
00144
00145
00146 virtual std::string uniqueName() = 0;
00147
00148 void copy(GeneralData* other);
00149
00150 protected:
00151 db_recno_t m_recno;
00152 };
00153
00154
00155
00156
00157
00158 namespace Database
00159 {
00160 void setFromDbt( const Dbt * dbtData, GeneralData * general);
00161
00162
00163
00164
00165
00166
00167
00168 template <class T>
00169 class Creator
00170 {
00171 public:
00172
00173
00174
00175
00176 Creator( TrapperDoc *doc, std::string dataType );
00177 ~Creator();
00178
00179
00180
00181
00182
00183
00184
00185
00186 db_recno_t create( bool useRecno, DbTxn *txnid = NULL );
00187
00188
00189 void destroy( DbTxn *txnid = NULL );
00190
00191
00192 T * data() { return m_data; }
00193 protected:
00194 T * m_data;
00195 Db * m_db;
00196 };
00197
00198 template <class T>
00199 Database::Creator<T>::Creator( TrapperDoc * doc, std::string dataType )
00200 {
00201 m_data = dynamic_cast< T * >(GeneralMaker::newData( dataType ));
00202 Q_CHECK_PTR( m_data );
00203 std::string datatype = m_data->uniqueName();
00204 m_db = doc->findTrDb( datatype )->primaryDb();
00205
00206 }
00207
00208 template <class T>
00209 Database::Creator<T>::~Creator()
00210 {
00211 Q_CHECK_PTR( m_data );
00212 delete m_data;
00213 }
00214
00215 template <class T>
00216 db_recno_t Database::Creator<T>::create( bool useRecno, DbTxn *txnid )
00217 {
00218
00219
00220 QByteArray ar;
00221 QDataStream stream( ar, IO_WriteOnly );
00222
00223 m_data->writeStream( stream );
00224
00225
00226 Dbt data( ar.data(), ar.size() );
00227
00228 Dbt key;
00229
00230
00231 db_recno_t the_recno(0);
00232 u_int32_t flags = 0;
00233 if ( useRecno )
00234 {
00235
00236 the_recno = m_data->getRecno();
00237 key.set_data( &the_recno );
00238 key.set_size( sizeof( the_recno ) );
00239 }
00240 else
00241 {
00242
00243 flags |= DB_APPEND;
00244 assert( flags == DB_APPEND );
00245 }
00246
00247
00248
00249
00250
00251 int ret;
00252 if ((ret = m_db->put(txnid, &key, &data, flags )) != 0)
00253 {
00254
00255 m_db->err(ret, "error in create");
00256
00257 exit( 1 );
00258 }
00259
00260 db_recno_t recnoRet = * static_cast< db_recno_t * >( key.get_data() );
00261
00262 return recnoRet;
00263 }
00264 template <class T>
00265 void Database::Creator<T>::destroy( DbTxn *txnid )
00266 {
00267 Dbt key;
00268
00269 db_recno_t the_recno(0);
00270 u_int32_t flags = 0;
00271 the_recno = m_data->getRecno();
00272 key.set_data( &the_recno );
00273 key.set_size( sizeof( the_recno ) );
00274
00275 int ret;
00276 if ((ret = m_db->del(txnid, &key, flags )) != 0)
00277 {
00278 m_db->err(ret, "error in Creator::destroy");
00279 exit( 1 );
00280 }
00281 }
00282
00283
00284
00285
00286
00287 template <class T>
00288 class SecondaryIterator
00289 {
00290 public:
00291
00292
00293
00294
00295
00296
00297
00298
00299 SecondaryIterator( string secondaryIndexStr, TrapperDoc * doc, string generalDataType, DbTxn *txnid = NULL );
00300 ~SecondaryIterator();
00301 std::string name() { return m_name; }
00302 int set();
00303 int setRange();
00304 int nextdup();
00305 int next();
00306 int first();
00307 int last();
00308 int delCurrentInclDups();
00309 int pget( Dbt & key, u_int32_t flags );
00310 T * key() { return m_GeneralData_key; }
00311 T * answer() { return m_GeneralData_answer; }
00312 void closeCursor();
00313 protected:
00314 void fillSecondaryDataDbt( Dbt & secondaryKey, const Dbt & primaryData );
00315 T * m_GeneralData_key;
00316 T * m_GeneralData_answer;
00317 Dbc * m_cursor;
00318 TrDb::Index index;
00319 std::string m_name;
00320 DbTxn* txn;
00321 };
00322
00323 template <class T>
00324 SecondaryIterator<T>::SecondaryIterator( string secondaryIndexStr, TrapperDoc * doc, string generalDataType, DbTxn *txnid )
00325 {
00326 assert( doc!= 0 );
00327
00328 m_name = generalDataType;
00329 m_GeneralData_key = dynamic_cast< T * >(GeneralMaker::newData( generalDataType ));
00330 m_GeneralData_answer = dynamic_cast< T * >(GeneralMaker::newData( generalDataType ));
00331 index = doc->findTrDb( generalDataType )->secondaryIndex( secondaryIndexStr );
00332 Q_CHECK_PTR(m_GeneralData_key);
00333 Q_CHECK_PTR(m_GeneralData_answer);
00334
00335 index.db->cursor( txnid , &m_cursor, 0 );
00336
00337 txn = txnid;
00338 }
00339
00340 template <class T>
00341 SecondaryIterator<T>::~SecondaryIterator( )
00342 {
00343 if ( m_cursor ) {
00344 m_cursor->close();
00345 }
00346 if ( m_GeneralData_key ) {
00347 delete m_GeneralData_key;
00348 m_GeneralData_key = NULL;
00349 }
00350 if ( m_GeneralData_answer ) {
00351 delete m_GeneralData_answer;
00352 m_GeneralData_answer = NULL;
00353 }
00354 }
00355 template <class T>
00356 void SecondaryIterator<T>::closeCursor()
00357 {
00358 assert( m_cursor != 0 );
00359 m_cursor->close();
00360 m_cursor = 0;
00361 }
00362
00363
00364 template <class T>
00365 int SecondaryIterator<T>::set()
00366 {
00367
00368 Dbt secondaryKey;
00369 QByteArray ar;
00370 QDataStream stream( ar, IO_WriteOnly );
00371 m_GeneralData_key->writeStream( stream );
00372 Dbt primaryData( ar.data(), ar.size() );
00373 fillSecondaryDataDbt( secondaryKey, primaryData );
00374 return pget( secondaryKey, DB_SET );
00375 }
00376
00377 template <class T>
00378 int SecondaryIterator<T>::delCurrentInclDups()
00379 {
00380 Dbt secondaryKey;
00381 QByteArray ar;
00382 QDataStream stream( ar, IO_WriteOnly );
00383 m_GeneralData_key->writeStream( stream );
00384 Dbt primaryData( ar.data(), ar.size() );
00385 fillSecondaryDataDbt( secondaryKey, primaryData );
00386
00387 int ret;
00388 if ( (ret = index.db->del(txn, &secondaryKey, 0)) != 0 ){
00389 if ( ret != DB_NOTFOUND )
00390 {
00391 index.db->err(ret, "del() call in SecondaryIterator::delCurrentInclDups()");
00392 }
00393
00394 }
00395 return ret;
00396 }
00397
00398
00399 template <class T>
00400 int SecondaryIterator<T>::setRange()
00401 {
00402 Dbt secondaryKey;
00403 QByteArray ar;
00404 QDataStream stream( ar, IO_WriteOnly );
00405 m_GeneralData_key->writeStream( stream );
00406 Dbt primaryData( ar.data(), ar.size() );
00407 fillSecondaryDataDbt( secondaryKey, primaryData );
00408 return pget( secondaryKey, DB_SET_RANGE );
00409 }
00410
00411 template <class T>
00412 void SecondaryIterator<T>::fillSecondaryDataDbt( Dbt & secondaryKey, const Dbt & primaryData )
00413 {
00414 Dbt primaryKey;
00415 index.associate_func( index.db , &primaryKey, &primaryData, &secondaryKey);
00416 return;
00417 }
00418
00419 template <class T>
00420 int SecondaryIterator<T>::pget( Dbt & key, u_int32_t flags )
00421 {
00422 if ( !m_cursor )
00423 index.db->cursor( txn , &m_cursor, 0 );
00424
00425
00426 Dbt primary_key;
00427 Dbt primary_data;
00428 int ret;
00429 if ((ret = m_cursor->pget(&key, &primary_key, &primary_data, flags )) != 0)
00430 {
00431 if ( ret != DB_NOTFOUND )
00432 {
00433 index.db->err(ret, "pget call in SecondaryIterator::pget");
00434 }
00435
00436 }
00437 else
00438 {
00439 Database::setFromDbt( &primary_data, m_GeneralData_answer );
00440 db_recno_t recno = * static_cast<db_recno_t *> ( primary_key.get_data() );
00441 m_GeneralData_answer->setRecno( recno );
00442 }
00443 return ret;
00444 }
00445
00446 template <class T>
00447 int SecondaryIterator<T>::nextdup()
00448 {
00449 Dbt secondaryKey;
00450 return pget( secondaryKey, DB_NEXT_DUP );
00451 }
00452
00453 template <class T>
00454 int SecondaryIterator<T>::next()
00455 {
00456 Dbt secondaryKey;
00457 return pget( secondaryKey, DB_NEXT );
00458 }
00459
00460 template <class T>
00461 int SecondaryIterator<T>::first()
00462 {
00463 Dbt secondaryKey;
00464 return pget( secondaryKey, DB_FIRST );
00465 }
00466
00467 template <class T>
00468 int SecondaryIterator<T>::last()
00469 {
00470 Dbt secondaryKey;
00471 return pget( secondaryKey, DB_LAST );
00472 }
00473
00474
00475
00476 template <class T>
00477 class PrimaryIterator
00478 {
00479 public:
00480 PrimaryIterator( TrapperDoc * doc, string generalDataType, DbTxn *txnid = NULL );
00481 ~PrimaryIterator();
00482 int first();
00483 int next();
00484 int get( u_int32_t flags, Dbt & primary_key );
00485 T * key() { return m_GeneralData_key; }
00486 T * answer() { return m_GeneralData_answer; }
00487 int delCurrent();
00488 int setFromRecno( db_recno_t recno );
00489 protected:
00490
00491
00492 void fillSecondaryDataDbt( Dbt & secondaryKey, const Dbt & primaryData );
00493 T * m_GeneralData_key;
00494 T * m_GeneralData_answer;
00495 Dbc * m_cursor;
00496 Db * m_db;
00497 std::string name;
00498 };
00499
00500
00501 template <class T>
00502 PrimaryIterator<T>::PrimaryIterator( TrapperDoc * doc, string generalDataType, DbTxn *txnid )
00503 {
00504 m_GeneralData_key = dynamic_cast< T * >(GeneralMaker::newData( generalDataType ));
00505 m_GeneralData_answer = dynamic_cast< T * >(GeneralMaker::newData( generalDataType ));
00506 m_db = doc->findTrDb( generalDataType )->primaryDb();
00507 Q_CHECK_PTR(m_GeneralData_key);
00508 Q_CHECK_PTR(m_GeneralData_answer);
00509 m_db->cursor( txnid , &m_cursor, 0 );
00510 }
00511
00512 template <class T>
00513 PrimaryIterator<T>::~PrimaryIterator( )
00514 {
00515 m_cursor->close();
00516 if ( m_GeneralData_key )
00517 {
00518 delete m_GeneralData_key;
00519 m_GeneralData_key = NULL;
00520 }
00521 if ( m_GeneralData_answer )
00522 {
00523 delete m_GeneralData_answer;
00524 m_GeneralData_answer = NULL;
00525 }
00526 }
00527
00528 template <class T>
00529 int PrimaryIterator<T>::delCurrent()
00530 {
00531 int ret;
00532 if ((ret = m_cursor->del(0)) != 0)
00533 {
00534 m_db->err(ret, "get call in PrimaryIterator::get");
00535 }
00536 return ret;
00537 }
00538
00539 template <class T>
00540 int PrimaryIterator<T>::first()
00541 {
00542 Dbt key;
00543 return get( DB_FIRST, key );
00544 }
00545
00546 template <class T>
00547 int PrimaryIterator<T>::get( u_int32_t flags, Dbt & primary_key )
00548 {
00549 Dbt primary_data;
00550 int ret;
00551 if ((ret = m_cursor->get
00552 (&primary_key, &primary_data, flags )) != 0)
00553 {
00554 if ( ret != DB_NOTFOUND )
00555 {
00556 m_db->err(ret, "get call in PrimaryIterator::get");
00557 }
00558
00559 }
00560 else
00561 {
00562 setFromDbt( &primary_data, m_GeneralData_answer );
00563 db_recno_t recno = * static_cast<db_recno_t *> ( primary_key.get_data() );
00564 m_GeneralData_answer->setRecno( recno );
00565 }
00566 return ret;
00567 }
00568
00569 template <class T>
00570 int PrimaryIterator<T>::setFromRecno( db_recno_t recno )
00571 {
00572 Dbt key;
00573 key.set_size( sizeof( db_recno_t ));
00574 key.set_data( &recno );
00575 return get( DB_SET, key);
00576 }
00577
00578 template <class T>
00579 int PrimaryIterator<T>::next()
00580 {
00581 Dbt key;
00582 return get( DB_NEXT, key );
00583 }
00584
00585 }
00586
00587 #endif