CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
DatabaseContainer.cc
Go to the documentation of this file.
2 #include "DatabaseContainer.h"
3 #include "DatabaseSession.h"
4 #include "IDatabaseSchema.h"
5 #include "ContainerSchema.h"
6 #include "IRelationalStreamer.h"
7 #include "RelationalBuffer.h"
8 #include "RelationalOperation.h"
9 #include "DataElement.h"
10 #include "RelationalDeleter.h"
12 #include "IDatabaseSchema.h"
13 #include "ClassUtils.h"
14 #include "MappingRules.h"
15 // externals
16 #include "CoralBase/Attribute.h"
17 //
18 #include <boost/lexical_cast.hpp>
19 
20 namespace ora {
21 
22  class WriteBuffer {
23  public:
24  explicit WriteBuffer( ContainerSchema& contSchema ):
25  m_buffer(),
26  m_contSchema( contSchema ){
27  }
28 
30  }
31 
32  void registerForWrite( int oid, const void* data ){
33  m_buffer.push_back( std::make_pair(oid, data ) );
34  }
35 
36  size_t flush(){
37  size_t nobj = 0;
38  if( m_buffer.size() ){
39  MappingElement& topLevelMapping = m_contSchema.mapping( true ).topElement();
40  RelationalBuffer operationBuffer( m_contSchema.storageSchema() );
41  InsertOperation* topLevelInsert = &operationBuffer.newInsert( topLevelMapping.tableName() );
42  topLevelInsert->addId( topLevelMapping.columnNames()[ 0 ] );
44  MappingElement::iterator iMap = topLevelMapping.find( type.Name(Reflex::SCOPED) );
45  // the first inner mapping is the relevant...
46  if( iMap == topLevelMapping.end()){
47  throwException("Could not find a mapping element for class \""+
48  type.Name(Reflex::SCOPED)+"\"",
49  "WriteBuffer::flush");
50  }
51  MappingElement& mapping = iMap->second;
52  RelationalStreamerFactory streamerFactory( m_contSchema );
53  DataElement topLevelElement;
54  std::auto_ptr<IRelationalWriter> writer( streamerFactory.newWriter( type, mapping ) );
55  writer->build( topLevelElement, *topLevelInsert, operationBuffer );
56 
57  for( std::vector<std::pair<int, const void*> >::const_iterator iW = m_buffer.begin();
58  iW != m_buffer.end(); ++iW ){
59  int oid = iW->first;
60  const void* data = iW->second;
61  coral::AttributeList& dataBuff = topLevelInsert->data();
62  dataBuff.begin()->data<int>() = oid;
63  writer->write( oid, data );
64  if( operationBuffer.flush() ) nobj++;
65  }
66  m_buffer.clear();
67  }
68  return nobj;
69  }
70 
71 
72  private:
73  std::vector<std::pair<int, const void*> > m_buffer;
75 
76  };
77 
78  class UpdateBuffer {
79  public:
80  explicit UpdateBuffer( ContainerSchema& contSchema ):
81  m_buffer(),
82  m_contSchema( contSchema ){
83  }
84 
86  }
87 
88 
89  void registerForUpdate( int oid, const void* data ){
90  m_buffer.push_back( std::make_pair( oid, data ));
91  }
92 
93 
94  size_t flush(){
95  size_t nobj = 0;
96  if( m_buffer.size() ){
97  RelationalBuffer operationBuffer( m_contSchema.storageSchema() );
98  std::vector<MappingElement> dependentMappings;
99  m_contSchema.mappingForDependentClasses( dependentMappings );
100  RelationalDeleter depDeleter( dependentMappings );
101  depDeleter.build( operationBuffer );
102  dependentMappings.clear();
103 
104  MappingElement& topLevelMapping = m_contSchema.mapping( true ).topElement();
105  UpdateOperation* topLevelUpdate = &operationBuffer.newUpdate( topLevelMapping.tableName(), true );
106  topLevelUpdate->addId( topLevelMapping.columnNames()[ 0 ] );
107  topLevelUpdate->addWhereId( topLevelMapping.columnNames()[ 0 ] );
108  const Reflex::Type& type = m_contSchema.type();
109  MappingElement::iterator iMap = topLevelMapping.find( type.Name(Reflex::SCOPED) );
110  // the first inner mapping is the relevant...
111  if( iMap == topLevelMapping.end()){
112  throwException("Could not find a mapping element for class \""+
113  type.Name(Reflex::SCOPED)+"\"",
114  "UpdateBuffer::flush");
115  }
116  MappingElement& mapping = iMap->second;
117  RelationalStreamerFactory streamerFactory( m_contSchema );
118  DataElement topLevelElement;
119  std::auto_ptr<IRelationalUpdater> updater( streamerFactory.newUpdater( type, mapping ));
120  updater->build( topLevelElement, *topLevelUpdate, operationBuffer );
121  for( std::vector<std::pair<int, const void*> >::const_iterator iU = m_buffer.begin();
122  iU != m_buffer.end(); ++iU ){
123  int oid = iU->first;
124  const void* data = iU->second;
125  // erase the dependencies (they cannot be updated...)
126  depDeleter.erase( oid );
127  coral::AttributeList& dataBuff = topLevelUpdate->data();
128  dataBuff.begin()->data<int>() = oid;
129  coral::AttributeList& whereDataBuff = topLevelUpdate->whereData();
130  whereDataBuff.begin()->data<int>() = oid;
131  updater->update( oid, data );
132  if( operationBuffer.flush()) nobj++;
133  }
134  m_buffer.clear();
135  }
136  return nobj;
137  }
138 
139  private:
140  std::vector<std::pair<int, const void*> > m_buffer;
142  };
143 
144  class ReadBuffer {
145  public:
146  explicit ReadBuffer( ContainerSchema& contSchema ):
148  m_type( contSchema.type() ),
149  m_reader(),
150  m_topLevelQuery( contSchema.mapping().topElement().tableName(), contSchema.storageSchema() ){
151 
152  MappingElement& topLevelMapping = contSchema.mapping().topElement();
153  m_topLevelQuery.addWhereId( topLevelMapping.columnNames()[ 0 ] );
154  MappingElement::iterator iMap = topLevelMapping.find( m_type.Name(Reflex::SCOPED) );
155  // the first inner mapping is the good one ...
156  if( iMap == topLevelMapping.end()){
157  throwException("Could not find a mapping element for class \""+
158  m_type.Name(Reflex::SCOPED)+"\"",
159  "ReadBuffer::ReadBuffer");
160  }
161  MappingElement& mapping = iMap->second;
162  RelationalStreamerFactory streamerFactory( contSchema );
163  m_reader.reset( streamerFactory.newReader( m_type, mapping )) ;
165  }
166 
168  }
169 
170  void* read( int oid ){
171  coral::AttributeList& dataBuff = m_topLevelQuery.whereData();
172  dataBuff.begin()->data<int>() = oid;
174  m_reader->select( oid );
175  void* destination = 0;
177  destination = ClassUtils::constructObject( m_type );
178  m_reader->read( destination );
179  } else {
180  throwException("Object with item id "+boost::lexical_cast<std::string>(oid)+" has not been found in the database.",
181  "ReadBuffer::read");
182  }
183  m_reader->clear();
185  return destination;
186  }
187 
188  const Reflex::Type& type(){
189  return m_type;
190  }
191 
192  private:
195  std::auto_ptr<IRelationalReader> m_reader;
197  };
198 
199  class DeleteBuffer {
200  public:
201  explicit DeleteBuffer( ContainerSchema& contSchema ):
202  m_buffer(),
203  m_contSchema( contSchema ){
204  }
205 
207  }
208 
209 
210  void registerForDelete( int oid ){
211  m_buffer.push_back( oid );
212  }
213 
214  size_t flush(){
215  size_t nobj = 0;
216  if( m_buffer.size()) {
217  RelationalBuffer operationBuffer( m_contSchema.storageSchema() );
219  mainDeleter.build( operationBuffer );
220  std::vector<MappingElement> dependentMappings;
221  m_contSchema.mappingForDependentClasses( dependentMappings );
222  RelationalDeleter depDeleter( dependentMappings );
223  depDeleter.build( operationBuffer );
224  dependentMappings.clear();
225 
226  for( std::vector<int>::const_iterator iD = m_buffer.begin();
227  iD != m_buffer.end(); ++iD ){
228  depDeleter.erase( *iD );
229  mainDeleter.erase( *iD );
230  if( operationBuffer.flush() ) nobj++;
231  }
232  m_buffer.clear();
233  }
234  return nobj;
235  }
236 
237  private:
238  std::vector<int> m_buffer;
240  };
241 
242 }
243 
245  ReadBuffer& buffer ):
246  m_query( schema.mapping().topElement().tableName(), schema.storageSchema() ),
247  m_itemId( -1 ),
248  m_readBuffer( buffer ){
249  const std::string& idCol = schema.mapping().topElement().columnNames()[0];
250  m_query.addId( idCol );
251  m_query.addOrderId( idCol );
252 }
253 
255 }
256 
258  m_query.execute();
259 }
260 
262  bool prevValid = (m_itemId != -1);
263  bool currValid = false;
264  m_itemId = -1;
265  if( m_query.nextCursorRow() ){
266  coral::AttributeList& row = m_query.data();
267  m_itemId = row.begin()->data<int>();
268  currValid = true;
269  }
270 
271  if( !currValid && prevValid ) m_query.clear();
272  return currValid;
273 }
274 
276  void* ret = 0;
277  if( m_itemId != -1 ){
278  ret = m_readBuffer.read( m_itemId );
279  }
280  return ret;
281 }
282 
284  if( !ClassUtils::isType( type(), asType ) ){
285  throwException("Provided output object type \""+asType.Name(Reflex::SCOPED)+"\" does not match with the container type \""+
286  type().Name(Reflex::SCOPED)+"\"","IteratorBuffer::getItemAsType");
287  }
288  return getItem();
289 }
290 
292  return m_itemId;
293 }
294 
296  return m_readBuffer.type();
297 }
298 
300  const std::string& containerName,
301  const std::string& className,
302  unsigned int containerSize,
304  m_dbSchema( session.schema() ),
305  m_schema( new ContainerSchema(contId, containerName, className, session) ),
306  m_writeBuffer(),
307  m_updateBuffer(),
308  m_readBuffer(),
309  m_deleteBuffer(),
310  m_iteratorBuffer(),
311  m_size( containerSize ),
312  m_containerUpdateTable( session.containerUpdateTable() ),
313  m_lock( false ){
314 }
315 
317  const std::string& containerName,
318  const Reflex::Type& containerType,
320  m_dbSchema( session.schema() ),
321  m_schema( new ContainerSchema(contId, containerName, containerType, session) ),
322  m_writeBuffer(),
323  m_updateBuffer(),
324  m_readBuffer(),
325  m_deleteBuffer(),
326  m_iteratorBuffer(),
327  m_size(0),
328  m_containerUpdateTable( session.containerUpdateTable() ),
329  m_lock( false ) {
330 }
331 
333  m_iteratorBuffer.clear();
334 }
335 
337  return m_schema->containerId();
338 }
339 
341  return m_schema->containerName();
342 }
343 
345  return m_schema->className();
346 }
347 
349  return m_schema->type();
350 }
351 
353  return m_schema->mappingVersion();
354 }
355 
357  return m_size;
358 }
359 
361  if(!m_readBuffer.get()){
362  m_readBuffer.reset( new ReadBuffer( *m_schema ) );
363  }
364  if( !m_iteratorBuffer ){
365  m_iteratorBuffer.reset( new IteratorBuffer(*m_schema, *m_readBuffer ) );
366  m_iteratorBuffer->reset();
367  }
368  return m_iteratorBuffer;
369 }
370 
372  if( !m_lock ){
373  ContainerHeaderData headerData;
374  m_lock = m_dbSchema.containerHeaderTable().lockContainer( m_schema->containerId(), headerData );
375  if(!m_lock) throwException("Container \""+name()+"\" has been dropped.","DatabaseContainer::lock()");
376  // once the lock has been taken over, update the size in case has been changed...
377  m_size = headerData.numberOfObjects;
378  }
379  return m_lock;
380 }
381 
383  return m_lock;
384 }
385 
387  m_schema->create();
388 }
389 
391  if(!m_schema->dbSession().testDropPermission()){
392  throwException("Drop permission has been denied for the current user.",
393  "DatabaseContainer::drop");
394  }
395  m_schema->drop();
396  m_containerUpdateTable.remove( m_schema->containerId() );
397 }
398 
400  m_schema->extendIfRequired( dependentType );
401 }
402 
404  bool forWrite ){
405  m_schema->setAccessPermission( principal, forWrite );
406 }
407 
409 
410  if(!m_readBuffer.get()){
411  m_readBuffer.reset( new ReadBuffer( *m_schema ) );
412  }
413  return m_readBuffer->read( itemId );
414 }
415 
417  const Reflex::Type& asType){
418  if(!m_readBuffer.get()){
419  m_readBuffer.reset( new ReadBuffer( *m_schema ) );
420  }
421  if( !ClassUtils::isType( type(), asType ) ){
422  throwException("Provided output object type \""+asType.Name(Reflex::SCOPED)+"\" does not match with the container type \""+
423  type().Name(Reflex::SCOPED)+"\"","DatabaseContainer::fetchItemAsType");
424  }
425  return m_readBuffer->read( itemId );
426 }
427 
429  const Reflex::Type& dataType ){
430  if(!m_writeBuffer.get()){
431  m_writeBuffer.reset( new WriteBuffer( *m_schema ) );
432  }
433  Reflex::Type inputResType = ClassUtils::resolvedType( dataType );
434  Reflex::Type contType = ClassUtils::resolvedType(m_schema->type());
435  if( inputResType.Name()!= contType.Name() && !inputResType.HasBase( contType ) ){
436  throwException( "Provided input object type=\""+inputResType.Name()+
437  "\" does not match with the container type=\""+contType.Name()+"\"",
438  "DatabaseContainer::insertItem" );
439  }
440 
441  int newId = m_schema->containerSequences().getNextId( MappingRules::sequenceNameForContainer( m_schema->containerName()) );
442  m_writeBuffer->registerForWrite( newId, data );
443  return newId;
444 }
445 
447  const void* data,
448  const Reflex::Type& dataType ){
449  if(!m_updateBuffer.get()){
450  m_updateBuffer.reset( new UpdateBuffer( *m_schema ) );
451  }
452  Reflex::Type inputResType = ClassUtils::resolvedType( dataType );
453  Reflex::Type contType = ClassUtils::resolvedType(m_schema->type());
454  if( inputResType.Name()!= contType.Name() && !inputResType.HasBase( contType ) ){
455  throwException( "Provided input object type=\""+inputResType.Name()+"\" does not match with the container type=\""+
456  contType.Name()+"\".",
457  "DatabaseContainer::updateItem" );
458  }
459 
460  m_updateBuffer->registerForUpdate( itemId, data );
461 }
462 
463 void ora::DatabaseContainer::erase( int itemId ){
464  if(!m_deleteBuffer.get()){
465  m_deleteBuffer.reset( new DeleteBuffer( *m_schema ) );
466  }
467  m_deleteBuffer->registerForDelete( itemId );
468 }
469 
471  size_t prevSize = m_size;
472  if(m_writeBuffer.get()) m_size += m_writeBuffer->flush();
473  if(m_updateBuffer.get()) m_updateBuffer->flush();
474  if(m_deleteBuffer.get()) m_size -= m_deleteBuffer->flush();
475  m_schema->containerSequences().sinchronizeAll();
476  if( prevSize != m_size ){
477  m_containerUpdateTable.takeNote( id(), m_size );
478  }
479 }
480 
482  int itemId ){
483  m_schema->dbSession().setObjectName( name, m_schema->containerId(), itemId );
484 }
485 
486 bool ora::DatabaseContainer::getNames( std::vector<std::string>& destination ){
487  return m_schema->dbSession().getNamesForContainer( m_schema->containerId(), destination );
488 }
489 
490 
type
Definition: HCALResponse.h:21
int addWhereId(const std::string &columnName)
void registerForUpdate(int oid, const void *data)
const std::string & name()
DatabaseContainer(int contId, const std::string &containerName, const std::string &className, unsigned int containerSize, DatabaseSession &session)
WriteBuffer(ContainerSchema &contSchema)
const Reflex::Type & type()
IRelationalReader * newReader(const Reflex::Type &dataType, MappingElement &dataMapping)
void * constructObject(const Reflex::Type &typ)
Definition: ClassUtils.cc:127
coral::AttributeList & whereData()
void updateItem(int itemId, const void *data, const Reflex::Type &type)
string destination
ContainerSchema & m_contSchema
void * read(int oid)
UpdateBuffer(ContainerSchema &contSchema)
int insertItem(const void *data, const Reflex::Type &type)
bool getNames(std::vector< std::string > &destination)
void * getItemAsType(const Reflex::Type &type)
DataElement m_topLevelElement
ContainerSchema & m_contSchema
const Reflex::Type & type()
ReadBuffer(ContainerSchema &contSchema)
int addWhereId(const std::string &columnName)
const Reflex::Type & type()
bool mappingForDependentClasses(std::vector< MappingElement > &destination)
const std::string & className()
const MappingElement & topElement() const
Definition: MappingTree.h:143
SelectOperation m_query
void extendSchema(const Reflex::Type &dependentType)
std::vector< std::pair< int, const void * > > m_buffer
IteratorBuffer(ContainerSchema &schema, ReadBuffer &buffer)
iterator find(const std::string &key)
Retrieves a sub-element.
std::map< std::string, MappingElement >::iterator iterator
Iterator definition.
const std::vector< std::string > & columnNames() const
const std::string & mappingVersion()
int addId(const std::string &columnName)
void build(RelationalBuffer &buffer)
Reflex::Type resolvedType(const Reflex::Type &typ)
Definition: ClassUtils.cc:404
void addOrderId(const std::string &columnName)
std::vector< std::pair< int, const void * > > m_buffer
void setAccessPermission(const std::string &principal, bool forWrite)
std::vector< int > m_buffer
coral::AttributeList & data()
IRelationalWriter * newWriter(const Reflex::Type &dataType, MappingElement &dataMapping)
void * fetchItem(int itemId)
coral::AttributeList & whereData()
IRelationalUpdater * newUpdater(const Reflex::Type &dataType, MappingElement &dataMapping)
void registerForWrite(int oid, const void *data)
coral::ISchema & storageSchema()
void throwException(const std::string &message, const std::string &methodName) __attribute__((noreturn))
Definition: Exception.cc:10
iterator end()
Returns an iterator in the end of the sequence.
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
void registerForDelete(int oid)
void setItemName(const std::string &name, int itemId)
MappingTree & mapping(bool writeEnabled=false)
Handle< IteratorBuffer > iteratorBuffer()
const Reflex::Type & m_type
void * fetchItemAsType(int itemId, const Reflex::Type &asType)
const Reflex::Type & type()
static std::string sequenceNameForContainer(const std::string &containerName)
Definition: MappingRules.cc:14
DeleteBuffer(ContainerSchema &contSchema)
int addId(const std::string &columnName)
const std::string & tableName() const
volatile std::atomic< bool > shutdown_flag false
std::auto_ptr< IRelationalReader > m_reader
ContainerSchema & m_contSchema
std::string className(const T &t)
Definition: ClassName.h:30
SelectOperation m_topLevelQuery
bool isType(const Reflex::Type &type, const Reflex::Type &baseType)
Definition: ClassUtils.cc:45