2010-01-23 03:52:57 +03:00
/*-*- Mode: C; c-basic-offset: 8 -*-*/
2010-02-03 15:03:47 +03:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
General Public License for more details .
You should have received a copy of the GNU General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-04-18 05:07:42 +04:00
# include <errno.h>
2010-01-26 23:39:06 +03:00
# include "unit.h"
2010-01-23 03:52:57 +03:00
# include "snapshot.h"
2010-04-18 05:07:42 +04:00
# include "unit-name.h"
# include "dbus-snapshot.h"
static const UnitActiveState state_translation_table [ _SNAPSHOT_STATE_MAX ] = {
[ SNAPSHOT_DEAD ] = UNIT_INACTIVE ,
[ SNAPSHOT_ACTIVE ] = UNIT_ACTIVE
} ;
2010-04-21 05:27:44 +04:00
static void snapshot_set_state ( Snapshot * s , SnapshotState state ) {
SnapshotState old_state ;
assert ( s ) ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
old_state = s - > state ;
s - > state = state ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
if ( state ! = old_state )
2010-04-23 22:25:55 +04:00
log_debug ( " %s changed %s -> %s " ,
2010-04-21 05:27:44 +04:00
UNIT ( s ) - > meta . id ,
snapshot_state_to_string ( old_state ) ,
snapshot_state_to_string ( state ) ) ;
2010-01-23 03:52:57 +03:00
2010-04-21 05:27:44 +04:00
unit_notify ( UNIT ( s ) , state_translation_table [ old_state ] , state_translation_table [ state ] ) ;
}
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
static int snapshot_coldplug ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
assert ( s ) ;
assert ( s - > state = = SNAPSHOT_DEAD ) ;
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
if ( s - > deserialized_state ! = s - > state )
snapshot_set_state ( s , s - > deserialized_state ) ;
2010-04-18 05:07:42 +04:00
return 0 ;
}
static void snapshot_dump ( Unit * u , FILE * f , const char * prefix ) {
2010-01-26 23:39:06 +03:00
Snapshot * s = SNAPSHOT ( u ) ;
2010-01-23 03:52:57 +03:00
assert ( s ) ;
2010-04-18 05:07:42 +04:00
assert ( f ) ;
2010-01-23 03:52:57 +03:00
2010-04-18 05:07:42 +04:00
fprintf ( f ,
" %sSnapshot State: %s \n "
" %sClean Up: %s \n " ,
2010-04-21 05:27:44 +04:00
prefix , snapshot_state_to_string ( s - > state ) ,
2010-04-18 05:07:42 +04:00
prefix , yes_no ( s - > cleanup ) ) ;
}
static int snapshot_start ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
assert ( s ) ;
assert ( s - > state = = SNAPSHOT_DEAD ) ;
snapshot_set_state ( s , SNAPSHOT_ACTIVE ) ;
if ( s - > cleanup )
unit_add_to_cleanup_queue ( u ) ;
return 0 ;
}
static int snapshot_stop ( Unit * u ) {
Snapshot * s = SNAPSHOT ( u ) ;
assert ( s ) ;
assert ( s - > state = = SNAPSHOT_ACTIVE ) ;
snapshot_set_state ( s , SNAPSHOT_DEAD ) ;
return 0 ;
2010-01-23 03:52:57 +03:00
}
2010-04-21 05:27:44 +04:00
static int snapshot_serialize ( Unit * u , FILE * f , FDSet * fds ) {
Snapshot * s = SNAPSHOT ( u ) ;
Unit * other ;
Iterator i ;
assert ( s ) ;
assert ( f ) ;
assert ( fds ) ;
unit_serialize_item ( u , f , " state " , snapshot_state_to_string ( s - > state ) ) ;
unit_serialize_item ( u , f , " cleanup " , yes_no ( s - > cleanup ) ) ;
SET_FOREACH ( other , u - > meta . dependencies [ UNIT_REQUIRES ] , i )
unit_serialize_item ( u , f , " requires " , other - > meta . id ) ;
return 0 ;
}
static int snapshot_deserialize_item ( Unit * u , const char * key , const char * value , FDSet * fds ) {
Snapshot * s = SNAPSHOT ( u ) ;
int r ;
assert ( u ) ;
assert ( key ) ;
assert ( value ) ;
assert ( fds ) ;
if ( streq ( key , " state " ) ) {
SnapshotState state ;
if ( ( state = snapshot_state_from_string ( value ) ) < 0 )
log_debug ( " Failed to parse state value %s " , value ) ;
else
s - > deserialized_state = state ;
} else if ( streq ( key , " cleanup " ) ) {
if ( ( r = parse_boolean ( value ) ) < 0 )
log_debug ( " Failed to parse cleanup value %s " , value ) ;
else
s - > cleanup = r ;
} else if ( streq ( key , " requires " ) ) {
2010-04-21 08:01:13 +04:00
if ( ( r = unit_add_dependency_by_name ( u , UNIT_AFTER , value , NULL , true ) ) < 0 )
2010-04-21 05:27:44 +04:00
return r ;
2010-04-21 08:01:13 +04:00
if ( ( r = unit_add_dependency_by_name ( u , UNIT_REQUIRES , value , NULL , true ) ) < 0 )
2010-04-21 05:27:44 +04:00
return r ;
} else
log_debug ( " Unknown serialization key '%s' " , key ) ;
return 0 ;
}
2010-01-26 23:39:06 +03:00
static UnitActiveState snapshot_active_state ( Unit * u ) {
2010-04-18 05:07:42 +04:00
assert ( u ) ;
return state_translation_table [ SNAPSHOT ( u ) - > state ] ;
}
static const char * snapshot_sub_state_to_string ( Unit * u ) {
assert ( u ) ;
2010-04-21 05:27:44 +04:00
return snapshot_state_to_string ( SNAPSHOT ( u ) - > state ) ;
2010-04-18 05:07:42 +04:00
}
int snapshot_create ( Manager * m , const char * name , bool cleanup , Snapshot * * _s ) {
2010-04-21 05:27:44 +04:00
Iterator i ;
Unit * other , * u = NULL ;
2010-04-18 05:07:42 +04:00
char * n = NULL ;
int r ;
2010-04-21 05:27:44 +04:00
const char * k ;
2010-04-18 05:07:42 +04:00
assert ( m ) ;
assert ( _s ) ;
if ( name ) {
if ( ! unit_name_is_valid ( name ) )
return - EINVAL ;
if ( unit_name_to_type ( name ) ! = UNIT_SNAPSHOT )
return - EINVAL ;
if ( manager_get_unit ( m , name ) )
return - EEXIST ;
} else {
for ( ; ; ) {
if ( asprintf ( & n , " snapshot-%u.snapshot " , + + m - > n_snapshots ) < 0 )
return - ENOMEM ;
if ( ! manager_get_unit ( m , n ) )
break ;
free ( n ) ;
}
name = n ;
}
r = manager_load_unit ( m , name , NULL , & u ) ;
free ( n ) ;
if ( r < 0 )
2010-04-21 05:27:44 +04:00
goto fail ;
HASHMAP_FOREACH_KEY ( other , k , m - > units , i ) {
if ( UNIT_VTABLE ( other ) - > no_snapshots )
continue ;
if ( k ! = other - > meta . id )
continue ;
2010-04-21 08:01:13 +04:00
if ( UNIT_VTABLE ( other ) - > check_snapshot )
if ( ! UNIT_VTABLE ( other ) - > check_snapshot ( other ) )
continue ;
2010-04-21 05:27:44 +04:00
if ( ! UNIT_IS_ACTIVE_OR_ACTIVATING ( unit_active_state ( other ) ) )
continue ;
2010-04-21 08:01:13 +04:00
if ( ( r = unit_add_dependency ( u , UNIT_REQUIRES , other , true ) ) < 0 )
2010-04-21 05:27:44 +04:00
goto fail ;
2010-04-21 08:01:13 +04:00
if ( ( r = unit_add_dependency ( u , UNIT_AFTER , other , true ) ) < 0 )
2010-04-21 05:27:44 +04:00
goto fail ;
}
2010-04-18 05:07:42 +04:00
SNAPSHOT ( u ) - > cleanup = cleanup ;
* _s = SNAPSHOT ( u ) ;
return 0 ;
2010-04-21 05:27:44 +04:00
fail :
if ( u )
unit_add_to_cleanup_queue ( u ) ;
return r ;
2010-04-18 05:07:42 +04:00
}
void snapshot_remove ( Snapshot * s ) {
assert ( s ) ;
unit_add_to_cleanup_queue ( UNIT ( s ) ) ;
2010-01-26 06:18:44 +03:00
}
2010-04-21 05:27:44 +04:00
static const char * const snapshot_state_table [ _SNAPSHOT_STATE_MAX ] = {
[ SNAPSHOT_DEAD ] = " dead " ,
[ SNAPSHOT_ACTIVE ] = " active "
} ;
DEFINE_STRING_TABLE_LOOKUP ( snapshot_state , SnapshotState ) ;
2010-01-26 23:39:06 +03:00
const UnitVTable snapshot_vtable = {
2010-01-23 03:52:57 +03:00
. suffix = " .snapshot " ,
2010-04-18 05:07:42 +04:00
. no_alias = true ,
. no_instances = true ,
. no_snapshots = true ,
2010-04-21 08:01:13 +04:00
. no_gc = true ,
2010-04-18 05:07:42 +04:00
2010-04-21 05:27:44 +04:00
. load = unit_load_nop ,
. coldplug = snapshot_coldplug ,
2010-04-18 05:07:42 +04:00
. dump = snapshot_dump ,
. start = snapshot_start ,
. stop = snapshot_stop ,
2010-04-21 05:27:44 +04:00
. serialize = snapshot_serialize ,
. deserialize_item = snapshot_deserialize_item ,
2010-04-18 05:07:42 +04:00
. active_state = snapshot_active_state ,
. sub_state_to_string = snapshot_sub_state_to_string ,
2010-01-23 03:52:57 +03:00
2010-04-18 05:07:42 +04:00
. bus_message_handler = bus_snapshot_message_handler
2010-01-23 03:52:57 +03:00
} ;