00001
00002
00003 #include "BaBar/BaBar.hh"
00004
00005
00006
00007
00008
00009
00010 #include "BaBar/BaBar.hh"
00011
00012 #include "CdbBdb/CdbBdbObjectProfilerImpl.hh"
00013
00014 #include "CdbBdb/CdbBdbObjectProfilerUserAction.hh"
00015 #include "CdbBdb/CdbBdbSimpleCache.hh"
00016
00017 #include <assert.h>
00018
00019 #include <iostream>
00020
00021
00022
00023 #include <ooMap.h>
00024 using std::cerr;
00025 using std::cout;
00026 using std::endl;
00027
00028
00029
00030
00031
00032
00033 CdbBdbObjectProfilerImpl::Prefix::Prefix( int& theLevel,
00034 const std::string& theStep ) :
00035 _level(theLevel),
00036 _str ("")
00037 {
00038 ++_level;
00039 for( int i = 0; i < _level; ++i ) _str += theStep;
00040 }
00041
00042 CdbBdbObjectProfilerImpl::Prefix::~Prefix( )
00043 {
00044 --_level;
00045 }
00046
00047 const char*
00048 CdbBdbObjectProfilerImpl::Prefix::c_str( ) const
00049 {
00050 return _str.c_str( );
00051 }
00052
00053
00054
00055
00056
00057 CdbBdbObjectProfilerImpl::CdbBdbObjectProfilerImpl( CdbBdbObjectProfilerUserAction* theUserAction,
00058 bool verboseMode,
00059 bool debugMode ) :
00060 _verboseMode(verboseMode),
00061 _debugMode (debugMode),
00062 _userAction (theUserAction),
00063 _dictionary (new CdbBdbSimpleCache( )),
00064 _level (0),
00065 _size (0),
00066 _topObjects (0)
00067 {
00068 if( 0 == theUserAction ) {
00069 cerr << "CdbBdbObjectProfilerImpl::CdbBdbObjectProfilerImpl() -- a null pointer instead of a user action object" << endl
00070 << "passed to the method." << endl;
00071 ::abort( );
00072 }
00073
00074
00075
00076 if( _debugMode ) _verboseMode = true;
00077 }
00078
00079 CdbBdbObjectProfilerImpl::~CdbBdbObjectProfilerImpl( )
00080 {
00081 if( 0 != _dictionary ) {
00082 delete _dictionary;
00083 _dictionary = 0;
00084 }
00085 }
00086
00087 bool
00088 CdbBdbObjectProfilerImpl::profile( const ooHandle(ooObj)& theInputH )
00089 {
00090 const char* context = "CdbBdbObjectProfilerImpl::profile() : ";
00091
00092
00093
00094 if( !theInputH.isValid( )) {
00095 cerr << context << "ERROR: invalid object passed to the procedure: " << theInputH.sprint( ) << endl;
00096 return false;
00097 }
00098
00099
00100
00101 _level = 0;
00102
00103
00104
00105 return profileObject( theInputH );
00106 }
00107
00108 CdbBdbObjectProfilerUserAction*
00109 CdbBdbObjectProfilerImpl::setUserAction( CdbBdbObjectProfilerUserAction* theUserAction )
00110 {
00111 if( 0 == theUserAction ) {
00112 cerr << "CdbBdbObjectProfilerImpl::setUserAction() -- a null pointer instead of a user action object" << endl
00113 << "passed to the method." << endl;
00114 ::abort( );
00115 }
00116 CdbBdbObjectProfilerUserAction* previousAction = _userAction;
00117 _userAction = theUserAction;
00118
00119 return previousAction;
00120 }
00121
00122 uint64
00123 CdbBdbObjectProfilerImpl::getSize( ) const
00124 {
00125 return _size;
00126 }
00127
00128 uint64
00129 CdbBdbObjectProfilerImpl::getTopObjects( ) const
00130 {
00131 return _topObjects;
00132 }
00133
00134 bool
00135 CdbBdbObjectProfilerImpl::profileObject( const ooHandle(ooObj)& theInputH )
00136 {
00137 const char* context = "CdbBdbObjectProfilerImpl::profileObject() : ";
00138
00139 Prefix prefix( _level );
00140
00141
00142 if( _verboseMode ) {
00143 std::string inStr = theInputH.sprint( );
00144 cout << prefix.c_str( ) << inStr.c_str( ) << " >> " << endl;
00145 }
00146
00147
00148
00149
00150
00151 if( theInputH == 0 ) {
00152
00153
00154 if( _verboseMode ) {
00155 std::string inStr = theInputH.sprint( );
00156 cout << prefix.c_str( ) << inStr.c_str( ) << " (NULL) \"\"" << endl;
00157 }
00158
00159
00160 } else {
00161
00162
00163
00164
00165 if( 0 != _dictionary->findObject( theInputH )) {
00166
00167
00168 if( _verboseMode ) {
00169 std::string inStr = theInputH.sprint( );
00170 cout << prefix.c_str( ) << inStr.c_str( ) << " (CACHED) \"" << theInputH.typeName( ) << "\"" << endl;
00171 }
00172
00173
00174 } else {
00175
00176
00177
00178 switch( _userAction->action( theInputH )) {
00179
00180 default :
00181
00182 cerr << context << "ERROR: unrecognized user action for: " << theInputH.sprint( ) << endl;
00183 ::abort( );
00184
00185 case CdbBdbObjectProfilerUserAction::ACTION_ERROR :
00186
00187 cerr << context << "ERROR: user action failed for: " << theInputH.sprint( ) << endl;
00188 return false;
00189
00190 case CdbBdbObjectProfilerUserAction::ACTION_STOP :
00191
00192 _dictionary->addObject( theInputH, theInputH );
00193
00194
00195 if( _verboseMode ) {
00196 std::string inStr = theInputH.sprint( );
00197 cout << prefix.c_str( ) << inStr.c_str( ) << " (STOP BY USER ACTION)" << endl;
00198 }
00199
00200
00201 break;
00202
00203 case CdbBdbObjectProfilerUserAction::ACTION_PROCEED :
00204
00205 {
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 ooTypeNumber typeN = theInputH.typeN( );
00220
00221 if( ooTypeN(ooMap) == typeN ) {
00222
00223 ooHandle(ooMap) inputMapH;
00224 inputMapH = (ooHandle(ooMap))theInputH;
00225
00226
00227
00228
00229 _dictionary->addObject( theInputH, theInputH );
00230
00231
00232 if( _verboseMode ) {
00233 std::string inStr = theInputH.sprint( );
00234 cout << prefix.c_str( ) << inStr.c_str( ) << " (PROFILE) \"" << theInputH.typeName( ) << "\"" << endl;
00235 }
00236
00237
00238 {
00239 ooMapItr itr( inputMapH );
00240 while( itr.next( )) {
00241
00242 ooRef(ooObj) inputRef = itr->oid( );
00243
00244 ooHandle(ooObj) inputH;
00245 inputH = inputRef;
00246
00247 if( ! profileObject( inputH )) return false;
00248 }
00249 }
00250
00251 } else {
00252
00253
00254
00255
00256
00257
00258
00259 ooas::Class_Object classObj((ooHandle(ooObj)&)theInputH );
00260 if( !classObj ) {
00261 cerr << context << "ERROR: no ooas::Class_Object for the input object reference: " << theInputH.sprint( ) << endl;
00262 ::abort( );
00263 }
00264
00265
00266
00267
00268 _dictionary->addObject( theInputH, theInputH );
00269
00270
00271 if( _verboseMode ) {
00272 std::string inStr = theInputH.sprint( );
00273 cout << prefix.c_str( ) << inStr.c_str( ) << " (PROFILE) \"" << theInputH.typeName( ) << "\"" << endl;
00274 }
00275
00276
00277 if( !profileObjectContents( classObj, prefix )) return false;
00278
00279
00280
00281
00282
00283
00284
00285
00286 if( 1 == _level ) ++_topObjects;
00287 }
00288 }
00289 }
00290 }
00291 }
00292
00293
00294 if( _verboseMode ) {
00295 std::string inStr = theInputH.sprint( );
00296 cout << prefix.c_str( ) << inStr.c_str( ) << " << " << endl;
00297 }
00298
00299
00300 return true;
00301 }
00302
00303 bool
00304 CdbBdbObjectProfilerImpl::profileObjectContents( const ooas::Class_Object& theClassObject,
00305 const Prefix& thePrefix )
00306 {
00307 if( !theClassObject ) {
00308 cerr << "CdbBdbObjectProfilerImpl::profileObjectContents() -- invalid class object passed to the method." << endl;
00309 ::abort( );
00310 }
00311
00312
00313
00314 const ooas::d_Class& classDsc = theClassObject.type_of( );
00315
00316
00317
00318 if( !classDsc.is_class ( )) return true;
00319 if( classDsc.is_internal( )) return true;
00320
00321
00322
00323 {
00324 attribute_iterator itr = classDsc.defines_attribute_begin( );
00325 while( classDsc.defines_attribute_end( ) != itr ) {
00326
00327 const ooas::d_Attribute& attrDsc = *itr;
00328
00329 if( attrDsc.is_base_class( )) {
00330
00331
00332 if( _debugMode ) {
00333 cout << thePrefix.c_str( ) << "BASE CLASS" << endl;
00334 }
00335
00336
00337 ooas::Class_Object inputClassObj = theClassObject.get_class_obj( attrDsc.position( ));
00338
00339 profileObjectContents( inputClassObj, thePrefix );
00340
00341 } else if( attrDsc.is_relationship( )) {
00342
00343 const d_Relationship& relDsc = (const d_Relationship&)attrDsc;
00344 ooas::Relationship_Object relationshipObj = theClassObject.get_relationship( attrDsc.position( ));
00345 assert( relationshipObj );
00346
00347 if( relDsc.is_to_many( )) {
00348
00349
00350 if( _debugMode ) {
00351 cout << thePrefix.c_str( ) << "n-RELATIONSHIP" << endl;
00352 }
00353
00354
00355 uint32 num = 0;
00356
00357 ooItr(ooObj) itr;
00358 relationshipObj.get_iterator( itr );
00359
00360 while( itr.next( )) {
00361
00362 ooHandle(ooObj) inputH;
00363 inputH = itr;
00364
00365 if( !profileObject( inputH )) return false;
00366
00367 ++num;
00368 }
00369 if( 0 != num ) _size += num * sizeOfReference( );
00370
00371 } else {
00372
00373
00374 if( _debugMode ) {
00375 cout << thePrefix.c_str( ) << "1-RELATIONSHIP" << endl;
00376 }
00377
00378
00379 ooHandle(ooObj) inputH;
00380 inputH = relationshipObj.get_ooref( );
00381
00382 if( !profileObject(inputH )) return false;
00383
00384 _size += sizeOfReference( );
00385 }
00386
00387 } else {
00388
00389 const ooas::d_Type& typeDsc = attrDsc.type_of( );
00390
00391 size_t fixedArraySize = attrDsc.array_size( );
00392
00393 if( typeDsc.is_ref_type( )) {
00394
00395
00396 if( _debugMode ) {
00397 cout << thePrefix.c_str( ) << "REFERENCE";
00398 if( fixedArraySize > 1 ) cout << "[" << fixedArraySize << "]";
00399 cout << endl;
00400 }
00401
00402
00403 for( size_t i = 0; i < fixedArraySize; ++i ) {
00404
00405 ooHandle(ooObj) inputH;
00406 inputH = theClassObject.get_ooref( attrDsc.position( ), i );
00407
00408 if( !profileObject( inputH )) return false;
00409 }
00410
00411 _size += fixedArraySize * sizeOfReference( );
00412
00413 } else if( typeDsc.is_basic_type( )) {
00414
00415 _size += fixedArraySize * sizeOfNumericValue( theClassObject.get( attrDsc.position( ), 0 ));
00416
00417 } else if( typeDsc.is_string_type( )) {
00418
00419
00420 for( size_t i = 0; i < fixedArraySize; ++i ) {
00421 _size += sizeOfStringValue( theClassObject.get_string( attrDsc.position( ), i ));
00422 }
00423
00424 } else if( typeDsc.is_class( ) && !typeDsc.is_string_type( )) {
00425
00426
00427
00428 if( _debugMode ) {
00429 cout << thePrefix.c_str( ) << "EMBEDDED OBJECT";
00430 if( fixedArraySize > 1 ) cout << "[" << fixedArraySize << "]";
00431 cout << endl;
00432 }
00433
00434
00435 for( size_t i = 0; i < fixedArraySize; ++i ) {
00436
00437 ooas::Class_Object inputClassObj = theClassObject.get_class_obj( attrDsc.position( ), i );
00438
00439 if( !profileObjectContents( inputClassObj, thePrefix )) return false;
00440 }
00441
00442 } else if( typeDsc.is_varray_type( )) {
00443
00444 ooas::VArray_Object inputVArrayObject = theClassObject.get_varray( attrDsc.position( ));
00445
00446 uint32 varraySize = inputVArrayObject.size( );
00447
00448 if( typeDsc.is_varray_basic_type( )) {
00449
00450
00451 if( _debugMode ) {
00452 cout << thePrefix.c_str( )
00453 << "V-ARRAY OF BASIC OBJECTS" << endl;
00454 }
00455
00456
00457
00458
00459 if( 0 != varraySize ) _size += varraySize * sizeOfNumericValue( inputVArrayObject.get( 0 ));
00460
00461 } else if( typeDsc.is_varray_ref_type( )) {
00462
00463
00464 if( _debugMode ) {
00465 cout << thePrefix.c_str( )
00466 << "V-ARRAY OF REFERENCES" << endl;
00467 }
00468
00469
00470 for( uint32 i = 0; i < varraySize; ++i ) {
00471
00472 ooHandle(ooObj) inputH;
00473 inputH = inputVArrayObject.get_ooref( i );
00474
00475 if( !profileObject( inputH )) return false;
00476 }
00477
00478 _size += varraySize * sizeOfReference( );
00479
00480
00481 } else if( typeDsc.is_string_type( )) {
00482
00483
00484
00485 if( _debugMode ) {
00486 cout << thePrefix.c_str( )
00487 << "V-ARRAY OF STRINGS" << endl;
00488 }
00489
00490
00491
00492
00493
00494
00495
00496 for( uint32 i = 0; i < varraySize; ++i )
00497 _size += sizeOfStringValue( inputVArrayObject.get_string( i ));
00498
00499 } else if( typeDsc.is_varray_embedded_class_type( ) &&
00500 !typeDsc.is_string_type( )) {
00501
00502
00503 if( _debugMode ) {
00504 cout << thePrefix.c_str( )
00505 << "V-ARRAY OF EMBEDDED OBJECTS" << endl;
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 for( uint32 i = 0; i < varraySize; ++i )
00518 if( !profileObjectContents( inputVArrayObject.get_class_obj( i ),
00519 thePrefix )) return false;
00520
00521 } else {
00522
00523 bool isKnownTypeOfVarrayElements = false;
00524 assert( isKnownTypeOfVarrayElements );
00525 }
00526
00527 } else {
00528
00529 bool isKnownElementType = false;
00530 assert( isKnownElementType );
00531 }
00532 }
00533 ++itr;
00534 }
00535 }
00536 return true;
00537 }
00538
00539 uint64
00540 CdbBdbObjectProfilerImpl::sizeOfNumericValue( const Numeric_Value& theNumericValue )
00541 {
00542 uint64 result = 0;
00543
00544 ooBaseType baseType = theNumericValue.type( );
00545
00546 switch( baseType ) {
00547
00548 case ooCHAR : result = 1; break;
00549 case ooINT8 : result = 1; break;
00550 case ooUINT8 : result = 1; break;
00551 case ooINT16 : result = 2; break;
00552 case ooUINT16 : result = 2; break;
00553 case ooINT32 : result = 4; break;
00554 case ooUINT32 : result = 4; break;
00555 case ooINT64 : result = 8; break;
00556 case ooUINT64 : result = 8; break;
00557 case ooFLOAT32 : result = 4; break;
00558 case ooFLOAT64 : result = 8; break;
00559 case ooPTR : result = sizeof( void* ); break;
00560
00561 default:
00562 {
00563 bool isKnownNumericType = false;
00564 assert( isKnownNumericType );
00565 }
00566 }
00567
00568 return result;
00569 }
00570
00571 uint64
00572 CdbBdbObjectProfilerImpl::sizeOfStringValue( String_Value theStringValue )
00573 {
00574 const char* context = "CdbBdbObjectProfilerImpl::sizeOfStringValue()";
00575
00576
00577
00578
00579 uint64 result = 0;
00580
00581 switch( theStringValue.type( )) {
00582
00583 case ooAsStringVSTRING:
00584 {
00585 ooVString* vStr = theStringValue;
00586 const char* str = (const char*)(*vStr);
00587 result = 1 + ( 0 == str ? 0 : strlen( str ));
00588 break;
00589 }
00590
00591 case ooAsStringUTF8:
00592 {
00593 ooUtf8String* utf8Str = theStringValue;
00594 const char* str = (const char*)(*utf8Str);
00595 result = 1 + ( 0 == str ? 0 : strlen( str ));
00596 break;
00597 }
00598
00599 case ooAsStringOPTIMIZED:
00600 {
00601
00602
00603 char* str = Optimized_String_Value(theStringValue).get_copy( );
00604 result = 1 + ( 0 == str ? 0 : strlen( str ));
00605 delete [] str;
00606 break;
00607 }
00608
00609 case ooAsStringST:
00610 {
00611 cerr << context << " - a Smalltalk string found in an object. These strings can't be measured." << endl;
00612 ::exit( 1 );
00613 }
00614
00615 default:
00616 {
00617 bool isKnownStringClass = false;
00618 assert( isKnownStringClass );
00619 }
00620 }
00621
00622 return result;
00623 }
00624
00625 uint64
00626 CdbBdbObjectProfilerImpl::sizeOfReference( )
00627 {
00628 return 8;
00629 }
00630
00631
00632
00633