00001 #include "CondCore/DBCommon/interface/CoralTransaction.h"
00002 #include "CondCore/DBCommon/interface/SequenceManager.h"
00003 #include "CondCore/DBCommon/interface/Exception.h"
00004 #include "RelationalAccess/ISchema.h"
00005 #include "RelationalAccess/TableDescription.h"
00006 #include "RelationalAccess/ITable.h"
00007 #include "RelationalAccess/ITableDataEditor.h"
00008 #include "RelationalAccess/ITablePrivilegeManager.h"
00009 #include "RelationalAccess/IQuery.h"
00010 #include "RelationalAccess/ICursor.h"
00011 #include "CoralBase/Attribute.h"
00012 #include "CoralBase/AttributeList.h"
00013 #include "CoralBase/AttributeSpecification.h"
00014 #include "RelationalAccess/SchemaException.h"
00015 #include <memory>
00016
00017 cond::SequenceManager::SequenceManager(cond::CoralTransaction& coraldb,
00018 const std::string& sequenceTableName):
00019 m_coraldb(coraldb),
00020 m_sequenceTableName( sequenceTableName ),
00021 m_tableToId(),
00022 m_sequenceTableExists( false ),
00023 m_whereClause( std::string("REFTABLE_NAME")+" =:"+std::string("REFTABLE_NAME")),
00024 m_whereData( 0 ),
00025 m_setClause( std::string("IDVALUE")+" = "+std::string("IDVALUE")+" + 1"),
00026 m_started( false )
00027 {
00028 m_whereData = new coral::AttributeList;
00029 m_whereData->extend<std::string>(std::string("REFTABLE_NAME"));
00030 init();
00031 }
00032 void
00033 cond::SequenceManager::init(){
00034 m_sequenceTableExists=m_coraldb.nominalSchema().existsTable(m_sequenceTableName) ;
00035 m_started=true;
00036 }
00037 cond::SequenceManager::~SequenceManager()
00038 {
00039 delete m_whereData;
00040 }
00041 unsigned long long
00042 cond::SequenceManager::incrementId( const std::string& tableName ){
00043 std::map< std::string, unsigned long long >::iterator iSequence = m_tableToId.find( tableName );
00044 coral::ISchema& schema=m_coraldb.nominalSchema();
00045 if ( iSequence == m_tableToId.end() ) {
00046
00047 if ( ! m_sequenceTableExists ) {
00048 throw cond::Exception("SequenceManager::incrementId");
00049 }
00050
00051 unsigned long long lastIdUsed = 0;
00052 if ( ! ( this->lockEntry( schema, tableName, lastIdUsed ) ) ) {
00053
00054 coral::AttributeList rowData;
00055 rowData.extend<std::string>("REFTABLE_NAME");
00056 rowData.extend<unsigned long long>("IDVALUE");
00057 coral::AttributeList::iterator iAttribute = rowData.begin();
00058 iAttribute->data< std::string >() = tableName;
00059 ++iAttribute;
00060 unsigned long long startingIdValue = lastIdUsed;
00061 iAttribute->data< unsigned long long >() = startingIdValue;
00062 try{
00063 schema.tableHandle( m_sequenceTableName ).dataEditor().insertRow( rowData );
00064 m_tableToId.insert( std::make_pair( tableName, startingIdValue ) );
00065 return startingIdValue;
00066 }catch(const coral::DataEditorException& er){
00067
00068 this->lockEntry( schema, tableName, lastIdUsed );
00069 ++lastIdUsed;
00070 iSequence = m_tableToId.insert( std::make_pair( tableName, lastIdUsed ) ).first;
00071 m_whereData->begin()->data<std::string>() = tableName;
00072 schema.tableHandle(m_sequenceTableName).dataEditor().updateRows(m_setClause,m_whereClause,*m_whereData );
00073 return lastIdUsed;
00074
00075
00076 }catch(std::exception& er){
00077
00078 throw cond::Exception(er.what());
00079 }
00080
00081 }
00082
00083 iSequence = m_tableToId.insert( std::make_pair( tableName, lastIdUsed ) ).first;
00084 }
00085
00086 unsigned long long& oid = iSequence->second;
00087 this->lockEntry( schema, tableName, oid );
00088 ++oid;
00089
00090
00091 m_whereData->begin()->data<std::string>() = tableName;
00092 schema.tableHandle(m_sequenceTableName).dataEditor().updateRows(m_setClause,m_whereClause,*m_whereData );
00093
00094 return oid;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 void
00137 cond::SequenceManager::clear()
00138 {
00139 m_tableToId.clear();
00140 }
00141 bool
00142 cond::SequenceManager::existSequencesTable(){
00143 return m_sequenceTableExists;
00144 }
00145 void
00146 cond::SequenceManager::createSequencesTable()
00147 {
00148 coral::ISchema& schema= m_coraldb.nominalSchema();
00149 coral::TableDescription description( "CONDSEQ" );
00150 description.setName(m_sequenceTableName);
00151 description.insertColumn(std::string("REFTABLE_NAME"),
00152 coral::AttributeSpecification::typeNameForType<std::string>() );
00153 description.setNotNullConstraint(std::string("REFTABLE_NAME"));
00154 description.insertColumn(std::string("IDVALUE"),
00155 coral::AttributeSpecification::typeNameForType<unsigned long long>() );
00156 description.setNotNullConstraint(std::string("IDVALUE"));
00157 description.setPrimaryKey( std::vector< std::string >( 1, std::string("REFTABLE_NAME")));
00158 schema.createTable( description ).privilegeManager().grantToPublic( coral::ITablePrivilegeManager::Select );
00159 m_sequenceTableExists=true;
00160 }
00161
00162 bool
00163 cond::SequenceManager::lockEntry( coral::ISchema& schema,
00164 const std::string& sequenceName,
00165 unsigned long long& lastId ){
00166 std::auto_ptr< coral::IQuery > query( schema.tableHandle(m_sequenceTableName).newQuery());
00167 query->limitReturnedRows( 1, 0 );
00168 query->addToOutputList( std::string("IDVALUE") );
00169 query->defineOutputType( std::string("IDVALUE"), coral::AttributeSpecification::typeNameForType<unsigned long long>() );
00170 query->setForUpdate();
00171 m_whereData->begin()->data< std::string >() = sequenceName;
00172 query->setCondition( m_whereClause, *m_whereData );
00173 coral::ICursor& cursor = query->execute();
00174 if ( cursor.next() ) {
00175 lastId = cursor.currentRow().begin()->data< unsigned long long >();
00176
00177
00178
00179 return true;
00180 }else {
00181 cursor.close();
00182
00183 return false;
00184 }
00185 }