LCOV - code coverage report
Current view: top level - utils/shmimPlot - shmimPlot.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 269 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /** \file shmimPlot.hpp
       2              :  * \brief The shmimPlot class declaration and definition.
       3              :  *
       4              :  * \ingroup xrif2hmim_files
       5              :  */
       6              : 
       7              : #ifndef shmimPlot_hpp
       8              : #define shmimPlot_hpp
       9              : 
      10              : #include <ImageStreamIO/ImageStruct.h>
      11              : #include <ImageStreamIO/ImageStreamIO.h>
      12              : 
      13              : #include <xrif/xrif.h>
      14              : 
      15              : #include <mx/ioutils/fileUtils.hpp>
      16              : #include <mx/improc/eigenCube.hpp>
      17              : 
      18              : #include <mx/sys/timeUtils.hpp>
      19              : #include <mx/math/plot/gnuPlot.hpp>
      20              : 
      21              : #include "../../libMagAOX/libMagAOX.hpp"
      22              : 
      23              : /** \defgroup shmimPlot shmimPlot: plot data from a shmim in gnuplot
      24              :  * \brief Monitor a shmim and update a gnuplot plot
      25              :  *
      26              :  * <a href="../handbook/utils/shmimPlot.html">Utility Documentation</a>
      27              :  *
      28              :  * \ingroup utils
      29              :  *
      30              :  */
      31              : 
      32              : /** \defgroup shmimPlot_files shmimPlot Files
      33              :  * \ingroup shmimPlot
      34              :  */
      35              : 
      36              : bool g_timeToDie = false;
      37              : 
      38            0 : void sigTermHandler( int signum, siginfo_t *siginf, void *ucont )
      39              : {
      40              :     // Suppress those warnings . . .
      41              :     static_cast<void>( signum );
      42              :     static_cast<void>( siginf );
      43              :     static_cast<void>( ucont );
      44              : 
      45            0 :     std::cerr << "\n"; // clear out the ^C char
      46              : 
      47            0 :     g_timeToDie = true;
      48            0 : }
      49              : 
      50              : /// A utility to stream MagaO-X images from xrif compressed archives to an ImageStreamIO stream.
      51              : /**
      52              :  * \todo finish md doc for shmimPlot
      53              :  *
      54              :  * \ingroup shmimPlot
      55              :  */
      56              : class shmimPlot : public mx::app::application
      57              : {
      58              :   protected:
      59              :     /** \name Configurable Parameters
      60              :      * @{
      61              :      */
      62              : 
      63              :     double m_fps{ 2 }; ///< The rate, in plots per second, at which to plot. Default is 2 Hz.
      64              : 
      65              :     bool m_logx{ false };
      66              :     bool m_logy{ false };
      67              : 
      68              :     float m_x0{ 0 };
      69              :     float m_x1{ 0 };
      70              :     bool  m_xr_set{ false };
      71              : 
      72              :     float m_y0{ 0 };
      73              :     float m_y1{ 0 };
      74              :     bool  m_yr_set{ false };
      75              : 
      76              :     std::vector<int> m_cols;
      77              : 
      78              :     std::vector<int> m_rows;
      79              : 
      80              :     ///@}
      81              : 
      82              :     /// Structure to manage the image threads, including startup.
      83              :     struct s_imageThread
      84              :     {
      85              :         shmimPlot *m_sp; ///< a pointer to a shmimPlot instance (normally this)
      86              : 
      87              :         std::thread *m_thread{ nullptr }; ///< Thread for receiving image slice updates.  A pointer to allow copying,
      88              :                                           ///< but must be deleted in d'tor of parent.
      89              : 
      90              :         std::string m_shmimName; ///< the name of the image to subscribe from this thread
      91              : 
      92              :         std::vector<std::vector<float>> m_y;
      93              : 
      94              :         /// C'tor to create the thread object
      95            0 :         s_imageThread()
      96            0 :         {
      97            0 :             m_thread = new std::thread;
      98            0 :         }
      99              :     };
     100              : 
     101              :     std::vector<s_imageThread> m_imageThreads; ///< The image threads, one per shared memory stream.
     102              : 
     103              :     mx::math::gnuPlot m_gp;
     104              :     ///@}
     105              : 
     106              :   public:
     107              :     ~shmimPlot();
     108              : 
     109              :     virtual void setupConfig();
     110              : 
     111              :     virtual void loadConfig();
     112              : 
     113              :     virtual int execute();
     114              : 
     115            0 :     void doPlot()
     116              :     {
     117              :         // m_gp.clear();
     118              : 
     119            0 :         for( size_t i = 0; i < m_imageThreads.size(); ++i )
     120              :         {
     121            0 :             for( size_t n = 0; n < m_imageThreads[i].m_y.size(); ++n )
     122              :             {
     123            0 :                 std::string tit = m_imageThreads[i].m_shmimName;
     124            0 :                 if( m_imageThreads[i].m_y.size() > 0 )
     125              :                 {
     126            0 :                     if( m_rows.size() > 0 )
     127              :                     {
     128            0 :                         tit += " " + std::to_string( m_rows[n] );
     129              :                     }
     130              :                     else
     131              :                     {
     132            0 :                         tit += " " + std::to_string( m_cols[n] );
     133              :                     }
     134              :                 }
     135              : 
     136            0 :                 m_gp.plot( m_imageThreads[i].m_y[n], "w l", tit, tit );
     137            0 :             }
     138              :         }
     139            0 :     }
     140              : 
     141              :   private:
     142              :     /// Thread starter, called by imageThreadStart on thread construction.  Calls imageThreadExec.
     143              :     static void internal_imageThreadStart( s_imageThread *mit /**< [in] a pointer to an s_imageThread structure */ );
     144              : 
     145              :   public:
     146              :     /// Start the image thread.
     147              :     int imageThreadStart( size_t thno /**< [in] the thread to start */ );
     148              : 
     149              :     /// Execute the image thread.
     150              :     void imageThreadExec( s_imageThread *mit /**< [in] a pointer to an s_imageThread structure */ );
     151              : };
     152              : 
     153            0 : inline shmimPlot::~shmimPlot()
     154              : {
     155            0 : }
     156              : 
     157            0 : inline void shmimPlot::setupConfig()
     158              : {
     159            0 :     config.add( "shmimName",
     160              :                 "n",
     161              :                 "shmimName",
     162              :                 argType::Required,
     163              :                 "",
     164              :                 "shmimName",
     165              :                 false,
     166              :                 "vector<string>",
     167              :                 "The names of the shared memory buffer to stream to.  Default is \"shmimPlot\"" );
     168              : 
     169            0 :     config.add( "circBuffLength",
     170              :                 "L",
     171              :                 "circBuffLength",
     172              :                 argType::Required,
     173              :                 "",
     174              :                 "circBuffLength",
     175              :                 false,
     176              :                 "int",
     177              :                 "The length of the shared memory circular buffer. Default is 1." );
     178              : 
     179            0 :     config.add( "fps",
     180              :                 "F",
     181              :                 "fps",
     182              :                 argType::Required,
     183              :                 "",
     184              :                 "fps",
     185              :                 false,
     186              :                 "float",
     187              :                 "The rate, in frames per second, at which to stream images. Default is 10 fps." );
     188              : 
     189            0 :     config.add( "logx", "", "logx", argType::True, "", "logx", false, "bool", "Set the x-axis to log scale" );
     190              : 
     191            0 :     config.add( "logy", "", "logy", argType::True, "", "logy", false, "bool", "Set the y-axis to log scale" );
     192              : 
     193            0 :     config.add( "x0", "", "x0", argType::Required, "", "x0", false, "float", "The x-axis minimum value" );
     194              : 
     195            0 :     config.add( "x1", "", "x1", argType::Required, "", "x1", false, "float", "The x-axis maximum value" );
     196              : 
     197            0 :     config.add( "y0", "", "y0", argType::Required, "", "y0", false, "float", "The y-axis minimum value" );
     198              : 
     199            0 :     config.add( "y1", "", "y1", argType::Required, "", "y1", false, "float", "The y-axis maximum value" );
     200              : 
     201            0 :     config.add( "rows", "r", "rows", argType::Required, "", "rows", false, "vector<int>", "The row(s) to plot." );
     202              : 
     203            0 :     config.add( "cols",
     204              :                 "c",
     205              :                 "cols",
     206              :                 argType::Required,
     207              :                 "",
     208              :                 "cols",
     209              :                 false,
     210              :                 "vector<int>",
     211              :                 "The column(s) to plot.  Default is column 0." );
     212            0 : }
     213              : 
     214            0 : inline void shmimPlot::loadConfig()
     215              : {
     216            0 :     std::vector<std::string> shmimNames;
     217            0 :     config( shmimNames, "shmimName" );
     218              : 
     219            0 :     if( shmimNames.size() == 0 )
     220              :     {
     221            0 :         std::cerr << "shmim names not specified with -n\n";
     222            0 :         doHelp = true;
     223            0 :         return;
     224              :     }
     225              : 
     226            0 :     for( auto &s : shmimNames )
     227              :     {
     228            0 :         s_imageThread nt;
     229            0 :         nt.m_sp        = this;
     230            0 :         nt.m_shmimName = s;
     231            0 :         m_imageThreads.push_back( nt );
     232            0 :     }
     233              : 
     234            0 :     config( m_fps, "fps" );
     235              : 
     236            0 :     if( config.isSet( "logx" ) )
     237              :     {
     238            0 :         m_logx = true;
     239              :     }
     240              : 
     241            0 :     if( config.isSet( "logy" ) )
     242              :     {
     243            0 :         m_logy = true;
     244              :     }
     245              : 
     246            0 :     if( config.isSet( "x0" ) && config.isSet( "x1" ) )
     247              :     {
     248            0 :         m_xr_set = true;
     249            0 :         config( m_x0, "x0" );
     250            0 :         config( m_x1, "x1" );
     251              :     }
     252              : 
     253            0 :     if( config.isSet( "y0" ) && config.isSet( "y1" ) )
     254              :     {
     255            0 :         m_yr_set = true;
     256            0 :         config( m_y0, "y0" );
     257            0 :         config( m_y1, "y1" );
     258              :     }
     259              : 
     260            0 :     if( config.isSet( "rows" ) )
     261              :     {
     262            0 :         m_rows.push_back( 0 );
     263            0 :         config( m_rows, "rows" );
     264              :     }
     265              :     else
     266              :     {
     267            0 :         m_cols.push_back( 0 );
     268            0 :         config( m_cols, "cols" );
     269              :     }
     270              : 
     271            0 :     for( size_t n = 0; n < m_imageThreads.size(); ++n )
     272              :     {
     273            0 :         if( m_rows.size() > 0 )
     274              :         {
     275            0 :             m_imageThreads[n].m_y.resize( m_rows.size() );
     276              :         }
     277              :         else
     278              :         {
     279            0 :             m_imageThreads[n].m_y.resize( m_cols.size() );
     280              :         }
     281              :     }
     282              : 
     283              :     // Setup gnuplot
     284            0 :     if( m_logx )
     285              :     {
     286            0 :         m_gp.logx();
     287              :     }
     288              : 
     289            0 :     if( m_logy )
     290              :     {
     291            0 :         m_gp.logy();
     292              :     }
     293              : 
     294            0 :     if( m_xr_set )
     295              :     {
     296            0 :         m_gp.xrange( m_x0, m_x1 );
     297              :     }
     298              : 
     299            0 :     if( m_yr_set )
     300              :     {
     301            0 :         m_gp.yrange( m_y0, m_y1 );
     302              :     }
     303              : 
     304              :     // m_gp.command( "set term qt font \"Arial,14\" title \"" + m_shmimName + "\" noraise" );
     305            0 :     m_gp.command( "set object 1 rectangle from screen 0,0 to screen 1,1 fillcolor rgb \"#23262a\" behind" );
     306            0 :     m_gp.command( "set border lc rgb \"#eff0f1\"" );
     307            0 :     m_gp.command( "set key font \"Arial,14\" textcolor \"#eff0f1\" noenhanced" );
     308            0 : }
     309              : 
     310            0 : inline int shmimPlot::execute()
     311              : {
     312              : 
     313              :     // Install signal handling
     314              :     struct sigaction act;
     315              :     sigset_t         set;
     316              : 
     317            0 :     act.sa_sigaction = sigTermHandler;
     318            0 :     act.sa_flags     = SA_SIGINFO;
     319            0 :     sigemptyset( &set );
     320            0 :     act.sa_mask = set;
     321              : 
     322            0 :     errno = 0;
     323            0 :     if( sigaction( SIGTERM, &act, 0 ) < 0 )
     324              :     {
     325            0 :         std::cerr << " (" << invokedName << "): error setting SIGTERM handler: " << strerror( errno ) << "\n";
     326            0 :         return -1;
     327              :     }
     328              : 
     329            0 :     errno = 0;
     330            0 :     if( sigaction( SIGQUIT, &act, 0 ) < 0 )
     331              :     {
     332            0 :         std::cerr << " (" << invokedName << "): error setting SIGQUIT handler: " << strerror( errno ) << "\n";
     333            0 :         return -1;
     334              :     }
     335              : 
     336            0 :     errno = 0;
     337            0 :     if( sigaction( SIGINT, &act, 0 ) < 0 )
     338              :     {
     339            0 :         std::cerr << " (" << invokedName << "): error setting SIGINT handler: " << strerror( errno ) << "\n";
     340            0 :         return -1;
     341              :     }
     342              : 
     343            0 :     for( size_t n = 0; n < m_imageThreads.size(); ++n )
     344              :     {
     345            0 :         std::cerr << "starting " << m_imageThreads[n].m_shmimName << '\n';
     346            0 :         imageThreadStart( n );
     347              :     }
     348              : 
     349            0 :     while( !g_timeToDie )
     350              :     {
     351            0 :         sleep( 1 );
     352            0 :         doPlot();
     353              :     }
     354              : 
     355            0 :     m_gp.command( "set term qt close" );
     356              : 
     357            0 :     return 0;
     358              : }
     359              : 
     360            0 : inline void shmimPlot::internal_imageThreadStart( s_imageThread *mit )
     361              : {
     362            0 :     mit->m_sp->imageThreadExec( mit );
     363            0 : }
     364              : 
     365            0 : inline int shmimPlot::imageThreadStart( size_t thno )
     366              : {
     367              :     try
     368              :     {
     369            0 :         *m_imageThreads[thno].m_thread = std::thread( internal_imageThreadStart, &m_imageThreads[thno] );
     370              :     }
     371            0 :     catch( const std::exception &e )
     372              :     {
     373            0 :         std::cerr << std::string( "exception in image thread startup: " ) + e.what() << ' ' << __FILE__ << ' '
     374            0 :                   << __LINE__ << '\n';
     375            0 :         return -1;
     376            0 :     }
     377            0 :     catch( ... )
     378              :     {
     379            0 :         std::cerr << "unknown exception in image thread startup: " << __FILE__ << ' ' << __LINE__ << '\n';
     380            0 :         return -1;
     381            0 :     }
     382              : 
     383            0 :     if( !m_imageThreads[thno].m_thread->joinable() )
     384              :     {
     385            0 :         std::cerr << "image thread did not start: " << __FILE__ << ' ' << __LINE__ << '\n';
     386            0 :         return -1;
     387              :     }
     388              : 
     389            0 :     return 0;
     390              : }
     391              : 
     392            0 : inline void shmimPlot::imageThreadExec( s_imageThread *mit )
     393              : {
     394            0 :     bool  opened = false;
     395              :     bool  restart;
     396            0 :     ino_t inode           = 0; ///< The inode of the image stream file
     397            0 :     int   semaphoreNumber = 9; ///< The image structure semaphore index.
     398              : 
     399              :     uint32_t width;
     400              :     uint32_t height;
     401              :     uint32_t depth;
     402              :     uint8_t  dataType;
     403              :     size_t   typeSize;
     404              :     IMAGE    imageStream;
     405              : 
     406            0 :     mx::improc::eigenImage<float> im;
     407              : 
     408            0 :     float ( *pixget )( void *, size_t ){ nullptr }; ///< Pointer to a function to extract the image data as float
     409              : 
     410            0 :     while( !g_timeToDie )
     411              :     {
     412              :         /* Initialize ImageStreamIO
     413              :          */
     414            0 :         opened  = false;
     415            0 :         restart = false; // Set this up front, since we're about to restart.
     416              : 
     417            0 :         int logged = 0;
     418            0 :         while( !opened && !g_timeToDie && !restart )
     419              :         {
     420              :             // b/c ImageStreamIO prints every single time, and latest version don't support stopping it yet, and that
     421              :             // isn't thread-safe-able anyway we do our own checks.  This is the same code in ImageStreamIO_openIm...
     422              :             int  SM_fd;
     423              :             char SM_fname[200];
     424            0 :             ImageStreamIO_filename( SM_fname, sizeof( SM_fname ), mit->m_shmimName.c_str() );
     425            0 :             SM_fd = open( SM_fname, O_RDWR );
     426            0 :             if( SM_fd == -1 )
     427              :             {
     428            0 :                 if( !logged )
     429              :                 {
     430            0 :                     std::cerr << "ImageStream " + mit->m_shmimName + " not found (yet).  Retrying . . .\n";
     431              :                 }
     432            0 :                 logged = 1;
     433            0 :                 sleep( 1 ); // be patient
     434            0 :                 continue;
     435              :             }
     436              : 
     437              :             // Found and opened,  close it and then use ImageStreamIO
     438            0 :             logged = 0;
     439            0 :             close( SM_fd );
     440              : 
     441            0 :             if( ImageStreamIO_openIm( &imageStream, mit->m_shmimName.c_str() ) == 0 )
     442              :             {
     443              :                 /// \todo this isn't right--> isn't there a define in cacao to use?
     444            0 :                 if( imageStream.md[0].sem <= semaphoreNumber )
     445              : 
     446              :                 {
     447            0 :                     ImageStreamIO_closeIm( &imageStream );
     448            0 :                     mx::sys::sleep( 1 ); // We just need to wait for the server process to finish startup.
     449              :                 }
     450              :                 else
     451              :                 {
     452            0 :                     opened = true;
     453              :                     char SM_fname[200];
     454            0 :                     ImageStreamIO_filename( SM_fname, sizeof( SM_fname ), mit->m_shmimName.c_str() );
     455              : 
     456              :                     struct stat buffer;
     457            0 :                     int         rv = stat( SM_fname, &buffer );
     458              : 
     459            0 :                     if( rv != 0 )
     460              :                     {
     461            0 :                         std::cerr << "Could not get inode for " + mit->m_shmimName +
     462            0 :                                          ". Source process will need to be restarted.\n";
     463            0 :                         ImageStreamIO_closeIm( &imageStream );
     464            0 :                         return;
     465              :                     }
     466            0 :                     inode = buffer.st_ino;
     467              :                 }
     468              :             }
     469              :             else
     470              :             {
     471            0 :                 mx::sys::sleep( 1 ); // be patient
     472              :             }
     473              :         }
     474              : 
     475            0 :         if( restart )
     476              :         {
     477            0 :             continue; // this is kinda dumb.  we just go around on restart, so why test in the while loop at all?
     478              :         }
     479              : 
     480            0 :         if( g_timeToDie )
     481              :         {
     482            0 :             if( !opened )
     483              :             {
     484            0 :                 return;
     485              :             }
     486              : 
     487            0 :             ImageStreamIO_closeIm( &imageStream );
     488            0 :             return;
     489              :         }
     490              : 
     491              :         semaphoreNumber =
     492            0 :             ImageStreamIO_getsemwaitindex( &imageStream, semaphoreNumber ); // ask for semaphore we had before
     493              : 
     494            0 :         if( semaphoreNumber < 0 )
     495              :         {
     496            0 :             std::cerr << "No valid semaphore found for " + mit->m_shmimName +
     497            0 :                              ". Source process will need to be restarted.\n";
     498            0 :             return;
     499              :         }
     500              : 
     501            0 :         ImageStreamIO_semflush( &imageStream, semaphoreNumber );
     502              : 
     503            0 :         sem_t *sem = imageStream.semptr[semaphoreNumber]; ///< The semaphore to monitor for new image data
     504              : 
     505            0 :         dataType = imageStream.md[0].datatype;
     506            0 :         typeSize = ImageStreamIO_typesize( dataType );
     507            0 :         width    = imageStream.md[0].size[0];
     508            0 :         int dim  = 1;
     509            0 :         if( imageStream.md[0].naxis > 1 )
     510              :         {
     511            0 :             height = imageStream.md[0].size[1];
     512              : 
     513            0 :             if( imageStream.md[0].naxis > 2 )
     514              :             {
     515            0 :                 dim   = 3;
     516            0 :                 depth = imageStream.md[0].size[2];
     517              :             }
     518              :             else
     519              :             {
     520            0 :                 dim   = 2;
     521            0 :                 depth = 1;
     522              :             }
     523              :         }
     524              :         else
     525              :         {
     526            0 :             height = 1;
     527            0 :             depth  = 1;
     528              :         }
     529              : 
     530              :         uint8_t  atype;
     531              :         size_t   snx, sny, snz;
     532              :         uint64_t curr_image; // The current cnt1 index
     533              : 
     534            0 :         if( imageStream.md[0].size[2] > 0 ) ///\todo change to naxis?
     535              :         {
     536            0 :             curr_image = imageStream.md[0].cnt1;
     537              :         }
     538              :         else
     539              :         {
     540            0 :             curr_image = 0;
     541              :         }
     542              : 
     543            0 :         atype = imageStream.md[0].datatype;
     544            0 :         snx   = imageStream.md[0].size[0];
     545              : 
     546            0 :         if( dim == 2 )
     547              :         {
     548            0 :             sny = imageStream.md[0].size[1];
     549            0 :             snz = 1;
     550              :         }
     551            0 :         else if( dim == 3 )
     552              :         {
     553            0 :             sny = imageStream.md[0].size[1];
     554            0 :             snz = imageStream.md[0].size[2];
     555              :         }
     556              :         else
     557              :         {
     558            0 :             sny = 1;
     559            0 :             snz = 1;
     560              :         }
     561              : 
     562            0 :         if( atype != dataType || snx != width || sny != height || snz != depth )
     563              :         {
     564            0 :             continue; // exit the nearest while loop and get the new image setup.
     565              :         }
     566              : 
     567            0 :         std::cerr << mit->m_shmimName << ' ' << width << " x " << height << '\n';
     568              : 
     569            0 :         im.resize( width, height );
     570            0 :         pixget = getPixPointer<float>( dataType );
     571              : 
     572            0 :         char *raw = reinterpret_cast<char *>( imageStream.array.raw ) + curr_image * width * height * typeSize;
     573              : 
     574            0 :         for( size_t idx = 0; idx < width * height; ++idx )
     575              :         {
     576            0 :             im( idx ) = pixget( raw, idx );
     577              :         }
     578              : 
     579            0 :         for( size_t n = 0; n < mit->m_y.size(); ++n )
     580              :         {
     581            0 :             if( m_rows.size() > 0 )
     582              :             {
     583            0 :                 mit->m_y[n].resize( height );
     584              : 
     585            0 :                 for( uint32_t c = 0; c < height; ++c )
     586              :                 {
     587            0 :                     mit->m_y[n][c] = im( m_rows[n], c );
     588              :                 }
     589              :             }
     590              :             else
     591              :             {
     592            0 :                 mit->m_y[n].resize( width );
     593              : 
     594            0 :                 for( uint32_t r = 0; r < width; ++r )
     595              :                 {
     596            0 :                     mit->m_y[n][r] = im( r, m_cols[n] );
     597              :                 }
     598              :             }
     599              :         }
     600              : 
     601              :         // This is the main image grabbing loop.
     602            0 :         while( !g_timeToDie && !restart )
     603              :         {
     604              :             timespec ts;
     605              : 
     606            0 :             if( clock_gettime( CLOCK_REALTIME, &ts ) < 0 )
     607              :             {
     608            0 :                 std::cerr << "error from clock_gettime\n";
     609            0 :                 return;
     610              :             }
     611              : 
     612            0 :             ts.tv_sec += 1;
     613              : 
     614            0 :             if( sem_timedwait( sem, &ts ) == 0 )
     615              :             {
     616            0 :                 if( imageStream.md[0].size[2] > 0 ) ///\todo change to naxis?
     617              :                 {
     618            0 :                     curr_image = imageStream.md[0].cnt1;
     619              :                 }
     620              :                 else
     621              :                 {
     622            0 :                     curr_image = 0;
     623              :                 }
     624              : 
     625            0 :                 atype = imageStream.md[0].datatype;
     626            0 :                 snx   = imageStream.md[0].size[0];
     627              : 
     628            0 :                 if( dim == 2 )
     629              :                 {
     630            0 :                     sny = imageStream.md[0].size[1];
     631            0 :                     snz = 1;
     632              :                 }
     633            0 :                 else if( dim == 3 )
     634              :                 {
     635            0 :                     sny = imageStream.md[0].size[1];
     636            0 :                     snz = imageStream.md[0].size[2];
     637              :                 }
     638              :                 else
     639              :                 {
     640            0 :                     sny = 1;
     641            0 :                     snz = 1;
     642              :                 }
     643              : 
     644            0 :                 if( atype != dataType || snx != width || sny != height || snz != depth )
     645              :                 {
     646              :                     break; // exit the nearest while loop and get the new image setup.
     647              :                 }
     648              : 
     649            0 :                 if( g_timeToDie || restart )
     650              :                 {
     651              :                     break; // Check for exit signals
     652              :                 }
     653              : 
     654            0 :                 char *raw = reinterpret_cast<char *>( imageStream.array.raw ) + curr_image * width * height * typeSize;
     655            0 :                 for( size_t idx = 0; idx < width * height; ++idx )
     656              :                 {
     657            0 :                     im( idx ) = pixget( raw, idx );
     658              :                 }
     659              : 
     660            0 :                 for( size_t n = 0; n < mit->m_y.size(); ++n )
     661              :                 {
     662            0 :                     if( m_rows.size() > 0 )
     663              :                     {
     664            0 :                         for( uint32_t c = 0; c < height; ++c )
     665              :                         {
     666            0 :                             mit->m_y[n][c] = im( m_rows[n], c );
     667              :                         }
     668              :                     }
     669              :                     else
     670              :                     {
     671            0 :                         for( uint32_t r = 0; r < width; ++r )
     672              :                         {
     673            0 :                             mit->m_y[n][r] = im( r, m_cols[n] );
     674              :                         }
     675              :                     }
     676              :                 }
     677              :             }
     678              :             else
     679              :             {
     680            0 :                 if( imageStream.md[0].sem <= 0 )
     681            0 :                     break; // Indicates that the server has cleaned up.
     682              : 
     683              :                 // Check for why we timed out
     684            0 :                 if( errno == EINTR )
     685            0 :                     break; // This indicates signal interrupted us, time to restart or shutdown, loop will exit normally
     686              :                            // if flags set.
     687              : 
     688              :                 // ETIMEDOUT means we should check for deletion, and then wait more.
     689              :                 // Otherwise, report an error.
     690            0 :                 if( errno != ETIMEDOUT )
     691              :                 {
     692            0 :                     std::cerr << "error from sem_timedwait\n";
     693            0 :                     break;
     694              :                 }
     695              : 
     696              :                 // Check if the file has disappeared.
     697              :                 int  SM_fd;
     698              :                 char SM_fname[200];
     699            0 :                 ImageStreamIO_filename( SM_fname, sizeof( SM_fname ), mit->m_shmimName.c_str() );
     700            0 :                 SM_fd = open( SM_fname, O_RDWR );
     701            0 :                 if( SM_fd == -1 )
     702              :                 {
     703            0 :                     restart = true;
     704              :                 }
     705            0 :                 close( SM_fd );
     706              : 
     707              :                 // Check if the inode changed
     708              :                 struct stat buffer;
     709            0 :                 int         rv = stat( SM_fname, &buffer );
     710            0 :                 if( rv != 0 )
     711              :                 {
     712            0 :                     restart = true;
     713              :                 }
     714              : 
     715            0 :                 if( buffer.st_ino != inode )
     716              :                 {
     717            0 :                     restart = true;
     718              :                 }
     719              :             }
     720              :         }
     721              : 
     722              :         // opened == true if we can get to this
     723            0 :         if( semaphoreNumber >= 0 )
     724            0 :             imageStream.semReadPID[semaphoreNumber] = 0; // release semaphore
     725            0 :         ImageStreamIO_closeIm( &imageStream );
     726            0 :         opened = false;
     727              : 
     728              :     } // outer loop, will exit if m_shutdown==true
     729              : 
     730            0 :     if( opened )
     731              :     {
     732            0 :         ImageStreamIO_closeIm( &imageStream );
     733              :     }
     734            0 : }
     735              : 
     736              : #endif // shmimPlot_hpp
        

Generated by: LCOV version 2.0-1