2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-01-23 03:52:57 +03:00
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
2012-04-12 02:20:58 +04:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-02-03 15:03:47 +03:00
( 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
2012-04-12 02:20:58 +04:00
Lesser General Public License for more details .
2010-02-03 15:03:47 +03:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2010-02-03 15:03:47 +03:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-01-28 04:44:47 +03:00
# include <errno.h>
2010-01-26 23:39:06 +03:00
# include "unit.h"
2010-05-24 03:45:54 +04:00
# include "unit-name.h"
2010-01-23 03:52:57 +03:00
# include "timer.h"
2010-05-24 03:45:54 +04:00
# include "dbus-timer.h"
2010-07-03 21:48:33 +04:00
# include "special.h"
2010-07-08 04:43:18 +04:00
# include "bus-errors.h"
2010-05-24 03:45:54 +04:00
static const UnitActiveState state_translation_table [ _TIMER_STATE_MAX ] = {
[ TIMER_DEAD ] = UNIT_INACTIVE ,
[ TIMER_WAITING ] = UNIT_ACTIVE ,
[ TIMER_RUNNING ] = UNIT_ACTIVE ,
[ TIMER_ELAPSED ] = UNIT_ACTIVE ,
2010-08-31 02:23:34 +04:00
[ TIMER_FAILED ] = UNIT_FAILED
2010-05-24 03:45:54 +04:00
} ;
static void timer_init ( Unit * u ) {
Timer * t = TIMER ( u ) ;
assert ( u ) ;
2012-01-15 15:04:08 +04:00
assert ( u - > load_state = = UNIT_STUB ) ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
t - > next_elapse_monotonic = ( usec_t ) - 1 ;
t - > next_elapse_realtime = ( usec_t ) - 1 ;
watch_init ( & t - > monotonic_watch ) ;
watch_init ( & t - > realtime_watch ) ;
2010-05-24 03:45:54 +04:00
}
2010-01-23 03:52:57 +03:00
2013-01-17 05:27:06 +04:00
void timer_free_values ( Timer * t ) {
2010-05-24 03:45:54 +04:00
TimerValue * v ;
assert ( t ) ;
while ( ( v = t - > values ) ) {
LIST_REMOVE ( TimerValue , value , t - > values , v ) ;
2012-11-24 00:37:58 +04:00
if ( v - > calendar_spec )
calendar_spec_free ( v - > calendar_spec ) ;
2010-05-24 03:45:54 +04:00
free ( v ) ;
}
2013-01-17 05:27:06 +04:00
}
static void timer_done ( Unit * u ) {
Timer * t = TIMER ( u ) ;
assert ( t ) ;
timer_free_values ( t ) ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
unit_unwatch_timer ( u , & t - > monotonic_watch ) ;
unit_unwatch_timer ( u , & t - > realtime_watch ) ;
2012-01-07 02:08:54 +04:00
unit_ref_unset ( & t - > unit ) ;
2010-05-24 03:45:54 +04:00
}
static int timer_verify ( Timer * t ) {
assert ( t ) ;
2012-01-15 15:25:20 +04:00
if ( UNIT ( t ) - > load_state ! = UNIT_LOADED )
2010-05-24 03:45:54 +04:00
return 0 ;
if ( ! t - > values ) {
2013-01-05 21:00:35 +04:00
log_error_unit ( UNIT ( t ) - > id ,
" %s lacks value setting. Refusing. " , UNIT ( t ) - > id ) ;
2010-05-24 03:45:54 +04:00
return - EINVAL ;
}
return 0 ;
}
2010-07-16 20:57:21 +04:00
static int timer_add_default_dependencies ( Timer * t ) {
int r ;
assert ( t ) ;
2012-09-18 19:11:12 +04:00
if ( UNIT ( t ) - > manager - > running_as = = SYSTEMD_SYSTEM ) {
2012-11-24 00:37:58 +04:00
r = unit_add_dependency_by_name ( UNIT ( t ) , UNIT_BEFORE , SPECIAL_BASIC_TARGET , NULL , true ) ;
if ( r < 0 )
2010-10-29 08:04:03 +04:00
return r ;
2012-11-24 00:37:58 +04:00
r = unit_add_two_dependencies_by_name ( UNIT ( t ) , UNIT_AFTER , UNIT_REQUIRES , SPECIAL_SYSINIT_TARGET , NULL , true ) ;
if ( r < 0 )
2010-07-16 20:57:21 +04:00
return r ;
2010-10-29 08:04:03 +04:00
}
2010-07-16 20:57:21 +04:00
2010-10-29 03:15:18 +04:00
return unit_add_two_dependencies_by_name ( UNIT ( t ) , UNIT_BEFORE , UNIT_CONFLICTS , SPECIAL_SHUTDOWN_TARGET , NULL , true ) ;
2010-07-16 20:57:21 +04:00
}
2010-05-24 03:45:54 +04:00
static int timer_load ( Unit * u ) {
Timer * t = TIMER ( u ) ;
int r ;
assert ( u ) ;
2012-01-15 15:04:08 +04:00
assert ( u - > load_state = = UNIT_STUB ) ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
r = unit_load_fragment_and_dropin ( u ) ;
if ( r < 0 )
2010-05-24 03:45:54 +04:00
return r ;
2012-01-15 15:04:08 +04:00
if ( u - > load_state = = UNIT_LOADED ) {
2010-05-24 03:45:54 +04:00
2012-01-07 02:08:54 +04:00
if ( ! UNIT_DEREF ( t - > unit ) ) {
Unit * x ;
r = unit_load_related_unit ( u , " .service " , & x ) ;
if ( r < 0 )
2010-05-24 03:45:54 +04:00
return r ;
2012-01-07 02:08:54 +04:00
unit_ref_set ( & t - > unit , x ) ;
}
r = unit_add_two_dependencies ( u , UNIT_BEFORE , UNIT_TRIGGERS , UNIT_DEREF ( t - > unit ) , true ) ;
if ( r < 0 )
2010-05-24 03:45:54 +04:00
return r ;
2010-07-03 21:48:33 +04:00
2012-11-24 00:37:58 +04:00
if ( UNIT ( t ) - > default_dependencies ) {
r = timer_add_default_dependencies ( t ) ;
if ( r < 0 )
2010-07-03 21:48:33 +04:00
return r ;
2012-11-24 00:37:58 +04:00
}
2010-05-24 03:45:54 +04:00
}
return timer_verify ( t ) ;
}
static void timer_dump ( Unit * u , FILE * f , const char * prefix ) {
Timer * t = TIMER ( u ) ;
TimerValue * v ;
2010-01-26 06:18:44 +03:00
2010-05-24 03:45:54 +04:00
fprintf ( f ,
" %sTimer State: %s \n "
2012-02-03 07:03:21 +04:00
" %sResult: %s \n "
2010-05-24 03:45:54 +04:00
" %sUnit: %s \n " ,
prefix , timer_state_to_string ( t - > state ) ,
2012-02-03 07:03:21 +04:00
prefix , timer_result_to_string ( t - > result ) ,
2012-01-15 15:04:08 +04:00
prefix , UNIT_DEREF ( t - > unit ) - > id ) ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
LIST_FOREACH ( value , v , t - > values ) {
if ( v - > base = = TIMER_CALENDAR ) {
_cleanup_free_ char * p = NULL ;
calendar_spec_to_string ( v - > calendar_spec , & p ) ;
fprintf ( f ,
" %s%s: %s \n " ,
prefix ,
timer_base_to_string ( v - > base ) ,
strna ( p ) ) ;
} else {
char timespan1 [ FORMAT_TIMESPAN_MAX ] ;
fprintf ( f ,
" %s%s: %s \n " ,
prefix ,
timer_base_to_string ( v - > base ) ,
strna ( format_timespan ( timespan1 , sizeof ( timespan1 ) , v - > value ) ) ) ;
}
}
2010-05-24 03:45:54 +04:00
}
static void timer_set_state ( Timer * t , TimerState state ) {
TimerState old_state ;
2010-01-26 06:18:44 +03:00
assert ( t ) ;
2010-05-24 03:45:54 +04:00
old_state = t - > state ;
t - > state = state ;
2012-11-24 00:37:58 +04:00
if ( state ! = TIMER_WAITING ) {
unit_unwatch_timer ( UNIT ( t ) , & t - > monotonic_watch ) ;
unit_unwatch_timer ( UNIT ( t ) , & t - > realtime_watch ) ;
}
2010-05-24 03:45:54 +04:00
if ( state ! = old_state )
2013-01-05 21:00:35 +04:00
log_debug_unit ( UNIT ( t ) - > id ,
" %s changed %s -> %s " , UNIT ( t ) - > id ,
timer_state_to_string ( old_state ) ,
timer_state_to_string ( state ) ) ;
2010-05-24 03:45:54 +04:00
2011-01-20 15:17:22 +03:00
unit_notify ( UNIT ( t ) , state_translation_table [ old_state ] , state_translation_table [ state ] , true ) ;
2010-05-24 03:45:54 +04:00
}
static void timer_enter_waiting ( Timer * t , bool initial ) ;
static int timer_coldplug ( Unit * u ) {
Timer * t = TIMER ( u ) ;
assert ( t ) ;
assert ( t - > state = = TIMER_DEAD ) ;
if ( t - > deserialized_state ! = t - > state ) {
2010-10-28 06:04:50 +04:00
if ( t - > deserialized_state = = TIMER_WAITING )
2010-05-24 03:45:54 +04:00
timer_enter_waiting ( t , false ) ;
else
timer_set_state ( t , t - > deserialized_state ) ;
}
return 0 ;
}
2012-02-03 07:03:21 +04:00
static void timer_enter_dead ( Timer * t , TimerResult f ) {
2010-05-24 03:45:54 +04:00
assert ( t ) ;
2012-02-03 07:03:21 +04:00
if ( f ! = TIMER_SUCCESS )
t - > result = f ;
2010-05-24 03:45:54 +04:00
2012-02-03 07:03:21 +04:00
timer_set_state ( t , t - > result ! = TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD ) ;
2010-05-24 03:45:54 +04:00
}
static void timer_enter_waiting ( Timer * t , bool initial ) {
TimerValue * v ;
2012-11-24 00:37:58 +04:00
usec_t base = 0 ;
dual_timestamp ts ;
bool found_monotonic = false , found_realtime = false ;
2010-05-24 03:45:54 +04:00
int r ;
2012-11-24 00:37:58 +04:00
dual_timestamp_get ( & ts ) ;
t - > next_elapse_monotonic = t - > next_elapse_realtime = 0 ;
2010-05-24 03:45:54 +04:00
LIST_FOREACH ( value , v , t - > values ) {
if ( v - > disabled )
continue ;
2012-11-24 00:37:58 +04:00
if ( v - > base = = TIMER_CALENDAR ) {
r = calendar_spec_next_usec ( v - > calendar_spec , ts . realtime , & v - > next_elapse ) ;
if ( r < 0 )
continue ;
if ( ! initial & & v - > next_elapse < ts . realtime ) {
v - > disabled = true ;
continue ;
}
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
if ( ! found_realtime )
t - > next_elapse_realtime = v - > next_elapse ;
2010-10-27 02:01:12 +04:00
else
2012-11-24 00:37:58 +04:00
t - > next_elapse_realtime = MIN ( t - > next_elapse_realtime , v - > next_elapse ) ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
found_realtime = true ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
} else {
switch ( v - > base ) {
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
case TIMER_ACTIVE :
if ( state_translation_table [ t - > state ] = = UNIT_ACTIVE )
base = UNIT ( t ) - > inactive_exit_timestamp . monotonic ;
else
base = ts . monotonic ;
break ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
case TIMER_BOOT :
/* CLOCK_MONOTONIC equals the uptime on Linux */
base = 0 ;
break ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
case TIMER_STARTUP :
base = UNIT ( t ) - > manager - > userspace_timestamp . monotonic ;
break ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
case TIMER_UNIT_ACTIVE :
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
if ( UNIT_DEREF ( t - > unit ) - > inactive_exit_timestamp . monotonic < = 0 )
continue ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
base = UNIT_DEREF ( t - > unit ) - > inactive_exit_timestamp . monotonic ;
break ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
case TIMER_UNIT_INACTIVE :
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
if ( UNIT_DEREF ( t - > unit ) - > inactive_enter_timestamp . monotonic < = 0 )
continue ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
base = UNIT_DEREF ( t - > unit ) - > inactive_enter_timestamp . monotonic ;
break ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
default :
assert_not_reached ( " Unknown timer base " ) ;
}
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
v - > next_elapse = base + v - > value ;
if ( ! initial & & v - > next_elapse < ts . monotonic ) {
v - > disabled = true ;
continue ;
}
if ( ! found_monotonic )
t - > next_elapse_monotonic = v - > next_elapse ;
else
t - > next_elapse_monotonic = MIN ( t - > next_elapse_monotonic , v - > next_elapse ) ;
found_monotonic = true ;
}
2010-05-24 03:45:54 +04:00
}
2012-11-24 00:37:58 +04:00
if ( ! found_monotonic & & ! found_realtime ) {
2013-01-05 21:00:35 +04:00
log_debug_unit ( UNIT ( t ) - > id , " %s: Timer is elapsed. " , UNIT ( t ) - > id ) ;
2010-05-24 03:45:54 +04:00
timer_set_state ( t , TIMER_ELAPSED ) ;
return ;
}
2012-11-24 00:37:58 +04:00
if ( found_monotonic ) {
char buf [ FORMAT_TIMESPAN_MAX ] ;
2013-01-05 21:00:35 +04:00
log_debug_unit ( UNIT ( t ) - > id ,
" %s: Monotonic timer elapses in %s the next time. " ,
UNIT ( t ) - > id ,
2013-01-10 03:54:46 +04:00
format_timespan ( buf , sizeof ( buf ) , t - > next_elapse_monotonic > ts . monotonic ? t - > next_elapse_monotonic - ts . monotonic : 0 ) ) ;
2010-05-24 03:45:54 +04:00
2012-11-24 00:37:58 +04:00
r = unit_watch_timer ( UNIT ( t ) , CLOCK_MONOTONIC , false , t - > next_elapse_monotonic , & t - > monotonic_watch ) ;
if ( r < 0 )
goto fail ;
} else
unit_unwatch_timer ( UNIT ( t ) , & t - > monotonic_watch ) ;
if ( found_realtime ) {
char buf [ FORMAT_TIMESTAMP_MAX ] ;
2013-01-05 21:00:35 +04:00
log_debug_unit ( UNIT ( t ) - > id ,
" %s: Realtime timer elapses at %s the next time. " ,
UNIT ( t ) - > id ,
format_timestamp ( buf , sizeof ( buf ) , t - > next_elapse_realtime ) ) ;
2012-11-24 00:37:58 +04:00
r = unit_watch_timer ( UNIT ( t ) , CLOCK_REALTIME , false , t - > next_elapse_realtime , & t - > realtime_watch ) ;
if ( r < 0 )
goto fail ;
} else
unit_unwatch_timer ( UNIT ( t ) , & t - > realtime_watch ) ;
2010-05-24 03:45:54 +04:00
timer_set_state ( t , TIMER_WAITING ) ;
return ;
fail :
2013-01-05 21:00:35 +04:00
log_warning_unit ( UNIT ( t ) - > id ,
" %s failed to enter waiting state: %s " ,
UNIT ( t ) - > id , strerror ( - r ) ) ;
2012-02-03 07:03:21 +04:00
timer_enter_dead ( t , TIMER_FAILURE_RESOURCES ) ;
2010-05-24 03:45:54 +04:00
}
static void timer_enter_running ( Timer * t ) {
2010-07-08 04:43:18 +04:00
DBusError error ;
2010-05-24 03:45:54 +04:00
int r ;
2010-07-08 04:43:18 +04:00
2010-05-24 03:45:54 +04:00
assert ( t ) ;
2010-07-08 04:43:18 +04:00
dbus_error_init ( & error ) ;
2010-05-24 03:45:54 +04:00
2010-07-13 02:27:27 +04:00
/* Don't start job if we are supposed to go down */
2012-01-15 15:25:20 +04:00
if ( UNIT ( t ) - > job & & UNIT ( t ) - > job - > type = = JOB_STOP )
2010-07-13 02:27:27 +04:00
return ;
2012-11-24 00:37:58 +04:00
r = manager_add_job ( UNIT ( t ) - > manager , JOB_START , UNIT_DEREF ( t - > unit ) , JOB_REPLACE , true , & error , NULL ) ;
if ( r < 0 )
2010-05-24 03:45:54 +04:00
goto fail ;
timer_set_state ( t , TIMER_RUNNING ) ;
return ;
fail :
2013-01-05 21:00:35 +04:00
log_warning_unit ( UNIT ( t ) - > id ,
" %s failed to queue unit startup job: %s " ,
UNIT ( t ) - > id , bus_error ( & error , r ) ) ;
2012-02-03 07:03:21 +04:00
timer_enter_dead ( t , TIMER_FAILURE_RESOURCES ) ;
2010-07-08 04:43:18 +04:00
dbus_error_free ( & error ) ;
2010-05-24 03:45:54 +04:00
}
static int timer_start ( Unit * u ) {
Timer * t = TIMER ( u ) ;
assert ( t ) ;
2010-08-31 02:23:34 +04:00
assert ( t - > state = = TIMER_DEAD | | t - > state = = TIMER_FAILED ) ;
2010-05-24 07:25:33 +04:00
2012-01-15 15:04:08 +04:00
if ( UNIT_DEREF ( t - > unit ) - > load_state ! = UNIT_LOADED )
2010-05-24 07:25:33 +04:00
return - ENOENT ;
2010-05-24 03:45:54 +04:00
2012-02-03 07:03:21 +04:00
t - > result = TIMER_SUCCESS ;
2010-05-24 03:45:54 +04:00
timer_enter_waiting ( t , true ) ;
return 0 ;
}
static int timer_stop ( Unit * u ) {
Timer * t = TIMER ( u ) ;
assert ( t ) ;
assert ( t - > state = = TIMER_WAITING | | t - > state = = TIMER_RUNNING | | t - > state = = TIMER_ELAPSED ) ;
2012-02-03 07:03:21 +04:00
timer_enter_dead ( t , TIMER_SUCCESS ) ;
2010-05-24 03:45:54 +04:00
return 0 ;
}
static int timer_serialize ( Unit * u , FILE * f , FDSet * fds ) {
Timer * t = TIMER ( u ) ;
assert ( u ) ;
assert ( f ) ;
assert ( fds ) ;
unit_serialize_item ( u , f , " state " , timer_state_to_string ( t - > state ) ) ;
2012-02-03 07:03:21 +04:00
unit_serialize_item ( u , f , " result " , timer_result_to_string ( t - > result ) ) ;
2010-05-24 03:45:54 +04:00
return 0 ;
}
static int timer_deserialize_item ( Unit * u , const char * key , const char * value , FDSet * fds ) {
Timer * t = TIMER ( u ) ;
assert ( u ) ;
assert ( key ) ;
assert ( value ) ;
assert ( fds ) ;
if ( streq ( key , " state " ) ) {
TimerState state ;
2012-11-24 00:37:58 +04:00
state = timer_state_from_string ( value ) ;
if ( state < 0 )
2013-01-05 21:00:35 +04:00
log_debug_unit ( u - > id , " Failed to parse state value %s " , value ) ;
2010-05-24 03:45:54 +04:00
else
t - > deserialized_state = state ;
2012-02-03 07:03:21 +04:00
} else if ( streq ( key , " result " ) ) {
TimerResult f ;
f = timer_result_from_string ( value ) ;
if ( f < 0 )
2013-01-05 21:00:35 +04:00
log_debug_unit ( u - > id , " Failed to parse result value %s " , value ) ;
2012-02-03 07:03:21 +04:00
else if ( f ! = TIMER_SUCCESS )
t - > result = f ;
2010-05-24 03:45:54 +04:00
} else
2013-01-05 21:00:35 +04:00
log_debug_unit ( u - > id , " Unknown serialization key '%s' " , key ) ;
2010-05-24 03:45:54 +04:00
return 0 ;
2010-01-26 06:18:44 +03:00
}
2010-01-26 23:39:06 +03:00
static UnitActiveState timer_active_state ( Unit * u ) {
2010-05-24 03:45:54 +04:00
assert ( u ) ;
return state_translation_table [ TIMER ( u ) - > state ] ;
}
static const char * timer_sub_state_to_string ( Unit * u ) {
assert ( u ) ;
return timer_state_to_string ( TIMER ( u ) - > state ) ;
}
static void timer_timer_event ( Unit * u , uint64_t elapsed , Watch * w ) {
Timer * t = TIMER ( u ) ;
assert ( t ) ;
assert ( elapsed = = 1 ) ;
2010-01-23 03:52:57 +03:00
2010-05-24 03:45:54 +04:00
if ( t - > state ! = TIMER_WAITING )
return ;
2010-01-23 03:52:57 +03:00
2013-01-05 21:00:35 +04:00
log_debug_unit ( u - > id , " Timer elapsed on %s " , u - > id ) ;
2010-05-24 03:45:54 +04:00
timer_enter_running ( t ) ;
2010-01-23 03:52:57 +03:00
}
2010-05-24 03:45:54 +04:00
void timer_unit_notify ( Unit * u , UnitActiveState new_state ) {
Iterator i ;
2012-01-07 02:08:54 +04:00
Unit * k ;
2010-05-24 03:45:54 +04:00
2012-01-15 15:04:08 +04:00
if ( u - > type = = UNIT_TIMER )
2010-05-24 03:45:54 +04:00
return ;
2012-01-15 15:04:08 +04:00
SET_FOREACH ( k , u - > dependencies [ UNIT_TRIGGERED_BY ] , i ) {
2010-05-24 03:45:54 +04:00
Timer * t ;
TimerValue * v ;
2012-01-15 15:04:08 +04:00
if ( k - > type ! = UNIT_TIMER )
2010-05-24 03:45:54 +04:00
continue ;
2012-01-15 15:04:08 +04:00
if ( k - > load_state ! = UNIT_LOADED )
2010-05-24 07:25:33 +04:00
continue ;
2012-01-07 02:08:54 +04:00
t = TIMER ( k ) ;
2010-05-24 03:45:54 +04:00
/* Reenable all timers that depend on unit state */
LIST_FOREACH ( value , v , t - > values )
if ( v - > base = = TIMER_UNIT_ACTIVE | |
v - > base = = TIMER_UNIT_INACTIVE )
v - > disabled = false ;
switch ( t - > state ) {
case TIMER_WAITING :
case TIMER_ELAPSED :
/* Recalculate sleep time */
timer_enter_waiting ( t , false ) ;
break ;
case TIMER_RUNNING :
2010-08-31 02:23:34 +04:00
if ( UNIT_IS_INACTIVE_OR_FAILED ( new_state ) ) {
2013-01-05 21:00:35 +04:00
log_debug_unit ( UNIT ( t ) - > id ,
" %s got notified about unit deactivation. " ,
UNIT ( t ) - > id ) ;
2010-05-24 03:45:54 +04:00
timer_enter_waiting ( t , false ) ;
}
break ;
case TIMER_DEAD :
2010-08-31 02:23:34 +04:00
case TIMER_FAILED :
2010-09-28 17:25:20 +04:00
break ;
2010-05-24 03:45:54 +04:00
default :
assert_not_reached ( " Unknown timer state " ) ;
}
}
}
2010-08-31 02:23:34 +04:00
static void timer_reset_failed ( Unit * u ) {
2010-07-18 06:58:01 +04:00
Timer * t = TIMER ( u ) ;
assert ( t ) ;
2010-08-31 02:23:34 +04:00
if ( t - > state = = TIMER_FAILED )
2010-07-18 06:58:01 +04:00
timer_set_state ( t , TIMER_DEAD ) ;
2012-02-03 07:03:21 +04:00
t - > result = TIMER_SUCCESS ;
2010-07-18 06:58:01 +04:00
}
2012-11-25 03:32:40 +04:00
static void timer_time_change ( Unit * u ) {
Timer * t = TIMER ( u ) ;
assert ( u ) ;
if ( t - > state ! = TIMER_WAITING )
return ;
2013-01-05 21:00:35 +04:00
log_info_unit ( u - > id ,
" %s: time change, recalculating next elapse. " , u - > id ) ;
2012-11-25 03:32:40 +04:00
timer_enter_waiting ( t , false ) ;
}
2010-05-24 03:45:54 +04:00
static const char * const timer_state_table [ _TIMER_STATE_MAX ] = {
[ TIMER_DEAD ] = " dead " ,
[ TIMER_WAITING ] = " waiting " ,
[ TIMER_RUNNING ] = " running " ,
[ TIMER_ELAPSED ] = " elapsed " ,
2010-08-31 02:23:34 +04:00
[ TIMER_FAILED ] = " failed "
2010-05-24 03:45:54 +04:00
} ;
DEFINE_STRING_TABLE_LOOKUP ( timer_state , TimerState ) ;
static const char * const timer_base_table [ _TIMER_BASE_MAX ] = {
2010-07-04 23:12:10 +04:00
[ TIMER_ACTIVE ] = " OnActiveSec " ,
[ TIMER_BOOT ] = " OnBootSec " ,
[ TIMER_STARTUP ] = " OnStartupSec " ,
[ TIMER_UNIT_ACTIVE ] = " OnUnitActiveSec " ,
2012-11-24 00:37:58 +04:00
[ TIMER_UNIT_INACTIVE ] = " OnUnitInactiveSec " ,
[ TIMER_CALENDAR ] = " OnCalendar "
2010-05-24 03:45:54 +04:00
} ;
DEFINE_STRING_TABLE_LOOKUP ( timer_base , TimerBase ) ;
2012-02-03 07:03:21 +04:00
static const char * const timer_result_table [ _TIMER_RESULT_MAX ] = {
[ TIMER_SUCCESS ] = " success " ,
[ TIMER_FAILURE_RESOURCES ] = " resources "
} ;
DEFINE_STRING_TABLE_LOOKUP ( timer_result , TimerResult ) ;
2010-01-26 23:39:06 +03:00
const UnitVTable timer_vtable = {
2012-01-15 13:53:49 +04:00
. object_size = sizeof ( Timer ) ,
2011-08-01 02:43:05 +04:00
. sections =
" Unit \0 "
" Timer \0 "
" Install \0 " ,
2010-01-23 03:52:57 +03:00
2010-05-24 03:45:54 +04:00
. init = timer_init ,
2010-01-26 06:18:44 +03:00
. done = timer_done ,
2010-05-24 03:45:54 +04:00
. load = timer_load ,
. coldplug = timer_coldplug ,
. dump = timer_dump ,
. start = timer_start ,
. stop = timer_stop ,
. serialize = timer_serialize ,
. deserialize_item = timer_deserialize_item ,
. active_state = timer_active_state ,
. sub_state_to_string = timer_sub_state_to_string ,
. timer_event = timer_timer_event ,
2010-01-23 03:52:57 +03:00
2010-08-31 02:23:34 +04:00
. reset_failed = timer_reset_failed ,
2012-11-25 03:32:40 +04:00
. time_change = timer_time_change ,
2010-07-18 06:58:01 +04:00
2010-08-20 04:26:05 +04:00
. bus_interface = " org.freedesktop.systemd1.Timer " ,
. bus_message_handler = bus_timer_message_handler ,
. bus_invalidating_properties = bus_timer_invalidating_properties
2010-01-23 03:52:57 +03:00
} ;