Changeset be07995 in mainline for uspace/srv/sysman/job_closure.c


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.)

File:
1 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__,
Note: See TracChangeset for help on using the changeset viewer.