Esempio n. 1
0
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);
    }
}
Esempio n. 2
0
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;   
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;   
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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);
}
Esempio n. 15
0
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);
   }
}
Esempio n. 16
0
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);
}
Esempio n. 17
0
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;
}
Esempio n. 18
0
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);
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
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);
    }
}
Esempio n. 21
0
buzzvm_state buzzvm_pushnil(buzzvm_t vm) {
   buzzobj_t o = buzzheap_newobj(vm, BUZZTYPE_NIL);
   buzzvm_push(vm, o);
   return vm->state;
}
Esempio n. 22
0
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;
   }
}
Esempio n. 23
0
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;
}