root/branches/orange-next/src/common/misc/msgpairarray.sm @ 8959

Revision 8959, 27.1 KB (checked in by mtmoore, 23 months ago)

remove extents, handle ranges, precreate pools and various other things that aren't needed in their current forms with UUIDs

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
494    /* response structure (decoded) */
495    struct PVFS_server_resp *resp_p = NULL;
496
497    js_p->error_code = 0;
498
499    gossip_debug(GOSSIP_MSGPAIR_DEBUG, "(%p) msgpairarray state: "
500                 "completion_fn\n", smcb);
501    gossip_debug(GOSSIP_MIRROR_DEBUG,"Executing msgpairarray_completion_fn..\n");
502
503    for (i = 0; i < mop->count; i++)
504    {
505        PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
506        assert(msg_p);
507
508        /*
509         * Can take multiple trips through this function as we retry
510         * ones that failed.
511         */
512        if (msg_p->complete)
513            continue;
514
515        if (msg_p->op_status != 0)
516        {
517            char s[1024];
518            PVFS_strerror_r(msg_p->op_status, s, sizeof(s));
519            server_string = PINT_cached_config_map_addr(
520                msg_p->fs_id, msg_p->svr_addr);
521            if(!server_string)
522            {
523                server_string = BMI_addr_rev_lookup(msg_p->svr_addr);
524            }
525
526            gossip_err("Warning: msgpair failed to %s, will retry: %s\n", server_string, s);
527                       
528            ++need_retry;
529            continue;
530        }
531
532        ret = PINT_serv_decode_resp(msg_p->fs_id,
533                                    msg_p->encoded_resp_p,
534                                    &decoded_resp,
535                                    &msg_p->svr_addr,
536                                    msg_p->recv_status.actual_size,
537                                    &resp_p);
538        if (ret != 0)
539        {
540            PVFS_perror_gossip("msgpairarray decode error", ret);
541            msg_p->op_status = ret;
542        }
543        else
544        {
545            /* if we've made it this far, the server response status is
546             * meaningful, so we save it.
547             */
548            msg_p->op_status = resp_p->status;
549        }
550
551        /* NOTE: we call the function associated with each message,
552         *       not just the one from the first array element.  so
553         *       there could in theory be different functions for each
554         *       message (to handle different types of messages all in
555         *       the same array).
556         */
557        if (msg_p->comp_fn != NULL)
558        {
559            gossip_debug(GOSSIP_MIRROR_DEBUG,"\texecuting msg_p->comp_fn..\n");
560            /* If we call the completion function, store the result on
561             * a per message pair basis.  Also store some non-zero
562             * (failure) value in js_p->error_code if we see one.
563             */
564            msg_p->op_status = msg_p->comp_fn(smcb, resp_p, i);
565            if (msg_p->op_status != 0)
566            {
567                js_p->error_code = msg_p->op_status;
568            }
569
570            /* even if we see a failure, continue to process with the
571             * completion function. -- RobR
572             */
573        }
574        else if( (msg_p->op_status != 0) && (resp_p == NULL) )
575        {
576            /* before we reference resp_p we need to catch the case where
577             * PINT_serv_decode_resp didn't give us a struct. We error out
578             * the same without referencing resp_p */
579            gossip_debug(GOSSIP_MSGPAIR_DEBUG,
580                         "%s: error code %d from PINT_serv_decode_resp, "
581                         "from server %d\n", __func__, msg_p->op_status, i);
582            js_p->error_code = msg_p->op_status;
583            break;
584        }
585        else if (resp_p->status != 0)
586        {
587            /* no comp_fn specified and status non-zero */
588            gossip_debug(GOSSIP_MSGPAIR_DEBUG,
589                         "notice: msgpairarray_complete: error %d "
590                         "from server %d\n", resp_p->status, i);
591
592            /* save a non-zero status to return if we see one */
593            js_p->error_code = resp_p->status;
594
595            /* If we don't have a completion function, there is no point
596             * in continuing to process after seeing a failure.
597             */
598            if (js_p->error_code)
599            {
600                break;
601            }
602        }
603
604        /* free all the resources that we used to send and receive. */
605        ret = PINT_serv_free_msgpair_resources(
606            &msg_p->encoded_req, msg_p->encoded_resp_p, &decoded_resp,
607            &msg_p->svr_addr, msg_p->max_resp_sz);
608        if (ret)
609        {
610            PVFS_perror_gossip("Failed to free msgpair resources", ret);
611            js_p->error_code = ret;
612            return SM_ACTION_COMPLETE;
613        }
614
615        memset(&msg_p->encoded_req,0,sizeof(msg_p->encoded_req));
616        msg_p->encoded_resp_p = NULL;
617        msg_p->max_resp_sz = 0;
618
619        /*
620          mark that this msgpair has been completed and should not be
621          retried in the case of possible future retries
622        */
623        msg_p->complete = 1;
624
625        gossip_debug(GOSSIP_MSGPAIR_DEBUG, "%s: sm %p msgpair %d "
626                     "marked complete\n", __func__, smcb, i);
627    }/*end for*/
628
629    if (need_retry) {
630        /*
631         * We only retry msgpairs that are not yet complete.  Factor
632         * of two since they are pairs.  If over the count, do not
633         * retry, just return one of the error codes.
634         */
635        mop->params.comp_ct = 0;
636        js_p->error_code = 0;
637        for (i=0; i < mop->count; i++) {
638
639            PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
640
641            if (msg_p->complete)
642                continue;
643
644            if (msg_p->retry_flag == PVFS_MSGPAIR_RETRY
645             && PVFS_ERROR_CLASS(-msg_p->op_status) == PVFS_ERROR_BMI
646             && msg_p->retry_count < mop->params.retry_limit) {
647
648                ++msg_p->retry_count;
649                mop->params.comp_ct += 2;
650                gossip_debug(GOSSIP_MSGPAIR_DEBUG,
651                  "*** %s: msgpair %d failed, retry %d\n",
652                  __func__, i, msg_p->retry_count);
653                if(msg_p->op_status == -BMI_ECANCEL)
654                {
655                    /* if the error code indicates cancel, then skip the
656                     * delay.  We have probably already been waiting a while
657                     */
658                    gossip_debug(GOSSIP_MSGPAIR_DEBUG,
659                       "*** %s: msgpair skipping retry delay.\n", __func__);
660                    js_p->error_code = MSGPAIRS_RETRY_NODELAY;
661                }
662                else
663                {
664                    gossip_debug(GOSSIP_MSGPAIR_DEBUG,
665                       "*** %s: msgpair retrying after delay.\n", __func__);
666                    js_p->error_code = MSGPAIRS_RETRY;
667                }
668
669            } else {
670                char s[1024];
671                server_string = PINT_cached_config_map_addr(
672                    msg_p->fs_id, msg_p->svr_addr);
673                if(!server_string)
674                {
675                    server_string = "[UNKNOWN]";
676                }
677                PVFS_strerror_r(msg_p->op_status, s, sizeof(s));
678                gossip_err_unless_quiet("*** %s: msgpair to server %s failed: %s\n",
679                        __func__, server_string, s);
680                if(msg_p->retry_flag != PVFS_MSGPAIR_RETRY)
681                {
682                    gossip_err_unless_quiet("*** No retries requested.\n");
683                }
684                else if(PVFS_ERROR_CLASS(-msg_p->op_status) !=
685                    PVFS_ERROR_BMI)
686                {
687                    gossip_err_unless_quiet("*** Non-BMI failure.\n");
688                }
689                else
690                {
691                    gossip_err_unless_quiet("*** Out of retries.\n");
692                }
693                if (js_p->error_code == 0)
694                    js_p->error_code = msg_p->op_status;
695            }
696
697        }
698    }
699    return SM_ACTION_COMPLETE;
700}
701
702static PINT_sm_action msgpairarray_done(
703        struct PINT_smcb *smcb, job_status_s *js_p)
704{
705    int task_id, error_code, remaining;
706    PINT_sm_pop_frame(smcb, &task_id, &error_code, &remaining);
707    return SM_ACTION_COMPLETE;
708}
709
710/*********************************************************************
711 * helper functions used in conjunction with state machine defined above
712 */
713
714int PINT_msgpairarray_init(
715    PINT_sm_msgarray_op *op,
716    int count)
717{
718    op->msgarray = (PINT_sm_msgpair_state *)malloc(
719        count * sizeof(PINT_sm_msgpair_state));
720    if(!op->msgarray)
721    {
722        return -PVFS_ENOMEM;
723    }
724    memset(op->msgarray, 0, (count * sizeof(PINT_sm_msgpair_state)));
725    op->count = count;
726
727    return 0;
728}
729
730/* we pass in a pointer to the array so that we can set it to NULL */
731void PINT_msgpairarray_destroy(
732    PINT_sm_msgarray_op *op)
733{
734    if(op->msgarray && (&op->msgpair) != op->msgarray)
735    {
736        free(op->msgarray);
737    }
738    op->msgarray = NULL;
739    op->count = 0;
740}
741
742int PINT_msgarray_status(PINT_sm_msgarray_op *op)
743{
744    int i;
745    for (i = 0; i < op->count; i++)
746    {
747        if (op->msgarray[i].op_status != 0)
748        {
749            return op->msgarray[i].op_status;
750        }
751    }
752    return 0;
753}
754
755int PINT_serv_decode_resp(PVFS_fs_id fs_id,
756                          void *encoded_resp_p,
757                          struct PINT_decoded_msg *decoded_resp_p,
758                          PVFS_BMI_addr_t *svr_addr_p,
759                          int actual_resp_sz,
760                          struct PVFS_server_resp **resp_out_pp)
761{
762    int ret = -1;
763    const char *server_string;
764
765    ret = PINT_decode(encoded_resp_p, PINT_DECODE_RESP,
766                      decoded_resp_p, /* holds data on decoded resp */
767                      *svr_addr_p, actual_resp_sz);
768    if (ret > -1)
769    {
770        *resp_out_pp = (struct PVFS_server_resp *)decoded_resp_p->buffer;
771        if ((*resp_out_pp)->op == PVFS_SERV_PROTO_ERROR)
772        {
773
774            gossip_err("Error: server does not seem to understand "
775                       "the protocol that this client is using.\n");
776            gossip_err("   Please check server logs for more "
777                       "information.\n");
778
779            if (fs_id != PVFS_FS_ID_NULL)
780            {
781                server_string = PINT_cached_config_map_addr(
782                    fs_id, *svr_addr_p);
783                gossip_err("   Server: %s.\n", server_string);
784            }
785            else
786            {
787                gossip_err("   Server: unknown; probably an error "
788                           "contacting server listed in pvfs2tab "
789                           "file.\n");
790            }
791            return(-EPROTONOSUPPORT);
792        }
793    }
794    return ret;
795}
796
797int PINT_serv_free_msgpair_resources(
798    struct PINT_encoded_msg *encoded_req_p,
799    void *encoded_resp_p,
800    struct PINT_decoded_msg *decoded_resp_p,
801    PVFS_BMI_addr_t *svr_addr_p,
802    int max_resp_sz)
803{
804    int ret = -PVFS_EINVAL;
805
806    if (encoded_req_p && decoded_resp_p && svr_addr_p)
807    {
808        PINT_encode_release(encoded_req_p, PINT_ENCODE_REQ);
809        memset(encoded_req_p,0,sizeof(*encoded_req_p));
810
811        PINT_decode_release(decoded_resp_p, PINT_DECODE_RESP);
812        memset(decoded_resp_p,0,sizeof(*decoded_resp_p));
813
814        BMI_memfree(*svr_addr_p, encoded_resp_p, max_resp_sz, BMI_RECV);
815        encoded_resp_p = NULL;
816
817        ret = 0;
818    }
819    return ret;
820}
821
822/* PINT_serv_msgpair_array_resolve_addrs()
823 *
824 * fills in BMI address of server for each entry in the msgpair array,
825 * based on the handle and fsid
826 *
827 * returns 0 on success, -PVFS_error on failure
828 */
829int PINT_serv_msgpairarray_resolve_addrs(
830    PINT_sm_msgarray_op *mop)
831{
832    int i = 0;
833    int ret = -PVFS_EINVAL;
834
835    if ((mop->count > 0) && mop->msgarray)
836    {
837        for(i = 0; i < mop->count; i++)
838        {
839            PINT_sm_msgpair_state *msg_p = &mop->msgarray[i];
840            assert(msg_p);
841
842            ret = PINT_cached_config_map_to_server(
843                &msg_p->svr_addr, msg_p->handle, msg_p->fs_id);
844
845            if (ret != 0)
846            {
847                gossip_err("Failed to map server address to handle\n");
848                break;
849            }
850
851            gossip_debug(GOSSIP_MSGPAIR_DEBUG,
852                         " mapped handle %llu to server %lld\n",
853                         llu(msg_p->handle), lld(msg_p->svr_addr));
854        }
855    }
856    return ret;
857}
858
859/*
860 * Local variables:
861 *  mode: c
862 *  c-indent-level: 4
863 *  c-basic-offset: 4
864 * End:
865 *
866 * vim: ft=c ts=8 sts=4 sw=4 expandtab
867 */
868
Note: See TracBrowser for help on using the browser.