1 thilo.boehm 1.2 //%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 thilo.boehm 1.2 // 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 karl 1.4.4.1 // This code implements part of PEP#348 - The CMPI infrastructure using SCMO
31 // (Single Chunk Memory Objects).
32 // The design document can be found on the OpenPegasus website openpegasus.org
33 // at https://collaboration.opengroup.org/pegasus/pp/documents/21210/PEP_348.pdf
34 //
|
35 thilo.boehm 1.2 //%/////////////////////////////////////////////////////////////////////////////
36
37 #include <Pegasus/Common/Config.h>
38 #include <cstdlib>
39 #include <cstdio>
40 #include <Pegasus/Common/SCMOStreamer.h>
41 #include <Pegasus/Common/ArrayIterator.h>
42 #include <Pegasus/Common/Tracer.h>
43
44 PEGASUS_USING_STD;
45
46 PEGASUS_NAMESPACE_BEGIN
47
48
49 #define PEGASUS_ARRAY_T SCMOResolutionTable
50 # include <Pegasus/Common/ArrayImpl.h>
51 #undef PEGASUS_ARRAY_T
52
53 SCMOStreamer::SCMOStreamer(CIMBuffer& out, Array<SCMOInstance>& x) :
54 _buf(out),
|
55 karl 1.4.4.1 _scmoInstances(x)
|
56 thilo.boehm 1.2 {
57 };
58
59 // Writes a single SCMOClass to the given CIMBuffer
60 void SCMOStreamer::serializeClass(CIMBuffer& out, const SCMOClass& scmoClass)
61 {
62 PEG_METHOD_ENTER(TRC_DISPATCHER,"SCMOStreamer::serializeClass");
63
64 Array<SCMBClass_Main*> classTable;
65 classTable.append(scmoClass.cls.hdr);
66
67 _putClasses(out, classTable);
68
69 PEG_METHOD_EXIT();
70 };
71
72 // Reads a single SCMOClass from the given CIMBuffer
73 bool SCMOStreamer::deserializeClass(CIMBuffer& in, SCMOClass& scmoClass)
74 {
75 PEG_METHOD_ENTER(TRC_DISPATCHER,"SCMOStreamer::deserializeClass");
76
77 thilo.boehm 1.2 Array<SCMBClass_Main*> classTable;
78 if(!_getClasses(in, classTable))
79 {
80 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
81 "Failed to get Class!");
82 PEG_METHOD_EXIT();
83 return false;
84 }
85
86 if (classTable.size() > 0)
87 {
88 scmoClass = SCMOClass(classTable[0]);
89 }
90
91 PEG_METHOD_EXIT();
92 return true;
93 };
94
95 // Writes the list of SCMOInstances stored in this instance of SCMOStreamer
96 // to the output buffer, including their referenced Classes and Instances
97 void SCMOStreamer::serialize()
98 thilo.boehm 1.2 {
99 PEG_METHOD_ENTER(TRC_DISPATCHER,"SCMOStreamer::serialize");
100
101 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL3,
102 "Serializing %d instances\n",
103 _scmoInstances.size()));
104
105 ConstArrayIterator<SCMOInstance> iterator(_scmoInstances);
106
107 // First build the tables for references classes and instances
108 for (Uint32 i = 0; i < iterator.size(); i++)
109 {
110 const SCMOInstance& inst = iterator[i];
111
112 _appendToResolverTables(inst);
113 }
114
115 _putClasses(_buf,_classTable);
116
117 _putInstances();
118
119 thilo.boehm 1.2 //dumpTables();
120
121 PEG_METHOD_EXIT();
122 }
123
124 // Reads a list of SCMOInstances from the input buffer and stores them in this
125 // instance of SCMOStreamer, including their referenced Classes and Instances
126 bool SCMOStreamer::deserialize()
127 {
128 PEG_METHOD_ENTER(TRC_DISPATCHER,"SCMOStreamer::deserialize");
129
130 if(!_getClasses(_buf,_classTable))
131 {
132 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
133 "Failed to get Classes!");
134 PEG_METHOD_EXIT();
135 return false;
136 }
137
138 if(!_getInstances())
139 {
140 thilo.boehm 1.2 PEG_TRACE_CSTRING(TRC_DISCARDED_DATA, Tracer::LEVEL1,
141 "Failed to get Instances!");
142 PEG_METHOD_EXIT();
143 return false;
144 }
145
146 //dumpTables();
147
148 PEG_METHOD_EXIT();
149 return true;
150 }
151
152 // This function takes and instance and adds all of its external
153 // references (SCMOClass and SCMOInstances) to the index tables
154 // For referenced SCMOInstances, the function recusively calls itself.
155 //
156 // Returns the index position at which the class for this instance was inserted
157 // in the class resolver table.
158 Uint32 SCMOStreamer::_appendToResolverTables(const SCMOInstance& inst)
159 {
160 // First handle the external references to other SCMOInstances
161 thilo.boehm 1.2 Uint32 numExtRefs = inst.numberExtRef();
162 for (Uint32 x=0; x < numExtRefs; x++)
163 {
164 SCMOInstance* extRef = inst.getExtRef(x);
165
166 Uint32 idx = _appendToResolverTables(*extRef);
167 _appendToInstResolverTable(*extRef,idx);
168 }
169
170 // Add the instance to the class resolution table
171 // (Also adds the class to the class table when neccessary)
172 return _appendToClassResolverTable(inst);
173 }
174
175
176 // This function adds the given instance to the instance resolver table,
177 // which stores the connections between instances and their external
178 // references.
179 //
180 // Returns the index position at which the instance was inserted in the
181 // instance resolver table.
182 thilo.boehm 1.2 Uint32 SCMOStreamer::_appendToInstResolverTable(
|
183 karl 1.4.4.1 SCMOInstance& inst,
|
184 thilo.boehm 1.2 Uint32 idx)
185 {
|
186 karl 1.4.4.1 SCMOResolutionTable tableEntry;
187 tableEntry.scmbptr.scmoInst = &inst;
188 tableEntry.index = idx;
189
|
190 thilo.boehm 1.2 _instResolverTable.append(tableEntry);
191
192 // The number of elements in the array minus 1 is the index position
193 // at which the instance was added.
194 return _instResolverTable.size() - 1;
195 }
196
197
198 // Adds an instance to the class resolution table.
199 // Also adds the class to the class table when neccessary
200 //
201 // Returns the index position at which the instance was inserted in the
202 // instance resolver table.
203 Uint32 SCMOStreamer::_appendToClassResolverTable(const SCMOInstance& inst)
204 {
205 // Add the SCMOClass for this instance to the class table,
206 // or give us the index at which the class resides in the table
207 Uint32 clsIdx = _appendToClassTable(inst);
208
209
210 // Now build a new entry for the class resolution table
|
211 karl 1.4.4.1 SCMOResolutionTable tableEntry;
212 tableEntry.scmbptr.scmbMain = inst.inst.hdr;
213 tableEntry.index = clsIdx;
|
214 thilo.boehm 1.2 _clsResolverTable.append(tableEntry);
215
216 // The number of elements in the array minus 1 is the index position
217 // at which the instance was added.
218 return _clsResolverTable.size() - 1;
219 }
220
221
222 // Add the SCMOClass for the given instance to the class table.
223 // If the class already exists in the table, it returns the index position
224 // for this class, otherwise appends the class at the end of the table
225 // and returns the new index position of the class.
226 Uint32 SCMOStreamer::_appendToClassTable(const SCMOInstance& inst)
227 {
228 Uint32 clsTableSize = _classTable.size();
229 SCMBClass_Main* clsPtr = inst.inst.hdr->theClass.ptr->cls.hdr;
230
231 const SCMBClass_Main* const* clsArray = _classTable.getData();
232
233 // Search through the table for the index of the class
234 for (Uint32 x=0; x < clsTableSize; x++)
235 thilo.boehm 1.2 {
236 if (clsArray[x] == clsPtr)
237 {
238 return x;
239 }
240 }
241
242 // Class is not yet listed in the table, therefore append it at the end ...
243 _classTable.append(clsPtr);
244
245 // ... and return the new size off the array minus one as the index
246 return _classTable.size()-1;
247 }
248
249 #ifdef PEGASUS_DEBUG
250 void SCMOStreamer::_dumpTables()
251 {
252 fprintf(stderr,"=====================================================\n");
253 fprintf(stderr,"Dump of SCMOStreamer Tables:\n");
254 fprintf(stderr,"CLASSES:\n");
255 for (Uint32 x=0; x < _classTable.size(); x++)
256 thilo.boehm 1.2 {
257 fprintf(stderr,"\t[%2d] %p %s\n",x, _classTable[x],
258 _getCharString(_classTable[x]->className,
259 (const char*)_classTable[x]));
260 }
261
262 fprintf(stderr,"INSTANCES:\n");
263 for (Uint32 x=0; x < _clsResolverTable.size(); x++)
264 {
|
265 sahana.prabhakar 1.4 fprintf(stderr,"\t[%2d] I = %llx - cls = %2lld\n",
|
266 thilo.boehm 1.2 x,
|
267 karl 1.4.4.1 _clsResolverTable[x].scmbptr.uint64,
|
268 thilo.boehm 1.2 _clsResolverTable[x].index);
269 }
270
271 fprintf(stderr,"INSTANCE REFERENCES:\n");
272 for (Uint32 x=0; x < _instResolverTable.size(); x++)
273 {
|
274 sahana.prabhakar 1.4 fprintf(stderr,"\t[%2d] R = %llx - I = %2lld\n",
|
275 thilo.boehm 1.2 x,
|
276 karl 1.4.4.1 _instResolverTable[x].scmbptr.uint64,
|
277 thilo.boehm 1.2 _instResolverTable[x].index);
278 }
279 fprintf(stderr,"=====================================================\n");
280 }
281 #endif
282
283
284 // Adds the list of SCMOClasses from the ClassTable to the output buffer
285 void SCMOStreamer::_putClasses(
286 CIMBuffer& out,
287 Array<SCMBClass_Main*>& classTable)
288 {
289 Uint32 numClasses = classTable.size();
290 const SCMBClass_Main* const* clsArray = classTable.getData();
291
292 // Number of classes
293 out.putUint32(numClasses);
294
295 // SCMOClasses, one by one
296 for (Uint32 x=0; x < numClasses; x++)
297 {
298 thilo.boehm 1.2 // Calculate the in-use size of the SCMOClass data
299 Uint64 size =
300 clsArray[x]->header.totalSize - clsArray[x]->header.freeBytes;
301 out.putUint64(size);
302
303 // Write class data
304 out.putBytes(clsArray[x],(size_t)size);
305 }
306
307 }
308
309 // Reads a list of SCMOClasses from the input buffer
310 bool SCMOStreamer::_getClasses(
311 CIMBuffer& in,
312 Array<SCMBClass_Main*>& classTable)
313 {
314 // Number of classes
315 Uint32 numClasses;
316 if(! in.getUint32(numClasses) )
317 {
318 return false;
319 thilo.boehm 1.2 }
320
321 // SCMOClasses, one by one
322 for (Uint32 x=0; x < numClasses; x++)
323 {
324 Uint64 size;
325 if (!in.getUint64(size))
326 {
327 return false;
328 }
329
330 // Read class data
331 SCMBClass_Main* scmbClassPtr = (SCMBClass_Main*)malloc((size_t)size);
332 if (0 == scmbClassPtr)
333 {
334 // Not enough memory!
335 throw PEGASUS_STD(bad_alloc)();
336 }
337
338 if (!in.getBytes(scmbClassPtr,(size_t)size))
339 {
340 thilo.boehm 1.2 return false;
341 }
342
343
344 // Resolve the class
345 scmbClassPtr->header.totalSize = size;
346 scmbClassPtr->header.freeBytes = 0;
347 scmbClassPtr->refCount.set(0);
348
349 classTable.append(scmbClassPtr);
350 }
351
352 return true;
353 }
354
355 // Adds the list of SCMO Instances from the _clsResolverTable to the
356 // output buffer
357 void SCMOStreamer::_putInstances()
358 {
359 Uint32 numInst = _clsResolverTable.size();
360 const SCMOResolutionTable* instArray = _clsResolverTable.getData();
361 thilo.boehm 1.2
362 // Number of instances
363 _buf.putUint32(numInst);
364
365 // Instance to class resolution table
366 _buf.putBytes(instArray, numInst*sizeof(SCMOResolutionTable));
367
368
369 Uint32 numExtRefs = _instResolverTable.size();
370 const SCMOResolutionTable* extRefArray = _instResolverTable.getData();
371
372 // Number of references
373 _buf.putUint32(numExtRefs);
374
375 // Instance references resolution table
376 _buf.putBytes(extRefArray, numExtRefs*sizeof(SCMOResolutionTable));
377
378
379 // SCMOInstances, one by one
380 for (Uint32 x=0; x < numInst; x++)
381 {
382 thilo.boehm 1.2 // Calculate the in-use size of the SCMOInstance data
|
383 karl 1.4.4.1 SCMBInstance_Main* instPtr = instArray[x].scmbptr.scmbMain;
|
384 thilo.boehm 1.2 Uint64 size = instPtr->header.totalSize - instPtr->header.freeBytes;
385 _buf.putUint64(size);
386
387 // Write class data
388 _buf.putBytes(instPtr,(size_t)size);
389 }
390 }
391
392
393 // Reads a list of SCMO Instances from the input buffer.
394 // Resolves the pointers to the SCMOClass and external references via the
395 // Class and Instance resolver tables.
396 bool SCMOStreamer::_getInstances()
397 {
398 // Number of instances
399 Uint32 numInst;
400 if(!_buf.getUint32(numInst))
401 {
402 return false;
403 }
404
405 thilo.boehm 1.2 // Instance to class resolution table
406 SCMOResolutionTable *instArray = new SCMOResolutionTable[numInst];
407 if(!_buf.getBytes(instArray, numInst*sizeof(SCMOResolutionTable)))
408 {
409 return false;
410 }
411
412 // Number of references
413 Uint32 numExtRefs;
414 if(!_buf.getUint32(numExtRefs))
415 {
416 return false;
417 }
418
419 // Instance references resolution table
420 SCMOResolutionTable *extRefArray = new SCMOResolutionTable[numExtRefs];
421 Uint32 extRefIndex=0;
422 if (numExtRefs > 0)
423 {
424 if(!_buf.getBytes(extRefArray, numExtRefs*sizeof(SCMOResolutionTable)))
425 {
426 thilo.boehm 1.2 return false;
427 }
428 }
429
430 // Use simple array for access to class pointers
431 const SCMBClass_Main* const* clsArray = _classTable.getData();
432
433 // SCMOInstances, one by one
434 for (Uint32 x=0; x < numInst; x++)
435 {
436 Uint64 size;
437 if(!_buf.getUint64(size))
438 {
439 return false;
440 }
441
442 // Reserve 64 bytes more of storage to allow for hostname and namespace
443 // updates without reallocation
444
445 // Read instance data
446 SCMBInstance_Main* scmbInstPtr =
447 thilo.boehm 1.2 (SCMBInstance_Main*)malloc((size_t)size+64);
448 if (0 == scmbInstPtr)
449 {
450 // Not enough memory!
451 throw PEGASUS_STD(bad_alloc)();
452 }
453
454 if(!_buf.getBytes(scmbInstPtr,(size_t)size))
455 {
456 return false;
457 }
458
459 // Resolve the instance
460 scmbInstPtr->header.totalSize = size+64;
461 scmbInstPtr->header.freeBytes = 64;
462 scmbInstPtr->refCount.set(0);
463 scmbInstPtr->theClass.ptr =
464 new SCMOClass((SCMBClass_Main*)clsArray[instArray[x].index]);
465
466 SCMOInstance* scmoInstPtr = new SCMOInstance(scmbInstPtr);
467
468 thilo.boehm 1.2 if (numExtRefs > 0)
469 {
470 // Handle the external references to other SCMOInstances
471 Uint32 numExtRefs = scmoInstPtr->numberExtRef();
472 for (Uint32 i=0; i < numExtRefs; i++)
473 {
474 Uint32 extRefPos = extRefArray[extRefIndex].index;
|
475 karl 1.4.4.1 SCMOInstance* extRefPtr = instArray[extRefPos].scmbptr.scmoInst;
|
476 thilo.boehm 1.2 scmoInstPtr->putExtRef(i,extRefPtr);
477
478 // Mark instance as already consumed
|
479 karl 1.4.4.1 instArray[extRefPos].scmbptr.uint64 = 0;
|
480 thilo.boehm 1.2
481 extRefIndex++;
482 }
483 }
484
|
485 karl 1.4.4.1 instArray[x].scmbptr.scmoInst = scmoInstPtr;
|
486 thilo.boehm 1.2
487 #ifdef PEGASUS_DEBUG
488 _clsResolverTable.append(instArray[x]);
489 #endif
490 }
491
492 // Append all non-referenced instances to output array
493 for (Uint32 x=0; x < numInst; x++)
494 {
|
495 karl 1.4.4.1 if (0 != instArray[x].scmbptr.scmoInst)
|
496 thilo.boehm 1.2 {
|
497 karl 1.4.4.1 _scmoInstances.append(*(instArray[x].scmbptr.scmoInst));
498 delete instArray[x].scmbptr.scmoInst;
|
499 thilo.boehm 1.2 }
500 }
501 delete [] instArray;
502 delete [] extRefArray;
503
504 return true;
505 }
506
507 PEGASUS_NAMESPACE_END
508
|