1 /* Copyright (c) 2009 The SimGrid team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #include "simgrid_config.h" /* getline */
7 #include "msg/private.h"
11 static xbt_dict_t action_funs;
12 static xbt_dict_t action_queues;
14 static xbt_dynar_t action_get_action(char *name);
16 /** \ingroup msg_actions
17 * \brief Registers a function to handle a kind of action
19 * Registers a function to handle a kind of action
20 * This table is then used by #MSG_action_trace_run
22 * The argument of the function is the line describing the action, splitted on spaces with xbt_str_split_quoted()
24 * \param name the reference name of the action.
25 * \param code the function; prototype given by the type: void...(xbt_dynar_t action)
27 void MSG_action_register(const char *action_name, msg_action_fun function)
29 xbt_dict_set(action_funs, action_name, function, NULL);
32 /** \ingroup msg_actions
33 * \brief Unregisters a function, which handled a kind of action
35 * \param name the reference name of the action.
37 void MSG_action_unregister(const char *action_name)
39 xbt_dict_remove(action_funs, action_name);
42 static int MSG_action_runner(int argc, char *argv[])
46 while ((evt = action_get_action(argv[0]))) {
47 msg_action_fun function =
48 xbt_dict_get(action_funs, xbt_dynar_get_as(evt, 1, char *));
56 void _MSG_action_init()
58 action_funs = xbt_dict_new();
59 action_queues = xbt_dict_new();
60 MSG_function_register_default(MSG_action_runner);
63 void _MSG_action_exit() {
64 xbt_dict_free(&action_queues);
65 action_queues = xbt_dict_new();
68 static FILE *action_fp=NULL;
69 static char *action_line = NULL;
70 static size_t action_len = 0;
72 static xbt_dynar_t action_get_action(char *name) {
77 xbt_dynar_t myqueue = xbt_dict_get_or_null(action_queues,name);
78 if (myqueue==NULL || xbt_dynar_length(myqueue)==0) { // nothing stored for me. Read the file further
80 if (action_fp==NULL) { // File closed now. There's nothing more to read. I'm out of here
84 // Read lines until I reach something for me (which breaks in loop body) or end of file
85 while ((read = getline(&action_line, &action_len, action_fp)) != -1) {
86 // cleanup and split the string I just read
87 char *comment = strchr(action_line, '#');
90 xbt_str_trim(action_line, NULL);
91 if (action_line[0] == '\0')
93 evt = xbt_str_split_quoted(action_line);
95 // if it's for me, I'm done
96 char *evtname = xbt_dynar_get_as(evt, 0, char *);
97 if (!strcmp(name,evtname)) {
100 // Else, I have to store it for the relevant colleague
101 xbt_dynar_t otherqueue = xbt_dict_get_or_null(action_queues,evtname);
102 if (otherqueue == NULL) { // Damn. Create the queue of that guy
103 otherqueue = xbt_dynar_new(sizeof(xbt_dynar_t), xbt_dynar_free_voidp);
104 xbt_dict_set(action_queues ,evtname, otherqueue, NULL/*xbt_dynar_free_voidp*/);
106 xbt_dynar_push(otherqueue,&evt);
109 return NULL; // end of file reached in vain while searching for more work
111 // Get something from my queue and return it
112 xbt_dynar_shift(myqueue,&evt);
117 /** \ingroup msg_actions
118 * \brief A trace loader
120 * Load a trace file containing actions, and execute them.
122 MSG_error_t MSG_action_trace_run(char *path)
126 action_fp = fopen(path, "r");
127 xbt_assert2(action_fp != NULL, "Cannot open %s: %s", path, strerror(errno));