#include "mpi.h"
#include <stdio.h>
#include "ic_nxtval.h"

#define ICTAG 0

int MPE_Counter_create_ic(MPI_Comm oldcomm, MPI_Comm *smaller_comm, 
			  MPI_Comm *counter_comm)
{
    int counter = 0, message, done = 0, myid, numprocs, server;
    int color, remote_leader_rank;
    MPI_Status status;
    MPI_Comm oldcommdup, splitcomm;

    MPI_Comm_dup(oldcomm, &oldcommdup); 
    MPI_Comm_size(oldcommdup, &numprocs);
    MPI_Comm_rank(oldcommdup, &myid);
    server = numprocs-1;       /* last proc is server */
    /* server = 0; */
    color = (myid == server);  /* split into server and rest */
    MPI_Comm_split(oldcomm, color, myid, &splitcomm);

    /* build intercommunicator using bridge w/ oldcommdup */
    if(!color) { /* I am not the server */
	/* 1) the non-server leader process is chosen to have rank
              "0" in the peer comm. oldcommdup != rank of server 
	   guaranteed that this leader "0" has rank "0" in both 
           oldcommdup and in this splitcomm too, by virtue of 
           MPI_Comm_split 
	   2) server has rank "server" in oldcommdup */

	remote_leader_rank = server; /* server rank, oldcommdup */
	*smaller_comm = splitcomm; /* return new, smaller world */
    }
    else {
	remote_leader_rank = 0; /* non-server leader, oldcommdup */
	*smaller_comm = MPI_COMM_NULL;
    }

    MPI_Intercomm_create(splitcomm, 0, oldcommdup,
                         remote_leader_rank, ICTAG, counter_comm);
    MPI_Comm_free(&oldcommdup); /* not needed after
                                   Intercomm_create */

    /* The rest is the same code as in nxtval_create.c */
    if (myid == server) {       /* I am the server */
        while (!done) {
            MPI_Recv(&message, 1, MPI_INT, MPI_ANY_SOURCE, 
                     MPI_ANY_TAG, *counter_comm, &status ); 
            if (status.MPI_TAG == REQUEST) {
                MPI_Send(&counter, 1, MPI_INT, status.MPI_SOURCE, 
                         VALUE, *counter_comm );
                counter++;
            }
            else if (status.MPI_TAG == GOAWAY) {
                done = 1;
            }
            else {
                fprintf(stderr, "bad tag %d sent to MPE counter\n",
                        status.MPI_TAG );
		MPI_Abort( *counter_comm, 1 );
	    }
        }
	MPI_Comm_free( counter_comm );
    }
}
