2009-11-18 00:42:52 +01:00
/*-*- Mode: C; c-basic-offset: 8 -*-*/
# include <assert.h>
# include <errno.h>
2009-11-19 02:50:52 +01:00
# include <string.h>
2009-11-18 00:42:52 +01:00
# include "set.h"
# include "name.h"
# include "macro.h"
# include "strv.h"
2010-01-20 05:03:52 +01:00
# include "load-fragment.h"
2010-01-23 01:52:57 +01:00
# include "load-dropin.h"
static const NameVTable * const name_vtable [ _NAME_TYPE_MAX ] = {
[ NAME_SERVICE ] = & service_vtable ,
[ NAME_TIMER ] = & timer_vtable ,
[ NAME_SOCKET ] = & socket_vtable ,
[ NAME_MILESTONE ] = & milestone_vtable ,
[ NAME_DEVICE ] = & device_vtable ,
[ NAME_MOUNT ] = & mount_vtable ,
[ NAME_AUTOMOUNT ] = & automount_vtable ,
[ NAME_SNAPSHOT ] = & snapshot_vtable
} ;
# define NAME_VTABLE(n) name_vtable[(n)->meta.type]
2009-11-18 00:42:52 +01:00
NameType name_type_from_string ( const char * n ) {
NameType t ;
assert ( n ) ;
for ( t = 0 ; t < _NAME_TYPE_MAX ; t + + )
2010-01-23 01:52:57 +01:00
if ( endswith ( n , name_vtable [ t ] - > suffix ) )
2009-11-18 00:42:52 +01:00
return t ;
return _NAME_TYPE_INVALID ;
}
2009-11-19 02:50:52 +01:00
# define VALID_CHARS \
" 0123456789 " \
" abcdefghijklmnopqrstuvwxyz " \
" ABCDEFGHIJKLMNOPQRSTUVWXYZ " \
" -_ "
bool name_is_valid ( const char * n ) {
NameType t ;
const char * e , * i ;
assert ( n ) ;
2010-01-23 01:52:57 +01:00
if ( strlen ( n ) > = NAME_MAX )
return false ;
2009-11-19 02:50:52 +01:00
t = name_type_from_string ( n ) ;
if ( t < 0 | | t > = _NAME_TYPE_MAX )
return false ;
if ( ! ( e = strrchr ( n , ' . ' ) ) )
return false ;
for ( i = n ; i < e ; i + + )
if ( ! strchr ( VALID_CHARS , * i ) )
return false ;
return true ;
}
2009-11-18 00:42:52 +01:00
Name * name_new ( Manager * m ) {
Name * n ;
assert ( m ) ;
if ( ! ( n = new0 ( Name , 1 ) ) )
return NULL ;
2010-01-18 23:50:13 +01:00
if ( ! ( n - > meta . names = set_new ( string_hash_func , string_compare_func ) ) ) {
free ( n ) ;
return NULL ;
}
2009-11-18 00:42:52 +01:00
/* Not much initialization happening here at this time */
n - > meta . manager = m ;
n - > meta . type = _NAME_TYPE_INVALID ;
/* We don't link the name here, that is left for name_link() */
return n ;
}
2010-01-20 02:12:51 +01:00
/* FIXME: Does not rollback on failure! */
int name_link_names ( Name * n , bool replace ) {
2010-01-19 04:15:20 +01:00
char * t ;
void * state ;
int r ;
assert ( n ) ;
if ( ! n - > meta . linked )
return 0 ;
2010-01-20 02:12:51 +01:00
/* Link all names that aren't linked yet. */
2010-01-19 04:15:20 +01:00
SET_FOREACH ( t , n - > meta . names , state )
2010-01-20 02:12:51 +01:00
if ( replace ) {
if ( ( r = hashmap_replace ( n - > meta . manager - > names , t , n ) ) < 0 )
return r ;
} else {
if ( ( r = hashmap_put ( n - > meta . manager - > names , t , n ) ) < 0 )
return r ;
2010-01-19 04:15:20 +01:00
}
return 0 ;
}
2009-11-18 00:42:52 +01:00
int name_link ( Name * n ) {
int r ;
assert ( n ) ;
2010-01-18 23:50:13 +01:00
assert ( ! set_isempty ( n - > meta . names ) ) ;
2009-11-18 00:42:52 +01:00
assert ( ! n - > meta . linked ) ;
2010-01-20 05:03:52 +01:00
if ( ( r = name_sanitize ( n ) ) < 0 )
return r ;
2010-01-19 04:15:20 +01:00
n - > meta . linked = true ;
2009-11-18 00:42:52 +01:00
2010-01-20 05:03:52 +01:00
if ( ( r = name_link_names ( n , false ) ) < 0 ) {
2010-01-19 04:15:20 +01:00
char * t ;
void * state ;
2009-11-18 00:42:52 +01:00
2010-01-19 04:15:20 +01:00
/* Rollback the registered names */
SET_FOREACH ( t , n - > meta . names , state )
2010-01-20 02:12:51 +01:00
hashmap_remove_value ( n - > meta . manager - > names , t , n ) ;
2009-11-18 00:42:52 +01:00
2010-01-19 04:15:20 +01:00
n - > meta . linked = false ;
return r ;
}
2009-11-18 00:42:52 +01:00
2010-01-23 01:52:57 +01:00
if ( n - > meta . load_state = = NAME_STUB )
2010-01-19 04:15:20 +01:00
LIST_PREPEND ( Meta , n - > meta . manager - > load_queue , & n - > meta ) ;
2009-11-18 00:42:52 +01:00
2010-01-19 04:15:20 +01:00
return 0 ;
2009-11-18 00:42:52 +01:00
}
2010-01-18 23:50:13 +01:00
static void bidi_set_free ( Name * name , Set * s ) {
void * state ;
Name * other ;
assert ( name ) ;
/* Frees the set and makes sure we are dropped from the
* inverse pointers */
SET_FOREACH ( other , s , state ) {
NameDependency d ;
for ( d = 0 ; d < _NAME_DEPENDENCY_MAX ; d + + )
set_remove ( other - > meta . dependencies [ d ] , name ) ;
}
set_free ( s ) ;
}
2009-11-18 00:42:52 +01:00
void name_free ( Name * name ) {
2010-01-18 23:50:13 +01:00
NameDependency d ;
char * t ;
2009-11-18 00:42:52 +01:00
assert ( name ) ;
/* Detach from next 'bigger' objects */
if ( name - > meta . linked ) {
2010-01-19 04:15:20 +01:00
char * t ;
2010-01-18 23:50:13 +01:00
void * state ;
2009-11-18 00:42:52 +01:00
2010-01-18 23:50:13 +01:00
SET_FOREACH ( t , name - > meta . names , state )
2010-01-20 02:12:51 +01:00
hashmap_remove_value ( name - > meta . manager - > names , t , name ) ;
2009-11-18 00:42:52 +01:00
2010-01-23 01:52:57 +01:00
if ( name - > meta . load_state = = NAME_STUB )
2010-01-18 23:50:13 +01:00
LIST_REMOVE ( Meta , name - > meta . manager - > load_queue , & name - > meta ) ;
2009-11-18 00:42:52 +01:00
}
/* Free data and next 'smaller' objects */
if ( name - > meta . job )
job_free ( name - > meta . job ) ;
2010-01-18 23:50:13 +01:00
for ( d = 0 ; d < _NAME_DEPENDENCY_MAX ; d + + )
bidi_set_free ( name , name - > meta . dependencies [ d ] ) ;
2009-11-18 00:42:52 +01:00
2010-01-23 01:52:57 +01:00
if ( NAME_VTABLE ( name ) - > free_hook )
NAME_VTABLE ( name ) - > free_hook ( name ) ;
2009-11-18 00:42:52 +01:00
free ( name - > meta . description ) ;
2010-01-18 23:50:13 +01:00
while ( ( t = set_steal_first ( name - > meta . names ) ) )
free ( t ) ;
set_free ( name - > meta . names ) ;
2009-11-18 00:42:52 +01:00
free ( name ) ;
}
2010-01-23 01:52:57 +01:00
NameActiveState name_active_state ( Name * name ) {
2009-11-18 00:42:52 +01:00
assert ( name ) ;
2010-01-23 01:52:57 +01:00
if ( name - > meta . load_state ! = NAME_LOADED )
return NAME_INACTIVE ;
2009-11-18 00:42:52 +01:00
2010-01-23 01:52:57 +01:00
return NAME_VTABLE ( name ) - > active_state ( name ) ;
2009-11-18 00:42:52 +01:00
}
static int ensure_in_set ( Set * * s , void * data ) {
int r ;
assert ( s ) ;
assert ( data ) ;
if ( ! * s )
if ( ! ( * s = set_new ( trivial_hash_func , trivial_compare_func ) ) )
return - ENOMEM ;
2010-01-20 05:03:52 +01:00
if ( ( r = set_put ( * s , data ) ) < 0 )
2009-11-18 00:42:52 +01:00
if ( r ! = - EEXIST )
return r ;
return 0 ;
}
2010-01-18 23:50:13 +01:00
static int ensure_merge ( Set * * s , Set * other ) {
if ( ! other )
return 0 ;
if ( * s )
return set_merge ( * s , other ) ;
if ( ! ( * s = set_copy ( other ) ) )
return - ENOMEM ;
return 0 ;
}
2010-01-20 02:12:51 +01:00
/* FIXME: Does not rollback on failure! */
2010-01-18 23:50:13 +01:00
int name_merge ( Name * name , Name * other ) {
int r ;
NameDependency d ;
assert ( name ) ;
assert ( other ) ;
assert ( name - > meta . manager = = other - > meta . manager ) ;
2010-01-20 02:12:51 +01:00
/* This merges 'other' into 'name'. FIXME: This does not
* rollback on failure . */
2010-01-18 23:50:13 +01:00
if ( name - > meta . type ! = other - > meta . type )
return - EINVAL ;
2010-01-23 01:52:57 +01:00
if ( other - > meta . load_state ! = NAME_STUB )
2010-01-18 23:50:13 +01:00
return - EINVAL ;
/* Merge names */
if ( ( r = ensure_merge ( & name - > meta . names , other - > meta . names ) ) < 0 )
return r ;
/* Merge dependencies */
for ( d = 0 ; d < _NAME_DEPENDENCY_MAX ; d + + )
if ( ( r = ensure_merge ( & name - > meta . dependencies [ d ] , other - > meta . dependencies [ d ] ) ) < 0 )
return r ;
2010-01-20 02:12:51 +01:00
/* Hookup new deps and names */
if ( name - > meta . linked ) {
2010-01-20 05:03:52 +01:00
if ( ( r = name_sanitize ( name ) ) < 0 )
2010-01-19 04:15:20 +01:00
return r ;
2010-01-20 02:12:51 +01:00
if ( ( r = name_link_names ( name , true ) ) < 0 )
return r ;
}
2010-01-18 23:50:13 +01:00
return 0 ;
}
2010-01-19 00:22:34 +01:00
2010-01-20 05:03:52 +01:00
/* FIXME: Does not rollback on failure! */
static int augment ( Name * n ) {
int r ;
void * state ;
Name * other ;
assert ( n ) ;
/* Adds in the missing links to make all dependencies
* bidirectional . */
SET_FOREACH ( other , n - > meta . dependencies [ NAME_BEFORE ] , state )
if ( ( r = ensure_in_set ( & other - > meta . dependencies [ NAME_AFTER ] , n ) ) < 0 )
return r ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_AFTER ] , state )
if ( ( r = ensure_in_set ( & other - > meta . dependencies [ NAME_BEFORE ] , n ) ) < 0 )
return r ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_CONFLICTS ] , state )
if ( ( r = ensure_in_set ( & other - > meta . dependencies [ NAME_CONFLICTS ] , n ) ) < 0 )
return r ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_REQUIRES ] , state )
if ( ( r = ensure_in_set ( & other - > meta . dependencies [ NAME_REQUIRED_BY ] , n ) ) < 0 )
return r ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_REQUISITE ] , state )
if ( ( r = ensure_in_set ( & other - > meta . dependencies [ NAME_REQUIRED_BY ] , n ) ) < 0 )
return r ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_SOFT_REQUIRES ] , state )
2010-01-23 01:52:57 +01:00
if ( ( r = ensure_in_set ( & other - > meta . dependencies [ NAME_SOFT_REQUIRED_BY ] , n ) ) < 0 )
2010-01-20 05:03:52 +01:00
return r ;
2010-01-23 01:52:57 +01:00
SET_FOREACH ( other , n - > meta . dependencies [ NAME_WANTS ] , state )
2010-01-20 05:03:52 +01:00
if ( ( r = ensure_in_set ( & other - > meta . dependencies [ NAME_WANTED_BY ] , n ) ) < 0 )
return r ;
return 0 ;
}
int name_sanitize ( Name * n ) {
NameDependency d ;
assert ( n ) ;
/* Remove loops */
for ( d = 0 ; d < _NAME_DEPENDENCY_MAX ; d + + )
set_remove ( n - > meta . dependencies [ d ] , n ) ;
return augment ( n ) ;
}
2010-01-19 00:22:34 +01:00
const char * name_id ( Name * n ) {
assert ( n ) ;
return set_first ( n - > meta . names ) ;
}
2010-01-23 01:52:57 +01:00
const char * name_description ( Name * n ) {
assert ( n ) ;
if ( n - > meta . description )
return n - > meta . description ;
return name_id ( n ) ;
}
2010-01-20 02:35:46 +01:00
void name_dump ( Name * n , FILE * f , const char * prefix ) {
2010-01-19 00:22:34 +01:00
2010-01-23 01:52:57 +01:00
static const char * const load_state_table [ _NAME_LOAD_STATE_MAX ] = {
2010-01-19 02:56:37 +01:00
[ NAME_STUB ] = " stub " ,
[ NAME_LOADED ] = " loaded " ,
[ NAME_FAILED ] = " failed "
} ;
2010-01-23 01:52:57 +01:00
static const char * const active_state_table [ _NAME_ACTIVE_STATE_MAX ] = {
[ NAME_ACTIVE ] = " active " ,
[ NAME_INACTIVE ] = " inactive " ,
[ NAME_ACTIVATING ] = " activating " ,
[ NAME_DEACTIVATING ] = " deactivating "
2010-01-19 00:22:34 +01:00
} ;
2010-01-20 05:03:52 +01:00
static const char * const dependency_table [ _NAME_DEPENDENCY_MAX ] = {
[ NAME_REQUIRES ] = " Requires " ,
[ NAME_SOFT_REQUIRES ] = " SoftRequires " ,
[ NAME_WANTS ] = " Wants " ,
[ NAME_REQUISITE ] = " Requisite " ,
[ NAME_SOFT_REQUISITE ] = " SoftRequisite " ,
[ NAME_REQUIRED_BY ] = " RequiredBy " ,
2010-01-23 01:52:57 +01:00
[ NAME_SOFT_REQUIRED_BY ] = " SoftRequiredBy " ,
2010-01-23 03:35:54 +01:00
[ NAME_WANTED_BY ] = " WantedBy " ,
2010-01-20 05:03:52 +01:00
[ NAME_CONFLICTS ] = " Conflicts " ,
[ NAME_BEFORE ] = " Before " ,
[ NAME_AFTER ] = " After " ,
} ;
2010-01-19 04:15:20 +01:00
void * state ;
char * t ;
2010-01-20 05:03:52 +01:00
NameDependency d ;
2010-01-19 04:15:20 +01:00
2010-01-19 00:22:34 +01:00
assert ( n ) ;
2010-01-20 02:35:46 +01:00
if ( ! prefix )
prefix = " " ;
2010-01-19 04:15:20 +01:00
fprintf ( f ,
2010-01-20 02:35:46 +01:00
" %sName %s: \n "
" %s \t Description: %s \n "
2010-01-23 01:52:57 +01:00
" %s \t Name Load State: %s \n "
" %s \t Name Active State: %s \n " ,
2010-01-20 02:35:46 +01:00
prefix , name_id ( n ) ,
2010-01-23 01:52:57 +01:00
prefix , name_description ( n ) ,
prefix , load_state_table [ n - > meta . load_state ] ,
prefix , active_state_table [ name_active_state ( n ) ] ) ;
2010-01-20 02:35:46 +01:00
2010-01-19 04:15:20 +01:00
SET_FOREACH ( t , n - > meta . names , state )
2010-01-23 01:52:57 +01:00
fprintf ( f , " %s \t Name: %s \n " , prefix , t ) ;
2010-01-19 04:15:20 +01:00
2010-01-20 05:03:52 +01:00
for ( d = 0 ; d < _NAME_DEPENDENCY_MAX ; d + + ) {
void * state ;
Name * other ;
if ( set_isempty ( n - > meta . dependencies [ d ] ) )
continue ;
SET_FOREACH ( other , n - > meta . dependencies [ d ] , state )
2010-01-23 01:52:57 +01:00
fprintf ( f , " %s \t %s: %s \n " , prefix , dependency_table [ d ] , name_id ( other ) ) ;
2010-01-20 05:03:52 +01:00
}
2010-01-23 01:52:57 +01:00
if ( NAME_VTABLE ( n ) - > dump )
NAME_VTABLE ( n ) - > dump ( n , f , prefix ) ;
2010-01-19 02:56:37 +01:00
2010-01-19 00:22:34 +01:00
if ( n - > meta . job ) {
2010-01-20 02:35:46 +01:00
char * p ;
if ( asprintf ( & p , " %s \t " , prefix ) > = 0 )
prefix = p ;
else
p = NULL ;
job_dump ( n - > meta . job , f , prefix ) ;
free ( p ) ;
2010-01-19 00:22:34 +01:00
}
}
2010-01-20 05:03:52 +01:00
static int verify_type ( Name * name ) {
char * n ;
void * state ;
assert ( name ) ;
/* Checks that all aliases of this name have the same and valid type */
SET_FOREACH ( n , name - > meta . names , state ) {
NameType t ;
if ( ( t = name_type_from_string ( n ) ) = = _NAME_TYPE_INVALID )
return - EINVAL ;
if ( name - > meta . type = = _NAME_TYPE_INVALID ) {
name - > meta . type = t ;
continue ;
}
if ( name - > meta . type ! = t )
return - EINVAL ;
}
if ( name - > meta . type = = _NAME_TYPE_INVALID )
return - EINVAL ;
return 0 ;
}
2010-01-23 01:52:57 +01:00
/* Common implementation for multiple backends */
int name_load_fragment_and_dropin ( Name * n ) {
int r ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
assert ( n ) ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
/* Load a .socket file */
if ( ( r = name_load_fragment ( n ) ) < 0 )
return r ;
/* Load drop-in directory data */
if ( ( r = name_load_dropin ( n ) ) < 0 )
return r ;
return 0 ;
2010-01-20 05:03:52 +01:00
}
2010-01-23 01:52:57 +01:00
int name_load ( Name * name ) {
int r ;
assert ( name ) ;
if ( name - > meta . load_state ! = NAME_STUB )
return 0 ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
if ( ( r = verify_type ( name ) ) < 0 )
return r ;
if ( NAME_VTABLE ( name ) - > load )
if ( ( r = NAME_VTABLE ( name ) - > load ( name ) ) < 0 )
goto fail ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
if ( ( r = name_sanitize ( name ) ) < 0 )
goto fail ;
if ( ( r = name_link_names ( name , false ) ) < 0 )
goto fail ;
name - > meta . load_state = NAME_LOADED ;
2010-01-20 05:03:52 +01:00
return 0 ;
2010-01-23 01:52:57 +01:00
fail :
name - > meta . load_state = NAME_FAILED ;
return r ;
2010-01-20 05:03:52 +01:00
}
2010-01-23 01:52:57 +01:00
/* Errors:
* - EBADR : This name type does not support starting .
* - EALREADY : Name is already started .
* - EAGAIN : An operation is already in progress . Retry later .
*/
int name_start ( Name * n ) {
NameActiveState state ;
assert ( n ) ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
if ( ! NAME_VTABLE ( n ) - > start )
return - EBADR ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
state = name_active_state ( n ) ;
if ( NAME_IS_ACTIVE_OR_RELOADING ( state ) )
return - EALREADY ;
if ( state = = NAME_ACTIVATING )
return 0 ;
return NAME_VTABLE ( n ) - > start ( n ) ;
2010-01-20 05:03:52 +01:00
}
2010-01-23 01:52:57 +01:00
bool name_type_can_start ( NameType t ) {
assert ( t > = 0 & & t < _NAME_TYPE_MAX ) ;
return ! ! name_vtable [ t ] - > start ;
}
/* Errors:
* - EBADR : This name type does not support stopping .
* - EALREADY : Name is already stopped .
* - EAGAIN : An operation is already in progress . Retry later .
*/
int name_stop ( Name * n ) {
NameActiveState state ;
2010-01-20 05:03:52 +01:00
assert ( n ) ;
2010-01-23 01:52:57 +01:00
if ( ! NAME_VTABLE ( n ) - > stop )
return - EBADR ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
state = name_active_state ( n ) ;
if ( state = = NAME_INACTIVE )
return - EALREADY ;
if ( state = = NAME_DEACTIVATING )
return 0 ;
return NAME_VTABLE ( n ) - > stop ( n ) ;
2010-01-20 05:03:52 +01:00
}
2010-01-23 01:52:57 +01:00
/* Errors:
* - EBADR : This name type does not support reloading .
* - ENOEXEC : Name is not started .
* - EAGAIN : An operation is already in progress . Retry later .
*/
int name_reload ( Name * n ) {
NameActiveState state ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
assert ( n ) ;
if ( ! NAME_VTABLE ( n ) - > reload )
return - EBADR ;
state = name_active_state ( n ) ;
if ( name_active_state ( n ) = = NAME_ACTIVE_RELOADING )
return - EALREADY ;
if ( name_active_state ( n ) ! = NAME_ACTIVE )
return - ENOEXEC ;
return NAME_VTABLE ( n ) - > reload ( n ) ;
}
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
bool name_type_can_reload ( NameType t ) {
assert ( t > = 0 & & t < _NAME_TYPE_MAX ) ;
return ! ! name_vtable [ t ] - > reload ;
}
static void retroactively_start_dependencies ( Name * n ) {
void * state ;
Name * other ;
assert ( n ) ;
assert ( NAME_IS_ACTIVE_OR_ACTIVATING ( name_active_state ( n ) ) ) ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_REQUIRES ] , state )
if ( ! NAME_IS_ACTIVE_OR_ACTIVATING ( name_active_state ( other ) ) )
manager_add_job ( n - > meta . manager , JOB_START , other , JOB_REPLACE , true , NULL ) ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_SOFT_REQUIRES ] , state )
if ( ! NAME_IS_ACTIVE_OR_ACTIVATING ( name_active_state ( other ) ) )
manager_add_job ( n - > meta . manager , JOB_START , other , JOB_FAIL , false , NULL ) ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_REQUISITE ] , state )
if ( ! NAME_IS_ACTIVE_OR_ACTIVATING ( name_active_state ( other ) ) )
manager_add_job ( n - > meta . manager , JOB_START , other , JOB_REPLACE , true , NULL ) ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_WANTS ] , state )
if ( ! NAME_IS_ACTIVE_OR_ACTIVATING ( name_active_state ( other ) ) )
manager_add_job ( n - > meta . manager , JOB_START , other , JOB_FAIL , false , NULL ) ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_CONFLICTS ] , state )
if ( ! NAME_IS_ACTIVE_OR_ACTIVATING ( name_active_state ( other ) ) )
manager_add_job ( n - > meta . manager , JOB_STOP , other , JOB_REPLACE , true , NULL ) ;
}
static void retroactively_stop_dependencies ( Name * n ) {
void * state ;
Name * other ;
assert ( n ) ;
assert ( NAME_IS_INACTIVE_OR_DEACTIVATING ( name_active_state ( n ) ) ) ;
SET_FOREACH ( other , n - > meta . dependencies [ NAME_REQUIRED_BY ] , state )
if ( ! NAME_IS_INACTIVE_OR_DEACTIVATING ( name_active_state ( other ) ) )
manager_add_job ( n - > meta . manager , JOB_STOP , other , JOB_REPLACE , true , NULL ) ;
}
2010-01-23 22:56:47 +01:00
void name_notify ( Name * n , NameActiveState os , NameActiveState ns ) {
2010-01-23 01:52:57 +01:00
assert ( n ) ;
assert ( os < _NAME_ACTIVE_STATE_MAX ) ;
assert ( ns < _NAME_ACTIVE_STATE_MAX ) ;
assert ( ! ( os = = NAME_ACTIVE & & ns = = NAME_ACTIVATING ) ) ;
assert ( ! ( os = = NAME_INACTIVE & & ns = = NAME_DEACTIVATING ) ) ;
if ( os = = ns )
2010-01-23 22:56:47 +01:00
return ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
if ( n - > meta . job ) {
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
if ( n - > meta . job - > state = = JOB_WAITING )
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
/* So we reached a different state for this
* job . Let ' s see if we can run it now if it
* failed previously due to EAGAIN . */
job_run_and_invalidate ( n - > meta . job ) ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
else {
assert ( n - > meta . job - > state = = JOB_RUNNING ) ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
/* Let's check of this state change
* constitutes a finished job , or maybe
* cotradicts a running job and hence needs to
* invalidate jobs . */
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
switch ( n - > meta . job - > type ) {
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
case JOB_START :
case JOB_VERIFY_ACTIVE :
2010-01-20 05:03:52 +01:00
2010-01-23 22:56:47 +01:00
if ( NAME_IS_ACTIVE_OR_RELOADING ( ns ) ) {
job_finish_and_invalidate ( n - > meta . job , true ) ;
return ;
} else if ( ns = = NAME_ACTIVATING )
return ;
2010-01-23 01:52:57 +01:00
else
job_finish_and_invalidate ( n - > meta . job , false ) ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
break ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
case JOB_RELOAD :
case JOB_RELOAD_OR_START :
2010-01-20 05:03:52 +01:00
2010-01-23 22:56:47 +01:00
if ( ns = = NAME_ACTIVE ) {
job_finish_and_invalidate ( n - > meta . job , true ) ;
return ;
} else if ( ns = = NAME_ACTIVATING | | ns = = NAME_ACTIVE_RELOADING )
return ;
2010-01-23 01:52:57 +01:00
else
job_finish_and_invalidate ( n - > meta . job , false ) ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
break ;
2010-01-20 05:03:52 +01:00
2010-01-23 01:52:57 +01:00
case JOB_STOP :
case JOB_RESTART :
case JOB_TRY_RESTART :
2010-01-23 22:56:47 +01:00
if ( ns = = NAME_INACTIVE ) {
job_finish_and_invalidate ( n - > meta . job , true ) ;
return ;
} else if ( ns = = NAME_DEACTIVATING )
return ;
2010-01-23 01:52:57 +01:00
else
job_finish_and_invalidate ( n - > meta . job , false ) ;
break ;
default :
assert_not_reached ( " Job type unknown " ) ;
}
}
}
/* If this state change happened without being requested by a
* job , then let ' s retroactively start or stop dependencies */
if ( NAME_IS_INACTIVE_OR_DEACTIVATING ( os ) & & NAME_IS_ACTIVE_OR_ACTIVATING ( ns ) )
retroactively_start_dependencies ( n ) ;
else if ( NAME_IS_ACTIVE_OR_ACTIVATING ( os ) & & NAME_IS_INACTIVE_OR_DEACTIVATING ( ns ) )
retroactively_stop_dependencies ( n ) ;
2010-01-20 05:03:52 +01:00
}