void buzzvm_vstig_onconflictlost(buzzvm_t vm, buzzvstig_t vs, buzzobj_t k, buzzvstig_elem_t lv) { /* Was a conflict manager defined? */ if(vs->onconflictlost) { /* Push closure */ buzzvm_push(vm, vs->onconflictlost); /* Push key */ buzzvm_push(vm, k); /* Make table for local value */ buzzvm_pusht(vm); buzzobj_t loc = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_pushi(vm, lv->robot); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_push(vm, lv->data); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "timestamp")); buzzvm_pushi(vm, lv->timestamp); buzzvm_tput(vm); /* Call closure with 2 arguments */ buzzvm_push(vm, loc); buzzvm_closure_call(vm, 2); } }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, SInt32 n_idx, const CColor& c_color) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushi(m_tBuzzVM, n_idx); buzzvm_pusht(m_tBuzzVM); buzzobj_t tColorTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); TablePut(tColorTable, "red", c_color.GetRed()); TablePut(tColorTable, "green", c_color.GetGreen()); TablePut(tColorTable, "blue", c_color.GetBlue()); return m_tBuzzVM->state; }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, const std::string& str_key, const CVector3& c_vec) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushs(m_tBuzzVM, buzzvm_string_register(m_tBuzzVM, str_key.c_str(), 1)); buzzvm_pusht(m_tBuzzVM); buzzobj_t tVecTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); TablePut(tVecTable, "x", c_vec.GetX()); TablePut(tVecTable, "y", c_vec.GetY()); TablePut(tVecTable, "z", c_vec.GetZ()); return m_tBuzzVM->state; }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, SInt32 n_idx, const CVector3& c_vec) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushi(m_tBuzzVM, n_idx); buzzvm_pusht(m_tBuzzVM); buzzobj_t tVecTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); TablePut(tVecTable, "x", c_vec.GetX()); TablePut(tVecTable, "y", c_vec.GetY()); TablePut(tVecTable, "z", c_vec.GetZ()); return m_tBuzzVM->state; }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, const std::string& str_key, const CColor& c_color) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushs(m_tBuzzVM, buzzvm_string_register(m_tBuzzVM, str_key.c_str(), 1)); buzzvm_pusht(m_tBuzzVM); buzzobj_t tColorTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); TablePut(tColorTable, "red", c_color.GetRed()); TablePut(tColorTable, "green", c_color.GetGreen()); TablePut(tColorTable, "blue", c_color.GetBlue()); return m_tBuzzVM->state; }
buzzvm_state buzzvm_pushs(buzzvm_t vm, uint16_t strid) { if(!buzzstrman_get(vm->strings, strid)) { buzzvm_seterror(vm, BUZZVM_ERROR_STRING, "id read = %" PRIu16, strid); return vm->state; } buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_STRING); o->s.value.sid = (strid); o->s.value.str = buzzstrman_get(vm->strings, strid); buzzvm_push(vm, o); return BUZZVM_STATE_READY; }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, SInt32 n_idx, const CQuaternion& c_quat) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushi(m_tBuzzVM, n_idx); buzzvm_pusht(m_tBuzzVM); buzzobj_t tQuatTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); CRadians cYaw, cPitch, cRoll; c_quat.ToEulerAngles(cYaw, cPitch, cRoll); TablePut(tQuatTable, "yaw", cYaw); TablePut(tQuatTable, "pitch", cPitch); TablePut(tQuatTable, "roll", cRoll); return m_tBuzzVM->state; }
buzzvm_state CBuzzController::TablePut(buzzobj_t t_table, const std::string& str_key, const CQuaternion& c_quat) { buzzvm_push(m_tBuzzVM, t_table); buzzvm_pushs(m_tBuzzVM, buzzvm_string_register(m_tBuzzVM, str_key.c_str(), 1)); buzzvm_pusht(m_tBuzzVM); buzzobj_t tQuatTable = buzzvm_stack_at(m_tBuzzVM, 1); buzzvm_tput(m_tBuzzVM); CRadians cYaw, cPitch, cRoll; c_quat.ToEulerAngles(cYaw, cPitch, cRoll); TablePut(tQuatTable, "yaw", cYaw); TablePut(tQuatTable, "pitch", cPitch); TablePut(tQuatTable, "roll", cRoll); return m_tBuzzVM->state; }
int buzzneighbors_reset(buzzvm_t vm) { if(vm->state != BUZZVM_STATE_READY) return vm->state; /* Make new table */ buzzobj_t t; vm->state = make_table(vm, &t); if(vm->state != BUZZVM_STATE_READY) return vm->state; /* Add extra methods */ function_register(t, "broadcast", buzzneighbors_broadcast); function_register(t, "listen", buzzneighbors_listen); function_register(t, "ignore", buzzneighbors_ignore); /* Register table as global symbol */ buzzvm_pushs(vm, buzzvm_string_register(vm, "neighbors", 1)); buzzvm_push(vm, t); buzzvm_gstore(vm); return vm->state; }
buzzvm_state buzzvm_tget(buzzvm_t vm) { buzzvm_stack_assert(vm, 2); buzzvm_type_assert(vm, 2, BUZZTYPE_TABLE); buzzobj_t k = buzzvm_stack_at(vm, 1); buzzobj_t t = buzzvm_stack_at(vm, 2); buzzvm_pop(vm); buzzvm_pop(vm); if(k->o.type != BUZZTYPE_INT && k->o.type != BUZZTYPE_FLOAT && k->o.type != BUZZTYPE_STRING) { buzzvm_seterror(vm, BUZZVM_ERROR_TYPE, "a %s value can't be used as table key", k->o.type); return vm->state; } const buzzobj_t* v = buzzdict_get(t->t.value, &k, buzzobj_t); if(v) buzzvm_push(vm, *v); else buzzvm_pushnil(vm); return BUZZVM_STATE_READY; }
buzzvm_state buzzvm_pushl(buzzvm_t vm, int32_t addr) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_CLOSURE); o->c.value.isnative = 1; o->c.value.ref = addr; if(vm->lsyms) { int i; for(i = 0; i < buzzdarray_size(vm->lsyms->syms); ++i) buzzdarray_push(o->c.value.actrec, &buzzdarray_get(vm->lsyms->syms, i, buzzobj_t)); } else { buzzobj_t nil = buzzheap_newobj(vm, BUZZTYPE_NIL); buzzdarray_push(o->c.value.actrec, &nil); } return buzzvm_push(vm, o); }
int buzzvm_vstig_create(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get vstig id */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_INT); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; buzzvm_pop(vm); /* Look for virtual stigmergy */ buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) /* Found, destroy it */ buzzdict_remove(vm->vstigs, &id); /* Create a new virtual stigmergy */ buzzvstig_t nvs = buzzvstig_new(); buzzdict_set(vm->vstigs, &id, &nvs); /* Create a table and add data and methods */ buzzobj_t t = buzzheap_newobj(vm->heap, BUZZTYPE_TABLE); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "size")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_size)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "put")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_put)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "get")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_get)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "onconflict")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_setonconflict)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "onconflictlost")); buzzvm_pushcc(vm, buzzvm_function_register(vm, buzzvm_vstig_setonconflictlost)); buzzvm_tput(vm); buzzvm_push(vm, t); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_pushi(vm, id); buzzvm_tput(vm); /* Push the table on the stack */ buzzvm_push(vm, t); /* Return */ return buzzvm_ret1(vm); }
int buzzneighbors_add(buzzvm_t vm, uint16_t robot, float distance, float azimuth, float elevation) { if(vm->state != BUZZVM_STATE_READY) return vm->state; /* Get "neighbors" table */ buzzvm_pushs(vm, buzzvm_string_register(vm, "neighbors", 1)); buzzvm_gload(vm); buzzvm_type_assert(vm, 1, BUZZTYPE_TABLE); buzzobj_t nbr = buzzvm_stack_at(vm, 1); /* Get "data" field */ buzzvm_pushs(vm, buzzvm_string_register(vm, "data", 1)); buzzvm_tget(vm); if(buzzvm_stack_at(vm, 1)->o.type == BUZZTYPE_NIL) { /* Empty data, create a new table */ buzzvm_pop(vm); buzzvm_push(vm, nbr); buzzvm_pushs(vm, buzzvm_string_register(vm, "data", 1)); buzzvm_pusht(vm); buzzobj_t data = buzzvm_stack_at(vm, 1); buzzvm_tput(vm); buzzvm_push(vm, data); } /* When we get here, the "data" table is on top of the stack */ /* Push robot id */ buzzvm_pushi(vm, robot); /* Create entry table */ buzzobj_t entry = buzzheap_newobj(vm->heap, BUZZTYPE_TABLE); /* Insert distance */ buzzvm_push(vm, entry); buzzvm_pushs(vm, buzzvm_string_register(vm, "distance", 1)); buzzvm_pushf(vm, distance); buzzvm_tput(vm); /* Insert azimuth */ buzzvm_push(vm, entry); buzzvm_pushs(vm, buzzvm_string_register(vm, "azimuth", 1)); buzzvm_pushf(vm, azimuth); buzzvm_tput(vm); /* Insert elevation */ buzzvm_push(vm, entry); buzzvm_pushs(vm, buzzvm_string_register(vm, "elevation", 1)); buzzvm_pushf(vm, elevation); buzzvm_tput(vm); /* Save entry into data table */ buzzvm_push(vm, entry); buzzvm_tput(vm); return vm->state; }
int buzzvm_vstig_get(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get vstig id */ buzzvm_lload(vm, 0); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_tget(vm); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; /* Get key */ buzzvm_lload(vm, 1); buzzobj_t k = buzzvm_stack_at(vm, 1); /* Look for virtual stigmergy */ buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) { /* Virtual stigmergy found */ /* Look for key and push result */ buzzvstig_elem_t* e = buzzvstig_fetch(*vs, &k); if(e) { /* Key found */ buzzvm_push(vm, (*e)->data); /* Append the message to the out message queue */ buzzoutmsg_queue_append_vstig(vm->outmsgs, BUZZMSG_VSTIG_QUERY, id, k, *e); } else { /* Key not found, add a new one containing nil */ buzzvm_pushnil(vm); buzzvstig_elem_t x = buzzvstig_elem_new(buzzvm_stack_at(vm, 1), 1, vm->robot); /* Append the message to the out message queue */ buzzoutmsg_queue_append_vstig(vm->outmsgs, BUZZMSG_VSTIG_QUERY, id, k, x); } } else { /* No virtual stigmergy found, just push false */ /* If this happens, its a bug */ buzzvm_pushnil(vm); fprintf(stderr, "[BUG] [ROBOT %u] Can't find virtual stigmergy %u\n", vm->robot, id); } /* Return the value found */ return buzzvm_ret1(vm); }
int buzzvm_swarm_exec(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get the id */ buzzvm_lload(vm, 0); buzzvm_pushs(vm, buzzvm_string_register(vm, "id")); buzzvm_tget(vm); uint16_t id = buzzvm_stack_at(vm, 1)->i.value; /* Get the swarm entry */ uint8_t* x = buzzdict_get(vm->swarms, &id, uint8_t); if(!x) { vm->state = BUZZVM_STATE_ERROR; vm->error = BUZZVM_ERROR_SWARM; return BUZZVM_STATE_ERROR; } /* Check whether the robot is in the swarm */ if(*x) { /* Get the closure */ buzzvm_lload(vm, 1); buzzvm_type_assert(vm, 1, BUZZTYPE_CLOSURE); buzzobj_t c = buzzvm_stack_at(vm, 1); /* Get rid of the current call structure */ if(buzzvm_ret0(vm) != BUZZVM_STATE_READY) return vm->state; /* Save the current stack depth */ uint32_t stacks = buzzdarray_size(vm->stacks); /* Push the current swarm in the stack */ buzzdarray_push(vm->swarmstack, &id); /* Call the closure */ buzzvm_push(vm, c); int32_t numargs = 0; buzzvm_pushi(vm, numargs); buzzvm_calls(vm); do if(buzzvm_step(vm) != BUZZVM_STATE_READY) return vm->state; while(stacks < buzzdarray_size(vm->stacks)); return vm->state; } else { /* Get rid of the current call structure */ return buzzvm_ret0(vm); } }
int buzzvstig_get(buzzvm_t vm) { buzzvm_lnum_assert(vm, 1); /* Get vstig id */ id_get(); /* Get key */ buzzvm_lload(vm, 1); buzzobj_t k = buzzvm_stack_at(vm, 1); /* Look for virtual stigmergy */ const buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(vs) { /* Virtual stigmergy found */ /* Look for key and push result */ const buzzvstig_elem_t* e = buzzvstig_fetch(*vs, &k); if(e) { /* Key found */ buzzvm_push(vm, (*e)->data); /* Append the message to the out message queue */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_QUERY, id, k, *e); } else { /* Key not found, make a new one containing nil */ buzzvm_pushnil(vm); buzzvstig_elem_t x = buzzvstig_elem_new(buzzvm_stack_at(vm, 1), // nil value 0, // timestamp vm->robot); // robot id /* Append the message to the out message queue */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_QUERY, id, k, x); free(x); } } else { /* No virtual stigmergy found, just push false */ /* If this happens, its a bug */ buzzvm_pushnil(vm); } /* Return the value found */ return buzzvm_ret1(vm); }
buzzvm_state buzzvm_pushf(buzzvm_t vm, float v) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_FLOAT); o->f.value = v; buzzvm_push(vm, o); return vm->state; }
void buzzvm_process_inmsgs(buzzvm_t vm) { /* Go through the messages */ while(!buzzinmsg_queue_isempty(vm->inmsgs)) { /* Make sure the VM is in the right state */ if(vm->state != BUZZVM_STATE_READY) return; /* Extract the message data */ uint16_t rid; buzzmsg_payload_t msg; buzzinmsg_queue_extract(vm, &rid, &msg); /* Dispatch the message wrt its type in msg->payload[0] */ switch(buzzmsg_payload_get(msg, 0)) { case BUZZMSG_BROADCAST: { /* Deserialize the topic */ buzzobj_t topic; int64_t pos = buzzobj_deserialize(&topic, msg, 1, vm); /* Make sure there's a listener to call */ const buzzobj_t* l = buzzdict_get(vm->listeners, &topic->s.value.sid, buzzobj_t); if(!l) { /* No listener, ignore message */ break; } /* Deserialize value */ buzzobj_t value; pos = buzzobj_deserialize(&value, msg, pos, vm); /* Make an object for the robot id */ buzzobj_t rido = buzzheap_newobj(vm, BUZZTYPE_INT); rido->i.value = rid; /* Call listener */ buzzvm_push(vm, *l); buzzvm_push(vm, topic); buzzvm_push(vm, value); buzzvm_push(vm, rido); buzzvm_closure_call(vm, 3); break; } case BUZZMSG_VSTIG_PUT: { /* Deserialize the vstig id */ uint16_t id; int64_t pos = buzzmsg_deserialize_u16(&id, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_PUT message received\n", vm->robot); break; } /* Look for virtual stigmergy */ const buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(!vs) break; /* Virtual stigmergy found */ /* Deserialize key and value from msg */ buzzobj_t k; // key buzzvstig_elem_t v = // value (buzzvstig_elem_t)malloc(sizeof(struct buzzvstig_elem_s)); if(buzzvstig_elem_deserialize(&k, &v, msg, pos, vm) < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_PUT message received\n", vm->robot); free(v); break; } /* Deserialization successful */ /* Fetch local vstig element */ const buzzvstig_elem_t* l = buzzvstig_fetch(*vs, &k); if((!l) || /* Element not found */ ((*l)->timestamp < v->timestamp)) { /* Local element is older */ /* Local element must be updated */ /* Store element */ buzzvstig_store(*vs, &k, &v); buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, v); } else if(((*l)->timestamp == v->timestamp) && /* Same timestamp */ ((*l)->robot != v->robot)) { /* Different robot */ /* Conflict! */ /* Call conflict manager */ buzzvstig_elem_t c = buzzvstig_onconflict_call(vm, *vs, k, *l, v); if(!c) { fprintf(stderr, "[WARNING] [ROBOT %u] Error resolving PUT conflict\n", vm->robot); break; } /* Get rid of useless vstig element */ free(v); /* Did this robot lose the conflict? */ if((c->robot != vm->robot) && ((*l)->robot == vm->robot)) { /* Yes */ /* Save current local entry */ buzzvstig_elem_t ol = buzzvstig_elem_clone(vm, *l); /* Store winning value */ buzzvstig_store(*vs, &k, &c); /* Call conflict lost manager */ buzzvstig_onconflictlost_call(vm, *vs, k, ol); } else { /* This robot did not lose the conflict */ /* Just propagate the PUT message */ buzzvstig_store(*vs, &k, &c); } buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, c); } else { /* Remote element is older, ignore it */ /* Get rid of useless vstig element */ free(v); } break; } case BUZZMSG_VSTIG_QUERY: { /* Deserialize the vstig id */ uint16_t id; int64_t pos = buzzmsg_deserialize_u16(&id, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_QUERY message received (1)\n", vm->robot); break; } /* Deserialize key and value from msg */ buzzobj_t k; // key buzzvstig_elem_t v = // value (buzzvstig_elem_t)malloc(sizeof(struct buzzvstig_elem_s)); if(buzzvstig_elem_deserialize(&k, &v, msg, pos, vm) < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_VSTIG_QUERY message received (2)\n", vm->robot); free(v); break; } /* Look for virtual stigmergy */ const buzzvstig_t* vs = buzzdict_get(vm->vstigs, &id, buzzvstig_t); if(!vs) { /* Virtual stigmergy not found, simply propagate the message */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_QUERY, id, k, v); free(v); break; } /* Virtual stigmergy found */ /* Fetch local vstig element */ const buzzvstig_elem_t* l = buzzvstig_fetch(*vs, &k); if(!l) { /* Element not found */ if(v->data->o.type == BUZZTYPE_NIL) { /* This robot knows nothing about the query, just propagate it */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_QUERY, id, k, v); free(v); } else { /* Store element and propagate PUT message */ buzzvstig_store(*vs, &k, &v); buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, v); } break; } /* Element found */ if((*l)->timestamp < v->timestamp) { /* Local element is older */ /* Store element */ buzzvstig_store(*vs, &k, &v); buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, v); } else if((*l)->timestamp > v->timestamp) { /* Local element is newer */ /* Append a PUT message to the out message queue */ buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, *l); free(v); } else if(((*l)->timestamp == v->timestamp) && /* Same timestamp */ ((*l)->robot != v->robot)) { /* Different robot */ /* Conflict! */ /* Call conflict manager */ buzzvstig_elem_t c = buzzvstig_onconflict_call(vm, *vs, k, *l, v); free(v); /* Make sure conflict manager returned with an element to process */ if(!c) break; /* Did this robot lose the conflict? */ if((c->robot != vm->robot) && ((*l)->robot == vm->robot)) { /* Yes */ /* Save current local entry */ buzzvstig_elem_t ol = buzzvstig_elem_clone(vm, *l); /* Store winning value */ buzzvstig_store(*vs, &k, &c); /* Call conflict lost manager */ buzzvstig_onconflictlost_call(vm, *vs, k, ol); } else { /* This robot did not lose the conflict */ /* Just propagate the PUT message */ buzzvstig_store(*vs, &k, &c); } buzzoutmsg_queue_append_vstig(vm, BUZZMSG_VSTIG_PUT, id, k, c); } else { /* Remote element is same as local, ignore it */ /* Get rid of useless vstig element */ free(v); } break; } case BUZZMSG_SWARM_LIST: { /* Deserialize number of swarm ids */ uint16_t nsids; int64_t pos = buzzmsg_deserialize_u16(&nsids, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_LIST message received\n", vm->robot); break; } if(nsids < 1) break; /* Deserialize swarm ids */ buzzdarray_t sids = buzzdarray_new(nsids, sizeof(uint16_t), NULL); uint16_t i; for(i = 0; i < nsids; ++i) { pos = buzzmsg_deserialize_u16(buzzdarray_makeslot(sids, i), msg, pos); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_LIST message received\n", vm->robot); break; } } /* Update the information */ buzzswarm_members_refresh(vm->swarmmembers, rid, sids); break; } case BUZZMSG_SWARM_JOIN: { /* Deserialize swarm id */ uint16_t sid; int64_t pos = buzzmsg_deserialize_u16(&sid, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_JOIN message received\n", vm->robot); break; } /* Update the information */ buzzswarm_members_join(vm->swarmmembers, rid, sid); break; } case BUZZMSG_SWARM_LEAVE: { /* Deserialize swarm id */ uint16_t sid; int64_t pos = buzzmsg_deserialize_u16(&sid, msg, 1); if(pos < 0) { fprintf(stderr, "[WARNING] [ROBOT %u] Malformed BUZZMSG_SWARM_LEAVE message received\n", vm->robot); break; } /* Update the information */ buzzswarm_members_leave(vm->swarmmembers, rid, sid); break; } } /* Get rid of the message */ buzzmsg_payload_destroy(&msg); } /* Update swarm membership */ buzzswarm_members_update(vm->swarmmembers); }
buzzvm_state buzzvm_pushi(buzzvm_t vm, int32_t v) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_INT); o->i.value = v; buzzvm_push(vm, o); return vm->state; }
buzzvstig_elem_t buzzvm_vstig_onconflict(buzzvm_t vm, buzzvstig_t vs, buzzobj_t k, buzzvstig_elem_t lv, buzzvstig_elem_t rv) { /* Was a conflict manager defined? */ if(vs->onconflict) { /* Push closure */ buzzvm_push(vm, vs->onconflict); /* Push key */ buzzvm_push(vm, k); /* Make table for local value */ buzzvm_pusht(vm); buzzobj_t loc = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_pushi(vm, lv->robot); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_push(vm, lv->data); buzzvm_tput(vm); buzzvm_push(vm, loc); buzzvm_pushs(vm, buzzvm_string_register(vm, "timestamp")); buzzvm_pushi(vm, lv->timestamp); buzzvm_tput(vm); /* Make table for remote value */ buzzvm_pusht(vm); buzzobj_t rem = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_pushi(vm, rv->robot); buzzvm_tput(vm); buzzvm_push(vm, rem); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_push(vm, rv->data); buzzvm_tput(vm); buzzvm_push(vm, rem); buzzvm_pushs(vm, buzzvm_string_register(vm, "timestamp")); buzzvm_pushi(vm, rv->timestamp); buzzvm_tput(vm); /* Call closure with 3 arguments */ buzzvm_push(vm, loc); buzzvm_push(vm, rem); buzzvm_closure_call(vm, 3); /* Make new entry with return value */ /* Make sure it's a table */ if(buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_TABLE) { fprintf(stderr, "[WARNING] [ROBOT %u] Return value type is %d\n", vm->robot, buzzvm_stack_at(vm, 1)->o.type); return NULL; } /* Get the robot id */ buzzobj_t ret = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot")); buzzvm_tget(vm); if(buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_INT) return NULL; uint16_t robot = buzzvm_stack_at(vm, 1)->i.value; buzzvm_pop(vm); /* Get the data */ buzzvm_push(vm, ret); buzzvm_pushs(vm, buzzvm_string_register(vm, "data")); buzzvm_tget(vm); buzzobj_t data = buzzvm_stack_at(vm, 1); buzzvm_pop(vm); /* Make new entry */ return buzzvstig_elem_new(data, lv->timestamp, robot); } else { /* No conflict manager, use default behavior */ if(lv->robot > rv->robot) return buzzvstig_elem_clone(lv); else return buzzvstig_elem_clone(rv); } }
buzzvm_state buzzvm_pushnil(buzzvm_t vm) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_NIL); buzzvm_push(vm, o); return vm->state; }
buzzvstig_elem_t buzzvstig_onconflict_call(buzzvm_t vm, buzzvstig_t vs, buzzobj_t k, buzzvstig_elem_t lv, buzzvstig_elem_t rv) { /* Was a conflict manager defined? */ if(vs->onconflict) { /* Push closure */ buzzvm_push(vm, vs->onconflict); /* Push key */ buzzvm_push(vm, k); /* Make table for local value */ buzzvm_pusht(vm); add_field(robot, lv, pushi); add_field(data, lv, push); add_field(timestamp, lv, pushi); /* Make table for remote value */ buzzvm_pusht(vm); add_field(robot, rv, pushi); add_field(data, rv, push); add_field(timestamp, rv, pushi); /* Call closure (key, lv, rv on the stack) */ buzzvm_closure_call(vm, 3); /* Make new entry with return value */ /* Make sure it's a table */ if(buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_TABLE) { fprintf(stderr, "[WARNING] [ROBOT %u] virtual stigmergy onconflict(): Return value type is %s, expected table\n", vm->robot, buzztype_desc[buzzvm_stack_at(vm, 1)->o.type]); return NULL; } /* Get the robot id */ buzzobj_t ret = buzzvm_stack_at(vm, 1); buzzvm_pushs(vm, buzzvm_string_register(vm, "robot", 1)); buzzvm_tget(vm); if(buzzvm_stack_at(vm, 1)->o.type != BUZZTYPE_INT) return NULL; uint16_t robot = buzzvm_stack_at(vm, 1)->i.value; buzzvm_pop(vm); /* Get the data */ buzzvm_push(vm, ret); buzzvm_pushs(vm, buzzvm_string_register(vm, "data", 1)); buzzvm_tget(vm); buzzobj_t data = buzzvm_stack_at(vm, 1); buzzvm_pop(vm); /* Make new entry */ return buzzvstig_elem_new(data, lv->timestamp, robot); } else { /* No conflict manager, use default behavior */ /* If both values are not nil, keep the value of the robot with the higher id */ if(((lv->data->o.type == BUZZTYPE_NIL) && (rv->data->o.type == BUZZTYPE_NIL)) || ((lv->data->o.type != BUZZTYPE_NIL) && (rv->data->o.type != BUZZTYPE_NIL))) { if(lv->robot > rv->robot) return buzzvstig_elem_clone(vm, lv); else return buzzvstig_elem_clone(vm, rv); } /* If my value is not nil, keep mine */ if(lv->data->o.type != BUZZTYPE_NIL) return buzzvstig_elem_clone(vm, lv); /* If the other value is not nil, keep that one */ if(rv->data->o.type != BUZZTYPE_NIL) return buzzvstig_elem_clone(vm, rv); /* Otherwise nothing to do */ return NULL; } }
buzzvm_state buzzvm_pushu(buzzvm_t vm, void* v) { buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_USERDATA); o->u.value = v; buzzvm_push(vm, o); return vm->state; }