static int DD_Find_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid, /* incoming GID to locate (in) */ ZOLTAN_ID_PTR lid, /* gid's LID (out) */ char *user, /* gid's user data (out) */ int *partition, /* gid's partition number (out) */ int *owner) /* gid's owner (processor number) (out) */ { DD_Node *ptr; DD_NodeIdx nodeidx; int index; char *yo = "DD_Find_Local"; /* input sanity check */ if (dd == NULL || owner == NULL || gid == NULL) { ZOLTAN_PRINT_ERROR ((dd == NULL) ? 0 : dd->my_proc, yo, "Invalid input"); return ZOLTAN_FATAL; } if (dd->debug_level > 5) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* compute offset into hash table to find head of linked list */ index = Zoltan_DD_Hash2 (gid, dd->gid_length, dd->table_length, dd->hashdata, NULL); /* walk link list until end looking for matching global ID */ for (nodeidx = dd->table[index]; nodeidx != -1; nodeidx = dd->nodelist[nodeidx].next) { ptr = dd->nodelist + nodeidx; if (ZOLTAN_EQ_ID (dd->gid_length, gid, ptr->gid) == TRUE) { /* matching global ID found! Return gid's information */ if (lid) ZOLTAN_SET_ID(dd->lid_length, lid, ptr->gid + dd->gid_length); if (user) memcpy(user, ptr->gid + (dd->gid_length + dd->lid_length), dd->user_data_length); if (owner) *owner = ptr->owner; if (partition) *partition = ptr->partition; if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; } } if (owner != NULL) *owner = -1; /* JDT Added -1 owner not found */ if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); if (dd->debug_level > 0) { ZOLTAN_PRINT_INFO(dd->my_proc, yo, "GID not found"); return ZOLTAN_WARN; } return ZOLTAN_WARN; }
static int DD_Find_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid, /* incoming GID to locate (in) */ ZOLTAN_ID_PTR lid, /* gid's LID (out) */ ZOLTAN_ID_PTR user, /* gid's user data (out) */ int *partition, /* gid's partition number (out) */ int *owner) /* gid's owner (processor number) (out) */ { DD_Node *ptr ; int index ; char *yo = "DD_Find_Local" ; /* input sanity check */ if (dd == NULL || owner == NULL || gid == NULL) { ZOLTAN_PRINT_ERROR ((dd == NULL) ? 0 : dd->my_proc, yo, "Invalid input argument.") ; return ZOLTAN_DD_INPUT_ERROR ; } if (dd->debug_level > 2) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL) ; /* compute offset into hash table to find head of linked list */ index = Zoltan_DD_Hash2 (gid, dd->gid_length, dd->table_length) ; /* walk link list until end looking for matching global ID */ for (ptr = dd->table[index] ; ptr != NULL ; ptr = ptr->next) if (ZOLTAN_EQ_ID (dd->gid_length, gid, ptr->gid) == TRUE) { /* matching global ID found! Return gid's information */ if (lid) ZOLTAN_SET_ID(dd->lid_length, lid, ptr->gid + dd->gid_length); if (user) ZOLTAN_SET_ID(dd->user_data_length, user, ptr->gid + (dd->gid_length + dd->lid_length)); if (owner != NULL) *owner = ptr->owner ; if (partition != NULL) *partition = ptr->partition ; if (dd->debug_level > 2) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL) ; return ZOLTAN_DD_NORMAL_RETURN ; } if (dd->debug_level > 0) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "GID not found."); if (dd->debug_level > 2) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL) ; return ZOLTAN_DD_GID_NOT_FOUND_ERROR ; }
void Zoltan_DD_Destroy (Zoltan_DD_Directory **dd) { char *yo = "ZOLTAN_DD_Destroy"; /* input sanity check */ if (dd == NULL || *dd == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Input argument dd is NULL"); return; } if ((*dd)->debug_level > 4) ZOLTAN_TRACE_IN ((*dd)->my_proc, yo, NULL); ZOLTAN_FREE(&((*dd)->nodelist)); ZOLTAN_FREE(&((*dd)->nodedata)); /* execute user registered cleanup function, if needed */ if ((*dd)->cleanup != NULL) (*dd)->cleanup((*dd)->hashdata); MPI_Comm_free (&((*dd)->comm)); /* free MPI Comm, ignore errors */ if ((*dd)->debug_level > 4) ZOLTAN_TRACE_OUT ((*dd)->my_proc, yo, NULL); ZOLTAN_FREE (dd); /* free directory structure */ return; }
static int DD_Remove_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid) /* GID to be removed (in) */ { DD_Node *ptr; DD_NodeIdx nodeidx, prevnodeidx; int index; char *yo = "DD_Remove_Local"; /* input sanity checking */ if (dd == NULL || gid == NULL) { ZOLTAN_PRINT_ERROR ((dd == NULL) ? ZOLTAN_DD_NO_PROC : dd->my_proc, yo, "Invalid input argument"); return ZOLTAN_FATAL; } if (dd->debug_level > 5) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* compute offset into hash table to find head of linked list */ index = Zoltan_DD_Hash2 (gid, dd->gid_length, dd->table_length, dd->hashdata, NULL); /* walk linked list until end looking for matching gid (key) */ prevnodeidx = -1; for (nodeidx = dd->table[index]; nodeidx != -1; nodeidx = dd->nodelist[nodeidx].next) { ptr = dd->nodelist + nodeidx; if (ZOLTAN_EQ_ID(dd->gid_length, gid, ptr->gid) == TRUE) { /* found node to remove, need to preserve its next ptr */ if (prevnodeidx != -1) dd->nodelist[prevnodeidx].next = ptr->next; else dd->table[index] = ptr->next; DD_Memory_Free_Node(dd, nodeidx); /* now OK to delete node */ if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; } prevnodeidx = nodeidx; } /* We get here only if the global ID has not been found */ if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_WARN; }
void Zoltan_DD_Stats ( Zoltan_DD_Directory *dd) /* directory state information */ { int node_count = 0 ; /* counts Nodes in local directory */ int maxlength = 0; /* length of longest linked list */ int list_count = 0 ; /* number of linked lints in hash table */ int length ; int i ; DD_Node *ptr ; char str[100] ; /* used to build message string */ char *yo = "Zoltan_DD_Stats" ; /* Input sanity check */ if (dd == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Invalid input argument.") ; return ; } if (dd->debug_level > 4) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL) ; /* walk down each list in hash table to find every Node */ for (i = 0 ; i < dd->table_length ; i++) { length = 0 ; /* reset length for next count */ if (dd->table[i] != NULL) list_count++ ; /* count of distict linked lists */ for (ptr = dd->table[i] ; ptr != NULL ; ptr = ptr->next) { if (dd->debug_level > 6) { sprintf (str, "GID %4u, Owner %d, Table Index %d.", *ptr->gid, ptr->owner, i) ; ZOLTAN_PRINT_INFO (dd->my_proc, yo, str) ; } length++ ; /* linked list length */ node_count++ ; /* count of Nodes */ } if (length > maxlength) maxlength = length ; /* save length of longest linked list */ } sprintf (str, "Hash table size %d, %d nodes on %d lists, max list length %d.", dd->table_length, node_count, list_count, maxlength) ; ZOLTAN_PRINT_INFO (dd->my_proc, yo, str) ; if (dd->debug_level > 4) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL) ; }
static int DD_Remove_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid) /* GID to be removed (in) */ { DD_Node **ptr; DD_Node *old; int index; char *yo = "DD_Remove_Local"; /* input sanity checking */ if (dd == NULL || gid == NULL) { ZOLTAN_PRINT_ERROR ((dd == NULL) ? ZOLTAN_DD_NO_PROC : dd->my_proc, yo, "Invalid input argument"); return ZOLTAN_FATAL; } if (dd->debug_level > 5) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* compute offset into hash table to find head of linked list */ index = Zoltan_DD_Hash2 (gid, dd->gid_length, dd->table_length, dd->hashdata, NULL); /* walk linked list until end looking for matching gid (key) */ for (ptr = dd->table + index; *ptr != NULL; ptr = &((*ptr)->next)) if (ZOLTAN_EQ_ID(dd->gid_length, gid, (*ptr)->gid) == TRUE) { /* found node to remove, need to preserve its next ptr */ old = *ptr; *ptr = (*ptr)->next; ZOLTAN_FREE (&old); /* now OK to delete node */ if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; } /* We get here only if the global ID has not been found */ if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_WARN; }
int Zoltan_DD_Print ( Zoltan_DD_Directory *dd) /* contains directory state information */ { int i,j; DD_Node *ptr; char *yo = "Zoltan_DD_Print"; /* input sanity checks */ if (dd == NULL) { ZOLTAN_PRINT_ERROR (ZOLTAN_DD_NO_PROC, yo, "NULL dd input argument"); return ZOLTAN_FATAL; } if (dd->debug_level > 4) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* walk linked list printing each node */ for (i = 0; i < dd->table_length; i++) for (ptr = dd->table[i]; ptr != NULL; ptr = ptr->next) { printf ("ZOLTAN DD Print(%d): \tList %3d, \tGID ", dd->my_proc, i); printf("("); for (j = 0 ; j < dd->gid_length; j++) printf("%u ", ptr->gid[j]); printf(") "); if (dd->lid_length > 0) { printf("\tLID ("); for (j = 0; j < dd->lid_length; j++) printf("%u ", ptr->gid[j+dd->gid_length]); printf(") "); } printf ("\tPart %d\n", ptr->partition); printf ("\tOwner %d\n", ptr->owner); } if (dd->debug_level > 4) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL) ; return ZOLTAN_OK; }
void Zoltan_DD_Destroy ( Zoltan_DD_Directory **dd) /* contains directory state information */ { int i; DD_Node *ptr; DD_Node *next; char *yo = "ZOLTAN_DD_Destroy"; /* input sanity check */ if (dd == NULL || *dd == NULL) { ZOLTAN_PRINT_ERROR (0, yo, "Input argument dd is NULL"); return; } if ((*dd)->debug_level > 4) ZOLTAN_TRACE_IN ((*dd)->my_proc, yo, NULL); /* for each linked list head, walk its list freeing memory */ for (i = 0; i < (*dd)->table_length; i++) for (ptr = (*dd)->table[i]; ptr != NULL; ptr = next) { next = ptr->next; /* save before deletion */ ZOLTAN_FREE (&ptr); /* destroy node */ } /* execute user registered cleanup function, if needed */ if ((*dd)->cleanup != NULL) (*dd)->cleanup((*dd)->hashdata); MPI_Comm_free (&((*dd)->comm)); /* free MPI Comm, ignore errors */ if ((*dd)->debug_level > 4) ZOLTAN_TRACE_OUT ((*dd)->my_proc, yo, NULL); ZOLTAN_FREE (dd); /* free directory structure */ return; }
int Zoltan_DD_Remove ( Zoltan_DD_Directory *dd, /* directory state infomation */ ZOLTAN_ID_PTR gid, /* Incoming list of GIDs to remove */ int count) /* Number of GIDs in removal list */ { int *procs = NULL; /* list of processors to contact */ DD_Remove_Msg *ptr = NULL; ZOLTAN_COMM_OBJ *plan = NULL; /* efficient MPI communication */ char *sbuff = NULL; /* send buffer */ char *sbufftmp = NULL;/* pointer into send buffer */ char *rbuff = NULL; /* receive buffer */ char *rbufftmp = NULL;/* pointer into receive buffer */ int nrec; /* number of receives to expect */ int i; int err; /* error condition to return */ int errcount; /* count of GIDs not found */ char str[100]; /* string to build error messages */ char *yo = "Zoltan_DD_Remove"; /* input sanity checks */ if (dd == NULL || count < 0 || (gid == NULL && count > 0)) { ZOLTAN_PRINT_ERROR (dd ? dd->my_proc : ZOLTAN_DD_NO_PROC, yo, "Invalid input argument"); return ZOLTAN_FATAL; } if (dd->debug_level > 4) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* allocate memory for processor contact list */ if (count) { procs = (int*) ZOLTAN_MALLOC (sizeof(int) * count); if (procs == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc proc list"); if (dd->debug_level > 4) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_MEMERR; } } /* allocate memory for DD_Remove_Msg send buffer */ if (count) { sbuff = (char*)ZOLTAN_MALLOC((size_t)(dd->remove_msg_size)*(size_t)count); if (sbuff == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc send buffer"); err = ZOLTAN_MEMERR; goto fini; } } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO (dd->my_proc, yo, "After proc & sbuff mallocs"); /* for each GID, fill in contact list and then message structure */ sbufftmp = sbuff; for (i = 0; i < count; i++) { procs[i] = dd->hash(gid + i*dd->gid_length, dd->gid_length, dd->nproc, dd->hashdata, dd->hashfn); ptr = (DD_Remove_Msg*) sbufftmp; sbufftmp += dd->remove_msg_size; ptr->owner = dd->my_proc; ZOLTAN_SET_ID (dd->gid_length, ptr->gid, gid + i * dd->gid_length); } /* now create efficient communication plan */ err = Zoltan_Comm_Create (&plan, count, procs, dd->comm, ZOLTAN_DD_REMOVE_MSG_TAG, &nrec); if (err != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Create error"); goto fini; } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO (dd->my_proc, yo, "After Zoltan_Comm_Create"); /* allocate receive buffer for nrec DD_Remove_Msg structures */ if (nrec) { rbuff = (char*)ZOLTAN_MALLOC((size_t)nrec*(size_t)(dd->remove_msg_size)); if (rbuff == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Receive buffer malloc failed"); err = ZOLTAN_MEMERR; goto fini; } } /* send my remove messages & receive removes directed to me */ err = Zoltan_Comm_Do (plan, ZOLTAN_DD_UPDATE_MSG_TAG+1, sbuff, dd->remove_msg_size, rbuff); if (err != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Do error"); goto fini; } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO (dd->my_proc, yo, "After Zoltan_Comm_Do"); /* for each message rec'd, remove local directory info */ errcount = 0; rbufftmp = rbuff; for (i = 0; i < nrec; i++) { ptr = (DD_Remove_Msg*) rbufftmp; rbufftmp += dd->remove_msg_size; err = DD_Remove_Local (dd, ptr->gid); if (err == ZOLTAN_WARN) ++errcount; } err = ZOLTAN_OK; if (dd->debug_level) { sprintf (str, "Processed %d GIDs (%d local), %d GIDs not found", count, nrec, errcount); ZOLTAN_PRINT_INFO (dd->my_proc, yo, str); err = (errcount) ? ZOLTAN_WARN : ZOLTAN_OK; } /* done, now free up things and return */ fini: ZOLTAN_FREE (&procs); ZOLTAN_FREE (&sbuff); ZOLTAN_FREE (&rbuff); Zoltan_Comm_Destroy (&plan); if (dd->debug_level > 4) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return err; }
int Zoltan_DD_Create ( Zoltan_DD_Directory **dd, /* contains directory state and pointers */ MPI_Comm comm, /* Dup'ed and saved for future use */ int num_gid, /* Number of entries in a global ID. */ int num_lid, /* Number of entries in a local ID. If zero, ignore LIDs */ int user_length, /* Optional user data length, 0 ignore */ int table_length, /* sizeof hash table, use default if 0 */ int debug_level) /* control actions to errors, normally 0 */ { int size ; int my_proc; int array[3], max_array[3], min_array[3] ; char *yo = "Zoltan_DD_Create" ; if (MPI_Comm_rank(comm, &my_proc) != MPI_SUCCESS) { ZOLTAN_PRINT_ERROR (-1, yo, "MPI_Comm_rank failed."); return ZOLTAN_DD_MPI_ERROR; } if (debug_level > 1) ZOLTAN_TRACE_IN (my_proc, yo, NULL); /* input sanity check */ if (dd == NULL || num_gid < 1 || table_length < 0 || num_lid < 0) { ZOLTAN_PRINT_ERROR (my_proc, yo, "Invalid input argument.") ; if (debug_level > 1) ZOLTAN_TRACE_OUT (my_proc, yo, NULL); return ZOLTAN_DD_INPUT_ERROR ; } /* insure all processors are using the same GID, LID, USER lengths */ array[0] = num_gid ; array[1] = num_lid ; array[2] = user_length ; MPI_Allreduce (array, max_array, 3, MPI_INT, MPI_MAX, comm) ; MPI_Allreduce (array, min_array, 3, MPI_INT, MPI_MIN, comm) ; if (max_array[0] != min_array[0] || max_array[1] != min_array[1] || max_array[2] != min_array[2]) { ZOLTAN_PRINT_ERROR (-1, yo, "LID, GID, USER data lengths differ globally"); return ZOLTAN_FATAL ; } /* malloc memory for the directory structure + hash table */ size = (table_length == 0) ? ZOLTAN_DD_HASH_TABLE_COUNT : table_length ; *dd = (Zoltan_DD_Directory *) ZOLTAN_MALLOC (sizeof (Zoltan_DD_Directory) + size * sizeof (DD_Node*)) ; if (*dd == NULL) { ZOLTAN_PRINT_ERROR (my_proc, yo, "Can not malloc hash table.") ; if (debug_level > 1) ZOLTAN_TRACE_OUT(my_proc, yo, NULL); return ZOLTAN_DD_MEMORY_ERROR ; } /* NULL heads of link list in hash table */ memset ((char *) (*dd)->table, '\0', size * sizeof (DD_Node*)) ; /* save useful constants into directory for convenience */ (*dd)->debug_level = debug_level ; /* [0,3], default 0 */ (*dd)->gid_length = num_gid ; /* saved input Num_GID */ (*dd)->lid_length = num_lid ; /* saved input Num_LIB */ (*dd)->table_length = size ; /* # of linked list heads */ (*dd)->user_data_length = user_length ; /* optional user data length */ (*dd)->hash = Zoltan_DD_Hash2;/* default hash algorithm */ (*dd)->cleanup = NULL ; /* user registered cleanup */ (*dd)->max_id_length = (num_gid > num_lid) ? num_gid : num_lid ; /* frequently used dynamic allocation computed sizes */ size = (num_gid + num_lid + user_length) * sizeof (ZOLTAN_ID_PTR) ; (*dd)->node_size = size + sizeof(DD_Node) ; (*dd)->update_msg_size = size + sizeof(DD_Update_Msg) ; size = num_gid * sizeof (ZOLTAN_ID_PTR) ; (*dd)->remove_msg_size = size + sizeof(DD_Remove_Msg) ; size = (user_length + (*dd)->max_id_length) * sizeof (ZOLTAN_ID_PTR) ; (*dd)->find_msg_size = size + sizeof (DD_Find_Msg) ; /* force alignment */ (*dd)->update_msg_size = Zoltan_Align((*dd)->update_msg_size); (*dd)->remove_msg_size = Zoltan_Align((*dd)->remove_msg_size); (*dd)->find_msg_size = Zoltan_Align((*dd)->find_msg_size); /* duplicate MPI comm to prevent future comm changes from disrupting */ /* directory communications & save the associated comm size & rank */ if (MPI_Comm_dup (comm, &((*dd)->comm)) != MPI_SUCCESS || MPI_Comm_size (comm, &((*dd)->nproc)) != MPI_SUCCESS || MPI_Comm_rank (comm, &((*dd)->my_proc)) != MPI_SUCCESS) { ZOLTAN_PRINT_ERROR (my_proc, yo, "MPI Problem, unable to continue.") ; if (debug_level > 1) ZOLTAN_TRACE_OUT(my_proc, yo, NULL); return ZOLTAN_DD_MPI_ERROR ; } if (debug_level > 1) ZOLTAN_TRACE_OUT (my_proc, yo, NULL); return ZOLTAN_DD_NORMAL_RETURN ; }
int Zoltan_DD_Update ( Zoltan_DD_Directory *dd, /* directory state information */ ZOLTAN_ID_PTR gid, /* Incoming list of GIDs to update */ ZOLTAN_ID_PTR lid, /* Incoming corresponding LIDs (optional) */ char *user, /* Incoming list of user data (optional) */ int *partition, /* Optional, grouping of GIDs to partitions */ int count) /* Number of GIDs in update list */ { int *procs = NULL; /* list of processors to contact */ DD_Update_Msg *ptr = NULL; ZOLTAN_COMM_OBJ *plan = NULL; /* for efficient MPI communication */ char *sbuff = NULL; /* send buffer */ char *sbufftmp = NULL;/* pointer into send buffer */ char *rbuff = NULL; /* receive buffer */ char *rbufftmp = NULL;/* pointer into receive buffer */ int nrec = 0; /* number of receives to expect */ int i; int err; int errcount = 0; /* count of GIDs not found, added */ char str[100]; /* build error message string */ char *yo = "Zoltan_DD_Update"; /* input sanity checking */ if (dd == NULL || count < 0 || (gid == NULL && count > 0)) { ZOLTAN_PRINT_ERROR ((dd == NULL ? ZOLTAN_DD_NO_PROC : dd->my_proc), yo, "Invalid input argument"); return ZOLTAN_FATAL; } if (dd->debug_level > 4) ZOLTAN_TRACE_IN(dd->my_proc, yo, NULL); /* part of initializing the error checking process */ /* for each linked list head, walk its list resetting errcheck */ if (dd->debug_level) for (i = 0; i < dd->table_length; i++) { DD_NodeIdx nodeidx; for (nodeidx = dd->table[i]; nodeidx != -1; nodeidx = dd->nodelist[nodeidx].next) dd->nodelist[nodeidx].errcheck = ZOLTAN_DD_NO_PROC; } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After reset errcheck"); /* allocate memory for list of processors to contact */ if (count) { procs = (int*) ZOLTAN_MALLOC (sizeof(int) * count); if (procs == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc proc list"); err = ZOLTAN_MEMERR; goto fini; } } /* allocate memory for DD_Update_Msg send buffer */ if (count) { sbuff = (char*) ZOLTAN_CALLOC (count, dd->update_msg_size); if (sbuff == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc send buffer"); err = ZOLTAN_MEMERR; goto fini; } } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After mallocs"); /* for each GID given, fill in contact list and then message structure */ sbufftmp = sbuff; for (i = 0; i < count; i++) { procs[i] = dd->hash(gid + i*dd->gid_length, dd->gid_length, dd->nproc, dd->hashdata, dd->hashfn); ptr = (DD_Update_Msg*) sbufftmp; sbufftmp += dd->update_msg_size; ptr->lid_flag = (lid) ? 1 : 0; ptr->user_flag = (user) ? 1 : 0; ptr->partition_flag = (partition) ? 1 : 0; ptr->partition = (partition) ? *(partition + i) : -1; ptr->owner = dd->my_proc; ZOLTAN_SET_ID (dd->gid_length, ptr->gid, gid + i * dd->gid_length); if (lid) { ZOLTAN_SET_ID(dd->lid_length, ptr->gid + dd->gid_length, lid + i * dd->lid_length); } else { memset(ptr->gid + dd->gid_length, 0, dd->lid_length); } if (user) { memcpy(ptr->gid + (dd->gid_length + dd->lid_length), user + (size_t)i * (size_t)(dd->user_data_length), dd->user_data_length); } else { memset(ptr->gid + (dd->gid_length + dd->lid_length), 0, dd->user_data_length); } } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill contact list"); /* now create efficient communication plan */ err = Zoltan_Comm_Create (&plan, count, procs, dd->comm, ZOLTAN_DD_UPDATE_MSG_TAG, &nrec); if (err != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Create error"); goto fini; } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Create"); /* If dd has no nodes allocated (e.g., first call to DD_Update; * create the nodelist and freelist */ if (nrec && dd->nodelistlen == 0) { DD_Memory_Alloc_Nodelist(dd, (DD_NodeIdx) nrec, 0.); /* TODO Add overalloc parameter */ } /* allocate receive buffer for nrec DD_Update_Msg structures */ if (nrec) { rbuff = (char*)ZOLTAN_MALLOC((size_t)nrec*(size_t)(dd->update_msg_size)); if (rbuff == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Receive buffer malloc failed"); err = ZOLTAN_MEMERR; goto fini; } } /* send my update messages & receive updates directed to me */ err = Zoltan_Comm_Do (plan, ZOLTAN_DD_UPDATE_MSG_TAG+1, sbuff, dd->update_msg_size, rbuff); if (err != ZOLTAN_OK) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Comm_Do error"); goto fini; } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Do"); /* for each message rec'd, update local directory information */ errcount = 0; rbufftmp = rbuff; for (i = 0; i < nrec; i++) { ptr = (DD_Update_Msg *) rbufftmp; rbufftmp += dd->update_msg_size; err = DD_Update_Local (dd, ptr->gid, (ptr->lid_flag) ? (ptr->gid + dd->gid_length) : NULL, (char*)((ptr->user_flag)?(ptr->gid+(dd->gid_length+dd->lid_length)):NULL), (ptr->partition_flag) ? (ptr->partition) : -1, /* illegal partition */ ptr->owner); if (err != ZOLTAN_OK) ++errcount; } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Local update"); err = ZOLTAN_OK; if (dd->debug_level) /* overwrite error return if extra checking is on */ err = (errcount) ? ZOLTAN_WARN : ZOLTAN_OK; fini: ZOLTAN_FREE (&procs); ZOLTAN_FREE (&sbuff); ZOLTAN_FREE (&rbuff); Zoltan_Comm_Destroy (&plan); if (dd->debug_level) { sprintf (str, "Processed %d GIDs (%d local), %d GID errors", count, nrec, errcount); ZOLTAN_PRINT_INFO (dd->my_proc, yo, str); } if (dd->debug_level > 4) ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL); return err; }
static int DD_Update_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid, /* GID to update (in) */ ZOLTAN_ID_PTR lid, /* gid's LID (in), NULL if not needed */ char *user, /* gid's user data (in), NULL if not needed */ int partition, /* gid's partition (in), -1 if not used */ int owner) /* gid's current owner (proc number) (in) */ { int index; char *yo = "DD_Update_Local"; DD_NodeIdx nodeidx; DD_Node *ptr; /* input sanity checking */ if (dd == NULL || owner < 0 || owner >= dd->nproc || gid == NULL) { ZOLTAN_PRINT_ERROR (dd ? dd->my_proc : ZOLTAN_DD_NO_PROC, yo, "Invalid input parameter"); return ZOLTAN_FATAL; } if (dd->debug_level > 5) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* compute offset into hash table to find head of linked list */ index = Zoltan_DD_Hash2 (gid, dd->gid_length, dd->table_length, dd->hashdata, NULL); /* walk linked list until end looking for matching gid */ for (nodeidx = dd->table[index]; nodeidx != -1; nodeidx = dd->nodelist[nodeidx].next) { ptr = dd->nodelist + nodeidx; if (ZOLTAN_EQ_ID (dd->gid_length, gid, ptr->gid) == TRUE) { /* found match, update directory information */ if (lid) ZOLTAN_SET_ID (dd->lid_length,ptr->gid + dd->gid_length, lid); if (user) memcpy(ptr->gid + (dd->gid_length + dd->lid_length), user, dd->user_data_length); ptr->owner = owner; if (partition != -1) ptr->partition = partition; /* Response to multiple updates to a gid in 1 update cycle */ if (dd->debug_level > 0 && ptr->errcheck != owner) { ZOLTAN_PRINT_INFO (dd->my_proc, yo, "Multiply defined GID"); if (dd->debug_level > 4) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_WARN; } ptr->errcheck = owner; if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; /* ignore all errors */ } } /* gid not found. Create new DD_Node and fill it in */ nodeidx = DD_Memory_Alloc_Node(dd); ptr = dd->nodelist + nodeidx; ZOLTAN_SET_ID (dd->gid_length, ptr->gid, gid); if (lid) { ZOLTAN_SET_ID(dd->lid_length,ptr->gid + dd->gid_length, lid); } else { memset(ptr->gid + dd->gid_length, 0, dd->lid_length*sizeof(ZOLTAN_ID_TYPE)); } if (user) { memcpy(ptr->gid + (dd->gid_length + dd->lid_length), user, dd->user_data_length); } else { memset(ptr->gid + (dd->gid_length+dd->lid_length), 0, dd->user_data_length); } ptr->partition = partition; ptr->owner = owner; ptr->errcheck = owner; /* Add node to the linked list */ ptr->next = dd->table[index]; dd->table[index] = nodeidx; if (dd->debug_level > 6) ZOLTAN_PRINT_INFO (dd->my_proc, yo, "Created new directory item"); if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; }
int Zoltan_DD_Find ( Zoltan_DD_Directory *dd, /* contains directory state information */ ZOLTAN_ID_PTR gid, /* Incoming list of GIDs to get owners proc */ ZOLTAN_ID_PTR lid, /* Outgoing corresponding list of LIDs */ char *data, /* Outgoing optional corresponding user data */ int *partition, /* Outgoing optional partition information */ int count, /* Count of GIDs in above list (in) */ int *owner) /* Outgoing optional list of data owners */ { ZOLTAN_COMM_OBJ *plan = NULL; /* efficient MPI communication */ char *rbuff = NULL; /* receive buffer */ char *rbufftmp = NULL; /* pointer into receive buffer */ char *sbuff = NULL; /* send buffer */ char *sbufftmp = NULL; /* pointer into send buffer */ int *procs = NULL; /* list of processors to contact */ DD_Find_Msg *ptr = NULL; int i; int nrec; /* number of messages to receive */ int err = ZOLTAN_OK; /* return error condition */ int errcount; /* count of GIDs not found */ char *yo = "Zoltan_DD_Find"; /* input sanity check */ if (dd == NULL || count < 0 || (gid == NULL && count > 0)) { ZOLTAN_PRINT_ERROR (dd ? dd->my_proc : ZOLTAN_DD_NO_PROC, yo, "Invalid input argument"); return ZOLTAN_FATAL; } if (dd->debug_level > 4) ZOLTAN_TRACE_IN(dd->my_proc, yo, NULL); /* allocate memory for processors to contact for directory info */ if (count) { procs = (int*) ZOLTAN_MALLOC (sizeof(int) * count); if (procs == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc proc list"); if (dd->debug_level > 4) ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL); return ZOLTAN_MEMERR; } } /* allocate memory for DD_Find_Msg send buffer */ if (count) { sbuff = (char*) ZOLTAN_CALLOC (count, dd->find_msg_size); if (sbuff == NULL) { ZOLTAN_FREE (&procs); ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc send buffer"); if (dd->debug_level > 4) ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL); return ZOLTAN_MEMERR; } } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After mallocs"); /* for each GID, fill DD_Find_Msg buffer and contact list */ sbufftmp = sbuff; for (i = 0; i < count; i++) { procs[i] = dd->hash (gid + i*dd->gid_length, dd->gid_length, dd->nproc, dd->hashdata, dd->hashfn); ptr = (DD_Find_Msg*) sbufftmp; sbufftmp += dd->find_msg_size; ptr->index = i; ptr->proc = procs[i]; ZOLTAN_SET_ID (dd->gid_length, ptr->id, gid + i*dd->gid_length); } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill"); /* create efficient communication plan */ err = Zoltan_Comm_Create (&plan, count, procs, dd->comm, ZOLTAN_DD_FIND_MSG_TAG, &nrec); if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Create"); if (err != ZOLTAN_OK) goto fini; /* allocate receive buffer */ if (nrec) { rbuff = (char*) ZOLTAN_MALLOC ((size_t)nrec*(size_t)(dd->find_msg_size)); if (rbuff == NULL) { err = ZOLTAN_MEMERR; goto fini; } } /* send out find messages across entire system */ err = Zoltan_Comm_Do (plan, ZOLTAN_DD_FIND_MSG_TAG+1, sbuff, dd->find_msg_size, rbuff); if (err != ZOLTAN_OK) goto fini; if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Do"); /* get find messages directed to me, fill in return information */ errcount = 0; rbufftmp = rbuff; for (i = 0; i < nrec; i++) { ptr = (DD_Find_Msg*) rbufftmp; rbufftmp += dd->find_msg_size; err = DD_Find_Local (dd, ptr->id, ptr->id, (char *)(ptr->id + dd->max_id_length), &ptr->partition, &ptr->proc); if (err == ZOLTAN_WARN) ++errcount; } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill in return info"); /* send return information back to requester */ err = Zoltan_Comm_Do_Reverse(plan, ZOLTAN_DD_FIND_MSG_TAG+2, rbuff, dd->find_msg_size, NULL, sbuff); if (err != ZOLTAN_OK) goto fini; if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Reverse"); /* fill in user supplied lists with returned information */ sbufftmp = sbuff; for (i = 0; i < count; i++) { ptr = (DD_Find_Msg*) sbufftmp; sbufftmp += dd->find_msg_size; if (owner) owner[ptr->index] = ptr->proc; if (partition) partition[ptr->index] = ptr->partition ; if (lid) ZOLTAN_SET_ID(dd->lid_length,lid+ptr->index*dd->lid_length,ptr->id); if (data) memcpy(data + (size_t)(ptr->index) * (size_t)(dd->user_data_length), ptr->id + dd->max_id_length, dd->user_data_length); } if (dd->debug_level > 6) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill return lists"); /* err = ZOLTAN_OK; */ MPI_Allreduce(&errcount, &err, 1, MPI_INT, MPI_SUM, dd->comm); err = (err) ? ZOLTAN_WARN : ZOLTAN_OK; /* if at least one GID was not found, potentially notify caller of error */ if (dd->debug_level > 0) { char str[100]; /* diagnostic message string */ sprintf (str, "Processed %d GIDs, GIDs not found: %d", count, errcount); ZOLTAN_PRINT_INFO (dd->my_proc, yo, str); } fini: ZOLTAN_FREE (&sbuff); ZOLTAN_FREE (&rbuff); ZOLTAN_FREE (&procs) ; Zoltan_Comm_Destroy (&plan); if (dd->debug_level > 4) ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL); return err; }
int Zoltan_DD_Find ( Zoltan_DD_Directory *dd, /* contains directory state information */ ZOLTAN_ID_PTR gid, /* Incoming list of GIDs to get owners proc */ ZOLTAN_ID_PTR lid, /* Outgoing corresponding list of LIDs */ ZOLTAN_ID_PTR data, /* Outgoing optional corresponding user data */ int *partition, /* Outgoing optional partition information */ int count, /* Count of GIDs in above list (in) */ int *owner) /* Outgoing corresponding list of data locations */ { ZOLTAN_COMM_OBJ *plan = NULL ; /* efficient MPI communication */ char *rbuff = NULL ; /* receive buffer */ char *sbuff = NULL ; /* send buffer */ int *procs = NULL ; /* list of processors to contact */ DD_Find_Msg *ptr = NULL ; int i ; int nrec ; /* number of messages to receive */ int err ; /* return error condition */ int errcount ; /* count of GIDs not found */ char *yo = "Zoltan_DD_Find" ; if (dd != NULL && dd->debug_level > 1) ZOLTAN_TRACE_IN(dd->my_proc, yo, NULL); /* input sanity check */ if (dd == NULL || count < 0 || ((owner == NULL || gid == NULL) && count > 0)) { ZOLTAN_PRINT_ERROR ((dd == NULL ? ZOLTAN_DD_NO_PROC : dd->my_proc), yo, "Invalid input argument.") ; if (dd != NULL && dd->debug_level > 1) ZOLTAN_TRACE_OUT((dd == NULL ? ZOLTAN_DD_NO_PROC : dd->my_proc), yo, NULL); return ZOLTAN_DD_INPUT_ERROR ; } /* allocate memory for processors to contact for directory info */ if (count > 0) { procs = (int *) ZOLTAN_MALLOC (sizeof (int) * count) ; if (procs == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc proc list.") ; if (dd->debug_level > 1) ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL); return ZOLTAN_DD_MEMORY_ERROR ; } } /* allocate memory for DD_Find_Msg send buffer */ if (count > 0) { sbuff = (char *) ZOLTAN_MALLOC (dd->find_msg_size * count) ; if (sbuff == NULL) { ZOLTAN_FREE (&procs) ; ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc send buffer.") ; if (dd->debug_level > 1) ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL); return ZOLTAN_DD_MEMORY_ERROR ; } } if (dd->debug_level > 2) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After mallocs."); /* for each GID, fill DD_Find_Msg buffer and contact list */ for (i = 0 ; i < count ; i++) { procs[i] = dd->hash (gid + i*dd->gid_length, dd->gid_length, dd->nproc) ; ptr = (DD_Find_Msg *) (sbuff + i * dd->find_msg_size) ; ptr->index = i ; ptr->proc = procs[i] ; ZOLTAN_SET_ID (dd->gid_length, ptr->id, gid + i*dd->gid_length) ; } if (dd->debug_level > 2) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill."); /* create efficient communication plan */ err = Zoltan_Comm_Create (&plan, count, procs, dd->comm, ZOLTAN_DD_FIND_MSG_TAG, &nrec) ; if (dd->debug_level > 2) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Create."); if (err != ZOLTAN_OK) goto fini ; /* allocate receive buffer */ if (nrec > 0) { rbuff = (char *) ZOLTAN_MALLOC (nrec * dd->find_msg_size) ; if (rbuff == NULL) { err = ZOLTAN_DD_MEMORY_ERROR ; goto fini ; } } /* send out find messages across entire system */ err = Zoltan_Comm_Do (plan, ZOLTAN_DD_FIND_MSG_TAG+1, sbuff, dd->find_msg_size, rbuff) ; if (err != ZOLTAN_OK) goto fini ; if (dd->debug_level > 2) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Do."); /* get find messages directed to me, fill in return information */ errcount = 0 ; for (i = 0 ; i < nrec ; i++) { ptr = (DD_Find_Msg *) (rbuff + i*dd->find_msg_size) ; err = DD_Find_Local (dd, ptr->id, ptr->id, ptr->id + dd->max_id_length, (partition) ? (&ptr->partition) : NULL, &ptr->proc) ; if (err == ZOLTAN_DD_GID_NOT_FOUND_ERROR) errcount++ ; } if (dd->debug_level > 2) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill in return info."); /* send return information back to requester */ err = Zoltan_Comm_Do_Reverse(plan, ZOLTAN_DD_FIND_MSG_TAG+2, rbuff, dd->find_msg_size, NULL, sbuff) ; if (err != ZOLTAN_OK) goto fini ; if (dd->debug_level > 2) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After Comm_Reverse."); /* fill in user supplied lists with returned information */ for (i = 0 ; i < count ; i++) { ptr = (DD_Find_Msg *) (sbuff + i*dd->find_msg_size) ; owner[ptr->index] = ptr->proc ; if (partition != NULL) partition[ptr->index] = ptr->partition ; if (lid != NULL) ZOLTAN_SET_ID (dd->lid_length, lid + ptr->index * dd->lid_length, ptr->id) ; if (data != NULL) ZOLTAN_SET_ID (dd->user_data_length, data + ptr->index * dd->user_data_length, ptr->id + dd->max_id_length) ; } /* if at least one GID was not found, notify caller of error */ err = (errcount == 0) ? ZOLTAN_DD_NORMAL_RETURN : ZOLTAN_DD_GID_NOT_FOUND_ERROR ; if (dd->debug_level > 2) ZOLTAN_PRINT_INFO(dd->my_proc, yo, "After fill return lists."); fini: ZOLTAN_FREE (&sbuff) ; ZOLTAN_FREE (&rbuff) ; ZOLTAN_FREE (&procs) ; Zoltan_Comm_Destroy (&plan) ; if (err != ZOLTAN_DD_NORMAL_RETURN) ZOLTAN_PRINT_WARN (dd->my_proc, yo, "Return is not normal.") ; if (dd->debug_level > 0) { char str[100] ; /* diagnostic message string */ sprintf (str, "Processed %d GIDs, GIDs not found: %d", count, errcount) ; ZOLTAN_PRINT_INFO (dd->my_proc, yo, str) ; } if (dd->debug_level > 1) ZOLTAN_TRACE_OUT(dd->my_proc, yo, NULL); return err ; }
static int DD_Update_Local (Zoltan_DD_Directory *dd, ZOLTAN_ID_PTR gid, /* GID to update (in) */ ZOLTAN_ID_PTR lid, /* gid's LID (in), NULL if not needed */ ZOLTAN_ID_PTR user, /* gid's user data (in), NULL if not needed */ int partition, /* gid's partition (in), -1 if not used */ int owner) /* gid's current owner (proc number) (in) */ { DD_Node **ptr; int index; char *yo = "DD_Update_Local"; /* input sanity checking */ if (dd == NULL || owner < 0 || owner >= dd->nproc || gid == NULL) { ZOLTAN_PRINT_ERROR (dd ? dd->my_proc : ZOLTAN_DD_NO_PROC, yo, "Invalid input parameter"); return ZOLTAN_FATAL; } if (dd->debug_level > 5) ZOLTAN_TRACE_IN (dd->my_proc, yo, NULL); /* compute offset into hash table to find head of linked list */ index = Zoltan_DD_Hash2 (gid, dd->gid_length, dd->table_length, dd->hashdata); /* walk linked list until end looking for matching gid */ for (ptr = dd->table+index; *ptr != NULL; ptr = &((*ptr)->next)) if (ZOLTAN_EQ_ID (dd->gid_length, gid, (*ptr)->gid) == TRUE) { /* found match, update directory information */ if (lid) ZOLTAN_SET_ID (dd->lid_length,(*ptr)->gid + dd->gid_length, lid); if (user) ZOLTAN_SET_ID (dd->user_data_length, (*ptr)->gid + (dd->gid_length + dd->lid_length), user); (*ptr)->owner = owner; if (partition != -1) (*ptr)->partition = partition; /* Response to multiple updates to a gid in 1 update cycle */ if (dd->debug_level > 0 && (*ptr)->errcheck != owner) { ZOLTAN_PRINT_INFO (dd->my_proc, yo, "Multiply defined GID"); if (dd->debug_level > 4) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_WARN; } (*ptr)->errcheck = owner; if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; /* ignore all errors */ } /* gid not found. Create new DD_Node and fill it in */ *ptr = (DD_Node*) ZOLTAN_MALLOC (dd->node_size); if (*ptr == NULL) { ZOLTAN_PRINT_ERROR (dd->my_proc, yo, "Unable to malloc new Node"); if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_MEMERR; } ZOLTAN_SET_ID (dd->gid_length, (*ptr)->gid, gid); if (lid) { ZOLTAN_SET_ID(dd->lid_length,(*ptr)->gid + dd->gid_length, lid); } else { memset((*ptr)->gid + dd->gid_length, 0, dd->lid_length*sizeof(ZOLTAN_ID_TYPE)); } if (user) { ZOLTAN_SET_ID(dd->user_data_length, (*ptr)->gid + (dd->gid_length + dd->lid_length), user); } else { memset((*ptr)->gid + (dd->gid_length+dd->lid_length), 0, dd->user_data_length*sizeof(ZOLTAN_ID_TYPE)); } (*ptr)->partition = partition ; (*ptr)->next = NULL; (*ptr)->owner = owner; (*ptr)->errcheck = owner; if (dd->debug_level > 6) ZOLTAN_PRINT_INFO (dd->my_proc, yo, "Created new directory item"); if (dd->debug_level > 5) ZOLTAN_TRACE_OUT (dd->my_proc, yo, NULL); return ZOLTAN_OK; }