Changeset 8ae8262 in mainline


Ignore:
Timestamp:
2019-08-07T11:08:17Z (5 years ago)
Author:
Matthieu Riolo <matthieu.riolo@…>
Children:
130ba46
Parents:
5353f50
git-author:
Michal Koutný <xm.koutny+hos@…> (2015-11-12 02:56:35)
git-committer:
Matthieu Riolo <matthieu.riolo@…> (2019-08-07 11:08:17)
Message:

sysman: Support for anonymous services

  • Daemons that only call task_retval and don't exit are recorded as anonymous services.
  • Split unit run-state and repository state.
  • Partial support for removal of units from repository (needs refcounting yet).
Location:
uspace
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/include/ipc/sysman.h

    r5353f50 r8ae8262  
    6969
    7070typedef enum {
    71         STATE_EMBRYO = 0, // embryo is orthogonal to states (again convergence to systemd...)
    7271        STATE_STARTING,
    7372        STATE_STARTED,
  • uspace/srv/sysman/repo.c

    r5353f50 r8ae8262  
    7474        .equal           = &units_by_handle_ht_equal,
    7575        .key_equal       = &units_by_handle_ht_key_equal,
    76         .remove_callback = NULL // TODO realy unneeded?
     76        .remove_callback = NULL
    7777};
    7878
     
    108108        .equal           = &units_by_name_ht_equal,
    109109        .key_equal       = &units_by_name_ht_key_equal,
    110         .remove_callback = NULL // TODO realy unneeded?
     110        .remove_callback = NULL
    111111};
    112112
    113113/* Repository functions */
     114
     115static void repo_remove_unit_internal(unit_t *u)
     116{
     117        hash_table_remove_item(&units_by_name, &u->units_by_name);
     118        hash_table_remove_item(&units_by_handle, &u->units_by_handle);
     119        list_remove(&u->units);
     120
     121        // TODO decrease refcount of unit
     122        // unit may be referenced e.g. from running job, thus we cannot simply destroy it
     123}
    114124
    115125void repo_init(void)
     
    122132{
    123133        assert(unit);
    124         assert(unit->state == STATE_EMBRYO);
     134        assert(unit->repo_state == REPO_EMBRYO);
    125135        assert(unit->handle == 0);
    126136        assert(unit->name != NULL);
     
    139149}
    140150
     151int repo_remove_unit(unit_t *unit)
     152{
     153        unit->repo_state = REPO_ZOMBIE;
     154        return EOK; /* We could check that unit is present in repo etc... */
     155}
     156
    141157void repo_begin_update(void) {
    142158        sysman_log(LVL_DEBUG2, "%s", __func__);
     
    146162{
    147163        unit_t *unit = hash_table_get_inst(ht_link, unit_t, units_by_name);
    148         if (unit->state == STATE_EMBRYO) {
    149                 unit->state = STATE_STOPPED;
     164        if (unit->repo_state == REPO_ZOMBIE) {
     165                repo_remove_unit_internal(unit);
     166                return true;
     167        }
     168
     169        if (unit->repo_state == REPO_EMBRYO) {
     170                unit->repo_state = REPO_LIVING;
    150171        }
    151172
     
    162183
    163184        /*
    164          * Apply commit to all units_by_name, each commited unit commits its outgoing
    165          * deps, thus eventually commiting all embryo deps as well.
     185         * Apply commit to all units_by_name, each commited unit commits its
     186         * outgoing deps, thus eventually commiting all embryo deps as well.
     187         *
     188         * TODO why not iterate over units list?
    166189         */
    167190        hash_table_apply(&units_by_name, &repo_commit_unit, NULL);
     
    180203        }
    181204
    182         if (unit->state == STATE_EMBRYO) {
    183                 hash_table_remove_item(&units_by_name, ht_link);
    184                 list_remove(&unit->units);
    185                 unit_destroy(&unit);
     205        if (unit->repo_state == REPO_EMBRYO) {
     206                repo_remove_unit_internal(unit);
     207        } else if (unit->repo_state == REPO_ZOMBIE) {
     208                unit->repo_state = REPO_LIVING;
    186209        }
    187210
  • uspace/srv/sysman/repo.h

    r5353f50 r8ae8262  
    3232#include <adt/list.h>
    3333#include <ipc/sysman.h>
     34#include <stdio.h>
    3435
    3536#include "unit.h"
     37
     38#define ANONYMOUS_SERVICE_MASK "service_%" PRIu64
    3639
    3740extern list_t units;
     
    4043
    4144extern int repo_add_unit(unit_t *);
     45extern int repo_remove_unit(unit_t *);
    4246
    4347extern void repo_begin_update(void);
  • uspace/srv/sysman/sm_task.c

    r5353f50 r8ae8262  
    2828
    2929#include <adt/list.h>
     30#include <errno.h>
    3031#include <stdlib.h>
    3132#include <task.h>
     33#include <sysman/unit.h>
    3234
    3335#include "repo.h"
     
    3537#include "sysman.h"
    3638#include "sm_task.h"
     39
    3740
    3841/** Structure for boxing task event */
     
    8588}
    8689
     90static unit_svc_t *sm_task_create_service(task_id_t tid)
     91{
     92        unit_t *u_svc = unit_create(UNIT_SERVICE);
     93        bool in_repo_update = false;
     94        int rc = EOK;
     95
     96        if (u_svc == NULL) {
     97                goto fail;
     98        }
     99
     100        rc = asprintf(&u_svc->name, ANONYMOUS_SERVICE_MASK "%c%s", tid,
     101            UNIT_NAME_SEPARATOR, UNIT_SVC_TYPE_NAME);
     102        if (rc < 0) {
     103                goto fail;
     104        }
     105
     106        CAST_SVC(u_svc)->main_task_id = tid;
     107        CAST_SVC(u_svc)->anonymous = true;
     108        /* exec_start is left undefined, maybe could be hinted by kernel's task
     109         * name */
     110
     111        repo_begin_update();
     112        in_repo_update = true;
     113
     114        rc = repo_add_unit(u_svc);
     115        if (rc != EOK) {
     116                goto fail;
     117        }
     118
     119        repo_commit();
     120
     121        return CAST_SVC(u_svc);
     122       
     123fail:
     124        if (in_repo_update) {
     125                repo_rollback();
     126        }
     127
     128        unit_destroy(&u_svc);
     129        return NULL;
     130}
     131
     132static void sm_task_delete_service(unit_svc_t *u_svc)
     133{
     134        repo_begin_update();
     135        int rc = repo_remove_unit(&u_svc->unit);
     136        if (rc != EOK) {
     137                sysman_log(LVL_WARN, "Can't remove unit %s (%i).",
     138                    unit_name(&u_svc->unit), rc);
     139                repo_rollback();
     140                return;
     141        }
     142
     143        repo_commit();
     144}
     145
    87146static void sysman_event_task_event(void *data)
    88147{
     
    92151            __func__, tev->task_id, tev->flags);
    93152        unit_svc_t *u_svc = sm_task_find_service(tev->task_id);
     153
    94154        if (u_svc == NULL) {
    95                 goto finish;
     155                if (tev->flags & TASK_WAIT_EXIT) {
     156                        /* Non-service task exited, ignore. */
     157                        goto finish;
     158                }
     159
     160                u_svc = sm_task_create_service(tev->task_id);
     161                if (u_svc == NULL) {
     162                        sysman_log(LVL_WARN,
     163                            "Unable to create anonymous service for task %" PRIu64 ".",
     164                            tev->task_id);
     165                        goto finish;
     166                }
     167
     168                sysman_log(LVL_DEBUG, "Created anonymous service %s.",
     169                    unit_name(&u_svc->unit));
     170
     171                /* Inject state so that further processing makes sense */
     172                u_svc->unit.state = STATE_STARTING;
    96173        }
    97174
     
    111188                        u->state = STATE_FAILED;
    112189                }
     190
    113191        }
    114192        if (tev->flags & TASK_WAIT_RETVAL) {
     
    119197        unit_notify_state(u);
    120198
     199        if ((tev->flags & TASK_WAIT_EXIT) && u_svc->anonymous) {
     200                sysman_log(LVL_DEBUG, "Deleted anonymous service %s.",
     201                    unit_name(&u_svc->unit));
     202                sm_task_delete_service(u_svc);
     203        }
    121204finish:
    122205        free(tev);
  • uspace/srv/sysman/unit.c

    r5353f50 r8ae8262  
    6868       
    6969        unit->type = type;
    70         unit->state = STATE_EMBRYO;
     70        unit->state = STATE_STOPPED;
     71        unit->repo_state = REPO_EMBRYO;
    7172
    7273        link_initialize(&unit->units);
  • uspace/srv/sysman/unit.h

    r5353f50 r8ae8262  
    4848struct job;
    4949
     50/* Represents presence of unit in repo during modifications */
     51typedef enum {
     52        REPO_EMBRYO,
     53        REPO_LIVING,
     54        REPO_ZOMBIE
     55} repo_state_t;
     56
    5057typedef struct {
    5158        /** Link to name-to-unit hash table */
     
    8087
    8188        unit_state_t state;
     89
     90        repo_state_t repo_state;
    8291
    8392        list_t edges_in;
  • uspace/srv/sysman/units/unit_cfg.c

    r5353f50 r8ae8262  
    177177                }
    178178
    179                 assert(unit->state == STATE_EMBRYO);
     179                assert(unit->repo_state == REPO_EMBRYO);
    180180                repo_add_unit(unit);
    181181        }
  • uspace/srv/sysman/units/unit_svc.h

    r5353f50 r8ae8262  
    4141
    4242        task_id_t main_task_id;
     43
     44        bool anonymous;
    4345} unit_svc_t;
    4446
Note: See TracChangeset for help on using the changeset viewer.