1 #include "lazyTypes.h"
2 #include "lazyInstMgr.h"
3 #include "Registry.h"
4 #include <SubSuperIterators.h>
5 #include "SdaiSchemaInit.h"
6 #include "instMgrHelper.h"
7 #include "lazyRefs.h"
8 
lazyInstMgr()9 lazyInstMgr::lazyInstMgr() {
10     _headerRegistry = new Registry( HeaderSchemaInit );
11     _instanceTypes = new instanceTypes_t( 255 ); //NOTE arbitrary max of 255 chars for a type name
12     _lazyInstanceCount = 0;
13     _loadedInstanceCount = 0;
14     _longestTypeNameLen = 0;
15     _mainRegistry = 0;
16     _errors = new ErrorDescriptor();
17     _ima = new instMgrAdapter( this );
18 }
19 
~lazyInstMgr()20 lazyInstMgr::~lazyInstMgr() {
21     delete _headerRegistry;
22     delete _errors;
23     delete _ima;
24     //loop over files, sections, instances; delete header instances
25     lazyFileReaderVec_t::iterator fit = _files.begin();
26     for( ; fit != _files.end(); ++fit ) {
27         delete *fit;
28     }
29     dataSectionReaderVec_t::iterator sit = _dataSections.begin();
30     for( ; sit != _dataSections.end(); ++sit ) {
31         delete *sit;
32     }
33     _instancesLoaded.clear();
34     _instanceStreamPos.clear();
35 }
36 
registerDataSection(lazyDataSectionReader * sreader)37 sectionID lazyInstMgr::registerDataSection( lazyDataSectionReader * sreader ) {
38     _dataSections.push_back( sreader );
39     return _dataSections.size() - 1;
40 }
41 
addLazyInstance(namedLazyInstance inst)42 void lazyInstMgr::addLazyInstance( namedLazyInstance inst ) {
43     _lazyInstanceCount++;
44     assert( inst.loc.begin > 0 && inst.loc.instance > 0 );
45     int len = strlen( inst.name );
46     if( len > _longestTypeNameLen ) {
47         _longestTypeNameLen = len;
48         _longestTypeName = inst.name;
49     }
50     _instanceTypes->insert( inst.name, inst.loc.instance );
51     /* store 16 bits of section id and 48 of instance offset into one 64-bit int
52     ** TODO: check and warn if anything is lost (in calling code?)
53     ** does 32bit need anything special?
54     **
55     ** create conversion class?
56     **  could then initialize conversion object with number of bits
57     **  also a good place to check for data loss
58     */
59     positionAndSection ps = inst.loc.section;
60     ps <<= 48;
61     ps |= ( inst.loc.begin & 0xFFFFFFFFFFFFULL );
62     _instanceStreamPos.insert( inst.loc.instance, ps );
63 
64     if( inst.refs ) {
65         if( inst.refs->size() > 0 ) {
66             //forward refs
67             _fwdInstanceRefs.insert( inst.loc.instance, *inst.refs );
68             instanceRefs::iterator it = inst.refs->begin();
69             for( ; it != inst.refs->end(); ++it ) {
70                 //reverse refs
71                 _revInstanceRefs.insert( *it, inst.loc.instance );
72             }
73         } else {
74             delete inst.refs;
75         }
76     }
77 }
78 
getNumTypes() const79 unsigned long lazyInstMgr::getNumTypes() const {
80     unsigned long n = 0 ;
81     instanceTypes_t::cpair curr, end;
82     end = _instanceTypes->end();
83     curr = _instanceTypes->begin();
84     if( curr.value != 0 ) {
85         n = 1;
86         while( curr.value != end.value ) {
87             n++;
88             curr = _instanceTypes->next();
89         }
90     }
91     return n ;
92 }
93 
openFile(std::string fname)94 void lazyInstMgr::openFile( std::string fname ) {
95     //don't want to hold a lock for the entire time we're reading the file.
96     //create a place in the vector and remember its location, then free lock
97     ///FIXME begin atomic op
98     size_t i = _files.size();
99     _files.push_back( (lazyFileReader * ) 0 );
100     ///FIXME end atomic op
101     lazyFileReader * lfr = new lazyFileReader( fname, this, i );
102     _files[i] = lfr;
103     /// TODO resolve inverse attr references
104     //between instances, or eDesc --> inst????
105 }
106 
loadInstance(instanceID id,bool reSeek)107 SDAI_Application_instance * lazyInstMgr::loadInstance( instanceID id, bool reSeek ) {
108     assert( _mainRegistry && "Main registry has not been initialized. Do so with initRegistry() or setRegistry()." );
109     std::streampos oldPos;
110     positionAndSection ps;
111     sectionID sid;
112     SDAI_Application_instance * inst = _instancesLoaded.find( id );
113     if( inst ) {
114         return inst;
115     }
116     instanceStreamPos_t::cvector * cv;
117     if( 0 != ( cv = _instanceStreamPos.find( id ) ) ) {
118         switch( cv->size() ) {
119             case 0:
120                 std::cerr << "Instance #" << id << " not found in any section." << std::endl;
121                 break;
122             case 1:
123                 long int off;
124                 ps = cv->at( 0 );
125                 off = ps & 0xFFFFFFFFFFFFULL;
126                 sid = ps >> 48;
127                 assert( _dataSections.size() > sid );
128                 if( reSeek ) {
129                     oldPos = _dataSections[sid]->tellg();
130                 }
131                 inst = _dataSections[sid]->getRealInstance( _mainRegistry, off, id );
132                 if( reSeek ) {
133                     _dataSections[sid]->seekg( oldPos );
134                 }
135                 break;
136             default:
137                 std::cerr << "Instance #" << id << " exists in multiple sections. This is not yet supported." << std::endl;
138                 break;
139         }
140         if( ( inst ) && ( inst != & NilSTEPentity ) ) {
141             _instancesLoaded.insert( id, inst );
142             _loadedInstanceCount++;
143             lazyRefs lr( this, inst );
144             lazyRefs::referentInstances_t insts = lr.result();
145         } else {
146             std::cerr << "Error loading instance #" << id << "." << std::endl;
147         }
148     } else {
149         std::cerr << "Instance #" << id << " not found in any section." << std::endl;
150     }
151     return inst;
152 }
153 
154 
instanceDependencies(instanceID id)155 instanceSet * lazyInstMgr::instanceDependencies( instanceID id ) {
156     instanceSet * checkedDependencies = new instanceSet();
157     instanceRefs dependencies; //Acts as queue for checking duplicated dependency
158 
159     instanceRefs_t * _fwdRefs = getFwdRefs();
160     instanceRefs_t::cvector * _fwdRefsVec = _fwdRefs->find( id );
161     //Initially populating direct dependencies of id into the queue
162     if( _fwdRefsVec != 0 ) {
163         dependencies.insert( dependencies.end(), _fwdRefsVec->begin(), _fwdRefsVec->end() );
164     }
165 
166     size_t curPos = 0;
167     while( curPos < dependencies.size() ) {
168 
169         bool isNewElement = ( checkedDependencies->insert( dependencies.at( curPos ) ) ).second;
170         if( isNewElement ) {
171             _fwdRefsVec = _fwdRefs->find( dependencies.at( curPos ) );
172 
173             if( _fwdRefsVec != 0 ) {
174                 dependencies.insert( dependencies.end(), _fwdRefsVec->begin(), _fwdRefsVec->end() );
175             }
176         }
177 
178         curPos++;
179     }
180 
181     return checkedDependencies;
182 }
183 
184