//send a train -> use sendOther to send the rest int sendTrain(address addr, bool isPred, ltsStruct lts){ int iovcnt = 3; struct iovec iov[iovcnt]; int rank = -1; trComm * aComm; int result; rank = addrToRank(addr); if (rank != -1) { aComm = getTComm(rank, isPred, globalAddrArray); if (aComm == NULL ) { return (-1); } //printf("The train %d/%d is sent to %d on comm %p\n",lts.stamp.id,lts.stamp.lc,addr, aComm); lts.lng = sizeof(lts.lng) + sizeof(lts.type) + sizeof(lts.stamp) + sizeof(lts.circuit); //to begin, let's enter the length of the message iov[0].iov_base = &(lts); iov[0].iov_len = lts.lng; //after loading the wagons //look after to be sure there are wagons to send... if (lts.w.len != 0) { //check if there are wagons lts.lng += lts.w.len; iov[1].iov_base = lts.w.w_w.p_wagon; iov[1].iov_len = lts.w.len; } else { iov[1].iov_base = NULL; iov[1].iov_len = 0; } //finally loading the wagon which is waiting to be sent //look after to be sure that p_wtosend exists or not... if (lts.p_wtosend == NULL ) { //check if p_wtosend is NULL iov[2].iov_base = NULL; iov[2].iov_len = 0; } else { if (firstMsg(lts.p_wtosend->p_wagon) == NULL ) { //check if p_wtosend is not just a header printf("wagonToSend is just a header \n"); iov[2].iov_base = NULL; iov[2].iov_len = 0; } else { lts.lng += lts.p_wtosend->p_wagon->header.len; iov[2].iov_base = lts.p_wtosend->p_wagon; iov[2].iov_len = lts.p_wtosend->p_wagon->header.len; } } //sending the whole train with writev //returning the number of bytes sent result = commWritev(aComm, iov, iovcnt); if (result != lts.lng) fprintf(stderr, "result!=lts.lng (bis) with result=%i and length=%i (errno = %i / %s)\n", result, lts.lng, errno, strerror(errno)); return (result); } else { //should return an error if the addr is out of rank error_at_line(EXIT_FAILURE, errno, __FILE__, __LINE__, "Sending failure in sendTrain (addr = %d)", addr); return (-1); //same error as commWritev !! } }
void trainHandling(womim *p_womim) { int id = p_womim->msg.body.train.stamp.id; int round = p_womim->msg.body.train.stamp.round; wagon *p_wag; counters.recent_trains_received++; counters.recent_trains_bytes_received += p_womim->msg.len; //printf("TRAIN id=%d\n", id); if (round == lts[id].stamp.round) { round = (round + 1) % nbRounds; } if (requiredOrder != CAUSAL_ORDER) { // Thus (requiredOrder == TOTAL_ORDER) || (requiredOrder == UNIFORM_TOTAL_ORDER)) bqueueExtend(wagonsToDeliver, unstableWagons[id][(round + 1) % nbRounds]); cleanList(unstableWagons[id][(round + 1) % nbRounds]); } if (id == 0) { lts[0].circuit = addrUpdateCircuit(p_womim->msg.body.train.circuit, myAddress, cameProc, goneProc); cameProc = 0; signalDepartures(goneProc, lts[0].circuit, false); goneProc = 0; } else { lts[id].circuit = lts[0].circuit; } releaseWiw(&(lts[id].w.w_w)); lts[id].w.len = 0; freeWiw(lts[id].p_wtosend); lts[id].p_wtosend = NULL; for (p_wag = firstWagon(&(p_womim->msg)); p_wag != NULL ; p_wag = nextWagon(p_womim, p_wag)) { if (addrIsMember(p_wag->header.sender, lts[id].circuit) && !(addrIsMember(p_wag->header.sender, goneProc)) && !(addrIsMine(p_wag->header.sender))) { // We add a wiw (corresponding to this p_wag) to unstableWagons[id][round] // (in case of TOTAL_ORDER or UNIFORM_TOTAL_ORDER) or directly to // wagonsToDeliver (in case of CAUSAL_ORDER) wiw *wi = malloc(sizeof(wiw)); assert(wi != NULL); wi->p_wagon = p_wag; wi->p_womim = p_womim; MUTEX_LOCK(p_womim->pfx.mutex); p_womim->pfx.counter++; MUTEX_UNLOCK(p_womim->pfx.mutex); if (requiredOrder != CAUSAL_ORDER) { // Thus (requiredOrder == TOTAL_ORDER) || (requiredOrder == UNIFORM_TOTAL_ORDER)) listAppend(unstableWagons[id][round], wi); } else { bqueueEnqueue(wagonsToDeliver, wi); } // Shall this wagon be sent to our successor if (!addrIsEqual(succ,p_wag->header.sender)) { // Yes, it must sent if (lts[id].w.w_w.p_wagon == NULL ) { // lts must be updated to point on the first wagon to be sent lts[id].w.w_w.p_wagon = p_wag; lts[id].w.w_w.p_womim = p_womim; MUTEX_LOCK(lts[id].w.w_w.p_womim->pfx.mutex); lts[id].w.w_w.p_womim->pfx.counter++; MUTEX_UNLOCK(lts[id].w.w_w.p_womim->pfx.mutex); } // We adapt len lts[id].w.len += p_wag->header.len; } } } lts[id].stamp.round = (char) round; MUTEX_LOCK(mutexWagonToSend); if (firstMsg(wagonToSend->p_wagon) != NULL ) { wagonToSend->p_wagon->header.round = round; // We add a wiw (corresponding to this p_wag) to wagonToSend wiw *wi = malloc(sizeof(wiw)); assert(wi != NULL); *wi = *wagonToSend; // We do not need to lock wagonToSend->p_wagon->pfx.mutex // as we are for the moment alone to access to // wagonToSend->p_wagon->pfx.counter wagonToSend->p_womim->pfx.counter++; if (requiredOrder != CAUSAL_ORDER) { // Thus (requiredOrder == TOTAL_ORDER) || (requiredOrder == UNIFORM_TOTAL_ORDER)) listAppend(unstableWagons[id][round], wi); } else { bqueueEnqueue(wagonsToDeliver, wi); } lts[id].p_wtosend = wagonToSend; wagonToSend = newWiw(); } MUTEX_UNLOCK(mutexWagonToSend); pthread_cond_signal(&condWagonToSend); lts[id].stamp.lc = p_womim->msg.body.train.stamp.lc + 1; }