CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ContainerSchema.cc
Go to the documentation of this file.
3 #include "ContainerSchema.h"
4 #include "DatabaseSession.h"
5 #include "IDatabaseSchema.h"
6 #include "MappingToSchema.h"
7 #include "MappingDatabase.h"
8 #include "MappingGenerator.h"
9 #include "MappingRules.h"
10 #include "ClassUtils.h"
11 // externals
12 #include "RelationalAccess/ISchema.h"
13 
14 namespace ora {
15 
17  std::map<std::string, std::set<std::string> >& tableList ){
18  const std::string& tableName = source.tableName();
19  std::map<std::string, std::set<std::string> >::iterator iTab = tableList.find( tableName );
20  if( iTab ==tableList.end() ){
21  std::set<std::string> dependencies;
22  tableList.insert(std::make_pair( tableName, dependencies ) );
23  }
24  for( MappingElement::const_iterator iElem = source.begin();
25  iElem != source.end(); iElem++ ){
26  std::map<std::string, std::set<std::string> >::iterator iT = tableList.find( tableName );
27  const std::string& innerTable = iElem->second.tableName();
28  if( innerTable != tableName ){
29  iT->second.insert( innerTable );
30  }
31  getTableHierarchyFromMappingElement( iElem->second, tableList );
32  }
33  }
34 
35  void addFromTableHierarchy( const std::string& tableName,
36  std::map<std::string, std::set<std::string> >& tableList,
37  std::vector<std::string>& orderedList ){
38  orderedList.push_back( tableName );
39  std::map<std::string, std::set<std::string> >::const_iterator iDeps = tableList.find( tableName );
40  if(iDeps != tableList.end() ){
41  for( std::set<std::string>::const_iterator iDt = iDeps->second.begin();
42  iDt != iDeps->second.end(); iDt++ ){
43  addFromTableHierarchy( *iDt, tableList, orderedList );
44  }
45  }
46  }
47 
48 }
49 
51  const std::string& containerName,
52  const Reflex::Type& containerType,
54  m_containerId( containerId ),
55  m_containerName( containerName ),
56  m_className( containerType.Name( Reflex::SCOPED ) ),
57  m_classDict( containerType ),
58  m_session( session ),
59  m_loaded( false ),
60  m_containerSchemaSequences( session.schema() ),
61  m_mapping(),
62  m_dependentMappings(){
63 }
64 
66  const std::string& containerName,
67  const std::string& className,
69  m_containerId( containerId ),
70  m_containerName( containerName ),
71  m_className( className ),
72  m_classDict(),
73  m_session( session ),
74  m_loaded( false ),
75  m_containerSchemaSequences( session.schema() ),
76  m_mapping(),
77  m_dependentMappings(){
78 }
79 
81  for( std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.begin();
82  iDep != m_dependentMappings.end(); ++iDep ){
83  delete iDep->second;
84  }
85 }
86 
88  if( !m_classDict ) m_classDict = ClassUtils::lookupDictionary( m_className, false );
89  if( !m_classDict ) throwException("Container class \""+m_className+"\" has not been found in the dictionary.",
90  "ContainerSchema::initClassDict");
91 }
92 
94 
95  initClassDict();
96  // adding the new entry in the container table
97  m_session.schema().containerHeaderTable().addContainer( m_containerId, m_containerName, m_className );
98 
99  // creating and storing the mapping
100  std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
101  MappingGenerator mapGen( m_session.schema().storageSchema() );
102  mapGen.createNewMapping( m_containerName, m_classDict, m_mapping );
103  m_mapping.setVersion( newMappingVersion );
104  m_session.mappingDatabase().storeMapping( m_mapping );
105  m_session.mappingDatabase().insertClassVersion( m_classDict, 0, m_containerId, newMappingVersion, true );
106  //m_mapping.tables();
107  // creating the sequences...
108  m_containerSchemaSequences.create( MappingRules::sequenceNameForContainer( m_containerName ) );
109  for( std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.begin();
110  iDep != m_dependentMappings.end(); ++iDep ){
111  m_containerSchemaSequences.create( MappingRules::sequenceNameForDependentClass( m_containerName, iDep->first ));
112  }
113  // finally create the tables...
114  MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
115  mapping2Schema.create( m_mapping );
116  m_loaded = true;
117 }
118 
119 void ora::ContainerSchema::getTableHierarchy( const std::set<std::string>& containerMappingVersions, std::vector<std::string>& destination ){
120  // building the table hierarchy
121  std::map< std::string, std::set<std::string> > tableHierarchy;
122  std::set<std::string> topLevelTables; // should be strictly only one!
123  for( std::set<std::string>::const_iterator iV = containerMappingVersions.begin();
124  iV!= containerMappingVersions.end(); ++iV ){
125  MappingTree mapping;
126  if( m_session.mappingDatabase().getMappingByVersion( *iV, mapping ) ){
127  topLevelTables.insert( mapping.topElement().tableName() );
128  getTableHierarchyFromMappingElement( mapping.topElement(), tableHierarchy );
129  }
130  }
131  for(std::set<std::string>::const_iterator iMainT = topLevelTables.begin();
132  iMainT != topLevelTables.end(); ++iMainT ){
133  addFromTableHierarchy( *iMainT, tableHierarchy, destination );
134  }
135 }
136 
138 
139  std::set<std::string> containerMappingVersions;
140  m_session.mappingDatabase().getMappingVersionsForContainer( m_containerId, containerMappingVersions );
141  std::vector<std::string> orderedTableList;
142  getTableHierarchy( containerMappingVersions, orderedTableList );
143 
144  // getting the dependent class list...
145  std::set<std::string> depClasses;
146  m_session.mappingDatabase().getDependentClassesForContainer( m_containerId, depClasses );
147 
148  // now the mappings can be removed
149  for( std::set<std::string>::const_iterator iM = containerMappingVersions.begin();
150  iM != containerMappingVersions.end(); ++iM ){
151  m_session.mappingDatabase().removeMapping( *iM );
152  }
153  // removing the sequences
154  m_containerSchemaSequences.erase( MappingRules::sequenceNameForContainer( m_containerName ));
155  for(std::set<std::string>::const_iterator iDepCl = depClasses.begin();
156  iDepCl != depClasses.end(); iDepCl++){
157  m_containerSchemaSequences.erase( MappingRules::sequenceNameForDependentClass( m_containerName, *iDepCl ) );
158  }
159 
160  // removing the entry in the containers table
161  m_session.schema().containerHeaderTable().removeContainer( m_containerId );
162 
163  // finally drop the container tables following the hierarchy
164  for(std::vector<std::string>::reverse_iterator iTable = orderedTableList.rbegin();
165  iTable != orderedTableList.rend(); iTable++ ){
166  m_session.schema().storageSchema().dropIfExistsTable( *iTable );
167  }
168 
169 }
170 
172  MappingGenerator mapGen( m_session.schema().storageSchema() );
173  // retrieve the base mapping
174  MappingTree baseMapping;
175  if( !m_session.mappingDatabase().getBaseMappingForContainer( m_classDict.Name(Reflex::SCOPED), m_containerId, baseMapping )){
176  throwException("Base mapping has not been found in the database.",
177  "ContainerSchema::evolve");
178  }
179  mapGen.createNewMapping( m_containerName, m_classDict, baseMapping, m_mapping );
180  std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
181  m_mapping.setVersion( newMappingVersion );
182  m_session.mappingDatabase().storeMapping( m_mapping );
183  m_session.mappingDatabase().insertClassVersion( m_classDict, 0, m_containerId, newMappingVersion );
184  MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
185  mapping2Schema.alter( m_mapping );
186  m_loaded = true;
187 }
188 
189 void ora::ContainerSchema::evolve( const Reflex::Type& dependentClass, MappingTree& baseMapping ){
190  std::string className = dependentClass.Name(Reflex::SCOPED);
191  MappingGenerator mapGen( m_session.schema().storageSchema() );
192  std::map<std::string,MappingTree*>::iterator iDep =
193  m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
194  if( baseMapping.className() != dependentClass.Name(Reflex::SCOPED) ){
195  throwException("Provided base mapping does not map class \""+dependentClass.Name(Reflex::SCOPED)+"\".",
196  "ContainerSchema::evolve");
197  }
198  mapGen.createNewDependentMapping( dependentClass, m_mapping, baseMapping, *iDep->second );
199  std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
200  iDep->second->setVersion( newMappingVersion );
201  m_session.mappingDatabase().storeMapping( *iDep->second );
202  m_session.mappingDatabase().insertClassVersion( dependentClass, 1, m_containerId, newMappingVersion, false );
203 }
204 
206  bool forWrite ){
207  std::set<std::string> containerMappingVersions;
208  m_session.mappingDatabase().getMappingVersionsForContainer( m_containerId, containerMappingVersions );
209  std::vector<std::string> orderedTableList;
210  getTableHierarchy( containerMappingVersions, orderedTableList );
211  for( std::vector<std::string>::const_iterator iT = orderedTableList.begin();
212  iT != orderedTableList.end(); iT++ ){
213  setTableAccessPermission( m_session.schema().storageSchema().tableHandle( *iT ), principal, forWrite );
214  }
215 }
216 
218  initClassDict();
219  return m_classDict;
220 }
221 
223  initClassDict();
224  if(!m_loaded ){
225  std::string classVersion = MappingDatabase::versionOfClass( m_classDict );
226  if( !m_session.mappingDatabase().getMappingForContainer( m_className, classVersion, m_containerId, m_mapping ) ){
227  // if enabled, invoke the evolution
228  if( writeEnabled && m_session.configuration().properties().getFlag( Configuration::automaticSchemaEvolution() )){
229  evolve();
230  } else {
231  std::string msg( "No mapping available for the class=\""+m_className+"\" version=\""+classVersion+"\"." );
232  throwException( msg,
233  "ContainerSchema::mapping");
234  }
235  } else {
236  m_loaded = true;
237  }
238 
239  }
240  if( m_mapping.topElement().find( m_className )==m_mapping.topElement().end() ){
241  throwException( "Mapping for container class \""+m_className+"\" could not be loaded.",
242  "ContainerSchema::mapping");
243  }
244  return m_mapping;
245 }
246 
248  if( !dependentClassDict ) throwException("The dependent class has not been found in the dictionary.",
249  "ContainerSchema::loadMappingForDependentClass");
250  std::string className = dependentClassDict.Name(Reflex::SCOPED);
251  std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.find( className );
252  if( iDep == m_dependentMappings.end() ){
253  // not in cache, search the database...
254  iDep = m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
255  if( ! m_session.mappingDatabase().getMappingForContainer( className,
256  MappingDatabase::versionOfClass( dependentClassDict ),
257  m_containerId,
258  *iDep->second ) ){
259  m_dependentMappings.erase( className );
260  return false;
261  }
262  }
263  return true;
264 }
265 
266 void ora::ContainerSchema::create( const Reflex::Type& dependentClassDict ){
267  std::string className = dependentClassDict.Name(Reflex::SCOPED);
268  std::map<std::string,MappingTree*>::iterator iDep =
269  m_dependentMappings.insert( std::make_pair( className, new MappingTree ) ).first;
270  MappingGenerator mapGen( m_session.schema().storageSchema() );
271  MappingToSchema mapping2Schema( m_session.schema().storageSchema() );
272  mapGen.createNewDependentMapping( dependentClassDict, m_mapping, *iDep->second );
273  mapping2Schema.create( *iDep->second );
274  std::string newMappingVersion = m_session.mappingDatabase().newMappingVersionForContainer( m_containerName );
275  iDep->second->setVersion( newMappingVersion );
276  m_session.mappingDatabase().storeMapping( *iDep->second );
277  m_session.mappingDatabase().insertClassVersion( dependentClassDict, 1, m_containerId, newMappingVersion, true );
278  m_containerSchemaSequences.create( MappingRules::sequenceNameForDependentClass( m_containerName, className ));
279 }
280 
281 void ora::ContainerSchema::extend( const Reflex::Type& dependentClassDict ){
282  std::string className = dependentClassDict.Name(Reflex::SCOPED);
283  MappingTree baseMapping;
284  if( !m_session.mappingDatabase().getBaseMappingForContainer( className,
285  m_containerId, baseMapping ) ){
286  create( dependentClassDict );
287  } else {
288  evolve( dependentClassDict, baseMapping );
289  }
290 }
291 
292 bool ora::ContainerSchema::extendIfRequired( const Reflex::Type& dependentClassDict ){
293  bool ret = false;
294  if( ! loadMappingForDependentClass( dependentClassDict ) ){
295  extend( dependentClassDict );
296  ret = true;
297  }
298  return ret;
299 }
300 
302  bool writeEnabled ){
303  std::string className = dependentClassDict.Name(Reflex::SCOPED);
304  if( ! loadMappingForDependentClass( dependentClassDict ) ){
305  if( writeEnabled ){
306  // check if a base is available:
307  MappingTree baseMapping;
308  if( !m_session.mappingDatabase().getBaseMappingForContainer( className,
309  m_containerId, baseMapping ) ){
310  // mapping has to be generated from scratch
311  if( m_session.configuration().properties().getFlag( Configuration::automaticDatabaseCreation()) ||
312  m_session.configuration().properties().getFlag( Configuration::automaticContainerCreation() ) ){
313  create( dependentClassDict );
314  }
315  } else {
316  // evolve if allowed
317  if( m_session.configuration().properties().getFlag( Configuration::automaticSchemaEvolution() )){
318  evolve( dependentClassDict, baseMapping );
319  }
320  }
321  }
322  }
323  std::map<std::string,MappingTree*>::iterator iDep = m_dependentMappings.find( className );
324  if( iDep == m_dependentMappings.end() ){
325  throwException( "Mapping for class \""+ className + "\" is not available in the database.",
326  "ContainerSchema::mappingForDependentClass");
327  }
328  return iDep->second->topElement();
329 }
330 
331 bool ora::ContainerSchema::mappingForDependentClasses( std::vector<ora::MappingElement>& destination ){
332  return m_session.mappingDatabase().getDependentMappingsForContainer( m_containerId, destination );
333 }
334 
336  return m_containerSchemaSequences;
337 }
338 
340  return m_session.configuration().blobStreamingService();
341 }
342 
344  return m_session.configuration().referenceHandler();
345 }
346 
348  return m_mapping.version();
349 }
350 
352  return m_containerId;
353 }
354 
356  return m_containerName;
357 }
358 
360  return m_className;
361 }
362 
364  return m_session.schema().storageSchema();
365 }
366 
368  return m_session;
369 }
370 
371 
372 
Sequences & containerSequences()
void addFromTableHierarchy(const std::string &tableName, std::map< std::string, std::set< std::string > > &tableList, std::vector< std::string > &orderedList)
const std::string & className() const
Definition: MappingTree.h:138
IReferenceHandler * referenceHandler()
void setAccessPermission(const std::string &principal, bool forWrite)
string destination
static std::string automaticContainerCreation()
void getTableHierarchyFromMappingElement(const MappingElement &source, std::map< std::string, std::set< std::string > > &tableList)
bool extendIfRequired(const Reflex::Type &dependentClass)
void setTableAccessPermission(coral::ITable &table, const std::string &principal, bool forWrite)
static std::string automaticDatabaseCreation()
void getTableHierarchy(const std::set< std::string > &containerMappingVersions, std::vector< std::string > &destination)
const Reflex::Type & type()
iterator begin()
Returns an iterator in the beginning of the sequence.
MappingElement & mappingForDependentClass(const Reflex::Type &dependentClass, bool writeEnabled=false)
bool mappingForDependentClasses(std::vector< MappingElement > &destination)
const std::string & className()
const MappingElement & topElement() const
Definition: MappingTree.h:143
void createNewMapping(const std::string &containerName, const Reflex::Type &classDictionary, MappingTree &destination)
static std::string versionOfClass(const Reflex::Type &dictionary)
bool loadMappingForDependentClass(const Reflex::Type &dependentClass)
DatabaseSession & dbSession()
Interface for a Streaming Service.
void alter(const MappingTree &mapping)
const std::string & containerName()
void create(const MappingTree &mapping)
coral::ISchema & storageSchema()
std::map< std::string, MappingElement >::const_iterator const_iterator
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.
MappingTree & mapping(bool writeEnabled=false)
static std::string sequenceNameForContainer(const std::string &containerName)
Definition: MappingRules.cc:14
const std::string & tableName() const
static std::string automaticSchemaEvolution()
static std::string sequenceNameForDependentClass(const std::string &containerName, const std::string &className)
Definition: MappingRules.cc:20
volatile std::atomic< bool > shutdown_flag false
ContainerSchema(int containerId, const std::string &containerName, const Reflex::Type &containerType, DatabaseSession &session)
Reflex::Type lookupDictionary(const std::type_info &typeInfo, bool throwFlag=true)
Definition: ClassUtils.cc:93
static std::string const source
Definition: EdmProvDump.cc:43
const std::string & mappingVersion()
SurfaceDeformation * create(int type, const std::vector< double > &params)
IBlobStreamingService * blobStreamingService()
std::string className(const T &t)
Definition: ClassName.h:30
void extend(const Reflex::Type &dependentClass)