File: test_common.c

package info (click to toggle)
openmpi 5.0.8-4
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 201,684 kB
  • sloc: ansic: 613,078; makefile: 42,353; sh: 11,194; javascript: 9,244; f90: 7,052; java: 6,404; perl: 5,179; python: 1,859; lex: 740; fortran: 61; cpp: 20; tcl: 12
file content (255 lines) | stat: -rw-r--r-- 8,366 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/*
 * Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
 * Copyright (c) 2015      Artem Y. Polyakov <artpol84@gmail.com>.
 *                         All rights reserved.
 * Copyright (c) 2015-2018 Mellanox Technologies, Inc.
 *                         All rights reserved.
 * Copyright (c) 2020-2021 Triad National Security, LLC
 *                         All rights reserved.
 * Copyright (c) 2021      Nanook Consulting.  All rights reserved.
 * $COPYRIGHT$
 *
 * Additional copyrights may follow
 *
 * $HEADER$
 *
 */

/* Note: this file is for functions called by both client and server and their
        callees. */

#include "pmix_common.h"
#include "src/include/pmix_config.h"

#include "test_common.h"
#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

int pmix_test_verbose = 0;
test_params params;
char **test_argv = NULL;
node_map *nodes = NULL;
char *v_params_ascii_str = NULL;
FILE *pmixt_outfile;

#define OUTPUT_MAX 1024
char *pmix_test_output_prepare(const char *fmt, ...)
{
    static char output[OUTPUT_MAX];
    va_list args;
    va_start(args, fmt);
    memset(output, 0, sizeof(output));
    vsnprintf(output, OUTPUT_MAX - 1, fmt, args);
    va_end(args);
    return output;
}

void pmixt_exit(int exit_code)
{
    if ((stdout != pmixt_outfile) && (stderr != pmixt_outfile)) {
        fclose(pmixt_outfile);
    }
    _exit(exit_code);
}

// initialize the global *nodes array
void init_nodes(int num_nodes)
{
    int i;
    nodes = malloc(num_nodes * sizeof(node_map));
    for (i = 0; i < num_nodes; i++) {
        nodes[i].pmix_rank = NULL;
        nodes[i].pmix_hostname[0] = '\0';
    }
}

// frees the global *nodes array
void free_nodes(int num_nodes)
{
    int i;
    if (NULL == nodes) {
        TEST_ERROR(("nodes pointer is NULL, cannot free; aborting"));
        exit(1);
    }
    TEST_VERBOSE(("num_nodes = %d, nodes[0].pmix_rank[0] = %d", num_nodes, nodes[0].pmix_rank[0]));
    for (i = 0; i < num_nodes; i++) {
        if (NULL == nodes[i].pmix_rank) {
            TEST_ERROR(
                ("Encountered NULL pointer in free loop of nodes[%d].pmix_rank; aborting", i));
            exit(1);
        }
        free(nodes[i].pmix_rank);
    }
    free(nodes);
}

// populates the global *nodes array for the default rank placement case
void populate_nodes_default_placement(uint32_t num_nodes, int num_procs)
{
    uint32_t i, j, base_rank = 0, base_rank_next_node = 0;

    for (i = 0; i < num_nodes; i++) {
        base_rank_next_node += (num_procs % num_nodes) > (uint32_t) i ? num_procs / num_nodes + 1
                                                                      : num_procs / num_nodes;
        nodes[i].pmix_nodeid = i;
        snprintf(nodes[i].pmix_hostname, PMIX_MAX_KEYLEN, "node%u", nodes[i].pmix_nodeid);
        nodes[i].pmix_rank = malloc(sizeof(pmix_rank_t));
        for (j = 0; j < base_rank_next_node - base_rank; j++) {
            nodes[i].pmix_rank = (pmix_rank_t *) realloc(nodes[i].pmix_rank,
                                                         (j + 1) * sizeof(pmix_rank_t));
            nodes[i].pmix_rank[j] = j + base_rank;
        }
        nodes[i].pmix_local_size = j;
        base_rank = base_rank_next_node;
        TEST_VERBOSE(
            ("Default rank placement: num_nodes: %u num_procs: %d nodes[%d].pmix_local_size: %d",
             num_nodes, num_procs, i, (int)nodes[i].pmix_local_size));
    }
}

// populates the global *nodes array for the custom rank placement case (rank placement string as
// command line arg)
void populate_nodes_custom_placement_string(char *placement_str, int num_nodes)
{
    /* example rank placement string:
    // 0:0,2,4;1:1,3,5
    // equates to: (node 0: ranks 0, 2, and 4; node 1: ranks 1, 3, and 5)
    // no error checking in this function, we assume the string has correct syntax
    // and all nodes/procs are properly accounted for */
    char *tempstr, *pch, **buf;
    char *saveptr = NULL;
    size_t i, j, idx = 0;

    buf = malloc(num_nodes * sizeof(char *));
    tempstr = strdup(placement_str);
    // first we separate the nodes from one another
    pch = strtok_r(tempstr, ";", &saveptr);
    while (NULL != pch) {
        buf[idx] = malloc(strlen(pch) + 1);
        strcpy(buf[idx], pch);
        pch = strtok_r(NULL, ";", &saveptr);
        idx++;
    }
    // now we go back over populated buf array and separate the numbered nodes from the
    // comma-delimited list of ranks; then we separate out each rank
    for (i = 0; i < idx; i++) {
        pch = strtok_r(buf[i], ":", &saveptr);
        nodes[i].pmix_nodeid = strtol(pch, NULL, 0);
        snprintf(nodes[i].pmix_hostname, PMIX_MAX_KEYLEN, "node%u", nodes[i].pmix_nodeid);
        nodes[i].pmix_rank = malloc(sizeof(pmix_rank_t));
        j = 0;
        pch = strtok_r(NULL, ",", &saveptr);
        while (NULL != pch) {
            nodes[i].pmix_rank = (pmix_rank_t *) realloc(nodes[i].pmix_rank,
                                                         (j + 1) * sizeof(pmix_rank_t));
            nodes[i].pmix_rank[j] = strtol(pch, NULL, 0);
            pch = strtok_r(NULL, ",", &saveptr);
            j++;
        }
        nodes[i].pmix_local_size = j;
        TEST_VERBOSE(("num_nodes: %d idx: %d nodes[%d].pmix_local_size: %d hostname: %s", num_nodes,
                      (int)idx, (int)i, (int)j, nodes[i].pmix_hostname));
    }

    free(tempstr);
    for (i = 0; i < idx; i++) {
        free(buf[i]);
    }
    free(buf);
}

void default_params(test_params *lparams, validation_params *v_params) {
    lparams->binary = NULL;
    lparams->np = NULL;
    lparams->prefix = NULL;
    lparams->timeout = TEST_DEFAULT_TIMEOUT;
    lparams->verbose = 0;
    lparams->nonblocking = 0;
    lparams->ns_size = -1;
    lparams->ns_id = -1;
    lparams->fence_timeout_ratio = TEST_DEFAULT_FENCE_TIMEOUT_RATIO;
    lparams->fence_time_multiplier = TEST_DEFAULT_FENCE_TIME_MULTIPLIER;
    lparams->time_fence = false;

    v_params->version = PMIXT_VALIDATION_PARAMS_VER;
    v_params->validate_params = false;
    v_params->custom_rank_placement = false;
    v_params->pmix_rank = PMIX_RANK_UNDEF;
    v_params->pmix_nspace[0] = '\0';
    v_params->pmix_job_size = 1;
    v_params->pmix_univ_size = 1;
    v_params->pmix_jobid[0] = '\0';
    v_params->pmix_local_size = 1;
    v_params->pmix_local_rank = 0;
    v_params->pmix_nodeid = 0;
    v_params->pmix_local_peers[0] = '\0';
    v_params->pmix_hostname[0] = '\0';
    v_params->pmix_num_nodes = 1;
    v_params->pmix_node_rank = 0;
}

// also frees the global array *nodes
void free_params(test_params *l_params, validation_params *vparams)
{
    if (NULL != l_params->binary) {
        free(l_params->binary);
    }
    if (NULL != l_params->np) {
        free(l_params->np);
    }
    if (NULL != l_params->prefix) {
        free(l_params->prefix);
    }

    if (NULL != v_params_ascii_str) {
        free(v_params_ascii_str);
    }

    free_nodes(vparams->pmix_num_nodes);
    TEST_VERBOSE(("Completed free_params"));
}

static void fcon(fence_desc_t *p)
{
    p->blocking = 0;
    p->data_exchange = 0;
    p->participants = PMIX_NEW(pmix_list_t);
}

static void fdes(fence_desc_t *p)
{
    PMIX_LIST_RELEASE(p->participants);
}

PMIX_CLASS_INSTANCE(fence_desc_t, pmix_list_item_t, fcon, fdes);

PMIX_CLASS_INSTANCE(participant_t, pmix_list_item_t, NULL, NULL);

PMIX_CLASS_INSTANCE(key_replace_t, pmix_list_item_t, NULL, NULL);

//static int ns_id = -1;
//static fence_desc_t *fdesc = NULL;
pmix_list_t *participants = NULL;
pmix_list_t test_fences;
pmix_list_t *noise_range = NULL;
pmix_list_t key_replace;

#define CHECK_STRTOL_VAL(val, str, store) do {                  \
    if (0 == val) {                                             \
        if (0 != strncmp(str, "0", 1)) {                        \
            if (!store) {                                       \
                return 1;                                       \
            }                                                   \
        }                                                       \
    }                                                           \
} while (0)

// cross-platform millisecond sleep function
void sleep_ms(unsigned long milliseconds) {
    if (1000 <= milliseconds) {
        sleep(milliseconds / 1000);
    }
    usleep((milliseconds % 1000) * 1000);
}