/data3/calcul/jacquem/working_dir/Micromegas/micromegasFrameWork/lcio/sio/src/SIO_record.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // CVS $Id: SIO_record.cc,v 1.6 2010/06/22 13:49:54 gaede Exp $
00003 // ----------------------------------------------------------------------------
00004 // => Controller for a single SIO record.                          
00005 // ----------------------------------------------------------------------------
00006 //
00007 // General Description:
00008 //
00009 // Each SIO_record controls one record type.
00010 //
00011 // ----------------------------------------------------------------------------
00012 
00013 #ifdef _MSC_VER
00014 #   pragma warning(disable:4786)        // >255 characters in debug information
00015 #endif
00016 
00017 #include <iostream>
00018 #include <cstdlib>
00019 
00020 #include "SIO_block.h"
00021 #include "SIO_blockManager.h"
00022 #include "SIO_definitions.h"
00023 #include "SIO_functions.h"
00024 #include "SIO_record.h"
00025 #include "SIO_stream.h"
00026 
00027 static unsigned int
00028     SIO_mark_block = 0xdeadbeef;
00029 
00030 // ----------------------------------------------------------------------------
00031 // Constructor.
00032 // ----------------------------------------------------------------------------
00033 SIO_record::SIO_record
00034 (
00035     const char*     i_name,
00036     SIO_verbosity   i_verbosity
00037 )
00038 {
00039 options   = 0;
00040 name      = i_name;
00041 unpack    = false;
00042 verbosity = i_verbosity;
00043 }
00044 
00045 // ----------------------------------------------------------------------------
00046 // Destructor.
00047 // ----------------------------------------------------------------------------
00048 SIO_record::~SIO_record() {}
00049 
00050 // ----------------------------------------------------------------------------
00051 // Connect a block to a record (by name).
00052 // ----------------------------------------------------------------------------
00053 unsigned int SIO_record::connect
00054 (
00055     const char*  i_name
00056 )
00057 {
00058 
00059 //
00060 // Local variables.
00061 //
00062 SIO_block
00063    *block;
00064 
00065 std::string
00066     s_name = i_name;
00067 
00068 //
00069 // Validate the name.
00070 //
00071 block = SIO_blockManager::get( i_name );
00072 if( block == NULL )
00073 {
00074     if( verbosity >= SIO_ERRORS )
00075     {
00076         std::cout << "SIO: [/"  << name << "/" << i_name << "] "
00077                   << "Block not connected (name not recognized)"
00078                   << std::endl;
00079     }
00080     return( SIO_RECORD_BADARGUMENT );
00081 }
00082 
00083 //
00084 // Go to the workhorse.
00085 //
00086 return( connect( &s_name, block ) );
00087 }
00088 
00089 // ----------------------------------------------------------------------------
00090 // Connect a block to a record (by pointer).
00091 // ----------------------------------------------------------------------------
00092 unsigned int SIO_record::connect
00093 (
00094     SIO_block*  block
00095 )
00096 {
00097 
00098 //
00099 // Local variables.
00100 //
00101 std::string
00102     s_name;
00103 
00104 //
00105 // Validate the block pointer.
00106 //
00107 if( block == NULL )
00108 {
00109     if( verbosity >= SIO_ERRORS )
00110     {
00111         std::cout << "SIO: [/"  << name << "/] "
00112                   << "SIO: Block not connected (pointer is NULL)"
00113                   << std::endl;
00114     }
00115     return( SIO_RECORD_BADARGUMENT );
00116 }
00117 s_name = *(block->getName());
00118 
00119 //
00120 // Go to the workhorse.
00121 //
00122 return( connect( &s_name, block ) );
00123 }
00124 
00125 // ----------------------------------------------------------------------------
00126 // Connect a block to a record (workhorse).                               
00127 // ----------------------------------------------------------------------------
00128 unsigned int SIO_record::connect
00129 (
00130    std::string*         s_name,
00131    SIO_block*           block    
00132 )
00133 {
00134 
00135 //
00136 // Local variables.
00137 //
00138 std::pair< connectMap_i, bool >
00139     status;
00140 
00141 //
00142 // Initialize the map entry.
00143 //
00144 std::pair< std::string const, SIO_block* >
00145     entry( *s_name, block );
00146 
00147 //
00148 // Insert the new entry.
00149 //
00150 
00151 status = connectMap.insert( entry );
00152 if( status.second )
00153 {
00154   if( verbosity >= SIO_ALL )
00155     {
00156         std::cout << "SIO: [/"  << name << "/" << entry.first << "] "
00157                   << "Connected" 
00158                   << std::endl;
00159     }
00160 }
00161 else
00162 {
00163   //fg:  no need to keep old block handler if user wants to connect a new one
00164 
00165   status.first->second = block ;
00166 
00167     if( verbosity >= SIO_ALL )
00168     {
00169         std::cout << "SIO: [/"  << name << "/" << entry.first << "] "
00170                   << "connected new handler "
00171                   << std::endl;
00172     }
00173 
00174 
00175 //     if( verbosity >= SIO_ERRORS )
00176 //     {
00177 //         std::cout << "SIO: [/"  << name << "/" << entry.first << "] "
00178 //                   << "Already connected"
00179 //                   << std::endl;
00180 //     }
00181 //    return( SIO_RECORD_DUPCONNECT );
00182 }
00183 
00184 //
00185 // That's all folks!
00186 //
00187 return( SIO_RECORD_SUCCESS );
00188 }
00189 
00190 
00191 // ----------------------------------------------------------------------------
00192 // fg: Disconnect all blocks from  record 
00193 // ----------------------------------------------------------------------------
00194 unsigned int SIO_record::disconnectAll() {
00195 
00196   connectMap_i iter;
00197   
00198   if( verbosity >= SIO_ALL ) {
00199     for( iter =  connectMap.begin() ; iter != connectMap.end() ; ++iter) {
00200 
00201     std::cout << "SIO: [/"  << name << "/" << iter->first << "]  "
00202               << *(iter->second->getName()) 
00203               << "  Disconnected" 
00204               << std::endl;
00205     }
00206   }
00207   connectMap.erase(connectMap.begin(), connectMap.end());
00208 
00209   return( SIO_RECORD_SUCCESS );
00210 }
00211 // ----------------------------------------------------------------------------
00212 // Disconnect a block from a record (by name).
00213 // ----------------------------------------------------------------------------
00214 unsigned int SIO_record::disconnect
00215 (
00216     const char*  i_name
00217 )
00218 {
00219 
00220 //
00221 // Local variables.
00222 //
00223 SIO_block
00224    *block;
00225 
00226 std::string
00227     s_name = i_name;
00228 
00229 //
00230 // Validate the name.
00231 //
00232 block = SIO_blockManager::get( i_name );
00233 if( block == NULL )
00234 {
00235     if( verbosity >= SIO_ERRORS )
00236     {
00237         std::cout << "SIO: [/"  << name << "/" << i_name << "] "
00238                   << "Not disconnected (block name not recognized)"
00239                   << std::endl;
00240     }
00241     return( SIO_RECORD_BADARGUMENT );
00242 }
00243 
00244 //
00245 // Go to the workhorse.
00246 //
00247 return( disconnect( &s_name, block ) );
00248 }
00249 
00250 // ----------------------------------------------------------------------------
00251 // Disconnect a block from a record (by pointer).
00252 // ----------------------------------------------------------------------------
00253 unsigned int SIO_record::disconnect
00254 (
00255     SIO_block*  block
00256 )
00257 {
00258 
00259 //
00260 // Local variables.
00261 //
00262 std::string
00263     s_name;
00264 
00265 //
00266 // Validate the block pointer.
00267 //
00268 if( block == NULL )
00269 {
00270     if( verbosity >= SIO_ERRORS )
00271     {
00272         std::cout << "SIO: [/"  << name << "/] "
00273                   << "Not disconnected (pointer is NULL)"
00274                   << std::endl;
00275     }
00276     return( SIO_RECORD_BADARGUMENT );
00277 }
00278 s_name = *(block->getName());
00279 
00280 //
00281 // Go to the workhorse.
00282 //
00283 return( disconnect( &s_name, block ) );
00284 }
00285 
00286 // ----------------------------------------------------------------------------
00287 // Disconnect a block from a record (workhorse).
00288 // ----------------------------------------------------------------------------
00289 unsigned int SIO_record::disconnect
00290 (
00291     std::string*          s_name,
00292     SIO_block*            block
00293 )
00294 {
00295 
00296 //
00297 // Local variables.
00298 //
00299 connectMap_i
00300     iter;
00301 
00302 //
00303 // Use the map's find function.  It the name doesn't exist, return an error.
00304 //
00305 if( (iter = connectMap.find( *s_name )) == connectMap.end() )
00306 {
00307     if( verbosity >= SIO_ERRORS )
00308     {
00309         std::cout << "SIO: [/"  << name << "/" << *s_name << "] "
00310                   << "Not disconnected (block is not connected)"
00311                   << std::endl;
00312     }
00313     return( SIO_RECORD_NOTCONNECTED );
00314 }
00315 
00316 //
00317 // Remove the connection in the connection map.
00318 //
00319 connectMap.erase( iter );
00320 
00321 if( verbosity >= SIO_ALL )
00322 {
00323     std::cout << "SIO: [/"  << name << "/" << *s_name << "] "
00324               << "Disconnected" 
00325               << std::endl;
00326 }
00327 
00328 //
00329 // That's all folks!
00330 //
00331 return( SIO_RECORD_SUCCESS );
00332 }
00333 
00334 // ----------------------------------------------------------------------------
00335 // Find a connected block pointer from the name.
00336 // ----------------------------------------------------------------------------
00337 SIO_block* SIO_record::getConnect
00338 (
00339    const char*   i_name
00340 )
00341 {
00342 
00343 //
00344 // Local variables.
00345 //
00346 connectMap_i
00347     iter;
00348 
00349 std::string
00350     s_name = i_name;
00351 
00352 //
00353 // Use the map's find function.  It the name doesn't exist, return NULL.
00354 //
00355 if( (iter = connectMap.find( s_name )) == connectMap.end() )
00356 {
00357     if( verbosity >= SIO_ERRORS )
00358     {
00359         std::cout << "SIO: [/"  << name << "/" << i_name << "] "
00360                   << "Block is not connected" 
00361                   << std::endl;
00362     }
00363     return( NULL );
00364 }
00365 
00366 if( verbosity >= SIO_ALL )
00367 {
00368     std::cout << "SIO: [/"  << name << "/" << i_name << "] "
00369               << "Block is connected" 
00370               << std::endl;
00371 }
00372 
00373 //
00374 // That's all folks!
00375 //
00376 return( iter->second );
00377 }
00378 
00379 // ----------------------------------------------------------------------------
00380 // Return compression flag.
00381 // ----------------------------------------------------------------------------
00382 bool SIO_record::getCompress()
00383 {
00384 if( (options & SIO_OPT_COMPRESS) != 0 )
00385     return( true ); 
00386 
00387 return( false );
00388 }
00389 
00390 // ----------------------------------------------------------------------------
00391 // Return pointer to record name.
00392 // ----------------------------------------------------------------------------
00393 std::string* SIO_record::getName()         { return( &name );     }
00394 
00395 // ----------------------------------------------------------------------------
00396 // Return options word.
00397 // ----------------------------------------------------------------------------
00398 unsigned int SIO_record::getOptions()      { return( options );   }
00399 
00400 // ----------------------------------------------------------------------------
00401 // Return unpacking flag.
00402 // ----------------------------------------------------------------------------
00403 bool SIO_record::getUnpack()               { return( unpack );    }
00404 
00405 // ----------------------------------------------------------------------------
00406 // Return verbosity.
00407 // ----------------------------------------------------------------------------
00408 SIO_verbosity SIO_record::getVerbosity()   { return( verbosity ); }
00409 
00410 // ----------------------------------------------------------------------------
00411 // Read a record.
00412 // ----------------------------------------------------------------------------
00413 unsigned int SIO_record::read
00414 (
00415     SIO_stream*         stream,
00416     unsigned int        i_options
00417 )
00418 {
00419 
00420 //
00421 // Local variables.
00422 //
00423 SIO_block
00424    *block;
00425 
00426 pointedAtMap_i
00427     pati;
00428 
00429 pointerToMap_i
00430     ptoh,
00431     ptoi,
00432     ptol;
00433     
00434 SIO_POINTER_DECL
00435    *pointer;
00436 
00437 unsigned int
00438     buflen,
00439     buftyp,
00440     status,
00441     tmplen,
00442     version;
00443 
00444 char
00445    *tmploc;
00446 
00447 //
00448 // Save the options.
00449 //
00450 options = i_options;
00451 
00452 //
00453 // Walk along the record buffer unpacking blocks.
00454 //
00455 while( stream->buffer < stream->recmax )
00456 {
00457     //
00458     // Set the block maximum marker out of the way while interpreting the
00459     // block length and type (but even so, don't let reads escape off the
00460     // total length of the buffer!
00461     //
00462     stream->blkmax = stream->recmax;
00463 
00464     //
00465     // Interpret: 1) The length of the block.
00466     //            2) The block marker.
00467     //
00468     SIO_DATA( stream, &buflen, 1 );
00469     SIO_DATA( stream, &buftyp, 1 );
00470     if( buftyp != SIO_mark_block )
00471     {
00472         if( verbosity >= SIO_ERRORS )
00473         {
00474             std::cout << "SIO: ["  << stream->name << "/" << name << "/] "
00475                       << "Expected block marker not found"
00476                       << std::endl;
00477         }
00478         return( SIO_RECORD_NOBLKMARKER );
00479     }
00480     stream->blkmax = stream->buffer + buflen - 8;
00481 
00482     //
00483     // Read the block version.
00484     //
00485     SIO_DATA( stream, &version, 1 );
00486 
00487     //
00488     // Read and interpret the block name.
00489     //
00490     SIO_DATA( stream, &tmplen, 1 );
00491 
00492     tmploc = static_cast<char *>(malloc( tmplen + 1 ));
00493     if( tmploc == NULL )
00494     {
00495         if( verbosity >= SIO_ERRORS )
00496         {
00497             std::cout << "SIO: ["  << stream->name << "/" << name << "/] "
00498                       << "Buffer allocation failed"
00499                       << std::endl;
00500         }
00501         return( SIO_STREAM_NOALLOC );
00502     }
00503 
00504     SIO_DATA( stream, tmploc, tmplen );
00505     tmploc[tmplen]   = '\0';
00506     block            = SIO_blockManager::get( tmploc );
00507     stream->blk_name = tmploc;
00508     free( tmploc );
00509 
00510     //
00511     // Try to unpack the block.
00512     //
00513     if( block != NULL )
00514     {
00515         status = block->xfer( stream, SIO_OP_READ, version );
00516         if( !(status & 1) )
00517             return( status );
00518     }
00519 
00520     else
00521         stream->buffer = stream->blkmax;
00522 }
00523 
00524 //
00525 // Pointer relocation on read.
00526 //
00527 // Some of these variables are a little terse!  Expanded meanings:
00528 //
00529 // ptol:  Iterator pointing to lower bound in the 'pointer to' multimap
00530 // ptoh:  Iterator pointing to upper bound in the 'pointer to' multimap
00531 // ptoi:  Iterator for the 'pointer to' multimap (runs [ptol, ptoh) )
00532 // pati:  Iterator in the 'pointed at' map (search map for ptol->first)
00533 //
00534 ptol  = stream->pointerTo->begin();
00535 while( ptol != stream->pointerTo->end() )
00536 {
00537     ptoh = stream->pointerTo->upper_bound( ptol->first );
00538     pati = stream->pointedAt->find( ptol->first );
00539 
00540     if( pati != stream->pointedAt->end() )
00541     {
00542         for( ptoi = ptol; ptoi != ptoh; ptoi++ )
00543         {
00544              pointer = static_cast     <SIO_POINTER_DECL *>(ptoi->second); 
00545             *pointer = reinterpret_cast<SIO_POINTER_DECL  >(pati->second);
00546         }
00547     }
00548     ptol = ptoh;
00549 }
00550 
00551 //
00552 // That's all folks!
00553 //
00554 return( SIO_RECORD_SUCCESS );
00555 }
00556 
00557 // ----------------------------------------------------------------------------
00558 // Set/reset the compression flag.
00559 // ----------------------------------------------------------------------------
00560 bool SIO_record::setCompress
00561 (
00562     bool     compress
00563 )
00564 {
00565 unsigned int 
00566     o_options = (options & SIO_OPT_COMPRESS);
00567 
00568                options &= ~SIO_OPT_COMPRESS;
00569 if( compress ) options |=  SIO_OPT_COMPRESS;
00570 
00571 if( o_options != 0 )
00572     return( true ); 
00573 
00574 return( false );
00575 }
00576 
00577 // ----------------------------------------------------------------------------
00578 // Set/reset the unpacking flag.
00579 // ----------------------------------------------------------------------------
00580 bool SIO_record::setUnpack
00581 (
00582     bool  i_unpack
00583 )
00584 { 
00585   bool o_unpack = unpack; 
00586   unpack = i_unpack; 
00587  
00588  if( verbosity >= SIO_ERRORS ){
00589    std::cout << "SIO: [/"  << name << "] "
00590              << " setting unpack from " << o_unpack << " to  " << unpack << std::endl ;
00591  }
00592 
00593  return( o_unpack ); 
00594 }
00595 
00596 // ----------------------------------------------------------------------------
00597 // Set the verbosity level.
00598 // ----------------------------------------------------------------------------
00599 SIO_verbosity SIO_record::setVerbosity
00600 (
00601     SIO_verbosity   i_verb
00602 )
00603 { SIO_verbosity o_verb = verbosity; verbosity = i_verb; return( o_verb ); } 
00604 
00605 // ----------------------------------------------------------------------------
00606 // Write a record.
00607 // ----------------------------------------------------------------------------
00608 unsigned int SIO_record::write
00609 (
00610     SIO_stream*         stream
00611 )
00612 {
00613 
00614 //
00615 // Local variables.
00616 //
00617 pointedAtMap_i
00618     pati;
00619 
00620 pointerToMap_i
00621     ptoh,
00622     ptoi,
00623     ptol;
00624     
00625 
00626 connectMap_i
00627     iter;
00628 
00629 unsigned int
00630     blkver,
00631     buflen,
00632     match,
00633     namlen,
00634     status;
00635 
00636 unsigned char
00637    *pointer;
00638 
00639 const char
00640    *nampnt;
00641 
00642 //
00643 // Loop over blocks, getting their input.
00644 //
00645 for( iter = connectMap.begin(); iter != connectMap.end(); iter++ )
00646 {
00647     //
00648     // Save the beginning of block pointer.  Reuse the stream->blkmax variable
00649     // (which has no use during buffer writing) to save it so that if the copy
00650     // routine in SIO_functions is forced to reallocate the output buffer,
00651     // the pointer to the beginning of block can be updated as well.
00652     // 
00653     stream->blkmax = stream->buffer;
00654 
00655     //
00656     // Output: 1) A placeholder where the block length will go.
00657     //         2) A 'framing' marker (to help in debugging).
00658     //         3) The version of the block.
00659     //         4) The length of the block name.
00660     //         5) The block name.
00661     //
00662     SIO_DATA( stream, &SIO_mark_block,             1      );
00663     SIO_DATA( stream, &SIO_mark_block,             1      );
00664 
00665     blkver = iter->second->version();
00666     SIO_DATA( stream, &blkver,                     1      );
00667 
00668     namlen = iter->first.size();
00669     nampnt = iter->first.c_str();
00670 
00671     SIO_DATA( stream, &namlen,                     1      );
00672     SIO_DATA( stream,  const_cast<char *>(nampnt), namlen );
00673 
00674     //
00675     // Write the block content.
00676     //
00677     status = iter->second->xfer( stream, SIO_OP_WRITE, blkver );
00678     if( status != SIO_BLOCK_SUCCESS )
00679     {
00680         if( verbosity >= SIO_ERRORS )
00681         {
00682             std::cout << "SIO: ["  
00683                       << stream->name << "/" 
00684                       << name << "/" 
00685                       << iter->first << "] "
00686                       << "Write error" 
00687                       << std::endl;
00688         }
00689         return( status );
00690     }
00691    
00692     //
00693     // Back fill the length of the block.
00694     //
00695     buflen = stream->buffer - stream->blkmax;
00696     SIO_functions::copy( UCHR_CAST(&buflen),
00697                          stream->blkmax, SIO_LEN_QB, 1 );
00698 }
00699 
00700 //
00701 // Pointer relocation on write.
00702 //
00703 // Some of these variables are a little terse!  Expanded meanings:
00704 //
00705 // ptol:  Iterator pointing to lower bound in the 'pointer to' multimap
00706 // ptoh:  Iterator pointing to upper bound in the 'pointer to' multimap
00707 // ptoi:  Iterator for the 'pointer to' multimap (runs [ptol, ptoh) )
00708 // pati:  Iterator in the 'pointed at' map (search map for ptol->first)
00709 //
00710 
00711 //
00712 // The next piece of code was just too valuable a debugging tool to toss out!
00713 //
00714 /*
00715 printf("\nPointer to:\n\n" );
00716 for( ptoi  = stream->pointerTo->begin();
00717      ptoi != stream->pointerTo->end();
00718      ptoi++ )
00719 {
00720     printf("%016lx    %016lx\n", ptoi->first, ptoi->second );
00721 }
00722 
00723 printf("\nPointed at:\n\n" );
00724 for( pati  = stream->pointedAt->begin();
00725      pati != stream->pointedAt->end();
00726      pati++ )
00727 {
00728     printf("%016lx    %016lx\n", pati->first, pati->second );
00729 }
00730 */
00731 
00732 match = 0x00000001;
00733 ptol  = stream->pointerTo->begin();
00734 while( ptol != stream->pointerTo->end() )
00735 {
00736     ptoh = stream->pointerTo->upper_bound( ptol->first );
00737     pati = stream->pointedAt->find( ptol->first );
00738 
00739     if( pati != stream->pointedAt->end() )
00740     {
00741         pointer = stream->bufloc + 
00742                   reinterpret_cast<SIO_POINTER_DECL>(pati->second);
00743 
00744         SIO_functions::copy( UCHR_CAST( &match ), pointer, SIO_LEN_QB, 1 );
00745 
00746         for( ptoi = ptol; ptoi != ptoh; ptoi++ )
00747         {
00748             pointer = stream->bufloc + 
00749                       reinterpret_cast<SIO_POINTER_DECL>(ptoi->second);
00750 
00751             SIO_functions::copy( UCHR_CAST( &match ), pointer, SIO_LEN_QB, 1 );
00752         }
00753     }
00754 
00755     match++;
00756     ptol = ptoh;
00757 }
00758 
00759 //
00760 // That's all folks!
00761 //
00762 return( SIO_RECORD_SUCCESS );
00763 }

Generated on Mon Jan 7 13:15:21 2013 for MicromegasFramework by  doxygen 1.4.7