28 #include <lib/abm_layer.h> 32 #include <lib/topology.h> 36 #define ACTION_START INIT 38 #define retrieve_agent(agent_id) ({ \ 39 struct _agent_abm_t *__ret = hash_map_lookup(current->region->agents_table, agent_id); \ 40 if(unlikely(!__ret)) \ 41 rootsim_error(true, "Looking for non existing agent id!"); \ 42 assert(agent_id == __ret->key); \ 53 unsigned long long key;
63 unsigned long long next_mark;
64 unsigned published_data_offset;
65 unsigned char *tracked_data;
74 unsigned long long key;
78 static inline unsigned long long get_agent_mark(
region_abm_t *region){
79 unsigned long long ret = region->next_mark;
80 region->next_mark += RegionsCount();
92 + array_dump_size(agent->future) + abm_settings.keep_history * array_dump_size(agent->past));
105 const unsigned char *buffer = event_content;
107 struct _agent_abm_t *agent = hash_map_reserve_elem(
current->
region->agents_table, *((
const unsigned long long *)event_content));
108 agent->leave_time = -1.0;
110 memcpy(agent, buffer,
sizeof(agent->
user_data_size) +
sizeof(agent->key));
117 array_load(agent->future, buffer);
118 if(abm_settings.keep_history)
119 array_load(agent->past, buffer);
121 memset(&agent->past, 0,
sizeof(agent->past));
124 assert(buffer == event_content + event_size);
138 unsigned char *to_send = buffer;
140 memcpy(buffer, agent,
sizeof(agent->
user_data_size) +
sizeof(agent->key));
145 array_dump(agent->future, buffer);
146 if(abm_settings.keep_history)
147 array_dump(agent->past, buffer);
163 size_t chkp_size_tot = region->chkp_size;
164 chkp_size_tot += hash_map_dump_size(region->agents_table);
166 unsigned i = hash_map_count(region->agents_table);
168 agent = &hash_map_items(region->agents_table)[i];
169 chkp_size_tot += array_dump_size(agent->future);
170 if(abm_settings.keep_history)
171 chkp_size_tot += array_dump_size(agent->past);
175 unsigned char *ret = rsalloc(chkp_size_tot), *chk = ret;
176 memcpy(ret, region, region->chkp_size);
177 ret += region->chkp_size;
178 hash_map_dump(region->agents_table, ret);
179 i = hash_map_count(region->agents_table);
181 agent = &hash_map_items(region->agents_table)[i];
182 array_dump(agent->future, ret);
183 if(abm_settings.keep_history)
184 array_dump(agent->past, ret);
188 assert(chk + chkp_size_tot == ret);
201 assert(((
region_abm_t *)data)->chkp_size == region->chkp_size);
203 unsigned i = hash_map_count(region->agents_table);
205 agent = &(hash_map_items(region->agents_table)[i]);
206 array_fini(agent->future);
207 if(abm_settings.keep_history)
208 array_fini(agent->past);
211 hash_map_fini(region->agents_table);
213 memcpy(region, data, region->chkp_size);
214 data += region->chkp_size;
216 hash_map_load(region->agents_table, data);
217 i = hash_map_count(region->agents_table);
219 agent = &(hash_map_items(region->agents_table)[i]);
220 array_load(agent->future, data);
221 if(abm_settings.keep_history)
222 array_load(agent->past, data);
237 unsigned actual_neighbours, i, region_alloc_size;
238 unsigned data_offset;
246 const unsigned directions = DirectionsCount();
249 rootsim_error(
true,
"Topology has not been initialized!");
256 actual_neighbours = NeighboursCount(lp->gid.to_int);
258 region_alloc_size = (unsigned)(
sizeof(
region_abm_t) + (
sizeof(
struct _n_info_t) * directions) + (abm_settings.neighbour_data_size * (actual_neighbours + 1)));
260 region = rsalloc(region_alloc_size);
261 memset(region, 0, region_alloc_size);
264 region->chkp_size = region_alloc_size;
266 data_offset = (unsigned)(
sizeof(
region_abm_t) + (
sizeof(
struct _n_info_t) * directions));
268 region->published_data_offset = data_offset;
270 for(i = 0; i < directions; ++i){
271 if((region->neighbours_info[i].src_lp = GetReceiver(lp->gid.to_int, i,
false)) ==
DIRECTION_INVALID){
272 region->neighbours_info[i].data_offset = UINT_MAX;
274 data_offset += abm_settings.neighbour_data_size;
275 region->neighbours_info[i].data_offset = data_offset;
279 region->tracked_data = NULL;
282 hash_map_init(region->agents_table);
284 region->next_mark = lp->gid.to_int;
302 if(array_empty(agent->future) || array_get_at(agent->future, 0).region !=
current->
gid.
to_int){
304 vis.action = abm_settings.traverse_handler;
307 vis = array_remove_at(agent->future, 0);
309 if(abm_settings.keep_history){
312 array_push(agent->past, vis);
317 switch_to_application_mode();
319 switch_to_platform_mode();
328 unsigned char* to_send;
329 unsigned buffer_size;
333 if(!agent || agent->leave_time >
current_evt->timestamp) {
339 switch_to_application_mode();
341 switch_to_platform_mode();
344 if(!agent || agent->leave_time >
current_evt->timestamp){
349 unsigned next_hop = UINT_MAX;
350 switch(topology_settings.type){
355 if(!array_empty(agent->future)){
361 next_hop = FindReceiverToward(array_peek(agent->future).region);
367 next_hop = FindReceiver();
370 rootsim_error(
true,
"unsupported");
373 if(next_hop == UINT_MAX){
383 if(array_empty(agent->future) || array_peek(agent->future).region !=
current->
gid.
to_int){
385 vis.action = abm_settings.traverse_handler;
388 vis = array_remove_at(agent->future, 0);
390 if(abm_settings.keep_history){
394 array_push(agent->past, vis);
397 switch_to_application_mode();
399 switch_to_platform_mode();
403 to_send = rsalloc(buffer_size);
409 KillAgent(agent->key);
424 unsigned i = DirectionsCount();
427 memcpy(((
unsigned char *)region) + region->neighbours_info[i].data_offset,
current_evt->event_content, abm_settings.neighbour_data_size);
431 rootsim_error(
true,
"Misuse of ABM api, unable to find neighbours info's memory area! EXITING!");
440 unsigned char* published_data = ((
unsigned char *)region) + region->published_data_offset;
442 if(!region->tracked_data || !memcmp(published_data, region->tracked_data, abm_settings.neighbour_data_size))
446 memcpy(published_data, region->tracked_data, abm_settings.neighbour_data_size);
449 unsigned i = DirectionsCount();
452 UncheckedScheduleNewEvent(region->neighbours_info[i].src_lp,
current_evt->timestamp,
ABM_UPDATE, published_data, abm_settings.neighbour_data_size);
479 ProcessEventTopology();
486 int GetNeighbourInfo(
direction_t i,
unsigned int *region_id,
void **data_p){
488 if(
unlikely(i >= DirectionsCount()))
489 rootsim_error(
true,
"bad argument in abm call");
494 *region_id = region->neighbours_info[i].src_lp;
495 *data_p = ((
unsigned char *)region) + region->neighbours_info[i].data_offset;
499 void TrackNeighbourInfo(
void *neighbour_data) {
503 bool IterAgents(agent_t *agent_p) {
504 switch_to_platform_mode();
506 static __thread map_size_t closure = 0;
507 if(!agent_p || closure >= hash_map_count(
current->
region->agents_table)) {
511 *agent_p = hash_map_items(
current->
region->agents_table)[closure++].key;
512 switch_to_application_mode();
516 unsigned CountAgents(
void) {
520 agent_t SpawnAgent(
unsigned user_data_size) {
521 switch_to_platform_mode();
523 unsigned long long new_key = get_agent_mark(
current->
region);
527 array_init(ret->future);
530 ret->
user_data = rsalloc(user_data_size);
534 if(abm_settings.keep_history){
535 array_init(ret->past);
537 array_push(ret->past, start_visit);
539 memset(&ret->past, 0,
sizeof(ret->past));
541 switch_to_application_mode();
545 void KillAgent(agent_t agent_id) {
546 switch_to_platform_mode();
549 array_fini(agent->future);
550 if(abm_settings.keep_history)
551 array_fini(agent->past);
555 switch_to_application_mode();
558 void * DataAgent(agent_t agent_id,
unsigned *data_size_p){
565 void ScheduleNewLeaveEvent(
simtime_t time,
unsigned int event_type, agent_t agent_id) {
566 switch_to_platform_mode();
571 agent->leave_time = time;
573 struct _leave_evt leave_evt = {agent_id, event_type};
578 switch_to_application_mode();
581 unsigned CountPastVisits(agent_t agent_id){
582 return array_count(retrieve_agent(agent_id)->past);
585 void GetPastVisit(agent_t agent_id,
unsigned *region_p,
unsigned *event_type_p,
simtime_t *time_p,
unsigned i){
586 switch_to_platform_mode();
589 if(
unlikely(i >= array_count(agent->past)))
590 rootsim_error(
true,
"trying to access an out of bounds past visit from agent %llu", agent_id);
592 *region_p = array_get_at(agent->past, array_count(agent->past) - 1 - i).region;
593 *event_type_p = array_get_at(agent->past, array_count(agent->past) - 1 - i).action;
594 *time_p = array_get_at(agent->past, array_count(agent->past) - 1 - i).time;
596 switch_to_application_mode();
599 unsigned CountVisits(agent_t agent_id){
600 return array_count(retrieve_agent(agent_id)->future);
603 void GetVisit(agent_t agent_id,
unsigned *region_p,
unsigned *event_type_p,
unsigned i){
605 if(
unlikely(i >= array_count(agent->future)))
606 rootsim_error(
true,
"trying to access an out of bounds future visit from agent %llu", agent_id);
608 *region_p = array_get_at(agent->future, i).region;
609 *event_type_p = array_get_at(agent->future, i).action;
612 void SetVisit(agent_t agent_id,
unsigned region,
unsigned event_type,
unsigned i){
614 if(
unlikely(i >= array_count(agent->future) || event_type == ACTION_START || region >= RegionsCount())) {
615 rootsim_error(
true,
"bad argument in abm call for agent %llu", agent_id);
618 array_items(agent->future)[i].region = region;
619 array_items(agent->future)[i].action = event_type;
622 void EnqueueVisit(agent_t agent_id,
unsigned region,
unsigned event_type){
624 if(
unlikely(event_type == ACTION_START || region >= RegionsCount())) {
625 rootsim_error(
true,
"bad argument in abm call for agent %llu", agent_id);
628 struct _visit_abm_t visit = {region, event_type, INFINITY};
629 array_push(agent->future, visit);
632 void AddVisit(agent_t agent_id,
unsigned region,
unsigned event_type,
unsigned i){
634 if(
unlikely(i > array_count(agent->future) || event_type == ACTION_START || region >= RegionsCount())) {
635 rootsim_error(
true,
"bad argument in abm call for agent %llu", agent_id);
638 struct _visit_abm_t visit = {region, event_type, INFINITY};
640 if(i == array_count(agent->future))
641 array_push(agent->future, visit);
643 array_add_at(agent->future, i, visit);
646 void RemoveVisit(agent_t agent_id,
unsigned i) {
648 if(i >= array_count(agent->future)) {
649 rootsim_error(
true,
"bad argument in abm call for agent %llu", agent_id);
652 array_remove_at(agent->future, i);
all crossing costs and probabilities are set to 1, but there can be not crossable regions ...
void abm_layer_init(void)
void ProcessEventABM(void)
A generic invalid direction.
ROOT-Sim header for model development.
unsigned char * abm_do_checkpoint(region_abm_t *region)
unsigned int to_int
The GID numerical value.
unsigned user_data_size
UUID that uniquely identifies the agent (this must be the first field of the struct for various reaso...
The ROOT-Sim scheduler main module header.
This is the implementation of a dynamic array, used for managing various data structures.
__thread struct lp_struct * current
This is a per-thread variable pointing to the block state of the LP currently scheduled.
double simtime_t
This defines the type with whom timestamps are represented.
__thread msg_t * current_evt
decisions are taken at random but are weighted on the palatability of neighbours
unsigned int size
Unique identifier of the message, used for rendez-vous events.
enum _direction_t direction_t
static void receive_update(void)
static void update_neighbours(void)
This header implements a simple hash map data structure.
region_abm_t * region
pointer to the region struct
GID_t gid
Global ID of the LP.
static struct _agent_abm_t * agent_from_buffer(const unsigned char *event_content, unsigned event_size)
static void agent_to_buffer(struct _agent_abm_t *agent, unsigned char *buffer)
decisions on next hops are taken based on the costs undertaken to cross the boundaries ...
void(* ProcessEvent)(unsigned int me, simtime_t now, int event_type, void *event_content, unsigned int size, void *state)
char * user_data
This must be the seonc filed of this struct for serialization reasons.
static unsigned agent_dump_size(const struct _agent_abm_t *agent)
void abm_restore_checkpoint(unsigned char *data, region_abm_t *region)
static void on_abm_visit(void)
void * current_base_pointer
The current state base pointer (updated by SetState())
static void on_abm_leave(void)
#define unlikely(exp)
Optimize the branch as likely not taken.