WIP: working on conditions

This commit is contained in:
Adrien Bourmault 2024-03-21 03:05:04 +02:00
parent 575612a77d
commit e9ba5643bb
Signed by: neox
GPG Key ID: 95F65F55F682A17A
7 changed files with 512 additions and 138 deletions

View File

@ -118,7 +118,8 @@ run: build_system
debug: build_system
@echo -e ${CL2}[$@] ${CL}executing...${CL3}
@gdb $(BINDIR)/gem-graph-server
@gdb --args $(BINDIR)/gem-graph-server -C data/config -M data/models \
-U data/users
@echo -e ${CL2}[$@] ${CL}done.${CL3}
valgrind: build_system

View File

@ -36,4 +36,29 @@ struct arrow_t {
uint x;
uint y;
uint z;
struct arrow_t *next;
struct arrow_t *prev;
};
struct condition_t {
uint id;
uint load;
uint site;
uint x;
uint y;
uint z;
struct condition_t *child;
struct condition_t *parent;
};
/* -------------------------------------------------------------------------- */
struct arrow_t *arrow_new(struct arrow_t *self);
struct arrow_t *arrow_destroy(struct arrow_t *self);
struct condition_t *condition_new(struct condition_t *self);
struct condition_t *condition_destroy(struct condition_t *self);

View File

@ -81,6 +81,7 @@ struct state_t
time_t date;
struct space_t *space;
struct arrow_t *arrows;
};
struct model_t
@ -115,6 +116,9 @@ struct model_t
// Handler to the current space of the model
struct space_t *space;
// Handler to the conditions
struct condition_t *conditions;
// Handler to the arrows
struct arrow_t *arrows;
size_t n_arrows;
@ -122,13 +126,9 @@ struct model_t
// Handler to the saved states array
struct state_t *states;
size_t n_states;
};
struct model_array_t
{
struct model_t *models;
size_t size;
struct model_t *next;
struct model_t *prev;
};
// -------------------------------------------------------------------------- //
@ -139,7 +139,7 @@ void model_system_init (struct parameters_t *parameters);
// -------------------------------------------------------------------------- //
// Model stopping function //
// -------------------------------------------------------------------------- //
// void model_system_shutdown (void);
void model_system_shutdown (void);
// -------------------------------------------------------------------------- //
// Load a model ready to execute //

View File

@ -25,3 +25,67 @@
/* -------------------------------------------------------------------------- */
struct arrow_t *arrow_new(struct arrow_t *self)
{
if (self == NULL) {
return calloc (1, sizeof(struct arrow_t));
}
self->next = calloc (1, sizeof(struct arrow_t));
self->next->prev = self;
return self->next;
}
struct arrow_t *arrow_destroy(struct arrow_t *self)
{
struct arrow_t *res = NULL;
if (self->next)
if (self->prev) {
self->prev->next = self->next;
} else {
res = self->next;
self->next->prev = NULL;
}
if (self->prev)
if (self->next) {
self->next->prev = self->prev;
} else {
res = self->prev;
self->prev->next = NULL;
}
free(self);
return res;
}
struct condition_t *condition_new(struct condition_t *self)
{
if (self == NULL) {
return calloc (1, sizeof(struct condition_t));
}
self->child = calloc (1, sizeof(struct condition_t));
self->child->parent = self;
return self->child;
}
struct condition_t *condition_destroy(struct condition_t *self)
{
struct condition_t *res = NULL;
if (self->child) {
condition_destroy(self->child);
}
if (self->parent)
self->parent->child = NULL;
free(self);
return res;
}

View File

@ -137,6 +137,8 @@ int main(int argc, char **argv)
returnValue = sched_start (&scheduler, &parameters);
}
model_system_shutdown();
free(parameters.userDir);
free(parameters.modelDir);
free(parameters.configDir);

View File

@ -24,6 +24,7 @@
#include "../include/model.h"
#include "../include/arrows.h"
#define ALLOWED_RADIUS 10
#define READ_SITE 1 << 0
#define READ_WEIGHT 1 << 1
#define READ_X 1 << 2
@ -35,70 +36,11 @@
/* -------------------------------------------------------------------------- */
struct model_array_t *knownModels;
struct model_t *knownModels = NULL;
/* -------------------------------------------------------------------------- */
static bool model_init(struct model_t *self)
{
xmlNode *node;
/*
* this initialize the library and check potential ABI mismatches
* between the version it was compiled for and the actual shared
* library used.
*/
LIBXML_TEST_VERSION
self->doc = xmlReadFile(self->filename, NULL, 0);
if (self->doc == NULL ) {
printerr("Error trying to open the XML model !\n");
return false;
}
node = xmlDocGetRootElement(self->doc);
if (node == NULL) {
printerr("Empty XML model !\n");
xmlFreeDoc(self->doc);
return false;
}
if (xmlStrcmp(node->name, (xmlChar *) "gem-graph-model")) {
printerr("document of the wrong type, root node != gem-graph-model\n");
xmlFreeDoc(self->doc);
return false;
}
self->hashtable = xmlHashCreate(0);
if (self->hashtable == NULL) {
printerr("Can't create model hash table !\n");
xmlFreeDoc(self->doc);
return false;
}
return true;
}
static bool model_shutdown(struct model_t *self)
{
xmlFreeDoc(self->doc);
xmlHashFree(self->hashtable, NULL);
// Cleanup function for the XML library
xmlCleanupParser();
// This is to debug memory for regression tests
xmlMemoryDump();
return true;
}
/* -------------------------------------------------------------------------- */
static inline xmlNodePtr getNextChild(xmlNodePtr node, xmlChar *last)
static inline xmlNodePtr getNextChild (xmlNodePtr node, xmlChar *last)
{
while (node != NULL && xmlStrcmp(node->name, last)) {
// //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name);
@ -107,14 +49,14 @@ static inline xmlNodePtr getNextChild(xmlNodePtr node, xmlChar *last)
return node;
}
static inline xmlChar* splitStrAtSlash(xmlChar *toSplit)
static inline xmlChar* splitStrAtSlash (xmlChar *toSplit)
{
toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit));
return toSplit;
}
static inline xmlChar* getFirstTag(xmlChar *path)
static inline xmlChar* getFirstTag (xmlChar *path)
{
xmlChar *preop = path;
path = (xmlChar *)xmlStrchr(path, '/');
@ -123,10 +65,10 @@ static inline xmlChar* getFirstTag(xmlChar *path)
return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1);
}
static inline xmlChar* getLastTag(xmlChar *path)
static inline xmlChar* getLastTag (xmlChar *path)
{
while ((ulong)xmlStrchr (path, '/'))
path = splitStrAtSlash((xmlChar *)path);
path = splitStrAtSlash ((xmlChar *)path);
// //printf("last tag in the path = <%s>\n", path);
return path; // which is no more the given path but only its last tag !
@ -134,7 +76,7 @@ static inline xmlChar* getLastTag(xmlChar *path)
/* -------------------------------------------------------------------------- */
static xmlNodePtr model_get_node(struct model_t *self, xmlChar *path)
static xmlNodePtr model_get_node (struct model_t *self, xmlChar *path)
{
xmlNodePtr node;
xmlChar *extrait;
@ -179,7 +121,7 @@ static xmlNodePtr model_get_node(struct model_t *self, xmlChar *path)
/* -------------------------------------------------------------------------- */
static inline long model_get_node_long_attrib(xmlNodePtr node, char *id)
static inline long model_get_node_long_attrib (xmlNodePtr node, char *id)
{
xmlAttr *attribute;
xmlChar* value;
@ -200,7 +142,7 @@ static inline long model_get_node_long_attrib(xmlNodePtr node, char *id)
return 0;
}
static inline bool model_get_node_str_attrib(xmlNodePtr node,
static inline bool model_get_node_str_attrib (xmlNodePtr node,
char *id,
char *dest)
{
@ -224,7 +166,7 @@ static inline bool model_get_node_str_attrib(xmlNodePtr node,
/* -------------------------------------------------------------------------- */
char model_get_dim(struct model_t *self)
char model_get_dim (struct model_t *self)
{
xmlAttr *attribute;
xmlChar* value;
@ -237,7 +179,7 @@ char model_get_dim(struct model_t *self)
return 0;
}
long model_get_dim_value(struct model_t *self, const char *axis)
long model_get_dim_value (struct model_t *self, const char *axis)
{
xmlAttr *attribute;
xmlChar *value;
@ -248,7 +190,7 @@ long model_get_dim_value(struct model_t *self, const char *axis)
return model_get_node_long_attrib(node, axis);
}
char model_get_multiplicity(struct model_t *self)
char model_get_multiplicity (struct model_t *self)
{
xmlAttr *attribute;
xmlChar* value;
@ -262,7 +204,7 @@ char model_get_multiplicity(struct model_t *self)
return 0;
}
bool model_get_next_state(struct model_t *self, char *new_state_id)
bool model_get_next_state (struct model_t *self, char *new_state_id)
{
static xmlNodePtr cur_node = NULL;
xmlAttr *attribute;
@ -288,7 +230,7 @@ bool model_get_next_state(struct model_t *self, char *new_state_id)
return false;
}
long model_get_state_arrows_count(struct model_t *self, const char *state_id)
long model_get_state_arrows_count (struct model_t *self, const char *state_id)
{
xmlNodePtr cur_node = NULL;
xmlAttr *attribute;
@ -339,7 +281,7 @@ long model_get_state_arrows_count(struct model_t *self, const char *state_id)
return value;
}
bool model_get_next_arrow(struct model_t *self,
bool model_get_next_arrow (struct model_t *self,
struct arrow_t *new_arrow,
const char *state_id,
char dimension)
@ -473,11 +415,232 @@ bool model_get_next_arrow(struct model_t *self,
return false;
}
bool model_get_next_conditions (struct model_t *self, char *new_cond_id)
{
static xmlNodePtr cur_node = NULL;
xmlAttr *attribute;
xmlChar *value;
if (cur_node == NULL) {
// Get first state
cur_node = model_get_node(self, (xmlChar *)"conditions");
} else {
// Get next state
if (cur_node->next)
cur_node = cur_node->next;
else
return false;
}
// Lookup in properties
if (model_get_node_str_attrib(cur_node, "id", new_cond_id))
return true;
cur_node = NULL;
return false;
}
bool model_get_next_condition (struct model_t *self,
struct condition_t *new_condition,
const char *cond_id,
char dimension)
{
static xmlNodePtr cur_node = NULL;
xmlAttr *attribute;
xmlChar *value;
bool found = false;
char temp_char[25];
uint check = 0; // bit field checker
//printf("NEW CALL : cur_node = %p\n", cur_node);
assert(new_condition);
assert(cond_id);
if (cur_node == NULL) {
// Get first state node
cur_node = model_get_node(self, (xmlChar *)"conditions");
// Lookup in properties
while (cur_node && cur_node->properties) {
attribute = cur_node->properties;
// Look for the id attribute
if (model_get_node_str_attrib(cur_node, "id", &temp_char)) {
if (!xmlStrcmp(temp_char, (const xmlChar *)cond_id)) {
found = true;
break;
}
}
cur_node = cur_node->next;
}
// Check if the state has been found
if (!found) {
cur_node = NULL;
return false;
}
// Get first arrow
if (cur_node->children) {
cur_node = cur_node->children;
found = false;
while (cur_node && cur_node->name) {
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
found = true;
break;
}
cur_node = cur_node->next;
}
}
// Check if the state has been found
if (!found) {
cur_node = NULL;
return false;
}
} else {
// Get next condition
found = false;
while (cur_node->next) {
cur_node = cur_node->next;
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
found = true;
break;
}
}
// Check if the state has been found
if (!found) {
cur_node = NULL;
return false;
}
}
//printf("DURING CALL : cur_node = %p\n", cur_node);
//printf("DURING CALL : cur_node->name = %s\n", cur_node->name);
// Lookup in properties
if (cur_node && cur_node->properties) {
attribute = cur_node->properties;
while(attribute && attribute->name && attribute->children) {
//printf("attr name : %s\n", attribute->name);
if (!xmlStrcmp(attribute->name, (const xmlChar *)"site")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_condition->site = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_SITE;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"weight")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_condition->load = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_WEIGHT;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"x")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_condition->x = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_X;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"y")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_condition->y = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_Y;
}
if (!xmlStrcmp(attribute->name, (const xmlChar *)"z")) {
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
new_condition->z = strtol((char *)value, NULL, 0);
xmlFree(value);
check |= READ_Z;
}
attribute = attribute->next;
}
switch(dimension) {
case 3:
return (bool)(check & SUCCESSFUL_READ_ARROW_XYZ);
case 2:
return (bool)(check & SUCCESSFUL_READ_ARROW_XY);
case 1:
return (bool)(check & SUCCESSFUL_READ_ARROW_X);
}
}
cur_node = NULL;
return false;
}
/* -------------------------------------------------------------------------- */
static bool model_init(struct model_t *self)
{
xmlNode *node;
/*
* this initialize the library and check potential ABI mismatches
* between the version it was compiled for and the actual shared
* library used.
*/
LIBXML_TEST_VERSION
self->doc = xmlReadFile(self->filename, NULL, 0);
if (self->doc == NULL ) {
printerr("Error trying to open the XML model !\n");
return false;
}
node = xmlDocGetRootElement(self->doc);
if (node == NULL) {
printerr("Empty XML model !\n");
xmlFreeDoc(self->doc);
return false;
}
if (xmlStrcmp(node->name, (xmlChar *) "gem-graph-model")) {
printerr("document of the wrong type, root node != gem-graph-model\n");
xmlFreeDoc(self->doc);
return false;
}
self->hashtable = xmlHashCreate(0);
if (self->hashtable == NULL) {
printerr("Can't create model hash table !\n");
xmlFreeDoc(self->doc);
return false;
}
return true;
}
static bool model_shutdown(struct model_t *self)
{
xmlFreeDoc(self->doc);
xmlHashFree(self->hashtable, NULL);
// This is to debug memory for regression tests
//xmlMemoryDump();
return true;
}
/* -------------------------------------------------------------------------- */
bool model_load (struct model_t *self)
{
char state_id[30] = {0};
char conditions_id[30] = {0};
struct arrow_t *arrow;
struct arrow_t *arrow_next;
struct arrow_t *arrow_prev;
int n_conditions;
if (!model_init (self))
return false;
@ -528,12 +691,12 @@ bool model_load (struct model_t *self)
self->multiplicity = model_get_multiplicity(self);
printlog("Multiplicity : %d\n", self->multiplicity);
// States and initial state
if (!model_get_next_state(self, &state_id)) {
printerr("No valid state to load\n");
return false;
}
// States and initial state
self->states = calloc (1, sizeof(struct state_t));
self->n_states = 1;
memcpy(&self->states[0].id, &state_id, 25);
@ -542,31 +705,155 @@ bool model_load (struct model_t *self)
printlog("Initial state : %s\n", &self->states[0].id);
// Initial state arrows
self->n_arrows = model_get_state_arrows_count(self, state_id);
self->arrows = calloc (self->n_arrows, sizeof(struct arrow_t));
self->arrows = arrow_new (self->arrows);
for (int i = 0; i < self->n_arrows; i++) {
model_get_next_arrow(self,
&self->arrows[i],
&self->states[0].id,
self->dimension);
if (model_get_next_arrow(self,
self->arrows,
&self->states[0].id,
self->dimension)) {
self->n_arrows++;
while (model_get_next_arrow(self,
arrow_new (self->arrows),
&self->states[0].id,
self->dimension)) {
self->n_arrows++;
}
}
printlog("Loaded %d arrows\n", self->n_arrows);
self->states[0].arrows = self->arrows;
// Conditions
if (!model_get_next_conditions(self, &conditions_id)) {
printerr("No valid conditions to load\n");
return false;
}
// Loading each condition
self->conditions = condition_new (self->conditions);
if (model_get_next_condition(self,
self->conditions,
&conditions_id,
self->dimension)) {
n_conditions = 1;
while (model_get_next_arrow(self,
condition_new (self->conditions),
&conditions_id,
self->dimension)) {
n_conditions++;
}
}
printlog("Loaded %d conditions\n", n_conditions);
return true;
}
bool model_unload (struct model_t *self)
{
if (!model_shutdown (self))
return false;
if (self->owner_name) {
free(self->owner_name);
self->owner_name = NULL;
}
if (self->model_name) {
free(self->model_name);
self->model_name = NULL;
}
if (self->space) {
if (self->space->units) {
free(self->space->units);
self->space->units = NULL;
}
free(self->space);
self->space = NULL;
}
if (self->arrows) {
while (self->arrows) {
self->arrows = arrow_destroy (self->arrows);
}
}
if (self->states) {
free(self->states);
self->states = NULL;
}
return true;
}
struct model_t *model_new(const char *path, const char *basename)
{
struct model_t *self = NULL;
struct model_t *prev = NULL;
// Allocate and insert in the list
self = calloc (1, sizeof(struct model_t));
// We want a cyclic chain
// This is the first model
if (!knownModels) {
knownModels = self;
self->next = self;
self->prev = self;
// This is not the first model
} else {
self->next = knownModels->next;
knownModels->next = self;
self->prev = knownModels;
}
// Allocate filename with trailing '\0'
self->filename =
calloc (1, strlen (path)
+ sizeof((char)'/')
+ strlen (basename)
+ sizeof((char)'\0'));
memcpy (self->filename,
path,
strlen (path));
self->filename[
strlen (path)] = '/';
memcpy (self->filename
+ strlen (path)
+ sizeof((char)'/'),
basename,
strlen (basename));
return self;
}
void model_destroy(struct model_t *self)
{
if (self->filename) {
free(self->filename);
self->filename = NULL;
}
if (self->next != self) {
self->prev->next = self->next;
self->next->prev = self->prev;
}
free(self);
}
void model_system_init (struct parameters_t *parameters)
{
struct dirent *modelDirEntry = NULL;
struct model_t *new_model;
DIR *modelDir = NULL;
char *extensionPosition;
int i;
// Allocate model storage
knownModels = calloc (1, sizeof(struct model_array_t));
// Open model directory
if ((modelDir = opendir (parameters->modelDir)) <= 0) {
printerr ("Could not open %s\n", parameters->modelDir);
@ -575,38 +862,40 @@ void model_system_init (struct parameters_t *parameters)
while ((modelDirEntry = readdir (modelDir)) != NULL) {
if ((extensionPosition = strstr (modelDirEntry->d_name, ".xml"))) {
i = knownModels->size;
// Creating model
knownModels->models = reallocarray (knownModels->models,
++knownModels->size,
sizeof(struct model_t));
// Allocate filename with trailing '\0'
knownModels->models[i].filename =
calloc (1, strlen (parameters->modelDir)
+ sizeof((char)'/')
+ strlen (modelDirEntry->d_name)
+ sizeof((char)'\0'));
memcpy (knownModels->models[i].filename,
parameters->modelDir,
strlen (parameters->modelDir));
knownModels->models[i].filename[
strlen (parameters->modelDir)] = '/';
memcpy (knownModels->models[i].filename
+ strlen (parameters->modelDir)
+ sizeof((char)'/'),
modelDirEntry->d_name,
strlen (modelDirEntry->d_name));
new_model = model_new (parameters->modelDir, modelDirEntry->d_name);
// Ask to parse the new model
if (model_load (&knownModels->models[i]))
if (model_load (new_model)) {
// XXX Check model is valid and/or parsed
printlog ("Loaded %s\n", knownModels->models[i].filename);
printlog ("Loaded %s\n", new_model->filename);
} else {
printerr ("Failed to load %s\n", new_model->filename);
model_unload (new_model);
model_destroy (new_model);
}
}
}
free(modelDir);
}
void model_system_shutdown (void)
{
struct model_t *model = knownModels;
struct model_t *next = NULL;
while ((model != model->next)) {
printlog ("Freeing %s\n", model->filename);
next = model->next;
model_unload(model);
model_destroy(model);
model = next;
}
if (model) {
model_unload (model);
model_destroy (model);
}
// Cleanup function for the XML library
xmlCleanupParser();
}

View File

@ -98,20 +98,14 @@ static int sched_run(struct scheduler_t *self,
int sched_start (struct scheduler_t *self, struct parameters_t *parameters)
{
int n_threads = omp_get_max_threads();
int n_models = 20;
int returnValue;
struct model_t *model;
self->id = sched_new_id();
printlog("Scheduler %d initialized with %d threads\n",
self->id,
n_threads);
// Allocating models
self->models = calloc(n_models, sizeof(struct model_t*));
for (int i = 0; i < n_models; i++) {
self->models[i] = calloc(1, sizeof(struct model_t));
//XXX populate model
}
// Allocating workers
self->workers = calloc(n_threads, sizeof(struct worker_t*));
@ -119,10 +113,13 @@ int sched_start (struct scheduler_t *self, struct parameters_t *parameters)
self->workers[i] = calloc(1, sizeof(struct worker_t));
}
// Run
#pragma omp for
for (int i = 0; i < n_models; i++)
returnValue = sched_run(self, parameters, self->models[i]);
// Retrieve models
model = self->models;
while(model) {
printlog ("Scheduling model %d\n", model->id);
returnValue = sched_run(self, parameters, self->models);
model = model->next;
}
// Freeing workers
for (int i = 0; i < n_threads; i++) {
@ -130,11 +127,7 @@ int sched_start (struct scheduler_t *self, struct parameters_t *parameters)
}
free(self->workers);
// Freeing models
for (int i = 0; i < n_models; i++) {
free(self->models[i]);
}
free(self->models);
return returnValue;
}