typedef union Name Name;
typedef struct Meta Meta;
-typedef struct Service Service;
-typedef struct Timer Timer;
-typedef struct Socket Socket;
-typedef struct Milestone Milestone;
-typedef struct Device Device;
-typedef struct Mount Mount;
-typedef struct Automount Automount;
-typedef struct Snapshot Snapshot;
+typedef struct NameVTable NameVTable;
+typedef enum NameType NameType;
+typedef enum NameLoadState NameLoadState;
+typedef enum NameActiveState NameActiveState;
+typedef enum NameDependency NameDependency;
#include "job.h"
#include "manager.h"
#include "set.h"
#include "util.h"
#include "list.h"
+#include "socket-util.h"
+#include "execute.h"
+#include "util.h"
+
+#define NAME_MAX 32
+#define DEFAULT_TIMEOUT_USEC (20*USEC_PER_SEC)
+#define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC)
-typedef enum NameType {
+enum NameType {
NAME_SERVICE = 0,
NAME_TIMER,
NAME_SOCKET,
- NAME_MILESTONE,
+ NAME_TARGET,
NAME_DEVICE,
NAME_MOUNT,
NAME_AUTOMOUNT,
NAME_SNAPSHOT,
_NAME_TYPE_MAX,
_NAME_TYPE_INVALID = -1,
-} NameType;
+};
-typedef enum NameState {
+enum NameLoadState {
NAME_STUB,
NAME_LOADED,
- NAME_FAILED
-} NameState;
+ NAME_FAILED,
+ _NAME_LOAD_STATE_MAX
+};
+
+enum NameActiveState {
+ NAME_ACTIVE,
+ NAME_ACTIVE_RELOADING,
+ NAME_INACTIVE,
+ NAME_ACTIVATING,
+ NAME_DEACTIVATING,
+ _NAME_ACTIVE_STATE_MAX
+};
+
+static inline bool NAME_IS_ACTIVE_OR_RELOADING(NameActiveState t) {
+ return t == NAME_ACTIVE || t == NAME_ACTIVE_RELOADING;
+}
+
+static inline bool NAME_IS_ACTIVE_OR_ACTIVATING(NameActiveState t) {
+ return t == NAME_ACTIVE || t == NAME_ACTIVATING || t == NAME_ACTIVE_RELOADING;
+}
+
+static inline bool NAME_IS_INACTIVE_OR_DEACTIVATING(NameActiveState t) {
+ return t == NAME_INACTIVE || t == NAME_DEACTIVATING;
+}
-typedef enum NameDependency {
+enum NameDependency {
/* Positive dependencies */
NAME_REQUIRES,
NAME_SOFT_REQUIRES,
NAME_WANTS,
NAME_REQUISITE,
NAME_SOFT_REQUISITE,
- NAME_REQUIRED_BY, /* inverse of 'requires' and 'requisite' is 'required_by' */
- NAME_WANTED_BY, /* inverse of 'wants', 'soft_requires' and 'soft_requisite' is 'wanted_by' */
+
+ /* Inverse of the above */
+ NAME_REQUIRED_BY, /* inverse of 'requires' and 'requisite' is 'required_by' */
+ NAME_SOFT_REQUIRED_BY, /* inverse of 'soft_requires' and 'soft_requisite' is 'soft_required_by' */
+ NAME_WANTED_BY, /* inverse of 'wants' */
/* Negative dependencies */
- NAME_CONFLICTS, /* inverse of 'conflicts' is 'conflicts' */
+ NAME_CONFLICTS, /* inverse of 'conflicts' is 'conflicts' */
/* Order */
- NAME_BEFORE, /* inverse of before is after and vice versa */
+ NAME_BEFORE, /* inverse of before is after and vice versa */
NAME_AFTER,
- _NAME_DEPENDENCY_MAX
-} NameDependency;
+
+ _NAME_DEPENDENCY_MAX,
+ _NAME_DEPENDENCY_INVALID = -1
+};
struct Meta {
Manager *manager;
NameType type;
- NameState state;
+ NameLoadState load_state;
+
+ char *id; /* One name is special because we use it for identification. Points to an entry in the names set */
Set *names;
Set *dependencies[_NAME_DEPENDENCY_MAX];
Job *job;
bool linked:1;
+ bool in_load_queue:1;
+
+ usec_t active_enter_timestamp;
+ usec_t active_exit_timestamp;
/* Load queue */
- LIST_FIELDS(Meta);
+ LIST_FIELDS(Meta, load_queue);
};
-typedef enum ServiceState {
- SERVICE_DEAD,
- SERVICE_BEFORE,
- SERVICE_START_PRE,
- SERVICE_START,
- SERVICE_START_POST,
- SERVICE_RUNNING,
- SERVICE_RELOAD_PRE,
- SERVICE_RELOAD,
- SERVICE_RELOAD_POST,
- SERVICE_STOP_PRE,
- SERVICE_STOP,
- SERVICE_SIGTERM,
- SERVICE_SIGKILL,
- SERVICE_STOP_POST,
- SERVICE_HOLDOFF,
- SERVICE_MAINTAINANCE
-} ServiceState;
-
-typedef enum ServiceMode {
- SERVICE_ONCE,
- SERVICE_RESTART
-} ServiceMode;
-
-struct Service {
- Meta meta;
-
- ServiceState state;
- ServiceMode mode;
-};
+#include "service.h"
+#include "timer.h"
+#include "socket.h"
+#include "target.h"
+#include "device.h"
+#include "mount.h"
+#include "automount.h"
+#include "snapshot.h"
-typedef enum TimerState {
- TIMER_DEAD,
- TIMER_BEFORE,
- TIMER_START_PRE,
- TIMER_START,
- TIMER_START_POST,
- TIMER_WAITING,
- TIMER_RUNNING,
- TIMER_STOP_PRE,
- TIMER_STOP,
- TIMER_STOP_POST,
- TIMER_MAINTAINANCE
-} TimerState;
-
-struct Timer {
- Meta meta;
-
- TimerState state;
- Service *subject;
-
- clockid_t clock_id;
- usec_t next_elapse;
-};
-
-typedef enum SocketState {
- SOCKET_DEAD,
- SOCKET_BEFORE,
- SOCKET_START_PRE,
- SOCKET_START,
- SOCKET_START_POST,
- SOCKET_LISTENING,
- SOCKET_RUNNING,
- SOCKET_STOP_PRE,
- SOCKET_STOP,
- SOCKET_STOP_POST,
- SOCKET_MAINTAINANCE
-} SocketState;
-
-struct Socket {
+union Name {
Meta meta;
-
- SocketState state;
- int *fds;
- unsigned n_fds;
-
- Service *subject;
+ Service service;
+ Timer timer;
+ Socket socket;
+ Target target;
+ Device device;
+ Mount mount;
+ Automount automount;
+ Snapshot snapshot;
};
-typedef enum MilestoneState {
- MILESTONE_DEAD,
- MILESTONE_BEFORE,
- MILESTONE_ACTIVE
-} MilestoneState;
-
-struct Milestone {
- Meta meta;
-
- MilestoneState state;
-};
+struct NameVTable {
+ const char *suffix;
-typedef enum DeviceState {
- DEVICE_DEAD,
- DEVICE_BEFORE,
- DEVICE_AVAILABLE
-} DeviceState;
+ int (*init)(Name *n);
+ void (*done)(Name *n);
-struct Device {
- Meta meta;
+ void (*dump)(Name *n, FILE *f, const char *prefix);
- DeviceState state;
- char *sysfs;
-};
+ int (*start)(Name *n);
+ int (*stop)(Name *n);
+ int (*reload)(Name *n);
-typedef enum MountState {
- MOUNT_DEAD,
- MOUNT_BEFORE,
- MOUNT_MOUNTED
-} MountState;
-struct Mount {
- Meta meta;
+ bool (*can_reload)(Name *n);
- MountState state;
- char *path;
-};
+ /* Boils down the more complex internal state of this name to
+ * a simpler one that the engine can understand */
+ NameActiveState (*active_state)(Name *n);
-typedef enum AutomountState {
- AUTOMOUNT_DEAD,
- AUTOMOUNT_BEFORE,
- AUTOMOUNT_START_PRE,
- AUTOMOUNT_START,
- AUTOMOUNT_START_POST,
- AUTOMOUNT_WAITING,
- AUTOMOUNT_RUNNING,
- AUTOMOUNT_STOP_PRE,
- AUTOMOUNT_STOP,
- AUTOMOUNT_STOP_POST,
- AUTOMOUNT_MAINTAINANCE
-} AutomountState;
-
-struct Automount {
- Meta meta;
+ void (*fd_event)(Name *n, int fd, uint32_t events);
+ void (*sigchld_event)(Name *n, pid_t pid, int code, int status);
+ void (*timer_event)(Name *n, int id, uint64_t n_elapsed);
- AutomountState state;
- char *path;
- Mount *subject;
+ void (*retry)(Name *n);
};
-typedef enum SnapshotState {
- SNAPSHOT_DEAD,
- SNAPSHOT_BEFORE,
- SNAPSHOT_ACTIVE
-} SnapshotState;
-
-struct Snapshot {
- Meta meta;
+extern const NameVTable * const name_vtable[_NAME_TYPE_MAX];
- SnapshotState state;
- bool cleanup:1;
-};
-
-union Name {
- Meta meta;
- Service service;
- Timer timer;
- Socket socket;
- Milestone milestone;
- Device device;
- Mount mount;
- Automount automount;
- Snapshot snapshot;
-};
+#define NAME_VTABLE(n) name_vtable[(n)->meta.type]
/* For casting a name into the various name types */
-
-#define DEFINE_CAST(UPPERCASE, MixedCase, lowercase) \
+#define DEFINE_CAST(UPPERCASE, MixedCase) \
static inline MixedCase* UPPERCASE(Name *name) { \
- if (name->meta.type != NAME_##UPPERCASE) \
+ if (!name || name->meta.type != NAME_##UPPERCASE) \
return NULL; \
\
- return &name->lowercase; \
+ return (MixedCase*) name; \
}
-DEFINE_CAST(SERVICE, Service, service);
-DEFINE_CAST(TIMER, Timer, timer);
-DEFINE_CAST(SOCKET, Socket, socket);
-DEFINE_CAST(MILESTONE, Milestone, milestone);
-DEFINE_CAST(DEVICE, Device, device);
-DEFINE_CAST(MOUNT, Mount, mount);
-DEFINE_CAST(AUTOMOUNT, Automount, automount);
-DEFINE_CAST(SNAPSHOT, Snapshot, snapshot);
-
/* For casting the various name types into a name */
#define NAME(o) ((Name*) (o))
-bool name_is_ready(Name *name);
+DEFINE_CAST(SOCKET, Socket);
+DEFINE_CAST(TIMER, Timer);
+DEFINE_CAST(SERVICE, Service);
+DEFINE_CAST(TARGET, Target);
+DEFINE_CAST(DEVICE, Device);
+DEFINE_CAST(MOUNT, Mount);
+DEFINE_CAST(AUTOMOUNT, Automount);
+DEFINE_CAST(SNAPSHOT, Snapshot);
+
+bool name_type_can_start(NameType t);
+bool name_type_can_reload(NameType t);
+bool name_can_reload(Name *n);
+#define name_can_start(n) name_type_can_start((n)->meta.type)
+
NameType name_type_from_string(const char *n);
bool name_is_valid(const char *n);
Name *name_new(Manager *m);
void name_free(Name *name);
int name_link(Name *name);
+int name_link_names(Name *name, bool replace);
int name_merge(Name *name, Name *other);
-int name_augment(Name *n);
+int name_sanitize(Name *n);
+int name_load_fragment_and_dropin(Name *n);
+int name_load(Name *name);
+const char* name_id(Name *n);
+const char *name_description(Name *n);
+
+int name_add_name(Name *n, const char *text);
+
+NameActiveState name_active_state(Name *name);
+
+void name_dump(Name *n, FILE *f, const char *prefix);
+
+int name_start(Name *n);
+int name_stop(Name *n);
+int name_reload(Name *n);
+
+void name_notify(Name *n, NameActiveState os, NameActiveState ns);
+
+int name_watch_fd(Name *n, int fd, uint32_t events);
+void name_unwatch_fd(Name *n, int fd);
+
+int name_watch_pid(Name *n, pid_t pid);
+void name_unwatch_pid(Name *n, pid_t pid);
+
+int name_watch_timer(Name *n, usec_t delay, int *id);
+void name_unwatch_timer(Name *n, int *id);
+
+char *name_change_suffix(const char *t, const char *suffix);
+
+bool name_job_is_applicable(Name *n, JobType j);
+
+int name_add_dependency(Name *n, NameDependency d, Name *other);
#endif