root/trunk/src/proto/PINT-reqproto-encode.c @ 4536

Revision 4536, 8.8 KB (checked in by pw, 8 years ago)

one line for nice logfile output

Line 
1/*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7#include <stdlib.h>
8#include <errno.h>
9#include <string.h>
10
11#include "bmi.h"
12#include "gossip.h"
13#include "pvfs2-req-proto.h"
14#include "PINT-reqproto-encode.h"
15#include "PINT-reqproto-module.h"
16#include "bmi-byteswap.h"
17#include "pint-event.h"
18#include "id-generator.h"
19
20#define ENCODING_TABLE_SIZE 5
21
22/* macros for logging encode and decode events */
23#define ENCODE_EVENT_START(__enctype, __reqtype, __ptr) \
24do { \
25    PVFS_id_gen_t __tmp_id; \
26    id_gen_fast_register(&__tmp_id, (__ptr)); \
27    PINT_event_timestamp(__enctype, \
28    (int32_t)(__reqtype), 0, __tmp_id, \
29    PVFS_EVENT_FLAG_START); \
30} while(0)
31#define ENCODE_EVENT_STOP(__enctype, __reqtype, __ptr, __size) \
32do { \
33    PVFS_id_gen_t __tmp_id; \
34    id_gen_fast_register(&__tmp_id, (__ptr)); \
35    PINT_event_timestamp(__enctype, \
36    (int32_t)(__reqtype), (__size), __tmp_id, \
37    PVFS_EVENT_FLAG_END); \
38} while(0)
39
40extern PINT_encoding_table_values le_bytefield_table;
41int g_admin_mode = 0;
42
43static PINT_encoding_table_values *PINT_encoding_table[
44    ENCODING_TABLE_SIZE] = {NULL};
45
46/* PINT_encode_initialize()
47 *
48 * starts up the protocol encoding interface
49 *
50 * returns 0 on success, -PVFS_error on failure
51 */
52int PINT_encode_initialize(void)
53{
54    int ret = -PVFS_EINVAL;
55
56    gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_initialize\n");
57    if (ENCODING_IS_SUPPORTED(ENCODING_LE_BFIELD))
58    {
59        /* setup little endian bytefield encoding */
60        PINT_encoding_table[ENCODING_LE_BFIELD] = &le_bytefield_table;
61        le_bytefield_table.init_fun();
62
63        /* header prepended to all messages of this type */
64        *((int32_t*)&(le_bytefield_table.generic_header[0])) =
65            htobmi32(PVFS_RELEASE_NR);
66        *((int32_t*)&(le_bytefield_table.generic_header[4])) =
67            htobmi32(ENCODING_LE_BFIELD);
68
69        ret = 0;
70    }
71    return ret;
72}
73
74/* PINT_encode_finalize()
75 *
76 * shuts down the protocol encoding interface
77 *
78 * no return value
79 */
80void PINT_encode_finalize(void)
81{
82    gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_finalize\n");
83    return;
84}
85
86
87/* PINT_encode()
88 *
89 * encodes a buffer (containing a PVFS2 request or response) to be
90 * sent over the network
91 *
92 * returns 0 on success, -PVFS_error on failure
93 */
94int PINT_encode(void* input_buffer,
95                enum PINT_encode_msg_type input_type,
96                struct PINT_encoded_msg* target_msg,
97                PVFS_BMI_addr_t target_addr,
98                enum PVFS_encoding_type enc_type)
99{
100    int ret = -PVFS_EINVAL;
101    target_msg->dest = target_addr;
102    target_msg->enc_type = enc_type;
103
104    gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode\n");
105    switch(enc_type)
106    {
107        case ENCODING_LE_BFIELD:
108            if (input_type == PINT_ENCODE_REQ)
109            {
110                struct PVFS_server_req* tmp_req = input_buffer;
111                ENCODE_EVENT_START(PVFS_EVENT_API_ENCODE_REQ,
112                    tmp_req->op, tmp_req);
113                ret =  PINT_encoding_table[enc_type]->op->encode_req(
114                    input_buffer, target_msg);
115                ENCODE_EVENT_STOP(PVFS_EVENT_API_ENCODE_REQ,
116                    tmp_req->op, tmp_req, target_msg->total_size);
117            }
118            else if (input_type == PINT_ENCODE_RESP)
119            {
120                struct PVFS_server_resp* tmp_resp = input_buffer;
121                ENCODE_EVENT_START(PVFS_EVENT_API_ENCODE_RESP,
122                    tmp_resp->op, tmp_resp);
123                ret =  PINT_encoding_table[enc_type]->op->encode_resp(
124                    input_buffer, target_msg);
125                ENCODE_EVENT_STOP(PVFS_EVENT_API_ENCODE_RESP,
126                    tmp_resp->op, tmp_resp, target_msg->total_size);
127            }
128            break;
129        default:
130            gossip_lerr("Error: encoding type not supported.\n");
131            ret = -PVFS_EINVAL;
132            break;
133    }
134    return(ret);
135}
136
137/* PINT_decode()
138 *
139 * decodes a buffer (containing a PVFS2 request or response) that
140 * has been received from the network
141 *
142 * Parameters:
143 * input_buffer - encoded input
144 * input_type   - PINT_DECODE_REQ or PINT_DECODE_RESP
145 * target_msg   - pointer to struct PINT_decoded_msg, hold pointer to
146 *                allocated memory holding decoded message, etc.
147 * size         - size of encoded input
148 *
149 * Notes:
150 * - One must call PINT_decode_release(target_msg, input_type, 0)
151 *   in order for the memory allocated during the decode process to be
152 *   freed.
153 *
154 * returns 0 on success, -PVFS_error on failure
155 */
156int PINT_decode(void* input_buffer,
157                enum PINT_encode_msg_type input_type,
158                struct PINT_decoded_msg* target_msg,
159                PVFS_BMI_addr_t target_addr,
160                PVFS_size size)
161{
162    int i=0;
163    char* buffer_index = (char*)input_buffer + PINT_ENC_GENERIC_HEADER_SIZE;
164    int size_index = (int)size - PINT_ENC_GENERIC_HEADER_SIZE;
165    char* enc_type_ptr = (char*)input_buffer + 4;
166    int ret;
167    int32_t enc_type_recved, proto_ver_recved;
168
169    gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_decode\n");
170    /* compare the header of the incoming buffer against the precalculated
171     * header associated with each module
172     */
173    for(i=0; i<ENCODING_TABLE_SIZE; i++)
174    {
175        if(PINT_encoding_table[i] && !(memcmp(input_buffer,
176            PINT_encoding_table[i]->generic_header,
177            PINT_ENC_GENERIC_HEADER_SIZE)))
178        {
179            struct PVFS_server_req* tmp_req;
180            struct PVFS_server_req* tmp_resp;
181            target_msg->enc_type = bmitoh32(*((int32_t*)enc_type_ptr));
182            if(input_type == PINT_DECODE_REQ)
183            {
184                ENCODE_EVENT_START(PVFS_EVENT_API_DECODE_REQ,
185                    0, input_buffer);
186                ret = PINT_encoding_table[i]->op->decode_req(buffer_index,
187                    size_index,
188                    target_msg,
189                    target_addr);
190                tmp_req = target_msg->buffer;
191                ENCODE_EVENT_STOP(PVFS_EVENT_API_DECODE_REQ,
192                    tmp_req->op, input_buffer, size);
193                return(ret);
194            }
195            else if(input_type == PINT_DECODE_RESP)
196            {
197                ENCODE_EVENT_START(PVFS_EVENT_API_DECODE_RESP,
198                    0, input_buffer);
199                ret = PINT_encoding_table[i]->op->decode_resp(buffer_index,
200                    size_index,
201                    target_msg,
202                    target_addr);
203                tmp_resp = target_msg->buffer;
204                ENCODE_EVENT_STOP(PVFS_EVENT_API_DECODE_RESP,
205                    tmp_resp->op, input_buffer, size);
206                return(ret);
207            }
208            else
209            {
210                return(-PVFS_EINVAL);
211            }
212        }
213    }
214
215    gossip_err("Error: poorly formatted protocol message received.\n");
216
217    enc_type_recved = bmitoh32(*((int32_t*)enc_type_ptr));
218    proto_ver_recved = (int)bmitoh32(*((int32_t*)input_buffer));
219
220    if(size < PINT_ENC_GENERIC_HEADER_SIZE)
221    {
222        gossip_err("   Too small: message only %Ld bytes.\n",
223            Ld(size));
224        return(-PVFS_EPROTO);
225    }
226
227    if(enc_type_recved != ENCODING_LE_BFIELD)
228    {
229        gossip_err("   Encoding type mismatch: received type %d when "
230            "expecting %d.\n", (int)enc_type_recved,
231            ENCODING_LE_BFIELD);
232    }
233
234    if(proto_ver_recved != PVFS_RELEASE_NR)
235    {
236        gossip_err("   Protocol version mismatch: received version %d when "
237            "expecting version %d.\n", (int)proto_ver_recved,
238            PVFS_RELEASE_NR);
239        gossip_err("   Please verify your PVFS2 installation and make sure "
240        "that the version is consistent.\n");
241    }
242
243    return(-PVFS_EPROTONOSUPPORT);
244}
245       
246/* PINT_encode_release()
247 *
248 * frees all resources associated with a message that has been
249 * encoded
250 *
251 * no return value
252 */
253void PINT_encode_release(struct PINT_encoded_msg* input_buffer,
254                         enum PINT_encode_msg_type input_type)
255{
256    gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_release\n");
257    if (ENCODING_IS_SUPPORTED(input_buffer->enc_type))
258    {
259        PINT_encoding_table[input_buffer->enc_type]->op->encode_release(
260            input_buffer, input_type);
261    }
262    else
263    {
264        gossip_err("PINT_encode_release: Encoder type %d is not "
265                   "supported.\n", input_buffer->enc_type);
266    }
267}
268
269/* PINT_decode_release()
270 *
271 * frees all resources associated with a message that has been
272 * decoded
273 *
274 * no return value
275 */
276void PINT_decode_release(struct PINT_decoded_msg* input_buffer,
277                         enum PINT_encode_msg_type input_type)
278{
279    gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_decode_release\n");
280    if (ENCODING_IS_SUPPORTED(input_buffer->enc_type))
281    {
282        PINT_encoding_table[input_buffer->enc_type]->op->decode_release(
283            input_buffer, input_type);
284    }
285    else
286    {
287        gossip_err("PINT_decode_release: Encoder type %d is not "
288                   "supported.\n", input_buffer->enc_type);
289    }
290}
291
292
293/* PINT_encode_calc_max_size()
294 *
295 * calculates maximum size of the encoded version of a protocol message.
296 *
297 * returns max size of encoded buffer on success, -PVFS_error on failure
298 */
299int PINT_encode_calc_max_size(
300    enum PINT_encode_msg_type input_type,
301    enum PVFS_server_op op_type,
302    enum PVFS_encoding_type enc_type)
303{   
304    int ret = -PVFS_EINVAL;
305
306    gossip_debug(GOSSIP_ENDECODE_DEBUG,"PINT_encode_calc_max_size\n");
307    switch(enc_type)
308    {
309        case ENCODING_LE_BFIELD:
310            ret = PINT_encoding_table[enc_type]->op->encode_calc_max_size
311                (input_type, op_type);
312            break;
313        default:
314            gossip_lerr("Error: encoding type not supported.\n");
315            break;
316    }
317
318    return(ret);
319}
320
321/*
322 * Local variables:
323 *  c-indent-level: 4
324 *  c-basic-offset: 4
325 * End:
326 *
327 * vim: ts=8 sts=4 sw=4 expandtab
328 */
Note: See TracBrowser for help on using the browser.