Changeset be07995 in mainline


Ignore:
Timestamp:
2019-08-17T13:54:09Z (5 years ago)
Author:
Matthieu Riolo <matthieu.riolo@…>
Children:
8d74fdd
Parents:
015b147
git-author:
Michal Koutný <xm.koutny+hos@…> (2016-01-10 23:36:33)
git-committer:
Matthieu Riolo <matthieu.riolo@…> (2019-08-17 13:54:09)
Message:

sysman: Add support for closure creation with CLOSURE_ISOLATE flag

Now can create closures, that contain start jobs for all transitively dependent
jobs and stop for all others. (Next step: enqueue and execute.)

Location:
uspace/srv/sysman
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/sysman/job_closure.c

    r015b147 rbe07995  
    8282/** During visit creates job and appends it to closure
    8383 *
    84  * @note Assumes BFS start unit's job is already present in closure!
     84 * @note Assumes BFS origin unit's job is already present in the closure on the
     85 *       last position!
    8586 *
    8687 * @return EOK on success
     
    9495
    9596        if (e == NULL) {
    96                 assert(u->bfs_data == NULL);
     97                if (u->bfs_data != NULL) {
     98                        goto finish;
     99                }
    97100                job_t *first_job = dyn_array_last(closure, job_t *);
    98101
     
    133136                job_del_ref(&created_job);
    134137        }
     138        return rc;
     139}
     140
     141static int visit_isolate(unit_t *u, unit_edge_t *e, bfs_ops_t *ops, void *arg)
     142{
     143        int rc = EOK;
     144        job_t *created_job = NULL;
     145        job_closure_t *closure = arg;
     146
     147        sysman_log(LVL_DEBUG2, "%s(%s)", __func__, unit_name(u));
     148        /*
     149         * Unit can have starting job from original request or from isolation
     150         * BFS with different origin.
     151         *
     152         * Don't check u->state == STATE_STOPPED, closure is created stateless
     153         * and its upon merging procedure to correctly resolve conflicting
     154         * jobs.
     155         *
     156         * If we're at the origin (no BFS incoming edge), create a stop job,
     157         * put it to the closure and let propagate as if called the propagate
     158         * visitor.
     159         */
     160        if (e == NULL && u->bfs_data == NULL) {
     161                created_job = job_create(u, STATE_STOPPED);
     162                if (created_job == NULL) {
     163                        rc = ENOMEM;
     164                        goto finish;
     165                }
     166
     167                /* Pass job reference to closure and add one for unit */
     168                rc = dyn_array_append(closure, job_t *, created_job);
     169                if (rc != EOK) {
     170                        goto finish;
     171                }
     172        }
     173        rc = visit_propagate_job(u, e, ops, closure);
     174
     175finish:
     176        if (rc != EOK) {
     177                job_del_ref(&created_job);
     178        }
     179        sysman_log(LVL_DEBUG2, "%s(%s) -> %i", __func__, unit_name(u), rc);
    135180        return rc;
    136181}
     
    217262}
    218263
    219 // TODO bfs_traverse_all
    220 
     264static int bfs_traverse_all(bfs_ops_t *ops, void *arg)
     265{
     266        /* Check invariant */
     267        repo_foreach(u) {
     268                assert(u->bfs_tag == false);
     269        }
     270        int rc = EOK;
     271
     272        repo_foreach(origin) {
     273                sysman_log(LVL_DEBUG2, "%s: %p, %i", __func__, origin, origin->bfs_tag);
     274                if (origin->bfs_tag == true) {
     275                        continue;
     276                }
     277                rc = bfs_traverse_component_internal(origin, ops, arg);
     278                if (rc != EOK) {
     279                        goto finish;
     280                }
     281        }
     282
     283finish:
     284        /* Clean after ourselves (BFS tag jobs) */
     285        repo_foreach(u) {
     286                u->bfs_tag = false;
     287        }
     288        return rc;
     289}
    221290
    222291/*
     
    230299 * @return EOK on success otherwise propagated error
    231300 */
    232 int job_create_closure(job_t *main_job, job_closure_t *job_closure)
     301int job_create_closure(job_t *main_job, job_closure_t *job_closure, int flags)
    233302{
    234303        sysman_log(LVL_DEBUG2, "%s(%s)", __func__, unit_name(main_job->unit));
    235304
    236         static bfs_ops_t ops = {
     305        if ((flags & CLOSURE_ISOLATE) && main_job->target_state != STATE_STARTED) {
     306                // TODO EINVAL?
     307                return ENOTSUP;
     308        }
     309
     310        int rc = dyn_array_append(job_closure, job_t *, main_job);
     311        if (rc != EOK) {
     312                return rc;
     313        }
     314        job_add_ref(main_job); /* Add one for the closure */
     315
     316        /* Propagate main_job to other (dependent) units */
     317        static bfs_ops_t propagate_ops = {
    237318                .clean = traverse_clean,
    238319                .visit = visit_propagate_job
    239320        };
    240 
    241321        switch (main_job->target_state) {
    242322        case STATE_STARTED:
    243                 ops.direction = BFS_FORWARD;
     323                propagate_ops.direction = BFS_FORWARD;
    244324                break;
    245325        case STATE_STOPPED:
    246                 ops.direction = BFS_BACKWARD;
     326                propagate_ops.direction = BFS_BACKWARD;
    247327                break;
    248328        default:
     
    250330        }
    251331
    252         int rc = dyn_array_append(job_closure, job_t *, main_job);
    253         if (rc != EOK) {
    254                 return rc;
    255         }
    256         job_add_ref(main_job); /* Add one for the closure */
    257 
    258         rc = bfs_traverse_component(main_job->unit, &ops, job_closure);
     332        rc = bfs_traverse_component(main_job->unit, &propagate_ops, job_closure);
     333
     334        sysman_log(LVL_DEBUG2, "%s: %i&%i", __func__, flags, CLOSURE_ISOLATE);
     335        if (flags & CLOSURE_ISOLATE) {
     336                static bfs_ops_t isolate_ops = {
     337                        .direction = BFS_BACKWARD,
     338                        .clean = traverse_clean,
     339                        .visit = visit_isolate
     340                };
     341                rc = bfs_traverse_all(&isolate_ops, job_closure);
     342        }
    259343
    260344        if (rc == EOK) {
    261                 sysman_log(LVL_DEBUG2, "%s(%s):", __func__, unit_name(main_job->unit));
    262345                dyn_array_foreach(*job_closure, job_t *, job_it) {
    263346                        sysman_log(LVL_DEBUG2, "%s\t%s, refs: %u", __func__,
  • uspace/srv/sysman/job_closure.h

    r015b147 rbe07995  
    3333
    3434#include "job.h"
    35 #include "unit.h"
     35
     36#define CLOSURE_ISOLATE 0x1
    3637
    3738typedef dyn_array_t job_closure_t;
    3839
    39 extern int job_create_closure(job_t *, job_closure_t *);
     40extern int job_create_closure(job_t *, job_closure_t *, int);
    4041
    4142#endif
  • uspace/srv/sysman/repo.c

    r015b147 rbe07995  
    176176}
    177177
    178 void repo_begin_update_(void) {
     178void repo_begin_update(void) {
    179179        sysman_log(LVL_DEBUG2, "%s", __func__);
    180180        fibril_rwlock_write_lock(&repo_lock);
     
    293293 * The function can be safely called from non-event loop fibrils
    294294 */
    295 unit_t *repo_find_unit_by_name_(const char *name)
     295unit_t *repo_find_unit_by_name(const char *name)
    296296{
    297297        return repo_find_unit_by_name_internal(name, true);
  • uspace/srv/sysman/sysman.c

    r015b147 rbe07995  
    373373        free(job_args);
    374374
    375         int rc = job_create_closure(job, &job_closure);
     375        int rc = job_create_closure(job, &job_closure, 0);
    376376        if (rc != EOK) {
    377377                sysman_log(LVL_ERROR, "Cannot create closure for job %p (%i)",
  • uspace/srv/sysman/test/job_closure.c

    r015b147 rbe07995  
    3232
    3333#include "../job_closure.h"
     34#include "../repo.h"
    3435
    3536#include "mock_unit.h"
     
    5051{
    5152        if (expected->size != actual->size) {
    52                 printf("%s: |expected| - |actual| = %u\n",
    53                     __func__, expected->size - actual->size);
     53                printf("%s: |expected|, |actual| = %u, %u\n",
     54                    __func__, expected->size, actual->size);
    5455                return false;
    5556        }
     
    119120        rc = dyn_array_reserve(&act_closure, MAX_TYPES * MAX_UNITS);
    120121        assert(rc == EOK);
     122
     123        repo_init();
    121124}
    122125
     
    148151        assert(main_job);
    149152
    150         int rc = job_create_closure(main_job, &act_closure);
     153        int rc = job_create_closure(main_job, &act_closure, 0);
    151154        PCUT_ASSERT_INT_EQUALS(EOK, rc);
    152155
     
    179182        assert(main_job);
    180183
    181         int rc = job_create_closure(main_job, &act_closure);
     184        int rc = job_create_closure(main_job, &act_closure, 0);
    182185        PCUT_ASSERT_INT_EQUALS(EOK, rc);
    183186
     
    212215        assert(main_job);
    213216
    214         int rc = job_create_closure(main_job, &act_closure);
     217        int rc = job_create_closure(main_job, &act_closure, 0);
    215218        PCUT_ASSERT_INT_EQUALS(EOK, rc);
    216219
     
    227230}
    228231
     232PCUT_TEST(job_closure_isolate_linears) {
     233        unit_t *u0 = mock_units[UNIT_SERVICE][0];
     234        unit_t *u1 = mock_units[UNIT_SERVICE][1];
     235        unit_t *u2 = mock_units[UNIT_SERVICE][2];
     236        unit_t *u3 = mock_units[UNIT_SERVICE][3];
     237        unit_t *u4 = mock_units[UNIT_SERVICE][4];
     238        unit_t *u5 = mock_units[UNIT_SERVICE][5];
     239        unit_t *u6 = mock_units[UNIT_SERVICE][6];
     240        repo_begin_update();
     241        for (int i = 0; i < 7; ++i) {
     242                repo_add_unit(mock_units[UNIT_SERVICE][i]);
     243        }
     244        repo_commit();
     245
     246        /*
     247         *
     248         * u0 -> u1 -> u2
     249         *
     250         * u3 -> u4 -> u5
     251         *
     252         * u6
     253         */
     254        mock_add_edge(u0, u1);
     255        mock_add_edge(u1, u2);
     256
     257        mock_add_edge(u3, u4);
     258        mock_add_edge(u4, u5);
     259
     260        job_t *main_job = job_create(u1, STATE_STARTED);
     261        assert(main_job);
     262
     263        int rc = job_create_closure(main_job, &act_closure, CLOSURE_ISOLATE);
     264        PCUT_ASSERT_INT_EQUALS(EOK, rc);
     265
     266        dyn_array_append(&exp_closure, job_t *, dummy_job(u0, STATE_STOPPED));
     267        dyn_array_append(&exp_closure, job_t *, dummy_job(u1, STATE_STARTED));
     268        dyn_array_append(&exp_closure, job_t *, dummy_job(u2, STATE_STARTED));
     269        dyn_array_append(&exp_closure, job_t *, dummy_job(u3, STATE_STOPPED));
     270        dyn_array_append(&exp_closure, job_t *, dummy_job(u4, STATE_STOPPED));
     271        dyn_array_append(&exp_closure, job_t *, dummy_job(u5, STATE_STOPPED));
     272        dyn_array_append(&exp_closure, job_t *, dummy_job(u6, STATE_STOPPED));
     273
     274        dummy_add_closure(&act_closure);
     275
     276        PCUT_ASSERT_TRUE(same_jobs(&exp_closure, &act_closure));
     277        PCUT_ASSERT_TRUE(job_blocked(u1->job, u2->job));
     278
     279        PCUT_ASSERT_TRUE(job_blocked(u5->job, u4->job));
     280        PCUT_ASSERT_TRUE(job_blocked(u4->job, u3->job));
     281
     282        PCUT_ASSERT_INT_EQUALS(0, u6->job->blocking_jobs);
     283        PCUT_ASSERT_INT_EQUALS(0, u0->job->blocking_jobs);
     284}
    229285
    230286PCUT_EXPORT(job_closure);
  • uspace/srv/sysman/test/mock_unit.h

    r015b147 rbe07995  
    3636#include "../unit.h"
    3737
    38 #define MAX_UNITS 5
     38#define MAX_UNITS 7
    3939#define MAX_TYPES 4
    4040
Note: See TracChangeset for help on using the changeset viewer.