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 namespace ora {
19 
20  class WriteBuffer {
21  public:
22  explicit WriteBuffer( ContainerSchema& contSchema ):
23  m_buffer(),
24  m_contSchema( contSchema ){
25  }
26 
28  }
29 
30  void registerForWrite( int oid, const void* data ){
31  m_buffer.push_back( std::make_pair(oid, data ) );
32  }
33 
34  size_t flush(){
35  size_t nobj = 0;
36  if( m_buffer.size() ){
37  MappingElement& topLevelMapping = m_contSchema.mapping( true ).topElement();
38  RelationalBuffer operationBuffer( m_contSchema.storageSchema() );
39  InsertOperation* topLevelInsert = &operationBuffer.newInsert( topLevelMapping.tableName() );
40  topLevelInsert->addId( topLevelMapping.columnNames()[ 0 ] );
42  MappingElement::iterator iMap = topLevelMapping.find( type.Name(Reflex::SCOPED) );
43  // the first inner mapping is the relevant...
44  if( iMap == topLevelMapping.end()){
45  throwException("Could not find a mapping element for class \""+
46  type.Name(Reflex::SCOPED)+"\"",
47  "WriteBuffer::flush");
48  }
49  MappingElement& mapping = iMap->second;
50  RelationalStreamerFactory streamerFactory( m_contSchema );
51  DataElement topLevelElement;
52  std::auto_ptr<IRelationalWriter> writer( streamerFactory.newWriter( type, mapping ) );
53  writer->build( topLevelElement, *topLevelInsert, operationBuffer );
54 
55  for( std::vector<std::pair<int, const void*> >::const_iterator iW = m_buffer.begin();
56  iW != m_buffer.end(); ++iW ){
57  int oid = iW->first;
58  const void* data = iW->second;
59  coral::AttributeList& dataBuff = topLevelInsert->data();
60  dataBuff.begin()->data<int>() = oid;
61  writer->write( oid, data );
62  if( operationBuffer.flush() ) nobj++;
63  }
64  m_buffer.clear();
65  }
66  return nobj;
67  }
68 
69 
70  private:
71  std::vector<std::pair<int, const void*> > m_buffer;
73 
74  };
75 
76  class UpdateBuffer {
77  public:
78  explicit UpdateBuffer( ContainerSchema& contSchema ):
79  m_buffer(),
80  m_contSchema( contSchema ){
81  }
82 
84  }
85 
86 
87  void registerForUpdate( int oid, const void* data ){
88  m_buffer.push_back( std::make_pair( oid, data ));
89  }
90 
91 
92  size_t flush(){
93  size_t nobj = 0;
94  if( m_buffer.size() ){
95  RelationalBuffer operationBuffer( m_contSchema.storageSchema() );
96  std::vector<MappingElement> dependentMappings;
97  m_contSchema.mappingForDependentClasses( dependentMappings );
98  RelationalDeleter depDeleter( dependentMappings );
99  depDeleter.build( operationBuffer );
100  dependentMappings.clear();
101 
102  MappingElement& topLevelMapping = m_contSchema.mapping( true ).topElement();
103  UpdateOperation* topLevelUpdate = &operationBuffer.newUpdate( topLevelMapping.tableName(), true );
104  topLevelUpdate->addId( topLevelMapping.columnNames()[ 0 ] );
105  topLevelUpdate->addWhereId( topLevelMapping.columnNames()[ 0 ] );
106  const Reflex::Type& type = m_contSchema.type();
107  MappingElement::iterator iMap = topLevelMapping.find( type.Name(Reflex::SCOPED) );
108  // the first inner mapping is the relevant...
109  if( iMap == topLevelMapping.end()){
110  throwException("Could not find a mapping element for class \""+
111  type.Name(Reflex::SCOPED)+"\"",
112  "UpdateBuffer::flush");
113  }
114  MappingElement& mapping = iMap->second;
115  RelationalStreamerFactory streamerFactory( m_contSchema );
116  DataElement topLevelElement;
117  std::auto_ptr<IRelationalUpdater> updater( streamerFactory.newUpdater( type, mapping ));
118  updater->build( topLevelElement, *topLevelUpdate, operationBuffer );
119  for( std::vector<std::pair<int, const void*> >::const_iterator iU = m_buffer.begin();
120  iU != m_buffer.end(); ++iU ){
121  int oid = iU->first;
122  const void* data = iU->second;
123  // erase the dependencies (they cannot be updated...)
124  depDeleter.erase( oid );
125  coral::AttributeList& dataBuff = topLevelUpdate->data();
126  dataBuff.begin()->data<int>() = oid;
127  coral::AttributeList& whereDataBuff = topLevelUpdate->whereData();
128  whereDataBuff.begin()->data<int>() = oid;
129  updater->update( oid, data );
130  if( operationBuffer.flush()) nobj++;
131  }
132  m_buffer.clear();
133  }
134  return nobj;
135  }
136 
137  private:
138  std::vector<std::pair<int, const void*> > m_buffer;
140  };
141 
142  class ReadBuffer {
143  public:
144  explicit ReadBuffer( ContainerSchema& contSchema ):
146  m_type( contSchema.type() ),
147  m_reader(),
148  m_topLevelQuery( contSchema.mapping().topElement().tableName(), contSchema.storageSchema() ){
149 
150  MappingElement& topLevelMapping = contSchema.mapping().topElement();
151  m_topLevelQuery.addWhereId( topLevelMapping.columnNames()[ 0 ] );
152  MappingElement::iterator iMap = topLevelMapping.find( m_type.Name(Reflex::SCOPED) );
153  // the first inner mapping is the good one ...
154  if( iMap == topLevelMapping.end()){
155  throwException("Could not find a mapping element for class \""+
156  m_type.Name(Reflex::SCOPED)+"\"",
157  "ReadBuffer::ReadBuffer");
158  }
159  MappingElement& mapping = iMap->second;
160  RelationalStreamerFactory streamerFactory( contSchema );
161  m_reader.reset( streamerFactory.newReader( m_type, mapping )) ;
163  }
164 
166  }
167 
168  void* read( int oid ){
169  coral::AttributeList& dataBuff = m_topLevelQuery.whereData();
170  dataBuff.begin()->data<int>() = oid;
172  m_reader->select( oid );
173  void* destination = 0;
175  destination = ClassUtils::constructObject( m_type );
176  m_reader->read( destination );
177  }
178  m_reader->clear();
180  return destination;
181  }
182 
183  const Reflex::Type& type(){
184  return m_type;
185  }
186 
187  private:
190  std::auto_ptr<IRelationalReader> m_reader;
192  };
193 
194  class DeleteBuffer {
195  public:
196  explicit DeleteBuffer( ContainerSchema& contSchema ):
197  m_buffer(),
198  m_contSchema( contSchema ){
199  }
200 
202  }
203 
204 
205  void registerForDelete( int oid ){
206  m_buffer.push_back( oid );
207  }
208 
209  size_t flush(){
210  size_t nobj = 0;
211  if( m_buffer.size()) {
212  RelationalBuffer operationBuffer( m_contSchema.storageSchema() );
214  mainDeleter.build( operationBuffer );
215  std::vector<MappingElement> dependentMappings;
216  m_contSchema.mappingForDependentClasses( dependentMappings );
217  RelationalDeleter depDeleter( dependentMappings );
218  depDeleter.build( operationBuffer );
219  dependentMappings.clear();
220 
221  for( std::vector<int>::const_iterator iD = m_buffer.begin();
222  iD != m_buffer.end(); ++iD ){
223  depDeleter.erase( *iD );
224  mainDeleter.erase( *iD );
225  if( operationBuffer.flush() ) nobj++;
226  }
227  m_buffer.clear();
228  }
229  return nobj;
230  }
231 
232  private:
233  std::vector<int> m_buffer;
235  };
236 
237 }
238 
240  ReadBuffer& buffer ):
241  m_query( schema.mapping().topElement().tableName(), schema.storageSchema() ),
242  m_itemId( -1 ),
243  m_readBuffer( buffer ){
244  const std::string& idCol = schema.mapping().topElement().columnNames()[0];
245  m_query.addId( idCol );
246  m_query.addOrderId( idCol );
247 }
248 
250 }
251 
253  m_query.execute();
254 }
255 
257  bool prevValid = (m_itemId != -1);
258  bool currValid = false;
259  m_itemId = -1;
260  if( m_query.nextCursorRow() ){
261  coral::AttributeList& row = m_query.data();
262  m_itemId = row.begin()->data<int>();
263  currValid = true;
264  }
265 
266  if( !currValid && prevValid ) m_query.clear();
267  return currValid;
268 }
269 
271  void* ret = 0;
272  if( m_itemId != -1 ){
273  ret = m_readBuffer.read( m_itemId );
274  }
275  return ret;
276 }
277 
279  if( !ClassUtils::isType( type(), asType ) ){
280  throwException("Provided output object type \""+asType.Name(Reflex::SCOPED)+"\" does not match with the container type \""+
281  type().Name(Reflex::SCOPED)+"\"","IteratorBuffer::getItemAsType");
282  }
283  return getItem();
284 }
285 
287  return m_itemId;
288 }
289 
291  return m_readBuffer.type();
292 }
293 
295  const std::string& containerName,
296  const std::string& className,
297  unsigned int containerSize,
299  m_dbSchema( session.schema() ),
300  m_schema( new ContainerSchema(contId, containerName, className, session) ),
301  m_writeBuffer(),
302  m_updateBuffer(),
303  m_readBuffer(),
304  m_deleteBuffer(),
305  m_iteratorBuffer(),
306  m_size( containerSize ),
307  m_containerUpdateTable( session.containerUpdateTable() ),
308  m_lock( false ){
309 }
310 
312  const std::string& containerName,
313  const Reflex::Type& containerType,
315  m_dbSchema( session.schema() ),
316  m_schema( new ContainerSchema(contId, containerName, containerType, session) ),
317  m_writeBuffer(),
318  m_updateBuffer(),
319  m_readBuffer(),
320  m_deleteBuffer(),
321  m_iteratorBuffer(),
322  m_size(0),
323  m_containerUpdateTable( session.containerUpdateTable() ),
324  m_lock( false ) {
325 }
326 
328  m_iteratorBuffer.clear();
329 }
330 
332  return m_schema->containerId();
333 }
334 
335 const std::string& ora::DatabaseContainer::name(){
336  return m_schema->containerName();
337 }
338 
340  return m_schema->className();
341 }
342 
344  return m_schema->type();
345 }
346 
348  return m_schema->mappingVersion();
349 }
350 
352  return m_size;
353 }
354 
356  if(!m_readBuffer.get()){
357  m_readBuffer.reset( new ReadBuffer( *m_schema ) );
358  }
359  if( !m_iteratorBuffer ){
360  m_iteratorBuffer.reset( new IteratorBuffer(*m_schema, *m_readBuffer ) );
361  m_iteratorBuffer->reset();
362  }
363  return m_iteratorBuffer;
364 }
365 
367  if( !m_lock ){
368  ContainerHeaderData headerData;
369  m_lock = m_dbSchema.containerHeaderTable().lockContainer( m_schema->containerId(), headerData );
370  if(!m_lock) throwException("Container \""+name()+"\" has been dropped.","DatabaseContainer::lock()");
371  // once the lock has been taken over, update the size in case has been changed...
372  m_size = headerData.numberOfObjects;
373  }
374  return m_lock;
375 }
376 
378  return m_lock;
379 }
380 
382  m_schema->create();
383 }
384 
386  if(!m_schema->dbSession().testDropPermission()){
387  throwException("Drop permission has been denied for the current user.",
388  "DatabaseContainer::drop");
389  }
390  m_schema->drop();
391  m_containerUpdateTable.remove( m_schema->containerId() );
392 }
393 
395  m_schema->extendIfRequired( dependentType );
396 }
397 
399  bool forWrite ){
400  m_schema->setAccessPermission( principal, forWrite );
401 }
402 
404 
405  if(!m_readBuffer.get()){
406  m_readBuffer.reset( new ReadBuffer( *m_schema ) );
407  }
408  return m_readBuffer->read( itemId );
409 }
410 
412  const Reflex::Type& asType){
413  if(!m_readBuffer.get()){
414  m_readBuffer.reset( new ReadBuffer( *m_schema ) );
415  }
416  if( !ClassUtils::isType( type(), asType ) ){
417  throwException("Provided output object type \""+asType.Name(Reflex::SCOPED)+"\" does not match with the container type \""+
418  type().Name(Reflex::SCOPED)+"\"","DatabaseContainer::fetchItemAsType");
419  }
420  return m_readBuffer->read( itemId );
421 }
422 
424  const Reflex::Type& dataType ){
425  if(!m_writeBuffer.get()){
426  m_writeBuffer.reset( new WriteBuffer( *m_schema ) );
427  }
428  Reflex::Type inputResType = ClassUtils::resolvedType( dataType );
429  Reflex::Type contType = ClassUtils::resolvedType(m_schema->type());
430  if( inputResType.Name()!= contType.Name() && !inputResType.HasBase( contType ) ){
431  throwException( "Provided input object type=\""+inputResType.Name()+
432  "\" does not match with the container type=\""+contType.Name()+"\"",
433  "DatabaseContainer::insertItem" );
434  }
435 
436  int newId = m_schema->containerSequences().getNextId( MappingRules::sequenceNameForContainer( m_schema->containerName()) );
437  m_writeBuffer->registerForWrite( newId, data );
438  return newId;
439 }
440 
442  const void* data,
443  const Reflex::Type& dataType ){
444  if(!m_updateBuffer.get()){
445  m_updateBuffer.reset( new UpdateBuffer( *m_schema ) );
446  }
447  Reflex::Type inputResType = ClassUtils::resolvedType( dataType );
448  Reflex::Type contType = ClassUtils::resolvedType(m_schema->type());
449  if( inputResType.Name()!= contType.Name() && !inputResType.HasBase( contType ) ){
450  throwException( "Provided input object type=\""+inputResType.Name()+"\" does not match with the container type=\""+
451  contType.Name()+"\".",
452  "DatabaseContainer::updateItem" );
453  }
454 
455  m_updateBuffer->registerForUpdate( itemId, data );
456 }
457 
458 void ora::DatabaseContainer::erase( int itemId ){
459  if(!m_deleteBuffer.get()){
460  m_deleteBuffer.reset( new DeleteBuffer( *m_schema ) );
461  }
462  m_deleteBuffer->registerForDelete( itemId );
463 }
464 
466  size_t prevSize = m_size;
467  if(m_writeBuffer.get()) m_size += m_writeBuffer->flush();
468  if(m_updateBuffer.get()) m_updateBuffer->flush();
469  if(m_deleteBuffer.get()) m_size -= m_deleteBuffer->flush();
470  m_schema->containerSequences().sinchronizeAll();
471  if( prevSize != m_size ){
472  m_containerUpdateTable.takeNote( id(), m_size );
473  }
474 }
475 
476 void ora::DatabaseContainer::setItemName( const std::string& name,
477  int itemId ){
478  m_schema->dbSession().setObjectName( name, m_schema->containerId(), itemId );
479 }
480 
481 bool ora::DatabaseContainer::getNames( std::vector<std::string>& destination ){
482  return m_schema->dbSession().getNamesForContainer( m_schema->containerId(), destination );
483 }
484 
485 
type
Definition: HCALResponse.h:22
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)
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()
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
void throwException(const std::string &message, const std::string &methodName)
Definition: Exception.cc:10
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