1 r.kieninger 1.1.2.1 //%LICENSE////////////////////////////////////////////////////////////////
2 //
3 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 r.kieninger 1.1.2.1 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //////////////////////////////////////////////////////////////////////////
29 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <Pegasus/Common/Config.h>
33 #include <cstdlib>
34 #include <cstdio>
35 #include <Pegasus/Common/SCMOStreamer.h>
36 #include <Pegasus/Common/ArrayIterator.h>
37 #include <Pegasus/Common/Tracer.h>
38
39 PEGASUS_USING_STD;
40
41 PEGASUS_NAMESPACE_BEGIN
42
43 r.kieninger 1.1.2.1
44 SCMOStreamer::SCMOStreamer(CIMBuffer& out, Array<SCMOInstance>& x) :
45 _buf(out),
46 _scmoInstances(x),
47 _ttlNumInstances(0),
48 _ttlNumClasses(0)
49 {
50 };
51
52
53 // Writes the list of SCMOInstances stored in this instance of SCMOStreamer
54 // to the output buffer, including their referenced Classes and Instances
55 void SCMOStreamer::serialize()
56 {
57 PEG_METHOD_ENTER(TRC_DISPATCHER,"SCMOStreamer::serialize");
58
59 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL3,
60 "Serializing %d instances\n",
61 _scmoInstances.size()));
62
63 ConstArrayIterator<SCMOInstance> iterator(_scmoInstances);
64 r.kieninger 1.1.2.1
65 // First build the tables for references classes and instances
66 for (Uint32 i = 0; i < iterator.size(); i++)
67 {
68 const SCMOInstance& inst = iterator[i];
69
70 _appendToResolverTables(inst);
71 }
72
73 _putClasses();
74
75 _putInstances();
76
77 //dumpTables();
78
79 PEG_METHOD_EXIT();
80 }
81
82 // Reads a list of SCMOInstances from the input buffer and stores them in this
83 // instance of SCMOStreamer, including their referenced Classes and Instances
84 bool SCMOStreamer::deserialize()
85 r.kieninger 1.1.2.1 {
86 PEG_METHOD_ENTER(TRC_DISPATCHER,"SCMOStreamer::serialize");
87
88 if(!_getClasses())
89 {
90 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
91 "Failed to get Classes!");
92 PEG_METHOD_EXIT();
93 return false;
94 }
95
96 if(!_getInstances())
97 {
98 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
99 "Failed to get Instances!");
100 PEG_METHOD_EXIT();
101 return false;
102 }
103
104 //dumpTables();
105
106 r.kieninger 1.1.2.1 PEG_METHOD_EXIT();
107 return true;
108 }
109
110 // This function takes and instance and adds all of its external
111 // references (SCMOClass and SCMOInstances) to the index tables
112 // For referenced SCMOInstances, the function recusively calls itself.
113 //
114 // Returns the index position at which the class for this instance was inserted
115 // in the class resolver table.
116 Uint32 SCMOStreamer::_appendToResolverTables(const SCMOInstance& inst)
117 {
118 // First handle the external references to other SCMOInstances
119 Uint32 numExtRefs = inst.numberExtRef();
120 for (Uint32 x=0; x < numExtRefs; x++)
121 {
122 SCMOInstance* extRef = inst.getExtRef(x);
123
124 Uint32 idx = _appendToResolverTables(*extRef);
125 _appendToInstResolverTable(*extRef,idx);
126 }
127 r.kieninger 1.1.2.1
128 // Add the instance to the class resolution table
129 // (Also adds the class to the class table when neccessary)
130 return _appendToClassResolverTable(inst);
131 }
132
133
134 // This function adds the given instance to the instance resolver table,
135 // which stores the connections between instances and their external
136 // references.
137 //
138 // Returns the index position at which the instance was inserted in the
139 // instance resolver table.
140 Uint32 SCMOStreamer::_appendToInstResolverTable(
141 const SCMOInstance& inst,
142 Uint32 idx)
143 {
144 SCMOResultionTable tableEntry;
145
146 tableEntry.scmbptr = (void*)&inst;
147 tableEntry.index = idx;
148 r.kieninger 1.1.2.1
149 _instResolverTable.append(tableEntry);
150
151 // The number of elements in the array minus 1 is the index position
152 // at which the instance was added.
153 return _instResolverTable.size() - 1;
154 }
155
156
157 // Adds an instance to the class resolution table.
158 // Also adds the class to the class table when neccessary
159 //
160 // Returns the index position at which the instance was inserted in the
161 // instance resolver table.
162 Uint32 SCMOStreamer::_appendToClassResolverTable(const SCMOInstance& inst)
163 {
164 // Add the SCMOClass for this instance to the class table,
165 // or give us the index at which the class resides in the table
166 Uint32 clsIdx = _appendToClassTable(inst);
167
168
169 r.kieninger 1.1.2.1 // Now build a new entry for the class resolution table
170 SCMOResultionTable tableEntry;
171
172 tableEntry.scmbptr = (void*)inst.inst.hdr;
173 tableEntry.index = clsIdx;
174
175 _clsResolverTable.append(tableEntry);
176
177 // The number of elements in the array minus 1 is the index position
178 // at which the instance was added.
179 return _clsResolverTable.size() - 1;
180 }
181
182
183 // Add the SCMOClass for the given instance to the class table.
184 // If the class already exists in the table, it returns the index position
185 // for this class, otherwise appends the class at the end of the table
186 // and returns the new index position of the class.
187 Uint32 SCMOStreamer::_appendToClassTable(const SCMOInstance& inst)
188 {
189 Uint32 clsTableSize = _classTable.size();
190 r.kieninger 1.1.2.1 const SCMBClass_Main* clsPtr = inst.inst.hdr->theClass->cls.hdr;
191
192 const SCMBClass_Main* const* clsArray = _classTable.getData();
193
194 // Search through the table for the index of the class
195 for (Uint32 x=0; x < clsTableSize; x++)
196 {
197 if (clsArray[x] == clsPtr)
198 {
199 return x;
200 }
201 }
202
203 // Class is not yet listed in the table, therefore append it at the end ...
204 _classTable.append(clsPtr);
205
206 // ... and return the new size off the array minus one as the index
207 return _classTable.size()-1;
208 }
209
210 #ifdef PEGASUS_DEBUG
211 r.kieninger 1.1.2.1 void SCMOStreamer::_dumpTables()
212 {
213 fprintf(stderr,"=====================================================\n");
214 fprintf(stderr,"Dump of SCMOStreamer Tables:\n");
215 fprintf(stderr,"CLASSES:\n");
216 for (Uint32 x=0; x < _classTable.size(); x++)
217 {
218 fprintf(stderr,"\t[%2d] %p %s\n",x, _classTable[x],
219 _getCharString(_classTable[x]->className,
220 (const char*)_classTable[x]));
221 }
222
223 fprintf(stderr,"INSTANCES:\n");
224 for (Uint32 x=0; x < _clsResolverTable.size(); x++)
225 {
226 fprintf(stderr,"\t[%2d] I = %p - cls = %2d\n",
227 x,
228 _clsResolverTable[x].scmbptr,
229 _clsResolverTable[x].index);
230 }
231
232 r.kieninger 1.1.2.1 fprintf(stderr,"INSTANCE REFERENCES:\n");
233 for (Uint32 x=0; x < _instResolverTable.size(); x++)
234 {
235 fprintf(stderr,"\t[%2d] R = %p - I = %2d\n",
236 x,
237 _instResolverTable[x].scmbptr,
238 _instResolverTable[x].index);
239 }
240 fprintf(stderr,"=====================================================\n");
241 }
242 #endif
243
244
245 // Adds the list of SCMOClasses from the ClassTable to the output buffer
246 void SCMOStreamer::_putClasses()
247 {
248 Uint32 numClasses = _classTable.size();
249 const SCMBClass_Main* const* clsArray = _classTable.getData();
250
251 // Number of classes
252 _buf.putUint32(numClasses);
253 r.kieninger 1.1.2.1
254 // SCMOClasses, one by one
255 for (Uint32 x=0; x < numClasses; x++)
256 {
257 // Calculate the in-use size of the SCMOClass data
258 Uint64 size =
259 clsArray[x]->header.totalSize - clsArray[x]->header.freeBytes;
260 _buf.putUint64(size);
261
262 // Write class data
263 _buf.putBytes(clsArray[x],size);
264 }
265
266 }
267
268 // Reads a list of SCMOClasses from the input buffer
269 bool SCMOStreamer::_getClasses()
270 {
271 // Number of classes
272 Uint32 numClasses;
273 if(! _buf.getUint32(numClasses) )
274 r.kieninger 1.1.2.1 {
275 return false;
276 }
277
278 // SCMOClasses, one by one
279 for (Uint32 x=0; x < numClasses; x++)
280 {
281 Uint64 size;
282 if (!_buf.getUint64(size))
283 {
284 return false;
285 }
286
287 // Read class data
288 SCMBClass_Main* scmbClassPtr = (SCMBClass_Main*)malloc(size);
289 if (0 == scmbClassPtr)
290 {
291 // Not enough memory!
292 throw PEGASUS_STD(bad_alloc)();
293 }
294
295 r.kieninger 1.1.2.1 if (!_buf.getBytes(scmbClassPtr,size))
296 {
297 return false;
298 }
299
300
301 // Resolve the class
302 scmbClassPtr->header.totalSize = size;
303 scmbClassPtr->header.freeBytes = 0;
304 scmbClassPtr->refCount.set(0);
305
306 _classTable.append(scmbClassPtr);
307 }
308
309 return true;
310 }
311
312 // Adds the list of SCMO Instances from the _clsResolverTable to the
313 // output buffer
314 void SCMOStreamer::_putInstances()
315 {
316 r.kieninger 1.1.2.1 Uint32 numInst = _clsResolverTable.size();
317 const SCMOResultionTable* instArray = _clsResolverTable.getData();
318
319 // Number of instances
320 _buf.putUint32(numInst);
321
322 // Instance to class resolution table
323 _buf.putBytes(instArray, numInst*sizeof(SCMOResultionTable));
324
325
326 Uint32 numExtRefs = _instResolverTable.size();
327 const SCMOResultionTable* extRefArray = _instResolverTable.getData();
328
329 // Number of references
330 _buf.putUint32(numExtRefs);
331
332 // Instance references resolution table
333 _buf.putBytes(extRefArray, numExtRefs*sizeof(SCMOResultionTable));
334
335
336 // SCMOInstances, one by one
337 r.kieninger 1.1.2.1 for (Uint32 x=0; x < numInst; x++)
338 {
339 // Calculate the in-use size of the SCMOInstance data
340 SCMBInstance_Main* instPtr = (SCMBInstance_Main*)instArray[x].scmbptr;
341 Uint64 size = instPtr->header.totalSize - instPtr->header.freeBytes;
342 _buf.putUint64(size);
343
344 // Write class data
345 _buf.putBytes(instPtr,size);
346 }
347 }
348
349
350 // Reads a list of SCMO Instances from the input buffer.
351 // Resolves the pointers to the SCMOClass and external references via the
352 // Class and Instance resolver tables.
353 bool SCMOStreamer::_getInstances()
354 {
355 // Number of instances
356 Uint32 numInst;
357 if(!_buf.getUint32(numInst))
358 r.kieninger 1.1.2.1 {
359 return false;
360 }
361
362 // Instance to class resolution table
363 SCMOResultionTable instArray[numInst];
364 if(!_buf.getBytes(&instArray, numInst*sizeof(SCMOResultionTable)))
365 {
366 return false;
367 }
368
369 // Number of references
370 Uint32 numExtRefs;
371 if(!_buf.getUint32(numExtRefs))
372 {
373 return false;
374 }
375
376 // Instance references resolution table
377 SCMOResultionTable extRefArray[numExtRefs];
378 Uint32 extRefIndex=0;
379 r.kieninger 1.1.2.1 if (numExtRefs > 0)
380 {
381 if(!_buf.getBytes(&extRefArray, numExtRefs*sizeof(SCMOResultionTable)))
382 {
383 return false;
384 }
385 }
386
387 // Use simple array for access to class pointers
388 const SCMBClass_Main* const* clsArray = _classTable.getData();
389
390 // SCMOInstances, one by one
391 for (Uint32 x=0; x < numInst; x++)
392 {
393 Uint64 size;
394 if(!_buf.getUint64(size))
395 {
396 return false;
397 }
398
399 // Reserve 64 bytes more of storage to allow for hostname and namespace
400 r.kieninger 1.1.2.1 // updates without reallocation
401
402 // Read instance data
403 SCMBInstance_Main* scmbInstPtr = (SCMBInstance_Main*)malloc(size+64);
404 if (0 == scmbInstPtr)
405 {
406 // Not enough memory!
407 throw PEGASUS_STD(bad_alloc)();
408 }
409
410 if(!_buf.getBytes(scmbInstPtr,size))
411 {
412 return false;
413 }
414
415 // Resolve the instance
416 scmbInstPtr->header.totalSize = size+64;
417 scmbInstPtr->header.freeBytes = 64;
418 scmbInstPtr->refCount.set(0);
419 scmbInstPtr->theClass =
420 new SCMOClass((SCMBClass_Main*)clsArray[instArray[x].index]);
421 r.kieninger 1.1.2.1
422 SCMOInstance* scmoInstPtr = new SCMOInstance(scmbInstPtr);
423
424 if (numExtRefs > 0)
425 {
426 // Handle the external references to other SCMOInstances
427 Uint32 numExtRefs = scmoInstPtr->numberExtRef();
428 for (Uint32 i=0; i < numExtRefs; i++)
429 {
430 Uint32 extRefPos = extRefArray[extRefIndex].index;
431 SCMOInstance* extRefPtr =
432 (SCMOInstance*)instArray[extRefPos].scmbptr;
433 scmoInstPtr->putExtRef(i,extRefPtr);
434
435 // Mark instance as already consumed
436 instArray[extRefPos].scmbptr = 0;
437
438 extRefIndex++;
439 }
440 }
441
442 r.kieninger 1.1.2.1 instArray[x].scmbptr = (void*)scmoInstPtr;
443
444 #ifdef PEGASUS_DEBUG
445 _clsResolverTable.append(instArray[x]);
446 #endif
447 }
448
449 // Append all non-referenced instances to output array
450 for (Uint32 x=0; x < numInst; x++)
451 {
452 if (instArray[x].scmbptr)
453 {
454 _scmoInstances.append(*((SCMOInstance*)instArray[x].scmbptr));
455 delete (SCMOInstance*)instArray[x].scmbptr;
456 }
457 }
458
459 return true;
460 }
461
462 PEGASUS_NAMESPACE_END
463 r.kieninger 1.1.2.1
|