root/branches/cu-security-branch/src/common/misc/msgpairarray.sm @ 8397

Revision 8397, 26.6 KB (checked in by nlmills, 3 years ago)

initial merge with Orange-Branch. much will be broken

Line 
1/*
2 * (C) 2003 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7/* pvfs2_msgpairarray_sm
8 *
9 * The purpose of this state machine is to prepare, send, and
10 * receive a collection of request/response pairs (msgpairs).
11 */
12
13#include <string.h>
14#include <assert.h>
15
16#include "msgpairarray.h"
17#include "pvfs2-debug.h"
18#include "pint-cached-config.h"
19#include "job.h"
20#include "gossip.h"
21#include "PINT-reqproto-encode.h"
22#include "pvfs2-util.h"
23#include "pint-util.h"
24#include "server-config-mgr.h"
25#include "pvfs2-internal.h"
26#include "state-machine.h"
27
28#define gossip_err_unless_quiet(format, f...) \
29do {\
30    if(mop->params.quiet_flag)\
31        gossip_debug(GOSSIP_MSGPAIR_DEBUG, format, ##f); \
32    else \
33        gossip_err(format, ##f); \
34} while(0)
35
36enum
37{
38    MSGPAIRS_COMPLETE = 190,
39    MSGPAIRS_RETRY = 191,
40    MSGPAIRS_RETRY_NODELAY = 192
41};
42
43%%
44
45nested machine pvfs2_msgpairarray_sm
46{
47    state init
48    {
49        run msgpairarray_init;
50        default => post;
51    }
52
53    state post
54    {
55        run msgpairarray_post;
56        MSGPAIRS_COMPLETE => completion_fn;
57        default => complete;
58    }
59
60    state post_retry
61    {
62        run msgpairarray_post_retry;
63        default => post;
64    }
65
66    state complete
67    {
68        run msgpairarray_complete;
69        MSGPAIRS_COMPLETE => completion_fn;
70        default => complete;
71    }
72
73    state completion_fn
74    {
75        run msgpairarray_completion_fn;
76        MSGPAIRS_RETRY => post_retry;
77        MSGPAIRS_RETRY_NODELAY => post;
78        default => done;
79    }
80
81    state done
82    {
83        run msgpairarray_done;
84        default => return;
85    }
86}
87
88%%
89
90static PINT_sm_action msgpairarray_init(
91        struct PINT_smcb *smcb, job_status_s *js_p)
92{
93    PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
94    int i = 0;
95    PINT_sm_msgpair_state *msg_p = NULL;
96
97    gossip_debug(GOSSIP_MIRROR_DEBUG,"Executing msgpairarray_init...\n");
98    gossip_debug(GOSSIP_MIRROR_DEBUG,"\tbase frame:%d\tframe count:%d\n"
99                                    ,smcb->base_frame,smcb->frame_count);
100
101    gossip_debug(GOSSIP_MSGPAIR_DEBUG, "(%p) msgpairarray state: init "
102                 "(%d msgpair(s))\n", smcb, mop->count);
103
104    assert(mop->count > 0);
105
106    js_p->error_code = 0;
107
108    /* set number of operations that must complete.  */
109    mop->params.comp_ct = (2 * mop->count);
110
111    for(i = 0; i < mop->count; i++)
112    {
113        msg_p = &mop->msgarray[i];
114        assert(msg_p);
115
116        assert((msg_p->retry_flag == PVFS_MSGPAIR_RETRY) ||
117               (msg_p->retry_flag == PVFS_MSGPAIR_NO_RETRY));
118
119        msg_p->encoded_resp_p = NULL;
120        msg_p->retry_count = 0;
121        msg_p->complete = 0;
122
123    }
124    return SM_ACTION_COMPLETE;
125}
126
127/* msgpairarray_post()
128 *
129 * The following elements of the PINT_sm_msgpair_state
130 * should be valid prior to this state (for each msgpair in array):
131 * - req (unencoded request)
132 * - srv_addr of each element in msg array
133 *
134 * This state performs the following operations for each msgpair,
135 * one at a time:
136 * (1) encodes request
137 * (2) calculates maximum response size
138 * (3) allocates BMI memory for response data (encoded)
139 * (4) gets a session tag for the pair of messages
140 * (5) posts the receive of the response
141 * (6) posts the send of the request
142 * (7) stores job ids for later matching
143 *
144 */
145static PINT_sm_action msgpairarray_post(
146        struct PINT_smcb *smcb, job_status_s *js_p)
147{
148    PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
149    int ret = -PVFS_EINVAL, i = 0, tmp = 0;
150    struct server_configuration_s *server_config = NULL;
151    PVFS_msg_tag_t session_tag;
152    PINT_sm_msgpair_state *msg_p = NULL;
153    struct filesystem_configuration_s *cur_fs = NULL;
154    int must_loop_encodings = 0;
155    int local_enc_and_alloc = 0;
156
157    gossip_debug(
158        GOSSIP_MSGPAIR_DEBUG, "%s: sm %p "
159        "%d total message(s) with %d incomplete\n", __func__, smcb,
160        mop->count * 2, mop->params.comp_ct);
161
162    js_p->error_code = 0;
163
164    assert(mop->count > 0);
165    assert(mop->params.comp_ct >= 2);
166
167    for (i = 0; i < mop->count; i++)
168    {
169        msg_p = &mop->msgarray[i];
170        assert(msg_p);
171
172        /*
173          here we skip over the msgs that have already completed in
174          the case of being in the retry code path when it's ok
175        */
176        if (msg_p->complete)
177        {
178            continue;
179        }
180
181        msg_p->op_status = 0;
182
183        if (msg_p->encoded_resp_p == NULL)
184        {
185            if (msg_p->fs_id != PVFS_FS_ID_NULL)
186            {
187                server_config = PINT_server_config_mgr_get_config(
188                    msg_p->fs_id);
189                assert(server_config);
190
191                cur_fs = PINT_config_find_fs_id(
192                    server_config, msg_p->fs_id);
193                PINT_server_config_mgr_put_config(server_config);
194                assert(cur_fs);
195                msg_p->enc_type = cur_fs->encoding;
196            }
197
198            if (!ENCODING_IS_VALID(msg_p->enc_type))
199            {
200                PRINT_ENCODING_ERROR("supported", msg_p->enc_type);
201                must_loop_encodings = 1;
202                msg_p->enc_type = (ENCODING_INVALID_MIN + 1);
203            }
204            else if (!ENCODING_IS_SUPPORTED(msg_p->enc_type))
205            {
206                PRINT_ENCODING_ERROR("supported", msg_p->enc_type);
207                must_loop_encodings = 1;
208                msg_p->enc_type = ENCODING_SUPPORTED_MIN;
209            }
210
211          try_next_encoding:
212            assert(ENCODING_IS_VALID(msg_p->enc_type));
213
214            ret = PINT_encode(&msg_p->req, PINT_ENCODE_REQ,
215                              &msg_p->encoded_req, msg_p->svr_addr,
216                              msg_p->enc_type);
217            if (ret != 0)
218            {
219                if (must_loop_encodings)
220                {
221                    gossip_debug(GOSSIP_MSGPAIR_DEBUG, "Looping through "
222                                 "encodings [%d/%d]\n", msg_p->enc_type,
223                                 ENCODING_INVALID_MAX);
224
225                    msg_p->enc_type++;
226                    if (ENCODING_IS_VALID(msg_p->enc_type))
227                    {
228                        goto try_next_encoding;
229                    }
230                }
231                gossip_lerr("msgpairarray_post: PINT_encode failed\n");
232                js_p->error_code = ret;
233                return SM_ACTION_COMPLETE;
234            }
235
236            /* calculate max response msg size and allocate space */
237            msg_p->max_resp_sz = PINT_encode_calc_max_size(
238                PINT_ENCODE_RESP, msg_p->req.op, msg_p->enc_type);
239
240
241            msg_p->encoded_resp_p = BMI_memalloc(
242                msg_p->svr_addr, msg_p->max_resp_sz, BMI_RECV);
243
244            if (msg_p->encoded_resp_p == NULL)
245            {
246                js_p->error_code = -PVFS_ENOMEM;
247                return SM_ACTION_COMPLETE;
248            }
249            local_enc_and_alloc = 1;
250        }
251
252        session_tag = PINT_util_get_next_tag();
253
254        /*store the session tag for this msgpair, so the msgpair completion */
255        /*function can pass it to the caller of msgpairarray.               */
256        msg_p->session_tag = session_tag;
257
258        gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d: "
259                     "posting recv\n", __func__, smcb, i);
260
261        /* post receive of response; job_id stored in recv_id */
262        ret = job_bmi_recv(msg_p->svr_addr,
263                           msg_p->encoded_resp_p,
264                           msg_p->max_resp_sz,
265                           session_tag,
266                           BMI_PRE_ALLOC,
267                           smcb,
268                           i,
269                           &msg_p->recv_status,
270                           &msg_p->recv_id,
271                           mop->params.job_context,
272                           mop->params.job_timeout,
273                           msg_p->req.hints);
274        if (ret == 0)
275        {
276            /* perform a quick test to see if the recv failed before posting
277             * the send; if it reports an error quickly then we can save the
278             * confusion of sending a request for which we can't recv a
279             * response
280             */
281            ret = job_test(msg_p->recv_id, &tmp, NULL,
282                           &msg_p->recv_status, 0,
283                           mop->params.job_context);
284        }
285
286        if ((ret < 0) || (ret == 1))
287        {
288            /* it is impossible for this recv to complete at this point
289             * without errors; we haven't sent the request yet!
290             */
291            assert(ret < 0 || msg_p->recv_status.error_code != 0);
292            if (ret < 0)
293            {
294                PVFS_perror_gossip("Post of receive failed", ret);
295            }
296            else
297            {
298                PVFS_perror_gossip("Receive immediately failed",
299                            msg_p->recv_status.error_code);
300            }
301
302            msg_p->recv_id = 0;
303            msg_p->send_id = 0;
304
305            /* mark send as bad too and don't post it */
306            msg_p->send_status.error_code = msg_p->recv_status.error_code;
307            msg_p->op_status = msg_p->recv_status.error_code;
308            mop->params.comp_ct -= 2;
309
310            if (local_enc_and_alloc)
311            {
312                PINT_encode_release(&msg_p->encoded_req, PINT_ENCODE_REQ);
313                memset(&msg_p->encoded_req,0,sizeof(msg_p->encoded_req));
314                BMI_memfree(msg_p->svr_addr,msg_p->encoded_resp_p,
315                            msg_p->max_resp_sz, BMI_RECV);
316                msg_p->encoded_resp_p = NULL;
317                local_enc_and_alloc = 0;
318            }
319
320            /* continue to send other array entries if possible */
321            continue;
322        }
323
324        /* if we reach here, the recv has been posted without failure, but
325         * has not completed yet
326         */
327        assert(ret == 0);
328
329        gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d: "
330                     "posting send\n", __func__, smcb, i);
331
332        /* post send of request; job_id stored in send_id */
333        ret = job_bmi_send_list(msg_p->encoded_req.dest,
334                                msg_p->encoded_req.buffer_list,
335                                msg_p->encoded_req.size_list,
336                                msg_p->encoded_req.list_count,
337                                msg_p->encoded_req.total_size,
338                                session_tag,
339                                msg_p->encoded_req.buffer_type,
340                                1,
341                                smcb,
342                                mop->count+i,
343                                &msg_p->send_status,
344                                &msg_p->send_id,
345                                mop->params.job_context,
346                                mop->params.job_timeout,
347                                msg_p->req.hints);
348
349         if ((ret < 0) ||
350            ((ret == 1) && (msg_p->send_status.error_code != 0)))
351        {
352            if (ret < 0)
353            {
354                PVFS_perror_gossip("Post of send failed", ret);
355            }
356            else
357            {
358                PVFS_perror_gossip("Send immediately failed",
359                    msg_p->send_status.error_code);
360            }
361
362            gossip_err_unless_quiet("Send error: cancelling recv.\n");
363
364            job_bmi_cancel(msg_p->recv_id, mop->params.job_context);
365           
366            /* we still have to wait for recv completion, so just decrement
367             * comp_ct by one and keep going
368             */
369            msg_p->op_status = msg_p->send_status.error_code;
370            msg_p->send_id = 0;
371            mop->params.comp_ct--;
372        }
373        else if (ret == 1)
374        {
375            /* immediate completion */
376            msg_p->send_id = 0;
377            /* decrement our count, since send is already done. */
378            mop->params.comp_ct--;
379        }
380        /* else: successful post, no immediate completion */
381    }
382
383    if (mop->params.comp_ct == 0)
384    {
385        /* everything is completed already (could happen in some failure
386         * cases); jump straight to final completion function.
387         */
388         js_p->error_code = MSGPAIRS_COMPLETE;
389         return SM_ACTION_COMPLETE;
390    }
391
392    /* we are still waiting on operations to complete, next state
393     * transition will handle them
394     */
395    return SM_ACTION_DEFERRED;
396}
397
398static PINT_sm_action msgpairarray_post_retry(
399        struct PINT_smcb *smcb, job_status_s *js_p)
400{
401    PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
402    job_id_t tmp_id;
403
404    gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p, wait %d ms\n",
405      __func__, smcb, mop->params.retry_delay);
406
407    js_p->error_code = 0;  /* do not leak MSGPAIRS_RETRY through to wait */
408    return job_req_sched_post_timer(
409        mop->params.retry_delay,
410        smcb, 0, js_p, &tmp_id,
411        mop->params.job_context);
412}
413
414static PINT_sm_action msgpairarray_complete(
415        struct PINT_smcb *smcb, job_status_s *js_p)
416{
417    PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
418    gossip_debug(GOSSIP_MSGPAIR_DEBUG,
419      "%s: sm %p status_user_tag %d msgarray_count %d\n",
420      __func__, smcb, (int) js_p->status_user_tag, mop->count);
421
422
423    /* match operation with something in the msgpair array */
424    /* the first N tags are receives, the second N are sends */
425    assert(js_p->status_user_tag < mop->count*2);
426
427    if (js_p->status_user_tag < mop->count)
428    {
429        PINT_sm_msgpair_state *msg_p =
430            &mop->msgarray[js_p->status_user_tag];
431
432        msg_p->recv_id = 0;
433        msg_p->recv_status = *js_p;
434
435        /* save error (if we don't already have one) in op_status */
436        if(msg_p->op_status == 0)
437            msg_p->op_status = msg_p->recv_status.error_code;
438
439        if(msg_p->recv_status.error_code && msg_p->send_id != 0)
440        {
441            /* we got a receive error, but send is still pending.  Cancel
442             * the send
443             */
444            job_bmi_cancel(msg_p->send_id, mop->params.job_context);
445        }
446    }
447    else
448    {
449        PINT_sm_msgpair_state *msg_p = &mop->msgarray[
450            js_p->status_user_tag - mop->count];
451
452        msg_p->send_id = 0;
453        msg_p->send_status = *js_p;
454
455        /* save error (if we don't already have one) in op_status */
456        if(msg_p->op_status == 0)
457            msg_p->op_status = msg_p->send_status.error_code;
458
459        if(msg_p->send_status.error_code && msg_p->recv_id != 0)
460        {
461            /* we got a send error, but recv is still pending.  Cancel
462             * the recv
463             */
464            job_bmi_cancel(msg_p->recv_id, mop->params.job_context);
465        }
466    }
467
468    /* decrement comp_ct until all operations have completed */
469    if (--mop->params.comp_ct > 0)
470    {
471        gossip_debug(GOSSIP_MSGPAIR_DEBUG,
472                 "  msgpairarray: %d operations remain\n",
473                mop->params.comp_ct);
474        return SM_ACTION_DEFERRED;
475    }
476
477    assert(mop->params.comp_ct == 0);
478    gossip_debug(GOSSIP_MSGPAIR_DEBUG,
479                 "  msgpairarray: all operations complete\n");
480
481    js_p->error_code = MSGPAIRS_COMPLETE;
482    return SM_ACTION_COMPLETE;
483}
484
485static PINT_sm_action msgpairarray_completion_fn(
486        struct PINT_smcb *smcb, job_status_s *js_p)
487{
488    PINT_sm_msgarray_op *mop = PINT_sm_frame(smcb, PINT_FRAME_CURRENT);
489    int ret = -PVFS_EINVAL, i = 0;
490    int need_retry = 0;
491    struct PINT_decoded_msg decoded_resp;
492    const char* server_string = NULL;
493    int server_type;
494
495    /* response structure (decoded) */
496    struct PVFS_server_resp *resp_p = NULL;
497
498    js_p->error_code = 0;
499
500    gossip_debug(GOSSIP_MSGPAIR_DEBUG, "(%p) msgpairarray state: "
501                 "completion_fn\n", smcb);
502    gossip_debug(GOSSIP_MIRROR_DEBUG,"Executing msgpairarray_completion_fn..\n");
503
504    for (i = 0; i < mop->count; i++)
505    {
506        PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
507        assert(msg_p);
508
509        /*
510         * Can take multiple trips through this function as we retry
511         * ones that failed.
512         */
513        if (msg_p->complete)
514            continue;
515
516        if (msg_p->op_status != 0)
517        {
518            char s[1024];
519            PVFS_strerror_r(msg_p->op_status, s, sizeof(s));
520            server_string = PINT_cached_config_map_addr(
521                msg_p->fs_id, msg_p->svr_addr, &server_type);
522            if(!server_string)
523            {
524                server_string = BMI_addr_rev_lookup(msg_p->svr_addr);
525            }
526
527            gossip_err("Warning: msgpair failed to %s, will retry: %s\n", server_string, s);
528                       
529            ++need_retry;
530            continue;
531        }
532
533        ret = PINT_serv_decode_resp(msg_p->fs_id,
534                                    msg_p->encoded_resp_p,
535                                    &decoded_resp,
536                                    &msg_p->svr_addr,
537                                    msg_p->recv_status.actual_size,
538                                    &resp_p);
539        if (ret != 0)
540        {
541            PVFS_perror_gossip("msgpairarray decode error", ret);
542            msg_p->op_status = ret;
543        }
544        else
545        {
546            /* if we've made it this far, the server response status is
547             * meaningful, so we save it.
548             */
549            msg_p->op_status = resp_p->status;
550        }
551
552        /* NOTE: we call the function associated with each message,
553         *       not just the one from the first array element.  so
554         *       there could in theory be different functions for each
555         *       message (to handle different types of messages all in
556         *       the same array).
557         */
558        if (msg_p->comp_fn != NULL)
559        {
560            gossip_debug(GOSSIP_MIRROR_DEBUG,"\texecuting msg_p->comp_fn..\n");
561            /* If we call the completion function, store the result on
562             * a per message pair basis.  Also store some non-zero
563             * (failure) value in js_p->error_code if we see one.
564             */
565            msg_p->op_status = msg_p->comp_fn(smcb, resp_p, i);
566            if (msg_p->op_status != 0)
567            {
568                js_p->error_code = msg_p->op_status;
569            }
570
571            /* even if we see a failure, continue to process with the
572             * completion function. -- RobR
573             */
574        }
575        else if (resp_p->status != 0)
576        {
577            /* no comp_fn specified and status non-zero */
578            gossip_debug(GOSSIP_MSGPAIR_DEBUG,
579                         "notice: msgpairarray_complete: error %d "
580                         "from server %d\n", resp_p->status, i);
581
582            /* save a non-zero status to return if we see one */
583            js_p->error_code = resp_p->status;
584
585            /* If we don't have a completion function, there is no point
586             * in continuing to process after seeing a failure.
587             */
588            if (js_p->error_code)
589            {
590                break;
591            }
592        }
593
594        /* free all the resources that we used to send and receive. */
595        ret = PINT_serv_free_msgpair_resources(
596            &msg_p->encoded_req, msg_p->encoded_resp_p, &decoded_resp,
597            &msg_p->svr_addr, msg_p->max_resp_sz);
598        if (ret)
599        {
600            PVFS_perror_gossip("Failed to free msgpair resources", ret);
601            js_p->error_code = ret;
602            return SM_ACTION_COMPLETE;
603        }
604
605        memset(&msg_p->encoded_req,0,sizeof(msg_p->encoded_req));
606        msg_p->encoded_resp_p = NULL;
607        msg_p->max_resp_sz = 0;
608
609        /*
610          mark that this msgpair has been completed and should not be
611          retried in the case of possible future retries
612        */
613        msg_p->complete = 1;
614
615        gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d "
616                     "marked complete\n", __func__, smcb, i);
617    }/*end for*/
618
619    if (need_retry) {
620        /*
621         * We only retry msgpairs that are not yet complete.  Factor
622         * of two since they are pairs.  If over the count, do not
623         * retry, just return one of the error codes.
624         */
625        mop->params.comp_ct = 0;
626        js_p->error_code = 0;
627        for (i=0; i < mop->count; i++) {
628
629            PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
630
631            if (msg_p->complete)
632                continue;
633
634            if (msg_p->retry_flag == PVFS_MSGPAIR_RETRY
635             && PVFS_ERROR_CLASS(-msg_p->op_status) == PVFS_ERROR_BMI
636             && msg_p->retry_count < mop->params.retry_limit) {
637
638                ++msg_p->retry_count;
639                mop->params.comp_ct += 2;
640                gossip_debug(GOSSIP_MSGPAIR_DEBUG,
641                  "*** %s: msgpair %d failed, retry %d\n",
642                  __func__, i, msg_p->retry_count);
643                if(msg_p->op_status == -BMI_ECANCEL)
644                {
645                    /* if the error code indicates cancel, then skip the
646                     * delay.  We have probably already been waiting a while
647                     */
648                    gossip_debug(GOSSIP_MSGPAIR_DEBUG,
649                       "*** %s: msgpair skipping retry delay.\n", __func__);
650                    js_p->error_code = MSGPAIRS_RETRY_NODELAY;
651                }
652                else
653                {
654                    gossip_debug(GOSSIP_MSGPAIR_DEBUG,
655                       "*** %s: msgpair retrying after delay.\n", __func__);
656                    js_p->error_code = MSGPAIRS_RETRY;
657                }
658
659            } else {
660                char s[1024];
661                server_string = PINT_cached_config_map_addr(
662                    msg_p->fs_id, msg_p->svr_addr, &server_type);
663                if(!server_string)
664                {
665                    server_string = "[UNKNOWN]";
666                }
667                PVFS_strerror_r(msg_p->op_status, s, sizeof(s));
668                gossip_err_unless_quiet("*** %s: msgpair to server %s failed: %s\n",
669                        __func__, server_string, s);
670                if(msg_p->retry_flag != PVFS_MSGPAIR_RETRY)
671                {
672                    gossip_err_unless_quiet("*** No retries requested.\n");
673                }
674                else if(PVFS_ERROR_CLASS(-msg_p->op_status) !=
675                    PVFS_ERROR_BMI)
676                {
677                    gossip_err_unless_quiet("*** Non-BMI failure.\n");
678                }
679                else
680                {
681                    gossip_err_unless_quiet("*** Out of retries.\n");
682                }
683                if (js_p->error_code == 0)
684                    js_p->error_code = msg_p->op_status;
685            }
686
687        }
688    }
689    return SM_ACTION_COMPLETE;
690}
691
692static PINT_sm_action msgpairarray_done(
693        struct PINT_smcb *smcb, job_status_s *js_p)
694{
695    int task_id, error_code, remaining;
696    PINT_sm_pop_frame(smcb, &task_id, &error_code, &remaining);
697    return SM_ACTION_COMPLETE;
698}
699
700/*********************************************************************
701 * helper functions used in conjunction with state machine defined above
702 */
703
704int PINT_msgpairarray_init(
705    PINT_sm_msgarray_op *op,
706    int count)
707{
708    op->msgarray = (PINT_sm_msgpair_state *)malloc(
709        count * sizeof(PINT_sm_msgpair_state));
710    if(!op->msgarray)
711    {
712        return -PVFS_ENOMEM;
713    }
714    memset(op->msgarray, 0, (count * sizeof(PINT_sm_msgpair_state)));
715    op->count = count;
716
717    return 0;
718}
719
720/* we pass in a pointer to the array so that we can set it to NULL */
721void PINT_msgpairarray_destroy(
722    PINT_sm_msgarray_op *op)
723{
724    if(op->msgarray && (&op->msgpair) != op->msgarray)
725    {
726        free(op->msgarray);
727    }
728    op->msgarray = NULL;
729    op->count = 0;
730}
731
732int PINT_msgarray_status(PINT_sm_msgarray_op *op)
733{
734    int i;
735    for (i = 0; i < op->count; i++)
736    {
737        if (op->msgarray[i].op_status != 0)
738        {
739            return op->msgarray[i].op_status;
740        }
741    }
742    return 0;
743}
744
745int PINT_serv_decode_resp(PVFS_fs_id fs_id,
746                          void *encoded_resp_p,
747                          struct PINT_decoded_msg *decoded_resp_p,
748                          PVFS_BMI_addr_t *svr_addr_p,
749                          int actual_resp_sz,
750                          struct PVFS_server_resp **resp_out_pp)
751{
752    int ret = -1, server_type = 0;
753    const char *server_string;
754
755    ret = PINT_decode(encoded_resp_p, PINT_DECODE_RESP,
756                      decoded_resp_p, /* holds data on decoded resp */
757                      *svr_addr_p, actual_resp_sz);
758    if (ret > -1)
759    {
760        *resp_out_pp = (struct PVFS_server_resp *)decoded_resp_p->buffer;
761        if ((*resp_out_pp)->op == PVFS_SERV_PROTO_ERROR)
762        {
763
764            gossip_err("Error: server does not seem to understand "
765                       "the protocol that this client is using.\n");
766            gossip_err("   Please check server logs for more "
767                       "information.\n");
768
769            if (fs_id != PVFS_FS_ID_NULL)
770            {
771                server_string = PINT_cached_config_map_addr(
772                    fs_id, *svr_addr_p, &server_type);
773                gossip_err("   Server: %s.\n", server_string);
774            }
775            else
776            {
777                gossip_err("   Server: unknown; probably an error "
778                           "contacting server listed in pvfs2tab "
779                           "file.\n");
780            }
781            return(-EPROTONOSUPPORT);
782        }
783    }
784    return ret;
785}
786
787int PINT_serv_free_msgpair_resources(
788    struct PINT_encoded_msg *encoded_req_p,
789    void *encoded_resp_p,
790    struct PINT_decoded_msg *decoded_resp_p,
791    PVFS_BMI_addr_t *svr_addr_p,
792    int max_resp_sz)
793{
794    int ret = -PVFS_EINVAL;
795
796    if (encoded_req_p && decoded_resp_p && svr_addr_p)
797    {
798        PINT_encode_release(encoded_req_p, PINT_ENCODE_REQ);
799        memset(encoded_req_p,0,sizeof(*encoded_req_p));
800
801        PINT_decode_release(decoded_resp_p, PINT_DECODE_RESP);
802        memset(decoded_resp_p,0,sizeof(*decoded_resp_p));
803
804        BMI_memfree(*svr_addr_p, encoded_resp_p, max_resp_sz, BMI_RECV);
805        encoded_resp_p = NULL;
806
807        ret = 0;
808    }
809    return ret;
810}
811
812/* PINT_serv_msgpair_array_resolve_addrs()
813 *
814 * fills in BMI address of server for each entry in the msgpair array,
815 * based on the handle and fsid
816 *
817 * returns 0 on success, -PVFS_error on failure
818 */
819int PINT_serv_msgpairarray_resolve_addrs(
820    PINT_sm_msgarray_op *mop)
821{
822    int i = 0;
823    int ret = -PVFS_EINVAL;
824
825    if ((mop->count > 0) && mop->msgarray)
826    {
827        for(i = 0; i < mop->count; i++)
828        {
829            PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
830            assert(msg_p);
831
832            ret = PINT_cached_config_map_to_server(
833                &msg_p->svr_addr, msg_p->handle, msg_p->fs_id);
834
835            if (ret != 0)
836            {
837                gossip_err("Failed to map server address to handle\n");
838                break;
839            }
840
841            gossip_debug(GOSSIP_MSGPAIR_DEBUG,
842                         " mapped handle %llu to server %lld\n",
843                         llu(msg_p->handle), lld(msg_p->svr_addr));
844        }
845    }
846    return ret;
847}
848
849/*
850 * Local variables:
851 *  mode: c
852 *  c-indent-level: 4
853 *  c-basic-offset: 4
854 * End:
855 *
856 * vim: ft=c ts=8 sts=4 sw=4 expandtab
857 */
858
Note: See TracBrowser for help on using the browser.