
This allows to reuse same step functions giving them different parameters on each step. Additionally move pipeline to utils, to make it accessible to other subsystems of OCF (e.g. metadata). Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
127 lines
2.7 KiB
C
127 lines
2.7 KiB
C
#include "ocf/ocf.h"
|
|
#include "../engine/cache_engine.h"
|
|
#include "../engine/engine_common.h"
|
|
#include "utils_pipeline.h"
|
|
#include "utils_req.h"
|
|
|
|
struct ocf_pipeline {
|
|
struct ocf_pipeline_properties *properties;
|
|
struct ocf_request *req;
|
|
int next_step;
|
|
int next_arg;
|
|
bool finish;
|
|
int error;
|
|
|
|
void *priv;
|
|
};
|
|
|
|
static int _ocf_pipeline_run_step(struct ocf_request *req)
|
|
{
|
|
ocf_pipeline_t pipeline = req->priv;
|
|
struct ocf_pipeline_step *step;
|
|
ocf_pipeline_arg_t arg;
|
|
|
|
if (pipeline->finish) {
|
|
pipeline->properties->finish(pipeline, pipeline->priv,
|
|
pipeline->error);
|
|
return 0;
|
|
}
|
|
|
|
while (true) {
|
|
step = &pipeline->properties->steps[pipeline->next_step];
|
|
switch (step->type) {
|
|
case ocf_pipeline_step_single:
|
|
pipeline->next_step++;
|
|
step->hndl(pipeline, pipeline->priv, &step->arg);
|
|
return 0;
|
|
case ocf_pipeline_step_foreach:
|
|
arg = &step->args[pipeline->next_arg++];
|
|
if (arg->type == ocf_pipeline_arg_terminator) {
|
|
pipeline->next_arg = 0;
|
|
pipeline->next_step++;
|
|
continue;
|
|
}
|
|
step->hndl(pipeline, pipeline->priv, arg);
|
|
return 0;
|
|
case ocf_pipeline_step_terminator:
|
|
pipeline->properties->finish(pipeline, pipeline->priv,
|
|
pipeline->error);
|
|
return 0;
|
|
default:
|
|
ENV_BUG();
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct ocf_io_if _io_if_pipeline = {
|
|
.read = _ocf_pipeline_run_step,
|
|
.write = _ocf_pipeline_run_step,
|
|
};
|
|
|
|
int ocf_pipeline_create(ocf_pipeline_t *pipeline, ocf_cache_t cache,
|
|
struct ocf_pipeline_properties *properties)
|
|
{
|
|
ocf_pipeline_t tmp_pipeline;
|
|
struct ocf_request *req;
|
|
|
|
tmp_pipeline = env_vzalloc(sizeof(*tmp_pipeline) +
|
|
properties->priv_size);
|
|
if (!tmp_pipeline)
|
|
return -OCF_ERR_NO_MEM;
|
|
|
|
if (properties->priv_size > 0) {
|
|
tmp_pipeline->priv = (void *)tmp_pipeline +
|
|
sizeof(*tmp_pipeline);
|
|
}
|
|
|
|
req = ocf_req_new(cache->mngt_queue, NULL, 0, 0, 0);
|
|
if (!req) {
|
|
env_vfree(tmp_pipeline);
|
|
return -OCF_ERR_NO_MEM;
|
|
}
|
|
|
|
tmp_pipeline->properties = properties;
|
|
tmp_pipeline->req = req;
|
|
tmp_pipeline->next_step = 0;
|
|
tmp_pipeline->finish = false;
|
|
tmp_pipeline->error = 0;
|
|
|
|
req->info.internal = true;
|
|
req->io_if = &_io_if_pipeline;
|
|
req->priv = tmp_pipeline;
|
|
|
|
*pipeline = tmp_pipeline;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ocf_pipeline_destroy(ocf_pipeline_t pipeline)
|
|
{
|
|
ocf_req_put(pipeline->req);
|
|
env_vfree(pipeline);
|
|
}
|
|
|
|
void ocf_pipeline_set_priv(ocf_pipeline_t pipeline, void *priv)
|
|
{
|
|
pipeline->priv = priv;
|
|
}
|
|
|
|
void *ocf_pipeline_get_priv(ocf_pipeline_t pipeline)
|
|
{
|
|
return pipeline->priv;
|
|
}
|
|
|
|
void ocf_pipeline_next(ocf_pipeline_t pipeline)
|
|
{
|
|
ocf_engine_push_req_front(pipeline->req, true);
|
|
}
|
|
|
|
void ocf_pipeline_finish(ocf_pipeline_t pipeline, int error)
|
|
{
|
|
pipeline->finish = true;
|
|
pipeline->error = error;
|
|
ocf_engine_push_req_front(pipeline->req, true);
|
|
}
|