/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/sed/sed_process.c

Go to the documentation of this file.
00001 
00002 //
00003 // This file is part of sedflux.
00004 //
00005 // sedflux is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // sedflux is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with sedflux; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //
00019 //---
00020 
00021 #include "sed_process.h"
00022 #include "sed_signal.h"
00023 
00024 typedef struct
00025 {
00026 // Public
00027    double mass_added;
00028    double mass_lost;
00029    gboolean error;
00030 
00031 // Private
00032    double mass_before;
00033    double mass_after;
00034    double mass_total_added;
00035    double mass_total_lost;
00036 
00037    GTimer* timer;
00038    double  secs;
00039    gulong  u_secs;
00040 }
00041 Sed_real_process_info;
00042 
00043 CLASS ( Sed_process )
00044 {
00045    gchar*           name;
00046    gchar*           tag;
00047 
00048    gpointer         data;
00049 
00050    gboolean         active;
00051    double           start;
00052    double           stop;
00053 
00054    gint             run_count;
00055    gboolean         is_set;
00056 
00057    Sed_process*     parent;
00058    Sed_process*     child;
00059 
00060    gboolean         is_child;
00061 
00062    gboolean         logging;
00063    FILE**           log_files;
00064    double           interval;
00065    GArray*          next_event;
00066    Sed_real_process_info* info;
00067 
00068    init_func        f_init;
00069    run_func         f_run;
00070    destroy_func     f_destroy;
00071 
00072    dump_func        f_dump;
00073    load_func        f_load;
00074 };
00075 
00076 typedef struct
00077 {
00078    Sed_process p;
00079    GList*      obj_list;
00080 }
00081 __Sed_process_link;
00082 
00083 #define SED_PROCESS( ptr )      ( (Sed_process)(ptr) )
00084 #define SED_PROCESS_LINK( ptr ) ( (__Sed_process_link*)(ptr) )
00085 
00086 CLASS( Sed_process_queue )
00087 {
00088    GList* l; //< A list of processes
00089 };
00090 
00091 __Sed_process_link* sed_process_link_new           ( gchar* name       ,
00092                                                      init_func f_init  ,
00093                                                      run_func f_run    ,
00094                                                      destroy_func f_destroy    ,
00095                                                      Eh_key_file file  ,
00096                                                      GError** error );
00097 __Sed_process_link* sed_process_link_destroy       ( __Sed_process_link* link );
00098 Sed_process_queue  sed_process_queue_append       ( Sed_process_queue q ,
00099                                                     __Sed_process_link* p );
00100 Sed_process_queue  sed_process_queue_prepend      ( Sed_process_queue q ,
00101                                                     __Sed_process_link* p );
00102 Sed_process_queue  sed_process_queue_insert       ( Sed_process_queue q     ,
00103                                                     __Sed_process_link* link ,
00104                                                    gint position );
00105 gint               sed_process_queue_find_position( Sed_process_queue q ,
00106                                                     const gchar* name );
00107 GList*             sed_process_queue_find         ( Sed_process_queue q ,
00108                                                     const gchar* name );
00109 
00110 GQuark
00111 sed_process_error_quark( void )
00112 {
00113    return g_quark_from_static_string( "sed-process-error-quark" );
00114 }
00115 
00116 Sed_process_queue
00117 sed_process_queue_new( void )
00118 {
00119    Sed_process_queue q;
00120 
00121    NEW_OBJECT( Sed_process_queue , q );
00122 
00123    q->l = NULL;
00124 
00125    return q;
00126 }
00127 
00128 Sed_process_queue
00129 sed_process_queue_dup( Sed_process_queue s )
00130 {
00131    return sed_process_queue_copy( NULL , s );
00132 }
00133 
00134 Sed_process_queue
00135 sed_process_queue_copy( Sed_process_queue d , Sed_process_queue s )
00136 {
00137    if ( s )
00138    {
00139       GList* l;
00140 
00141       if ( d ) d = sed_process_queue_destroy( d );
00142 
00143       d = sed_process_queue_new( );
00144 
00145       for ( l=s->l ; l ; l=l->next )
00146          d->l = g_list_append( d->l , sed_process_dup( l->data ) );
00147       
00148    }
00149    return d;
00150 }
00151 
00152 __Sed_process_link*
00153 sed_process_link_new( gchar*       name      ,
00154                       init_func    f_init    ,
00155                       run_func     f_run     ,
00156                       destroy_func f_destroy ,
00157                       Eh_key_file  file      ,
00158                       GError**     error )
00159 {
00160    __Sed_process_link* link = eh_new( __Sed_process_link , 1 );
00161 
00162    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00163 
00164    eh_require( name );
00165    eh_require( file );
00166 
00167    if ( link )
00168    {
00169       GError* tmp_e = NULL;
00170 
00171       /* Create an empty process that will be used as a template for future objects */
00172       link->p        = sed_process_create( name , f_init , f_run , f_destroy );
00173 
00174       /* Scan object based on the template */
00175       link->obj_list = sed_process_scan  ( file , link->p , &tmp_e );
00176 
00177       if ( tmp_e && tmp_e->code == SED_PROC_ERROR_NOT_FOUND )
00178          g_clear_error( &tmp_e );
00179 
00180       if ( tmp_e )
00181       {
00182          link = sed_process_link_destroy( link );
00183          g_propagate_error( error , tmp_e );
00184       }
00185    }
00186 
00187    return link;
00188 }
00189 
00190 Sed_process_queue
00191 sed_process_queue_destroy( Sed_process_queue q )
00192 {
00193    if ( q )
00194    {
00195       GList* link;
00196 
00197       for ( link=q->l ; link ; link=link->next )
00198          sed_process_link_destroy( link->data );
00199 
00200       g_list_free( q->l );
00201 
00202       eh_free( q );
00203    }
00204 
00205    return NULL;
00206 }
00207 
00208 __Sed_process_link*
00209 sed_process_link_destroy( __Sed_process_link* link )
00210 {
00211    if ( link )
00212    {
00213       g_list_foreach( link->obj_list , (GFunc)sed_process_destroy , NULL );
00214       g_list_free   ( link->obj_list );
00215       sed_process_destroy( link->p );
00216       eh_free( link );
00217    }
00218    return NULL;
00219 }
00220 
00221 Sed_process_queue
00222 sed_process_queue_init( const gchar*       file       ,
00223                         Sed_process_init_t p_list[]   ,
00224                         Sed_process_family p_family[] ,
00225                         Sed_process_check  p_check[]  ,
00226                         GError**           error )
00227 {
00228    Sed_process_queue q = NULL;
00229 
00230    eh_require( file   );
00231    eh_require( p_list );
00232    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00233 
00234    if ( file && p_list )
00235    {
00236       GError*     tmp_err  = NULL;
00237       Eh_key_file key_file = NULL;
00238 
00239       key_file = eh_key_file_scan( file , &tmp_err );
00240 
00241       if ( key_file )
00242       {
00243          gssize i;
00244 
00245          q = sed_process_queue_new( );
00246          for ( i=0 ; p_list[i].name ; i++ )
00247             sed_process_queue_push( q , p_list[i] );
00248 
00249          sed_process_queue_scan( q , key_file , &tmp_err );
00250 
00251          if ( !tmp_err && p_family ) sed_process_queue_set_families( q , p_family , &tmp_err );
00252          if ( !tmp_err && p_check  ) sed_process_queue_validate    ( q , p_check  , &tmp_err );
00253 
00254 /*
00255          if ( !tmp_err )
00256          {
00257             if ( on_procs )
00258             {
00259                gchar** name;
00260                sed_process_queue_deactivate( q , "<all>" );
00261 
00262                for ( name=on_procs ; *name ; name++ )
00263                   sed_process_queue_activate( q , *name );
00264             }
00265 
00266             //if ( hook_func ) hook_func( q );
00267             if ( !tmp_err && p_check  ) sed_process_queue_validate( q , p_check , &tmp_err );
00268             if ( !tmp_err && p_family ) sed_process_queue_set_families( q , p_family , &tmp_err );
00269          }
00270 */
00271       }
00272 
00273       if ( tmp_err )
00274       {
00275          g_propagate_error( error , tmp_err );
00276          q = sed_process_queue_destroy( q );
00277       }
00278    }
00279    return q;
00280 }
00281 
00282 Sed_process_queue
00283 sed_process_queue_set_families( Sed_process_queue q , Sed_process_family f[] , GError** error )
00284 {
00285    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00286 
00287    if ( q )
00288    {
00289       GError*     tmp_err = NULL;
00290       gint        i;
00291       Sed_process p;
00292       Sed_process c;
00293       gchar**     err_s = NULL;
00294 
00295       for ( i=0 ; f[i].parent ; i++ )
00296       {
00297          p = sed_process_queue_find_nth_obj( q , f[i].parent , 0 );
00298          c = sed_process_queue_find_nth_obj( q , f[i].child  , 0 );
00299 
00300          if ( !sed_process_is_active(p) ) p=NULL;
00301          if ( !sed_process_is_active(c) ) c=NULL;
00302 
00303          if ( c && !p )
00304          {
00305             eh_strv_append( &err_s , g_strdup_printf( "Child process has a missing or inactive parent" ) );
00306             eh_strv_append( &err_s , g_strdup_printf( "Missing %s needed by %s" , f[i].parent , f[i].child ) );
00307          }
00308          else if ( c && p )
00309             sed_process_append_child( p , c );
00310       }
00311       if ( tmp_err )
00312       {
00313          eh_set_error_strv( &tmp_err ,
00314                             SED_PROC_ERROR ,
00315                             SED_PROC_ERROR_MISSING_PARENT ,
00316                             err_s );
00317          g_propagate_error( error , tmp_err );
00318          q = NULL;
00319       }
00320 
00321       g_strfreev( err_s );
00322    }
00323 
00324    return q;
00325 }
00326 
00327 Sed_process
00328 sed_process_child( Sed_process p , const gchar* child_s )
00329 {
00330    Sed_process found_child = NULL;
00331 
00332    if ( p && p->child && child_s )
00333    {
00334       Sed_process* c = NULL;
00335 
00336       for ( c=p->child ; !found_child && *c ; c++ )
00337       {
00338          if ( g_ascii_strcasecmp( (*c)->name , child_s )==0 )
00339             found_child = *c;
00340       }
00341 
00342    }
00343 
00344    return found_child;
00345 }
00346 
00347 Sed_process
00348 sed_process_append_child( Sed_process p , Sed_process c )
00349 {
00350    eh_require( p );
00351    eh_require( c );
00352 
00353    if ( p && c )
00354    {
00355       eh_strv_append( (gchar***)(&(p->child )) , (gchar*)c );
00356       eh_strv_append( (gchar***)(&(c->parent)) , (gchar*)p );
00357 
00358       c->is_child = TRUE;
00359    }
00360    return p;
00361 }
00362 
00363 gboolean
00364 sed_process_is_parent( Sed_process p )
00365 {
00366    gboolean is_parent = FALSE;
00367 
00368    if ( p ) is_parent = !(p->is_child);
00369 
00370    return is_parent;
00371 }
00372 
00373 Sed_process_queue
00374 sed_process_queue_scan( Sed_process_queue q , Eh_key_file file , GError** error )
00375 {
00376    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00377 
00378    if ( q && file )
00379    {
00380       GList*              link;
00381       GList*              new_p;
00382       __Sed_process_link* data;
00383       GError*             tmp_e = NULL;
00384 
00385       for ( link=q->l ; !tmp_e && link ; link=link->next )
00386       {
00387          data = link->data;
00388 
00389          new_p = sed_process_scan( file , data->p , &tmp_e );
00390 
00391          if ( tmp_e && tmp_e->code == SED_PROC_ERROR_NOT_FOUND )
00392             g_clear_error( &tmp_e );
00393 
00394          if ( !tmp_e )
00395             data->obj_list = g_list_concat( data->obj_list , new_p );
00396       }
00397 
00398       if ( tmp_e )
00399       {
00400          g_propagate_error( error , tmp_e );
00401          q = NULL;
00402       }
00403 
00404    }
00405 
00406    return q;
00407 }
00408 
00409 Sed_process_queue
00410 sed_process_queue_append( Sed_process_queue q , __Sed_process_link* p )
00411 {
00412    if ( q && p )
00413    {
00414       q->l = g_list_append( q->l , p );
00415    }
00416 
00417    return q;
00418 }
00419 
00420 Sed_process_queue
00421 sed_process_queue_prepend( Sed_process_queue q , __Sed_process_link* p )
00422 {
00423    if ( q && p )
00424    {
00425       q->l = g_list_prepend( q->l , p );
00426    }
00427 
00428    return q;
00429 }
00430 
00431 Sed_process_queue
00432 sed_process_queue_insert( Sed_process_queue q , __Sed_process_link* link , gint position )
00433 {
00434    if ( q && link )
00435    {
00436       q->l = g_list_insert( q->l , link , position );
00437    }
00438 
00439    return q;
00440 }
00441 
00442 gint
00443 sed_process_queue_find_position( Sed_process_queue q , const gchar* name )
00444 {
00445    gint position = -1;
00446 
00447    if ( q && name )
00448    {
00449       GList* link = sed_process_queue_find( q , name );
00450 
00451       position = g_list_position( q->l , link );
00452    }
00453 
00454    return position;
00455 }
00456 
00457 gint __sed_process_compare_name( const __Sed_process_link* link , const gchar* name )
00458 {
00459    return g_ascii_strcasecmp( link->p->name , name );
00460 }
00461 
00462 GList*
00463 sed_process_queue_find( Sed_process_queue q , const gchar* name )
00464 {
00465    GList* link = NULL;
00466 
00467    if ( q && name )
00468    {
00469       link = g_list_find_custom( q->l , name , (GCompareFunc)__sed_process_compare_name );
00470    }
00471 
00472    return link;
00473 }
00474 
00475 Sed_process_queue
00476 sed_process_queue_push( Sed_process_queue q , Sed_process_init_t init )
00477 {
00478    if ( q )
00479    {
00480       __Sed_process_link* new_link = eh_new( __Sed_process_link , 1 );
00481 
00482       new_link->p = sed_process_create( init.name , init.init_f , init.run_f , init.destroy_f );
00483       new_link->obj_list = NULL;
00484 
00485       sed_process_queue_append( q , new_link );
00486    }
00487 
00488    return q;
00489 }
00490 
00491 Sed_process
00492 sed_process_queue_find_nth_obj( Sed_process_queue q , const gchar* name , gssize n )
00493 {
00494    Sed_process obj = NULL;
00495 
00496    if ( n>=0 && name && q )
00497    {
00498       GList* link = sed_process_queue_find( q , name );
00499       if ( link ) obj = g_list_nth_data( SED_PROCESS_LINK(link->data)->obj_list , n );
00500    }
00501 
00502    return obj;
00503 }
00504 
00505 gpointer*
00506 sed_process_queue_obj_data( Sed_process_queue q , const char* name )
00507 {
00508    gpointer* data = NULL;
00509 
00510    if ( q && name )
00511    {
00512       GList* link     = sed_process_queue_find( q , name );
00513       GList* obj_list = SED_PROCESS_LINK(link->data)->obj_list;
00514       GList* this_obj = obj_list;
00515       gssize len      = g_list_length( obj_list );
00516       gssize i;
00517 
00518       data = eh_new( gpointer , len+1 );
00519 
00520       for ( i=0,this_obj=obj_list ; this_obj ; i++,this_obj=this_obj->next )
00521          data[i] = SED_PROCESS(this_obj->data)->data;
00522       data[i] = NULL;
00523    }
00524 
00525    return data;
00526 }
00527 
00528 Sed_process_queue
00529 sed_process_queue_delete( Sed_process_queue q , const gchar* name )
00530 {
00531    if ( q && name )
00532    {
00533       GList* link = sed_process_queue_find( q , name );
00534 
00535       link->data = sed_process_link_destroy( link->data );
00536 
00537       q->l = g_list_delete_link( q->l , link );
00538    }
00539 
00540    return q;
00541 }
00542 
00543 Sed_process_queue
00544 sed_process_queue_run( Sed_process_queue q , Sed_cube p )
00545 {
00546    if ( q && p )
00547    {
00548       GList* link;
00549 
00550       for ( link=q->l ; link ; link=link->next )
00551       {
00552          g_list_foreach( SED_PROCESS_LINK(link->data)->obj_list , (GFunc)sed_process_run , p );
00553       }
00554    }
00555 
00556    return q;
00557 }
00558 
00559 Sed_process_queue
00560 sed_process_queue_run_until( Sed_process_queue q , Sed_cube p , double t_total )
00561 {
00562    eh_require( q );
00563    eh_require( p );
00564 
00565    if ( q && p )
00566    {
00567       double         t; /* Time in years */
00568 //      Eh_status_bar* bar = eh_status_bar_new( &t , &t_total );
00569 
00570       for ( t  = sed_cube_time_step( p ) ;
00571                t < t_total
00572             && !sed_signal_is_pending( SED_SIG_QUIT )
00573             && !sed_signal_is_pending( SED_SIG_NEXT ) ;
00574             t += sed_cube_time_step( p ) )
00575       {
00576          sed_process_queue_run( q , p );
00577 
00578          if ( sed_signal_is_pending( SED_SIG_DUMP ) )
00579          {
00580             sed_process_queue_run_process_now( q , "data dump" , p );
00581             sed_signal_reset( SED_SIG_DUMP );
00582          }
00583 
00584          sed_cube_increment_age( p );
00585 
00586          //fprintf( stderr , "%7g (%3.0g%%)\r" , t , t/t_total*100 );
00587       }
00588 
00589       if ( sed_signal_is_pending( SED_SIG_NEXT ) )
00590       {
00591          sed_cube_set_age( p , t_total );
00592          sed_signal_reset( SED_SIG_NEXT );
00593       }
00594 
00595 //      eh_status_bar_destroy( bar );
00596    }
00597 
00598    return q;
00599 }
00600 
00601 Sed_process_queue
00602 sed_process_queue_run_at_end( Sed_process_queue q , Sed_cube p )
00603 {
00604    if ( q && p )
00605    {
00606       GList* link;
00607 
00608       for ( link=q->l ; link ; link=link->next )
00609       {
00610          g_list_foreach( SED_PROCESS_LINK(link->data)->obj_list , (GFunc)sed_process_run_at_end , p );
00611       }
00612    }
00613 
00614    return q;
00615 }
00616 
00617 Sed_process_queue
00618 sed_process_queue_run_process_now( Sed_process_queue q , const gchar* name , Sed_cube cube )
00619 {
00620    if ( q )
00621    {
00622       GList* link = sed_process_queue_find( q , name );
00623 
00624       if ( link && link->data )
00625          g_list_foreach( SED_PROCESS_LINK(link->data)->obj_list , (GFunc)sed_process_run_now , cube );
00626    }
00627 
00628    return q;
00629 }
00630 
00631 #define TRACK_MASS_BALANCE TRUE
00632 
00633 static FILE*     info_fp        = NULL;
00634 static gboolean  info_fp_is_set = FALSE;
00635 
00636 Sed_process sed_process_create( const char*  name   ,
00637                                 init_func    f_init ,
00638                                 run_func     f_run  ,
00639                                 destroy_func f_destroy )
00640 {
00641    Sed_process p;
00642 
00643    NEW_OBJECT( Sed_process , p );
00644 
00645 //   p->data = eh_new( gchar , data_size );
00646    p->data         = NULL;
00647 
00648    p->log_files    = eh_new( FILE* , SED_MAX_LOG_FILES+1 );
00649    p->log_files[0] = NULL;
00650 
00651 //   p->data_size    = data_size;
00652 
00653    p->active       = FALSE;
00654    p->start        = -G_MAXDOUBLE;
00655    p->stop         =  G_MAXDOUBLE;
00656 
00657    p->run_count    = 0;
00658    p->is_set       = FALSE;
00659 
00660    p->parent       = NULL;
00661    p->child        = NULL;
00662 
00663    p->is_child     = FALSE;
00664 
00665    p->name         = g_strdup( name );
00666    p->tag          = NULL;
00667    p->interval     = -1;
00668    p->next_event   = g_array_new(TRUE,TRUE,sizeof(double));
00669 
00670    p->f_init       = f_init;
00671    p->f_run        = f_run;
00672    p->f_destroy    = f_destroy;
00673    p->f_load       = NULL;
00674    p->f_dump       = NULL;
00675 
00676    p->info                   = eh_new0( Sed_real_process_info , 1 );
00677    p->info->mass_total_added = 0.;
00678    p->info->mass_total_lost  = 0.;
00679    p->info->error            = FALSE;
00680 
00681    p->info->timer            = g_timer_new();
00682    p->info->secs             = 0.;
00683    p->info->u_secs           = 0;
00684 
00685    if ( g_getenv("SED_TRACK_MASS")  && !info_fp_is_set )
00686    {
00687       info_fp_is_set = TRUE;
00688       info_fp        = eh_fopen( "mass_balance.txt" , "w" );
00689    }
00690 
00691 /*
00692    (*f_init)(NULL,p->data);
00693    (*f_run)(p->data,NULL);
00694 */
00695 
00696    return p;
00697 }
00698 
00699 Sed_process sed_process_copy(Sed_process d , Sed_process s)
00700 {
00701    eh_return_val_if_fail( s , NULL );
00702 
00703    eh_require( s->data==NULL );
00704 
00705    {
00706       gssize i;
00707 
00708       if ( !d )
00709          d = sed_process_create( s->name , s->f_init , s->f_run , s->f_destroy );
00710 
00711       d->next_event = g_array_new(TRUE,TRUE,sizeof(double));
00712 
00713       for ( i=0 ; i<s->next_event->len ; i++ )
00714          g_array_append_val(d->next_event,g_array_index(s->next_event,double,i));
00715 
00716       d->tag = g_strdup( s->tag );
00717 
00718       //g_memmove( d->data , s->data , s->data_size );
00719       d->data = s->data;
00720 
00721       g_memmove( d->log_files , 
00722                  s->log_files ,
00723                  (SED_MAX_LOG_FILES+1)*sizeof( FILE* ) );
00724       g_memmove( d->info , s->info , sizeof(Sed_real_process_info) );
00725 
00726       d->info->timer  = g_timer_new();
00727       d->info->secs   = s->info->secs;
00728       d->info->u_secs = s->info->u_secs;
00729 
00730       d->active   = s->active;
00731       d->start    = s->start;
00732       d->stop     = s->stop;
00733 
00734       d->run_count= s->run_count;
00735       d->is_set   = s->is_set;
00736 
00737       d->parent   = s->parent;
00738       d->child    = s->child;
00739       d->is_child = s->is_child;
00740 
00741       d->logging  = s->logging;
00742       d->interval = s->interval;
00743    }
00744 
00745    return d;
00746 }
00747 
00748 Sed_process
00749 sed_process_dup( Sed_process s )
00750 {
00751    return sed_process_copy( NULL , s );
00752 }
00753 
00754 Sed_process
00755 sed_process_destroy( Sed_process p )
00756 {
00757    if ( p )
00758    {
00759       if ( p->f_destroy ) p->f_destroy( p );
00760 
00761       g_array_free(p->next_event,TRUE);
00762 
00763       g_timer_destroy( p->info->timer );
00764 
00765       eh_free( p->child     );
00766       eh_free( p->parent    );
00767       eh_free( p->info      );
00768       eh_free( p->log_files );
00769       eh_free( p->name      );
00770       eh_free( p->tag       );
00771       eh_free( p            );
00772    }
00773 
00774    return NULL;
00775 }
00776 
00777 void
00778 sed_process_clean( Sed_process p )
00779 {
00780    eh_return_if_fail( p );
00781 
00782    if ( p->f_destroy ) p->f_destroy( p );
00783 
00784 //   p->f_run ( p->data , NULL    );
00785 //   p->f_init( NULL    , p->data );
00786 }
00787 
00788 double
00789 sed_process_next_event( Sed_process p )
00790 {
00791    return g_array_index(p->next_event,double,p->next_event->len-1);
00792 }
00793 
00794 Sed_process
00795 sed_process_set_next_event( Sed_process p , double new_next_event )
00796 {
00797    g_array_index( p->next_event , double , p->next_event->len-1 ) = new_next_event ;
00798    return p;
00799 }
00800 
00801 gboolean
00802 sed_process_is_on( Sed_process p , double time )
00803 {
00804    gboolean is_on = FALSE;
00805 
00806    eh_return_val_if_fail( p , FALSE );
00807 
00808    if ( p )
00809    {
00810       double last_event;
00811       if (    !p->active
00812            || sed_process_interval_is_at_end(p) 
00813            || time < p->start
00814            || time > p->stop )
00815          is_on = FALSE;
00816       else if ( sed_process_interval_is_always(p) )
00817          is_on = TRUE;
00818       else if ( time >= sed_process_next_event(p) )
00819       {
00820          last_event = sed_process_next_event(p);
00821          g_array_index( p->next_event , double , 0 ) = eh_round(time,p->interval) + p->interval;
00822          is_on = TRUE;
00823       }
00824       else
00825          is_on = FALSE;
00826    }
00827 
00828    return is_on;
00829 }
00830 
00831 gboolean
00832 sed_process_array_run( GPtrArray *a , Sed_cube p )
00833 {
00834    gssize i;
00835    gboolean rtn_val = TRUE;
00836    for (i=0;i<a->len;i++)
00837       rtn_val = rtn_val && sed_process_run( (Sed_process)(a->pdata)[i] , p );
00838    return rtn_val;
00839 }
00840 
00841 gboolean
00842 sed_process_run( Sed_process a , Sed_cube p )
00843 {
00844    gboolean rtn_val = TRUE;
00845    if ( sed_process_is_on( a , sed_cube_age(p) ) && sed_process_is_parent(a) )
00846       rtn_val = sed_process_run_now(a,p);
00847    return rtn_val;
00848 }
00849 
00850 gboolean
00851 sed_process_run_at_end( Sed_process a , Sed_cube p )
00852 {
00853    gboolean rtn_val = TRUE;
00854    if ( sed_process_is_active(a) && sed_process_interval_is_at_end(a) && sed_process_is_parent(a) )
00855       rtn_val = sed_process_run_now(a,p);
00856    return rtn_val;
00857 }
00858 
00859 gboolean
00860 sed_process_run_now( Sed_process a , Sed_cube p )
00861 {
00862    gboolean rtn_val = TRUE;
00863 
00864    if ( a && a->f_run && a->is_set )
00865    {
00866       gchar*           log_name;
00867       Sed_process_info info;
00868       gulong           u_secs = 0;
00869 
00870       g_timer_start( a->info->timer );
00871 
00872       if ( a->logging ) log_name = a->name;
00873       else              log_name = "/dev/null";
00874 
00875       eh_redirect_log( log_name , DEFAULT_LOG );
00876 
00877       fprintf( stderr , "%7g years [ Running process: %-25s]\r" , sed_cube_age_in_years(p) , a->name );
00878 
00879       if ( g_getenv("SED_TRACK_MASS") )
00880       {
00881          double mass_before = sed_cube_mass(p) + sed_cube_mass_in_suspension(p);
00882 
00883          info = a->f_run(a,p);
00884 
00885          a->info->mass_added        = info.mass_added;
00886          a->info->mass_lost         = info.mass_lost;
00887          a->info->error             = info.error;
00888 
00889          a->info->mass_before       = mass_before;
00890          a->info->mass_after        = sed_cube_mass(p) + sed_cube_mass_in_suspension(p);
00891 
00892          a->info->mass_total_added += info.mass_added;
00893          a->info->mass_total_lost  += info.mass_lost;
00894 
00895          sed_process_fprint_info( info_fp , a );
00896 
00897          if ( sed_process_error( a ) )
00898          {
00899             eh_warning( "A mass balance error was detected (%s)." , a->name );
00900             rtn_val = FALSE;
00901          }
00902       }
00903       else
00904       {
00905          info = a->f_run( a , p );
00906 
00907          a->info->mass_total_added += info.mass_added;
00908          a->info->mass_total_lost  += info.mass_lost;
00909       }
00910 
00911       eh_reset_log(DEFAULT_LOG);
00912 
00913       a->info->secs   += g_timer_elapsed( a->info->timer , NULL );
00914       a->info->u_secs += u_secs;
00915 
00916       a->run_count++;
00917    }
00918 
00919    return rtn_val;
00920 }
00921 
00922 void
00923 sed_process_init( Sed_process p , Eh_symbol_table t , GError** error )
00924 {
00925    if ( p->f_init ) p->f_init( p , t , error );
00926    p->is_set = TRUE;
00927 }
00928 
00929 #define SED_KEY_TAG         "process tag"
00930 #define SED_KEY_ACTIVE      "active"
00931 #define SED_KEY_LOGGING     "logging"
00932 #define SED_KEY_INTERVAL    "repeat interval"
00933 
00934 static gchar* sed_process_req_labels[] =
00935 {
00936    SED_KEY_ACTIVE   ,
00937    SED_KEY_LOGGING  ,
00938    SED_KEY_INTERVAL ,
00939    NULL
00940 };
00941 
00942 GList*
00943 sed_process_scan( Eh_key_file k , Sed_process p , GError** error )
00944 {
00945    GList*  p_array = NULL;
00946    GError* tmp_err = NULL;
00947 
00948    eh_require( k );
00949    eh_require( p );
00950 
00951    eh_return_val_if_fail( error==NULL || *error==NULL , NULL );
00952    if ( !eh_key_file_has_group( k , p->name ) )
00953    {
00954       Sed_process new_proc;
00955 
00956       g_set_error( &tmp_err , SED_PROC_ERROR , SED_PROC_ERROR_NOT_FOUND , "Process not found: %s" , p->name );
00957 
00958       new_proc         = sed_process_dup( p );
00959       new_proc->active = FALSE;
00960       p_array          = g_list_append( p_array , new_proc );
00961    }
00962    else
00963    {
00964       //gboolean*  active  = eh_key_file_get_bool_values  ( k , p->name , SED_KEY_ACTIVE  );
00965       Eh_symbol_table* t        = eh_key_file_get_symbol_tables( k , p->name );
00966       gchar**          tag      = eh_key_file_get_str_values   ( k , p->name , SED_KEY_TAG  );
00967       gchar**          active_s = eh_key_file_get_str_values   ( k , p->name , SED_KEY_ACTIVE  );
00968       gboolean*        logging  = eh_key_file_get_bool_values  ( k , p->name , SED_KEY_LOGGING );
00969       gchar**          interval = eh_key_file_get_all_values   ( k , p->name , SED_KEY_INTERVAL );
00970       gssize           len      = eh_key_file_group_size       ( k , p->name );
00971       gssize           i;
00972       Sed_process      new_proc;
00973       gboolean         is_active;
00974 
00975       for ( i=0 ; !tmp_err && i<len ; i++ )
00976          eh_symbol_table_require_labels( t[i] , sed_process_req_labels , &tmp_err );
00977 
00978       for ( i=0 ; !tmp_err && i<len ; i++ )
00979       {
00980          new_proc      = sed_process_dup( p );
00981          new_proc->tag = tag[i];
00982 
00983          if ( eh_str_is_boolean( active_s[i] ) )
00984          {
00985             is_active   = eh_str_to_boolean( active_s[i] , &tmp_err );
00986 
00987             if ( is_active )
00988             {
00989                new_proc->start = -G_MAXDOUBLE;
00990                new_proc->stop  =  G_MAXDOUBLE;
00991             }
00992          }
00993          else
00994          {
00995             double* active_time = eh_str_to_time_range( active_s[i] , &tmp_err );
00996 
00997             is_active       = TRUE;
00998 
00999             new_proc->start = active_time[0];
01000             new_proc->stop  = active_time[1];
01001 
01002             eh_free( active_time );
01003          }
01004 
01005          new_proc->active = is_active;
01006 
01007          if ( !tmp_err && is_active )
01008          {
01009             new_proc->logging = logging[i];
01010 
01011             if      ( g_ascii_strcasecmp( interval[i] , "always" ) == 0 )
01012                new_proc->interval = -1;
01013             else if ( g_ascii_strcasecmp( interval[i] , "at-end" ) == 0 )
01014                new_proc->interval = -2;
01015             else
01016                new_proc->interval = eh_str_to_time_in_years( interval[i] , &tmp_err );
01017 
01018             g_array_append_val( new_proc->next_event , new_proc->interval );
01019 
01020             if ( !tmp_err ) sed_process_init( new_proc , t[i] , &tmp_err );
01021 
01022             if ( new_proc->logging )
01023             {
01024                gchar* log_file_name = g_strconcat( new_proc->name , ".log" , NULL );
01025 
01026                new_proc->log_files[0] = eh_open_log_file( new_proc->name );
01027                new_proc->log_files[1] = stderr;
01028                new_proc->log_files[2] = NULL;
01029 
01030                eh_free( log_file_name );
01031             }
01032             else
01033                new_proc->log_files[0] = NULL;
01034 
01035             g_log_set_handler( new_proc->name ,
01036                                  G_LOG_LEVEL_MASK 
01037                                | G_LOG_FLAG_FATAL 
01038                                | G_LOG_FLAG_RECURSION ,
01039                                eh_logger ,
01040                                new_proc->log_files );
01041          }
01042 
01043          p_array = g_list_append(p_array,new_proc);
01044       }
01045 
01046       if ( tmp_err )
01047       {
01048          g_list_foreach( p_array , (GFunc)sed_process_destroy , NULL );
01049          g_list_free   ( p_array );
01050          p_array = NULL;
01051       }
01052 
01053       for ( i=0 ; i<len ; i++ )
01054          eh_symbol_table_destroy( t[i] );
01055 
01056       eh_free( t       );
01057       eh_free( active_s );
01058       eh_free( logging );
01059       eh_free( tag     );
01060       g_strfreev( interval );
01061    }
01062 
01063    if ( tmp_err )
01064    {
01065       gchar* err_s = g_strdup_printf( "Process scan error (%s): %s" , p->name , tmp_err->message );
01066       eh_free( tmp_err->message );
01067       tmp_err->message = err_s;
01068       g_propagate_error( error , tmp_err );
01069    }
01070 
01071    return p_array;
01072 }
01073 
01074 gssize
01075 sed_process_fprint( FILE *fp , Sed_process p )
01076 {
01077    gssize n = 0;
01078 
01079    eh_return_val_if_fail( fp , 0 );
01080    eh_return_val_if_fail( p  , 0 );
01081 
01082    if ( fp && p )
01083    {
01084       const gchar* active_str  = (p->active)?"yes":"no";
01085       const gchar* logging_str = (p->logging)?"yes":"no";
01086       const gchar* tag_str     = (p->tag)?p->tag:"(null)";
01087 
01088       n += fprintf( fp,"[Process info]\n" );
01089       n += fprintf( fp,"name          = %s\n" , p->name     );
01090       n += fprintf( fp,"tag           = %s\n" , tag_str     );
01091       n += fprintf( fp,"active        = %s\n" , active_str  );
01092       if ( p->active )
01093       {
01094          if ( eh_compare_dbl( p->start , -G_MAXDOUBLE , 1e-6 ) )
01095             n += fprintf( fp,"start         = %s\n" , "The begining" );
01096          else
01097             n += fprintf( fp,"start         = %f\n" , p->start    );
01098 
01099          if ( eh_compare_dbl( p->stop  ,  G_MAXDOUBLE , 1e-6 ) )
01100             n += fprintf( fp,"stop          = %s\n" , "The end" );
01101          else
01102             n += fprintf( fp,"stop          = %f\n" , p->stop     );
01103       }
01104       else
01105       {
01106          n += fprintf( fp,"start         = N/A\n" );
01107          n += fprintf( fp,"stop          = N/A\n" );
01108       }
01109 
01110       n += fprintf( fp,"run count     = %d\n" , p->run_count );
01111       n += fprintf( fp,"is set        = %d\n" , p->is_set    );
01112 
01113       if ( sed_process_interval_is_always(p) )
01114          n += fprintf( fp,"interval      = %s\n" , "Always" );
01115       else
01116          n += fprintf( fp,"interval      = %f\n" , p->interval );
01117 
01118       n += fprintf( fp,"logging       = %s\n" , logging_str );
01119    }
01120 
01121    return n;
01122 }
01123 
01124 gssize
01125 sed_process_queue_summary( FILE* fp , Sed_process_queue q )
01126 {
01127    gssize n = 0;
01128    if ( q )
01129    {
01130       __Sed_process_link* link;
01131       GList* this_link;
01132       GList* this_obj;
01133 
01134       n += fprintf( fp , "             Name | Mass Added | Mass Removed | Time\n" );
01135 
01136       for ( this_link=q->l ; this_link ; this_link=this_link->next )
01137       {
01138          link = this_link->data;
01139          for ( this_obj=link->obj_list ; this_obj ; this_obj=this_obj->next )
01140             n += sed_process_summary( fp , this_obj->data );
01141       }
01142    }
01143    return n;
01144 }
01145 
01146 gssize
01147 sed_process_queue_fprint( FILE* fp , Sed_process_queue q )
01148 {
01149    gssize n = 0;
01150    if ( q )
01151    {
01152       __Sed_process_link* link;
01153       GList* this_link;
01154       GList* this_obj;
01155 
01156       n += fprintf( fp , "[Process queue info]\n" );
01157       n += fprintf( fp , "No. of processes = %d\n" , (gint)sed_process_queue_size(q)       );
01158       n += fprintf( fp , "No. active       = %d\n" , (gint)sed_process_queue_n_active(q)   );
01159       n += fprintf( fp , "No. inactive     = %d\n" , (gint)sed_process_queue_n_inactive(q) );
01160       n += fprintf( fp , "No. absent       = %d\n" , (gint)sed_process_queue_n_absent(q)   );
01161 
01162       for ( this_link=q->l ; this_link ; this_link=this_link->next )
01163       {
01164          link = this_link->data;
01165          for ( this_obj=link->obj_list ; this_obj ; this_obj=this_obj->next )
01166             n += sed_process_fprint( fp , this_obj->data );
01167       }
01168    }
01169    return n;
01170 }
01171 
01172 gssize
01173 sed_process_queue_size( Sed_process_queue q )
01174 {
01175    return g_list_length( q->l );
01176 }
01177 
01178 gssize
01179 sed_process_queue_n_active( Sed_process_queue q )
01180 {
01181    gssize n = 0;
01182    if ( q )
01183    {
01184       GList* list;
01185       GList* obj_list;
01186       GList* this_obj;
01187       gboolean is_active;
01188 
01189       /* Cycle through each process in the queue */
01190       for ( list=q->l ; list ; list=list->next )
01191       {
01192          obj_list = SED_PROCESS_LINK(list->data)->obj_list;
01193 
01194          is_active = FALSE;
01195 
01196          /* Cycle through each object of this process */
01197          for ( this_obj=obj_list ; this_obj && !is_active ; this_obj=this_obj->next )
01198             is_active = sed_process_is_active( this_obj->data );
01199 
01200          if ( is_active )
01201             n += 1;
01202       }
01203    }
01204 
01205    return n;
01206 }
01207 
01208 gssize
01209 sed_process_queue_n_absent( Sed_process_queue q )
01210 {
01211    gssize n = 0;
01212 
01213    if ( q )
01214    {
01215       GList* list;
01216       GList* obj_list;
01217 
01218       /* Cycle through each process in the queue */
01219       for ( list=q->l ; list ; list=list->next )
01220       {
01221          obj_list = SED_PROCESS_LINK(list->data)->obj_list;
01222 
01223          /* If there is no object list, the process was absent from the input file. */
01224          if ( !obj_list )
01225             n += 1;
01226       }
01227    }
01228 
01229    return n;
01230 }
01231 
01232 gssize
01233 sed_process_queue_n_inactive( Sed_process_queue q )
01234 {
01235    gssize n = 0;
01236 
01237    if ( q )
01238    {
01239       gssize n_active = sed_process_queue_n_active( q );
01240       gssize n_absent = sed_process_queue_n_absent( q );
01241       gssize len      = sed_process_queue_size    ( q );
01242    
01243       n = len - n_active - n_absent;
01244 
01245       eh_require( n>=0   );
01246       eh_require( n<=len );
01247    }
01248 
01249    return n;
01250 }
01251 
01260 gpointer
01261 sed_process_data( Sed_process p )
01262 {
01263    eh_return_val_if_fail( p!=NULL , NULL );
01264    return p->data;
01265 }
01266 
01267 void
01268 sed_process_provide( Sed_process p , GQuark key , gpointer data )
01269 {
01270    if ( p ) g_dataset_id_set_data_full( p , key , data , NULL );
01271 }
01272 
01273 void
01274 sed_process_withhold( Sed_process p , GQuark key )
01275 {
01276    if ( p ) g_dataset_id_remove_data( p , key );
01277 }
01278 
01279 gpointer
01280 sed_process_use( Sed_process p , GQuark key )
01281 {
01282    gpointer data = NULL;
01283 
01284    if ( p ) data = g_dataset_id_get_data( p , key );
01285 
01286    return data;
01287 }
01288 
01297 gchar*
01298 sed_process_name( Sed_process p )
01299 {
01300    eh_return_val_if_fail( p!=NULL , NULL );
01301    return g_strdup( p->name );
01302 }
01303 
01304 gint
01305 sed_process_run_count( Sed_process p )
01306 {
01307    eh_return_val_if_fail( p , 0 );
01308    return p->run_count;
01309 }
01310 
01311 gboolean
01312 sed_process_is_set( Sed_process p )
01313 {
01314    eh_return_val_if_fail( p , FALSE );
01315    return p->is_set;
01316 }
01317 gpointer
01318 sed_process_user_data( Sed_process p )
01319 {
01320    eh_return_val_if_fail( p , NULL );
01321    return p->data;
01322 }
01323 
01324 gpointer
01325 sed_process_malloc_user_data( Sed_process p , gssize n_bytes )
01326 {
01327    gpointer data = NULL;
01328 
01329    if ( p )
01330    {
01331       if ( !p->data )
01332          p->data = eh_new( gchar , n_bytes );
01333       data = p->data;
01334    }
01335 
01336    return data;
01337 }
01338 
01346 gboolean
01347 sed_process_name_is_same( Sed_process a , Sed_process b )
01348 {
01349    gboolean same_name = FALSE;
01350 
01351    if ( a && b )
01352    {
01353       same_name = (g_ascii_strcasecmp( a->name , b->name )==0)?TRUE:FALSE;
01354    }
01355 
01356    return same_name;
01357 }
01358 
01365 double
01366 sed_process_interval( Sed_process p )
01367 {
01368    eh_return_val_if_fail( p!=NULL , 0. );
01369    return p->interval;
01370 }
01371 
01381 gboolean
01382 sed_process_interval_is_always( Sed_process p )
01383 {
01384    eh_return_val_if_fail( p , FALSE );
01385    return p->interval>-1.5 && p->interval<-.5;
01386 }
01387 
01397 gboolean
01398 sed_process_interval_is_at_end( Sed_process p )
01399 {
01400    eh_return_val_if_fail( p , FALSE );
01401    return p->interval>-2.5 && p->interval<-1.5;
01402 }
01403 
01410 gboolean
01411 sed_process_is_active( Sed_process p )
01412 {
01413    gboolean is_active = FALSE;
01414 
01415    if ( p )
01416       is_active = p->active;
01417    
01418    return is_active;
01419 }
01420 
01421 gssize
01422 sed_process_summary( FILE* fp , Sed_process p )
01423 {
01424    gint n = 0;
01425    if ( fp && p )
01426    {
01427       double t = p->info->secs + p->info->u_secs/1.e6;
01428       gchar* t_str = eh_render_time_str( t );
01429 
01430       n += fprintf( fp , "%18s | %10.3g | %10.3g | %s\n" ,
01431                     p->name ,
01432                     p->info->mass_total_added ,
01433                     p->info->mass_total_lost ,
01434                     t_str );
01435    }
01436    return n;
01437 }
01438 
01439 gssize sed_process_fprint_info( FILE* fp , Sed_process p )
01440 {
01441    gssize n = 0;
01442 
01443    eh_require( fp );
01444 
01445    if ( fp )
01446    {
01447       Sed_real_process_info* info = p->info;
01448       double mass_bal = info->mass_after - ( info->mass_before - info->mass_lost + info->mass_added );
01449       double mass_f   = eh_safe_dbl_division( fabs(mass_bal ) ,
01450                                               info->mass_after );
01451 
01452       n += fprintf( fp , "Process name                             : %s\n" , p->name                );
01453       n += fprintf( fp , "Mass of cube before process (kg)         : %g\n" , info->mass_before      );
01454       n += fprintf( fp , "Mass of sediment added to cube (kg)      : %g\n" , info->mass_added       );
01455       n += fprintf( fp , "Mass of sediment lost by process (kg)    : %g\n" , info->mass_lost        );
01456       n += fprintf( fp , "Mass of cube after process (kg)          : %g\n" , info->mass_after       );
01457       n += fprintf( fp , "Mass balance (kg)                        : %g\n" , mass_bal               );
01458       n += fprintf( fp , "Mass fraction (-)                        : %f\n" , mass_f                 );
01459       n += fprintf( fp , "Mass error                               : %s\n" , mass_f>.01?"YES":"NO"  );
01460       n += fprintf( fp , "Total mass of sediment added (kg)        : %g\n" , info->mass_total_added );
01461       n += fprintf( fp , "Total mass of sediment lost (kg)         : %g\n" , info->mass_total_lost  );
01462       n += fprintf( fp , "Error                                    : %d\n" , info->error            );
01463    }
01464 
01465    return n;
01466 }
01467 
01468 gboolean
01469 sed_process_error( Sed_process p )
01470 {
01471    gboolean error = FALSE;
01472 
01473    if ( p )
01474    {
01475       if ( p->info->error )
01476          error = TRUE;
01477       else
01478       {
01479          double mass_bal = p->info->mass_after - (   p->info->mass_before
01480                                                    - p->info->mass_lost
01481                                                    + p->info->mass_added );
01482          if ( eh_safe_dbl_division( fabs(mass_bal) ,
01483                                     p->info->mass_after  ) > .01 )
01484                error = TRUE;
01485       }
01486    }
01487 
01488    return error;
01489 }
01490 
01491 int
01492 sed_process_queue_check_item( Sed_process_queue q , const gchar* p_name )
01493 {
01494    int    flag = 0;
01495    GList* item;
01496 
01497    item = sed_process_queue_find( q , p_name );
01498 
01499    if ( item )
01500    {
01501       GList* list = SED_PROCESS_LINK(item->data)->obj_list;
01502 
01503       /* Check if there are any instances of this process */
01504       if ( g_list_length( list )==1 )
01505          flag |= SED_PROC_UNIQUE;
01506 
01507       if ( list )
01508       {
01509          gboolean is_active = FALSE;
01510          gboolean is_always = TRUE;
01511          GList*   l;
01512 
01513          /* Check if the time step of each instance is set to always */
01514          for ( l=list ; l ; l=l->next )
01515          {
01516             is_active |= sed_process_is_active( l->data );
01517             is_always &= sed_process_interval_is_always( l->data );
01518          }
01519       
01520          /* Check if any of the instances are turned on */
01521          if ( is_active )
01522             flag |= SED_PROC_ACTIVE;
01523 
01524          /* Check if all of the instances are always */
01525          if ( is_always )
01526             flag |= SED_PROC_ALWAYS;
01527       }
01528    }
01529 
01530    return flag;
01531 }
01532 
01533 gint
01534 sed_process_queue_check_family( Sed_process_queue q ,
01535                                 const gchar* parent_name ,
01536                                 const gchar* child_name  )
01537 {
01538    gint flag = 0;
01539 
01540    eh_require( q           );
01541    eh_require( parent_name );
01542 
01543    /* There should be a parent. */
01544    if ( parent_name && child_name )
01545    {
01546       gint   parent_flag = sed_process_queue_check_item( q , parent_name );
01547       gint   child_flag  = sed_process_queue_check_item( q , child_name );
01548       double parent_dt;
01549       double child_dt;
01550 
01551       flag |= parent_flag;
01552 
01553       if ( parent_flag&SED_PROC_UNIQUE ) flag |= SED_PROC_UNIQUE_PARENT;
01554       if ( parent_flag&SED_PROC_ACTIVE ) flag |= SED_PROC_ACTIVE_PARENT;
01555       if ( child_flag &SED_PROC_UNIQUE ) flag |= SED_PROC_UNIQUE_CHILD;
01556       if ( child_flag &SED_PROC_ACTIVE ) flag |= SED_PROC_ACTIVE_CHILD;
01557 
01558       child_dt  = sed_process_queue_item_interval( q , child_name  );
01559       parent_dt = sed_process_queue_item_interval( q , parent_name );
01560 
01561       if ( eh_compare_dbl( parent_dt , child_dt , 1e-12 ) )
01562          flag |= SED_PROC_SAME_INTERVAL;
01563    }
01564    else if ( parent_name )
01565       flag |= sed_process_queue_check_item( q , parent_name );
01566    else
01567       eh_require_not_reached();
01568 
01569    return flag;
01570 }
01571 
01572 double
01573 sed_process_queue_item_interval( Sed_process_queue q , const gchar* name )
01574 {
01575    double interval = G_MAXDOUBLE;
01576 
01577    if ( q && name )
01578    {
01579       GList* item       = sed_process_queue_find( q , name );
01580       GList* obj_list   = SED_PROCESS_LINK(item->data)->obj_list;
01581       gboolean is_found = TRUE;
01582       GList* l;
01583 
01584       for ( l=obj_list ; l && !is_found ; l=l->next )
01585       {
01586          if ( sed_process_is_active( l->data ) )
01587          {
01588             interval = sed_process_interval( l->data );
01589             is_found = TRUE;
01590          }
01591       }
01592    }
01593 
01594    return interval;
01595 }
01596 
01597 Sed_process sed_process_set_active( Sed_process p , gboolean val )
01598 {
01599    if ( p )
01600    {
01601       p->active = val;
01602    }
01603    return p;
01604 }
01605 
01606 Sed_process sed_process_activate( Sed_process p )
01607 {
01608    if ( p )
01609    {
01610       p->active = TRUE;
01611    }
01612    return p;
01613 }
01614 
01615 Sed_process sed_process_deactivate( Sed_process p )
01616 {
01617    if ( p )
01618    {
01619       p->active = FALSE;
01620    }
01621    return p;
01622 }
01623 
01624 Sed_process_queue sed_process_queue_activate( Sed_process_queue q ,
01625                                               const gchar* name )
01626 {
01627    return sed_process_queue_set_active( q , name , TRUE );
01628 }
01629 
01630 Sed_process_queue sed_process_queue_deactivate( Sed_process_queue q ,
01631                                                 const gchar* name )
01632 {
01633    return sed_process_queue_set_active( q , name , FALSE );
01634 }
01635 
01636 Sed_process_queue sed_process_queue_set_active( Sed_process_queue q ,
01637                                                 const gchar* name   ,
01638                                                 gboolean val )
01639 {
01640    if ( q )
01641    {
01642       if ( g_ascii_strncasecmp( name , "<all>" , 5 )==0 )
01643       {
01644          /* set all processes */
01645          GList* list;
01646 
01647          for ( list=q->l ; list ; list=list->next )
01648          {
01649             sed_process_queue_set_active( q ,
01650                                           SED_PROCESS_LINK( list->data )->p->name ,
01651                                           val );
01652          }
01653       }
01654       else if ( g_ascii_strncasecmp( name , "<just>" , 6 )==0 )
01655       {
01656          /* set just this process */
01657          sed_process_queue_set_active( q , "<all>" , !val );
01658          sed_process_queue_set_active( q , name+6  ,  val );
01659       }
01660       else
01661       {
01662          /* It's just a name */
01663          GList* list = sed_process_queue_find( q , name );
01664 
01665          if ( list )
01666          {
01667             if ( val )
01668                g_list_foreach( SED_PROCESS_LINK(list->data)->obj_list , (GFunc)sed_process_activate , NULL );
01669             else
01670                g_list_foreach( SED_PROCESS_LINK(list->data)->obj_list , (GFunc)sed_process_deactivate , NULL );
01671          }
01672       }
01673    }
01674 
01675    return q;
01676 }
01677 
01678 gchar*
01679 sed_process_flag_str( gint flag )
01680 {
01681    gchar* flag_s = NULL;
01682 
01683    if ( flag )
01684    {
01685       gchar* s = NULL;
01686 
01687       switch ( flag )
01688       {
01689          case SED_PROC_UNIQUE:        s = "Process is unique"; break;
01690          case SED_PROC_ACTIVE:        s = "Process is active"; break;
01691          case SED_PROC_ACTIVE_PARENT: s = "Parent process is active"; break;
01692          case SED_PROC_ACTIVE_CHILD:  s = "Child process is active"; break;
01693          case SED_PROC_UNIQUE_PARENT: s = "Parent process is unique"; break;
01694          case SED_PROC_UNIQUE_CHILD:  s = "Child process is unique"; break;
01695          case SED_PROC_SAME_INTERVAL: s = "Parent and child process have same interval"; break;
01696       }
01697 
01698       flag_s = g_strdup( s );
01699    }
01700 
01701    return flag_s;
01702 }
01703 
01704 gchar*
01705 sed_process_render_flag_str( gint flag , const gchar* pre_s , const gchar* name )
01706 {
01707    gchar* err_s = NULL;
01708 
01709    if ( flag!=0 )
01710    {
01711       gchar** all_strs = NULL;
01712 
01713       eh_strv_append( &all_strs , sed_process_flag_str( flag&SED_PROC_UNIQUE        ) );
01714       eh_strv_append( &all_strs , sed_process_flag_str( flag&SED_PROC_ACTIVE        ) );
01715       eh_strv_append( &all_strs , sed_process_flag_str( flag&SED_PROC_ACTIVE_PARENT ) );
01716       eh_strv_append( &all_strs , sed_process_flag_str( flag&SED_PROC_ACTIVE_CHILD  ) );
01717       eh_strv_append( &all_strs , sed_process_flag_str( flag&SED_PROC_UNIQUE_PARENT ) );
01718       eh_strv_append( &all_strs , sed_process_flag_str( flag&SED_PROC_UNIQUE_CHILD  ) );
01719       eh_strv_append( &all_strs , sed_process_flag_str( flag&SED_PROC_SAME_INTERVAL ) );
01720 
01721       {
01722          gchar* s;
01723          gint   i;
01724 
01725          for ( i=0 ; all_strs[i] ; i++ )
01726          {
01727             s = all_strs[i];
01728 
01729             if   ( pre_s ) all_strs[i] = g_strjoin( ": " , pre_s , all_strs[i] , name , NULL );
01730             else           all_strs[i] = g_strjoin( ": " ,         all_strs[i] , name , NULL );
01731 
01732             eh_free( s );
01733          }
01734       }
01735          
01736       err_s = g_strjoinv( "\n" , all_strs );
01737 
01738       g_strfreev( all_strs );
01739    }
01740 
01741    return err_s;
01742 }
01743 
01744 gboolean
01745 sed_process_queue_validate( Sed_process_queue q , Sed_process_check check[] , GError** error )
01746 {
01747    gboolean is_valid;
01748 
01749    eh_require( q );
01750    eh_return_val_if_fail( error==NULL || *error==NULL , FALSE );
01751    
01752    if ( q && check )
01753    {
01754       gint    i;
01755       gchar*  err_s      = NULL;
01756       gchar** err_s_list = NULL;
01757       gint    on_flags;
01758       gint    req_flags;
01759 
01760       for ( i=0 ; check[i].parent ; i++ )
01761       {
01762          req_flags = check[i].flags;
01763          on_flags  = sed_process_queue_check_family( q , check[i].parent , check[i].child )
01764                    & req_flags;
01765 
01766          if ( on_flags != req_flags )
01767          {
01768             err_s = sed_process_render_flag_str( on_flags^req_flags , "Failed requirement" , check[i].parent );
01769             eh_strv_append( &err_s_list , err_s );
01770          }
01771       }
01772 
01773       if ( err_s_list!=NULL )
01774       {
01775          GError* tmp_err = NULL;
01776          gchar*  err_msg = g_strjoinv( "\n" , err_s_list );
01777 
01778          g_set_error( &tmp_err , SED_PROC_ERROR , SED_PROC_ERROR_BAD_INIT_FILE , err_msg );
01779 
01780          g_propagate_error( error , tmp_err );
01781 
01782          eh_free   ( err_msg    );
01783          g_strfreev( err_s_list );
01784 
01785          is_valid = FALSE;
01786       }
01787       else
01788          is_valid = TRUE;
01789    }
01790 
01791    return is_valid;
01792 }
01793 

Generated on Fri Jan 4 18:04:15 2008 for sedflux by  doxygen 1.5.2