Exemplo n.º 1
0
void CBuzzController::ProcessOutMsgs() {
   /* Send robot id */
   CByteArray cData;
   cData << m_tBuzzVM->robot;
   /* Send messages from FIFO */
   do {
      /* Are there more messages? */
      if(buzzoutmsg_queue_isempty(m_tBuzzVM->outmsgs)) break;
      /* Get first message */
      buzzmsg_payload_t m = buzzoutmsg_queue_first(m_tBuzzVM->outmsgs);
      /* Make sure the next message fits the data buffer */
      if(cData.Size() + buzzmsg_payload_size(m) + sizeof(UInt16)
         >
         m_pcRABA->GetSize()) {
         buzzmsg_payload_destroy(&m);
         break;
      }
      /* Add message length to data buffer */
      cData << static_cast<UInt16>(buzzmsg_payload_size(m));
      /* Add payload to data buffer */
      cData.AddBuffer(reinterpret_cast<UInt8*>(m->data), buzzmsg_payload_size(m));
      /* Get rid of message */
      buzzoutmsg_queue_next(m_tBuzzVM->outmsgs);
      buzzmsg_payload_destroy(&m);
   } while(1);
   /* Pad the rest of the data with zeroes */
   while(cData.Size() < m_pcRABA->GetSize()) cData << static_cast<UInt8>(0);
   /* Send message */
   m_pcRABA->SetData(cData);
}
Exemplo n.º 2
0
void CBuzzController::ProcessOutMsgs() {
   /* Process outgoing messages */
   buzzvm_process_outmsgs(m_tBuzzVM);
   /* Send robot id */
   CByteArray cData;
   cData << m_tBuzzVM->robot;
   /* Send messages from FIFO */
   do {
      /* Are there more messages? */
      if(buzzoutmsg_queue_isempty(m_tBuzzVM)) break;
      /* Get first message */
      buzzmsg_payload_t m = buzzoutmsg_queue_first(m_tBuzzVM);
      /* Make sure the message is smaller than the data buffer
       * Without this check, large messages would clog the queue forever
       */
      size_t unMsgSize = buzzmsg_payload_size(m) + sizeof(UInt16);
      if(unMsgSize < m_pcRABA->GetSize() - sizeof(UInt16)) {
         /* Make sure the next message fits the data buffer */
         if(cData.Size() + unMsgSize > m_pcRABA->GetSize()) {
            buzzmsg_payload_destroy(&m);
            break;
         }
         /* Add message length to data buffer */
         cData << static_cast<UInt16>(buzzmsg_payload_size(m));
         /* Add payload to data buffer */
         cData.AddBuffer(reinterpret_cast<UInt8*>(m->data), buzzmsg_payload_size(m));
      }
      else {
         RLOGERR << "Discarded oversize message ("
                 << unMsgSize
                 << " bytes). Max size is "
                 << m_pcRABA->GetSize() - sizeof(UInt16)
                 << " bytes."
                 << std::endl;
      }
      /* Get rid of message */
      buzzoutmsg_queue_next(m_tBuzzVM);
      buzzmsg_payload_destroy(&m);
   } while(1);
   /* Pad the rest of the data with zeroes */
   while(cData.Size() < m_pcRABA->GetSize()) cData << static_cast<UInt8>(0);
   /* Send message */
   m_pcRABA->SetData(cData);
}
Exemplo n.º 3
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);
}