else mpiPi_msg_debug ("mpiPi.av[0] is NULL.\n");
mpiPi_mergeResults (){  int ac;  callsite_stats_t **av;  int totalCount = 0;  /* gather local task data */  h_gather_data (mpiPi.task_callsite_stats, &ac, (void ***) &av);  /* determine size of space necessary on collector */  PMPI_Reduce (&ac, &totalCount, 1, MPI_INT, MPI_SUM, mpiPi.collectorRank,	       mpiPi.comm);  if ((totalCount < 1) && (mpiPi.rank == mpiPi.collectorRank))    {      mpiPi_msg_warn	("Collector found no records to merge. Omitting report.\n");      return 0;    }  /* gather global data at collector */  if (mpiPi.rank == mpiPi.collectorRank)    {      int i;      int ndx = 0;      mpiPi.rawCallsiteData =	(callsite_stats_t *) calloc (totalCount, sizeof (callsite_stats_t));      for (ndx = 0; ndx < ac; ndx++)	{	  bcopy (av[ndx], &(mpiPi.rawCallsiteData[ndx]),		 sizeof (callsite_stats_t));	}      for (i = 1; i < mpiPi.size; i++)	/* n-1 */	{	  MPI_Status status;	  int count;	  /* okay in any order */	  PMPI_Probe (MPI_ANY_SOURCE, mpiPi.tag, mpiPi.comm, &status);	  PMPI_Get_count (&status, MPI_CHAR, &count);	  PMPI_Recv (&(mpiPi.rawCallsiteData[ndx]), count, MPI_CHAR,		     status.MPI_SOURCE, mpiPi.tag, mpiPi.comm, &status);	  count /= sizeof (callsite_stats_t);	  ndx += count;	}    }  else    {      int ndx;      char *sbuf = (char *) malloc (ac * sizeof (callsite_stats_t));      for (ndx = 0; ndx < ac; ndx++)	{	  bcopy (av[ndx],		 &(sbuf[ndx * sizeof (callsite_stats_t)]),		 sizeof (callsite_stats_t));	}      PMPI_Send (sbuf, ac * sizeof (callsite_stats_t),		 MPI_CHAR, mpiPi.collectorRank, mpiPi.tag, mpiPi.comm);      free (sbuf);    }  /* TODO: need to free all these pointers as well. */  free (av);  /* only work for collector remains */  if (mpiPi.rank == mpiPi.collectorRank)    {      int i;#ifndef DISABLE_BFD      if ( mpiPi.av[0] != NULL )        open_bfd_executable (mpiPi.av[0]);#endif      /* convert data to src line; merge, if nec */      mpiPi.global_callsite_stats = h_open (mpiPi.tableSize,					    mpiPi_callsite_stats_src_hashkey,					    mpiPi_callsite_stats_src_comparator);      mpiPi.global_callsite_stats_agg = h_open (mpiPi.tableSize,						mpiPi_callsite_stats_src_id_hashkey,						mpiPi_callsite_stats_src_id_comparator);      callsite_pc_cache = h_open (mpiPi.tableSize,				  callsite_pc_cache_hashkey,				  callsite_pc_cache_comparator);      callsite_src_id_cache = h_open (mpiPi.tableSize,				      callsite_src_id_cache_hashkey,				      callsite_src_id_cache_comparator);      /* TODO: when is the best time to free/close these tables? */      mpiPi_msg_debug ("Beginning src code lookup and accumulation of raw "		       "callsite data. %d records.\n", totalCount);      for (i = 0; i < totalCount; i++)	{	  callsite_stats_t *p = &(mpiPi.rawCallsiteData[i]);	  callsite_stats_t *csp = NULL;	  /* lookup file/line */          mpiPi_query_src (p);	/* sets the file/line in p */	  /* If exists, accumulate, otherwise insert. This is	     specifically for optimizations that have multiple PCs for	     one src line. We aggregate across rank after this. */	  if (NULL ==	      h_search (mpiPi.global_callsite_stats, p, (void **) &csp))	    {	      int j;	      callsite_stats_t *newp = NULL;	      newp = (callsite_stats_t *) malloc (sizeof (callsite_stats_t));	      bzero (newp, sizeof (callsite_stats_t));	      newp->op = p->op;	      newp->rank = p->rank;	      for (j = 0; j < MPIP_CALLSITE_STACK_DEPTH; j++)		{		  newp->pc[j] = p->pc[j];		  newp->filename[j] = p->filename[j];		  newp->functname[j] = p->functname[j];		  newp->lineno[j] = p->lineno[j];		}	      newp->csid = p->csid;	      newp->count = p->count;	      newp->cumulativeTime = p->cumulativeTime;	      newp->cumulativeTimeSquared = p->cumulativeTimeSquared;	      newp->maxDur = p->maxDur;	      newp->minDur = p->minDur;	      newp->maxDataSent = p->maxDataSent;	      newp->minDataSent = p->minDataSent;	      newp->cumulativeDataSent = p->cumulativeDataSent;	      newp->maxIO = p->maxIO;	      newp->minIO = p->minIO;	      newp->cumulativeIO = p->cumulativeIO;	      newp->cookie = MPIP_CALLSITE_STATS_COOKIE;	      /* insert new record into global */	      h_insert (mpiPi.global_callsite_stats, newp);	    }	  else	    {	      csp->count += p->count;	      csp->cumulativeTime += p->cumulativeTime;	      csp->cumulativeTimeSquared += p->cumulativeTimeSquared;	      csp->maxDur = max (csp->maxDur, p->maxDur);	      csp->minDur = min (csp->minDur, p->minDur);              csp->maxDataSent = max (csp->maxDataSent, p->maxDataSent);              csp->minDataSent = min (csp->minDataSent, p->minDataSent);              csp->cumulativeDataSent += p->cumulativeDataSent;	      csp->maxIO = max (csp->maxIO, p->maxIO);	      csp->minIO = min (csp->minIO, p->minIO);              csp->cumulativeIO += p->cumulativeIO;	    }	  /* agg. Don't use rank */	  if (NULL ==	      h_search (mpiPi.global_callsite_stats_agg, p, (void **) &csp))	    {	      int j;	      callsite_stats_t *newp = NULL;	      newp = (callsite_stats_t *) malloc (sizeof (callsite_stats_t));	      bzero (newp, sizeof (callsite_stats_t));	      newp->op = p->op;	      newp->rank = -1;	      for (j = 0; j < MPIP_CALLSITE_STACK_DEPTH; j++)		{		  newp->pc[j] = p->pc[j];		  newp->filename[j] = p->filename[j];		  newp->functname[j] = p->functname[j];		  newp->lineno[j] = p->lineno[j];		}	      newp->csid = p->csid;	      newp->count = p->count;	      newp->cumulativeTime = p->cumulativeTime;	      newp->cumulativeTimeSquared = p->cumulativeTimeSquared;	      newp->maxDur = p->maxDur;	      newp->minDur = p->minDur;	      newp->maxDataSent = p->maxDataSent;	      newp->minDataSent = p->minDataSent;	      newp->cumulativeDataSent = p->cumulativeDataSent;	      newp->cumulativeIO = p->cumulativeIO;	      newp->maxIO = p->maxIO;	      newp->minIO = p->minIO;	      newp->cookie = MPIP_CALLSITE_STATS_COOKIE;	      if ( mpiPi.calcCOV )	      {                newp->siteData = (double*)malloc(mpiPi.size*sizeof(double));                newp->siteData[0] = p->cumulativeTime;                newp->siteDataIdx = 1;	      }	      /* insert new record into global */	      h_insert (mpiPi.global_callsite_stats_agg, newp);	    }	  else	    {	      csp->count += p->count;	      csp->cumulativeTime += p->cumulativeTime;	      csp->cumulativeTimeSquared += p->cumulativeTimeSquared;	      csp->maxDur = max (csp->maxDur, p->maxDur);	      csp->minDur = min (csp->minDur, p->minDur);              csp->maxDataSent = max (csp->maxDataSent, p->maxDataSent);              csp->minDataSent = min (csp->minDataSent, p->minDataSent);	      csp->cumulativeDataSent += p->cumulativeDataSent;              csp->maxIO = max (csp->maxIO, p->maxIO);              csp->minIO = min (csp->minIO, p->minIO);	      csp->cumulativeIO += p->cumulativeIO;	      if ( mpiPi.calcCOV )	      {                csp->siteData[csp->siteDataIdx] = p->cumulativeTime;                csp->siteDataIdx++;	      }	    }	  mpiPi_msg_debug ("%d: %d %d=[%s,%d,%s]\n", i, p->op, p->csid,			   p->filename[0], p->lineno[0], p->functname[0]);	}#ifndef DISABLE_BFD      /* clean up */      if ( mpiPi.av[0] != NULL )        close_bfd_executable ();#endif    }  return 1;}