Beispiel #1
0
void offlineInit() {

#ifdef INSERTION_TEST
    gettimeofday(&offlineInitDate, NULL);
#endif /* INSERTION_TEST */

    participate(true);
    succ = searchSucc(myAddress);
    if (addrIsMine(succ)) {
        signalArrival(myAddress, (addressSet) myAddress);
        bqueueEnqueue(wagonsToDeliver, wagonToSend);
        wagonToSend = newWiw();
        automatonState = ALONE_INSERT_WAIT;
        //printf("Nextstate(fake) = %s\n", stateToStr(automatonState));
        int rc = sem_post(sem_init_done);
        if (rc)
            ERROR_AT_LINE(EXIT_FAILURE, errno, __FILE__, __LINE__,
                          "error in sem_post");
        prec = myAddress;
        return;
    }
    sendOther(succ, false, INSERT, myAddress);
    automatonState = OFFLINE_CONNECTION_ATTEMPT;
    //printf("Nextstate(fake) = %s\n", stateToStr(automatonState));
    return;
}
Beispiel #2
0
void automatonInit() {
    int id;
    int round;
    srand(getpid() + time(NULL ));
    pthread_mutex_init(&stateMachineMutex, NULL );

    lis = ntr - 1;
    for (id = 0; id < ntr; id++) {
        //(lts[id]).lng is not initialized because lng is only set in sendTrain()
        (lts[id]).type = TRAIN;
        (lts[id]).stamp.id = id;
        (lts[id]).stamp.lc = 0;
        (lts[id]).stamp.round = 0;
        (lts[id]).circuit = 0;
        (lts[id]).w.w_w.p_wagon = NULL;
        (lts[id]).w.w_w.p_womim = NULL;
        (lts[id]).w.len = 0;
        (lts[id]).p_wtosend = NULL;
        for (round = 0; round < NR; round++) {
            unstableWagons[id][round] = newList();
        }
    }
    cameProc = 0;
    goneProc = 0;
    wagonToSend = newWiw();
    wagonsToDeliver = newBqueue();

    prec = 0;
    succ = 0;
    MUTEX_LOCK(stateMachineMutex);
    nextState(OFFLINE_CONNECTION_ATTEMPT);
    MUTEX_UNLOCK(stateMachineMutex);
}
Beispiel #3
0
int main(int argc, char *argv[]){

  int i, j;
  int rc;
  int msgCounter;
  int wagonSizes[] = { 1024, 2048, 4096, 8192, 16384, 32768, 65536 };
  int payloadSizes[] = { 10, 100, 200, 500, 1000, 2000, 5000, 10000, 15000,
      20000 };
  struct timeval debut, fin, duree;
  struct rusage debutCPU, finCPU, dureeCPU;
  long elapsedTime, cpuTime;

  MUTEX_LOCK(stateMachineMutex);
  automatonState = SEVERAL;
  MUTEX_UNLOCK(stateMachineMutex);

  printf("Début de l'experience\n");

  for (i = 0; i < 7; i++) {
    for (j = 0; j < 10; j++) {
      // initialisation du wagon
      wagonMaxLen = wagonSizes[i];
      wagonToSend = newWiw();
      msgCounter = 0;

// start timers
      printf("Début du remplissage...\n");
      getrusage(RUSAGE_SELF, &debutCPU);
      gettimeofday(&debut, NULL );

// remplissage du wagon

      while (wagonToSend->p_wagon->header.len + payloadSizes[j]
          + sizeof(messageHeader) < wagonMaxLen) {
        message *mp = newmsg(payloadSizes[j]);
        if (mp == NULL ) {
          trError_at_line(rc, trErrno, __FILE__, __LINE__, "newmsg()");
          exit(EXIT_FAILURE);
        }
        if (utoBroadcast(mp) < 0) {
          trError_at_line(rc, trErrno, __FILE__, __LINE__, "utoBroadcast()");
          exit(EXIT_FAILURE);
        }
        msgCounter++;
      }

// stop timers
      gettimeofday(&fin, NULL );
      getrusage(RUSAGE_SELF, &finCPU);
      printf("Remplissage terminé\n");

// calculs
      timersub(&(finCPU.ru_utime), &(debutCPU.ru_utime), &(dureeCPU.ru_utime));
      timersub(&(finCPU.ru_stime), &(debutCPU.ru_stime), &(dureeCPU.ru_stime));
      timersub(&fin, &debut, &duree);

      elapsedTime = (1000000 * duree.tv_sec + duree.tv_usec);
      cpuTime = ((1000000
          * (dureeCPU.ru_utime.tv_sec + dureeCPU.ru_stime.tv_sec))
          + dureeCPU.ru_utime.tv_usec + dureeCPU.ru_stime.tv_usec);

      printf("********************************\n"
          "*********************************\n"
          "Messages de %d octets dans un wagon de %d octets\n", payloadSizes[j],
          wagonSizes[i]);
      printf("%d messages écrits\n", msgCounter);
      if (msgCounter > 0) {
        printf(
            "Temps absolu écoulé :          %9ld usec par message (%9ld au total)\n",
            elapsedTime / msgCounter, elapsedTime);
        printf(
            "Temps CPU (user+sys) écoulé :  %9ld usec par message (%9ld au total)\n",
            cpuTime / msgCounter, cpuTime);
      }
      printf("**************************\n");

      // free ressources
      freeWiw(wagonToSend);

    }
  }

  return EXIT_SUCCESS;
}
Beispiel #4
0
void stateMachine(womim* p_womim) {
    int id;
    MUTEX_LOCK(stateMachineMutex);
    //printf("State = %s, receive message = %s\n", stateToStr(automatonState), msgTypeToStr(p_womim->msg.type));
    switch (automatonState) {
    case OFFLINE_CONNECTION_ATTEMPT:
        switch (p_womim->msg.type) {
        case NAK_INSERT:
        case DISCONNECT_PRED:
        case DISCONNECT_SUCC:
            freeWomim(p_womim);
            nextState(WAIT);
            break;
        case INSERT:
            prec = p_womim->msg.body.insert.sender;
            sendOther(p_womim->msg.body.insert.sender, true, NAK_INSERT, myAddress);
            freeWomim(p_womim);
            break;
        case ACK_INSERT:
            prec = p_womim->msg.body.ackInsert.sender;
            openConnection(prec, true);
            sendOther(prec, true, NEWSUCC, myAddress);
            freeWomim(p_womim);
            nextState(OFFLINE_CONFIRMATION_WAIT);
            break;
        default:
            ERROR_AT_LINE_WITHOUT_ERRNUM(EXIT_FAILURE, __FILE__, __LINE__,
                                         "unexpected case : received message %s in state %s",
                                         msgTypeToStr(p_womim->msg.type), stateToStr(automatonState));
            break;
        }
        break;

    case OFFLINE_CONFIRMATION_WAIT:
        switch (p_womim->msg.type) {
        case NEWSUCC:
        case DISCONNECT_PRED:
        case DISCONNECT_SUCC:
            freeWomim(p_womim);
            nextState(WAIT);
            break;
        case INSERT:
            sendOther(p_womim->msg.body.insert.sender, true, NAK_INSERT, myAddress);
            freeWomim(p_womim);
            break;
        case TRAIN:
            id = (int) p_womim->msg.body.train.stamp.id;
            if (addrIsMember(myAddress, p_womim->msg.body.train.circuit)) {
                p_womim->msg.body.train.stamp.lc++;
            }
            releaseWiw(&(lts[id].w.w_w));
            lts[id].w.len = 0;
            if (firstWagon(&(p_womim->msg)) != NULL ) {
                lts[id].w.w_w.p_wagon = firstWagon(&(p_womim->msg));
                lts[id].w.w_w.p_womim = p_womim;
                lts[id].w.len = (p_womim->msg.len - sizeof(stamp) - sizeof(int)
                                 - sizeof(MType) - sizeof(address));
                // We do not need to lock the p_womim->pfx.mutex as we are the only thread
                // accessing to counter
                p_womim->pfx.counter++;
            }
            lts[id].circuit = p_womim->msg.body.train.circuit;
            lts[id].stamp = p_womim->msg.body.train.stamp;
            sendTrain(succ, false, lts[id]);
            if (isInLts(myAddress, lts)) {
#ifdef INSERTION_TEST
                gettimeofday(&trainDate, NULL);
                timersub(&trainDate, &offlineInitDate, &insertionDuration);
                floatInsertionDuration = ((double) insertionDuration.tv_sec) * 1000
                                         + ((double) insertionDuration.tv_usec) / 1000;
                printf("My insertion duration : %.3lfms\n", floatInsertionDuration);
                printf("number of times automaton has been in state WAIT ; %llu\n", counters.wait_states);
#endif /* INSERTION_TEST */
                lis = p_womim->msg.body.train.stamp.id;
                signalArrival(myAddress, lts[lis].circuit);
                nextState(SEVERAL);
                int rc = sem_post(sem_init_done);
                if (rc)
                    ERROR_AT_LINE(EXIT_FAILURE, errno, __FILE__, __LINE__,
                                  "error in sem_post");
            }
            freeWomim(p_womim);
            break;
        default:
            ERROR_AT_LINE_WITHOUT_ERRNUM(EXIT_FAILURE, __FILE__, __LINE__,
                                         "unexpected case : received message %s in state %s",
                                         msgTypeToStr(p_womim->msg.type), stateToStr(automatonState));
            freeWomim(p_womim);
            break;
        }
        break;

    case WAIT:
        freeWomim(p_womim);
        break;

    case ALONE_INSERT_WAIT:
        switch (p_womim->msg.type) {
        case DISCONNECT_PRED:
        case DISCONNECT_SUCC:
            // May happen in case there are 2 processes on the circuit and one process dies
            // The other process receives DISCONNECT in SEVERAL state and switched to
            // ALONE_INSERT_WAIT state, where it receives the DISCONNECT corresponding
            // to the loss of the second connection
            freeWomim(p_womim);
            break;
        case INSERT:
            MUTEX_LOCK(mutexWagonToSend);
            sendOther(p_womim->msg.body.insert.sender, true, ACK_INSERT, myAddress);
            prec = p_womim->msg.body.insert.sender;
            freeWomim(p_womim);
            nextState(ALONE_CONNECTION_WAIT);
            MUTEX_UNLOCK(mutexWagonToSend);
            break;
        default:
            ERROR_AT_LINE_WITHOUT_ERRNUM(EXIT_FAILURE, __FILE__, __LINE__,
                                         "unexpected case : received message %s in state %s",
                                         msgTypeToStr(p_womim->msg.type), stateToStr(automatonState));
            freeWomim(p_womim);
            break;
        }
        break;

    case ALONE_CONNECTION_WAIT:
        switch (p_womim->msg.type) {
        case DISCONNECT_PRED:
            nextState(ALONE_INSERT_WAIT);
            freeWomim(p_womim);
            break;
        case INSERT:
            // In the PhD-thesis algorithm, we are supposed to do a
            // saveUntilNextstate(p_womim). Sending a NAK_INSERT is more simple.
            sendOther(p_womim->msg.body.insert.sender, true, NAK_INSERT, myAddress);
            freeWomim(p_womim);
            break;
        case NEWSUCC:
            succ = p_womim->msg.body.newSucc.sender;
            int i;
            for (i = 1; i <= ntr; i++) {
                int id = ((lis + i) % ntr);
                (lts[(int) id]).stamp.lc += 1;
                (lts[(int) id]).circuit = myAddress | prec;
                (lts[(int) id]).w.w_w.p_wagon = NULL;
                (lts[(int) id]).w.w_w.p_womim = NULL;
                (lts[(int) id]).w.len = 0;
                sendTrain(succ, false, lts[(int) id]);
            }
            freeWomim(p_womim);
            nextState(SEVERAL);
            break;
        default:
            ERROR_AT_LINE_WITHOUT_ERRNUM(EXIT_FAILURE, __FILE__, __LINE__,
                                         "unexpected case : received message %s in state %s",
                                         msgTypeToStr(p_womim->msg.type), stateToStr(automatonState));
            freeWomim(p_womim);
            break;
        }
        break;

    case SEVERAL:
        switch (p_womim->msg.type) {
        case TRAIN:
            if (addrIsMember(myAddress, p_womim->msg.body.train.circuit)) {
                if (isRecentTrain(p_womim->msg.body.train.stamp, lts, lis)) {
#ifdef INSERTION_TEST
                    if (theLostPrec != 0) {
                        if (recentlyLostMyPred) {
                            gettimeofday(&firstRecentTrainDate, NULL);
                            recentlyLostMyPred = false;
                        }
                        if (!isInLts(theLostPrec,lts)) {
                            gettimeofday(&firstNewCircuitDate, NULL);
                            theLostPrec = 0;

                            timersub(&firstRecentTrainDate, &discoPredDate, &recoveryRecentTrainDuration);
                            timersub(&firstNewCircuitDate, &discoPredDate, &recoveryNewCircuitDuration);

                            floatRecoveryRecentTrainDuration = ((double) recoveryRecentTrainDuration.tv_sec) * 1000
                                                               + ((double) recoveryRecentTrainDuration.tv_usec) / 1000;

                            floatRecoveryNewCircuitDuration = ((double) recoveryNewCircuitDuration.tv_sec) * 1000
                                                              + ((double) recoveryNewCircuitDuration.tv_usec) / 1000;

                            printf("Disconnection pred recovery :\n");
                            printf("\t- First recent train after %.3lfms\n", floatRecoveryRecentTrainDuration);
                            printf("\t- Up-to-date circuit received after %.3lfms\n", floatRecoveryNewCircuitDuration);

                        }
                    }
#endif /* INSERTION_TEST */
                    trainHandling(p_womim);
                    lis = p_womim->msg.body.train.stamp.id;
                    if (succ != 0)
                        sendTrain(succ, false, lts[lis]);
                }
            } else {
                ERROR_AT_LINE_WITHOUT_ERRNUM(EXIT_FAILURE, __FILE__, __LINE__,
                                             "myAddress not in the circuit ==> Suicide");
            }
            freeWomim(p_womim);
            break;
        case INSERT:
            closeConnection(prec, true);
            sendOther(p_womim->msg.body.insert.sender, true, ACK_INSERT, prec);
            prec = p_womim->msg.body.insert.sender;
            addrAppendArrived(&cameProc, prec);
            freeWomim(p_womim);
            break;
        case NEWSUCC:
            if (succ != 0)
                closeConnection(succ, false);
            succ = p_womim->msg.body.newSucc.sender;
            int i;
            for (i = 1; i <= ntr; i++) {
                sendTrain(succ, false, lts[(lis + i) % ntr]);
            }
            freeWomim(p_womim);
            break;
        case DISCONNECT_PRED:
#ifdef INSERTION_TEST
            gettimeofday(&discoPredDate, NULL);
            recentlyLostMyPred = true;
            theLostPrec = prec;
#endif /* INSERTION_TEST */
            MUTEX_LOCK(mutexWagonToSend);
            while (!(addrIsEqual(prec,myAddress))) {
                if (openConnection(prec, true) != (-1)) {
                    sendOther(prec, true, NEWSUCC, myAddress);
                    freeWomim(p_womim);
                    nextState(SEVERAL);
                    MUTEX_UNLOCK(stateMachineMutex);
                    MUTEX_UNLOCK(mutexWagonToSend);
                    return;
                }
                addrAppendGone(&cameProc, &goneProc, prec);
                prec = addrPrec(prec, lts[lis].circuit);
            }
            signalDepartures(goneProc, lts[lis].circuit, true);
            goneProc = 0;
            int aRound;
            for (aRound = 1; aRound <= NR; aRound++) {
                int i;
                for (i = 1; i <= ntr; i++) {
                    int id = (lis + i) % ntr;
                    int round = (lts[id].stamp.round + aRound) % NR;
                    bqueueExtend(wagonsToDeliver, unstableWagons[id][round]);
                    cleanList(unstableWagons[id][round]);
                }
            }
            bqueueEnqueue(wagonsToDeliver, wagonToSend);
            wagonToSend = newWiw();
            freeWomim(p_womim);
#ifdef INSERTION_TEST
            gettimeofday(&firstNewCircuitDate, NULL);
            timersub(&firstNewCircuitDate, &discoPredDate, &recoveryNewCircuitDuration);
            floatRecoveryNewCircuitDuration = ((double) recoveryNewCircuitDuration.tv_sec) * 1000
                                              + ((double) recoveryNewCircuitDuration.tv_usec) / 1000;
            printf("I am alone !\n"
                   "%.3lfms since the DISCONNECT_PRED message\n", floatRecoveryNewCircuitDuration);
#endif /* INSERTION_TEST */
            nextState(ALONE_INSERT_WAIT);
            MUTEX_UNLOCK(stateMachineMutex);
            MUTEX_UNLOCK(mutexWagonToSend);
            pthread_cond_signal(&condWagonToSend);
            break;
        case DISCONNECT_SUCC:
            succ = 0;
            freeWomim(p_womim);
            break;
        default:
            ERROR_AT_LINE_WITHOUT_ERRNUM(EXIT_FAILURE, __FILE__, __LINE__,
                                         "unexpected case : received message %s in state %s",
                                         msgTypeToStr(p_womim->msg.type), stateToStr(automatonState));
            break;
        }
        break;
    default:
        ERROR_AT_LINE_WITHOUT_ERRNUM(EXIT_FAILURE, __FILE__, __LINE__, "Unknown state : %d",
                                     automatonState);
        freeWomim(p_womim);
        break;
    }
    MUTEX_UNLOCK(stateMachineMutex);
}
Beispiel #5
0
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;
}