00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "sed_process.h"
00022 #include "sed_signal.h"
00023
00024 typedef struct
00025 {
00026
00027 double mass_added;
00028 double mass_lost;
00029 gboolean error;
00030
00031
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;
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
00172 link->p = sed_process_create( name , f_init , f_run , f_destroy );
00173
00174
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
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
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;
00568
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
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
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
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
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
00693
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
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
00785
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
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
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
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
01219 for ( list=q->l ; list ; list=list->next )
01220 {
01221 obj_list = SED_PROCESS_LINK(list->data)->obj_list;
01222
01223
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
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
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
01521 if ( is_active )
01522 flag |= SED_PROC_ACTIVE;
01523
01524
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
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
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
01657 sed_process_queue_set_active( q , "<all>" , !val );
01658 sed_process_queue_set_active( q , name+6 , val );
01659 }
01660 else
01661 {
01662
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