root/trunk/src/io/bmi/op-list.c @ 8304

Revision 8304, 6.1 KB (checked in by pcarns, 3 years ago)

merging bmi-experimental-branch to trunk

Line 
1/*
2 * (C) 2001 Clemson University and The University of Chicago
3 *
4 * See COPYING in top-level directory.
5 */
6
7/*
8 * functions to handle storage of 
9 * operation info structures for the BMI
10 *
11 * This is built on top of the quicklist.[ch] files
12 */
13
14/*
15 * NOTE: I am not locking any data structures in here!  It is assumed
16 * that the calling process is locking the appropriate operation
17 * structures before calling any of the functions provided here.
18 */
19
20#include <stdlib.h>
21#include <errno.h>
22
23#include "bmi-method-support.h"
24#include "op-list.h"
25#include "gossip.h"
26
27
28/***************************************************************
29 * Function prototypes
30 */
31
32static void gossip_print_op(method_op_p print_op);
33static int op_list_cmp_key(struct op_list_search_key *my_key,
34                           method_op_p my_op);
35
36/***************************************************************
37 * Visible functions
38 */
39
40/*
41 * op_list_dump()
42 *
43 * dumps the contents of the op list to stderr
44 *
45 * returns 0 on success, -errno on failure
46 */
47void op_list_dump(op_list_p olp)
48{
49    op_list_p tmp_entry = NULL;
50
51    gossip_err("op_list_dump():\n");
52    qlist_for_each(tmp_entry, olp)
53    {
54        gossip_print_op(qlist_entry(tmp_entry, struct method_op,
55                                    op_list_entry));
56    }
57}
58
59
60/*
61 * op_list_count()
62 *
63 * counts the number of entries in the op_list
64 *
65 * returns integer number of items on success, -errno on failure
66 */
67int op_list_count(op_list_p olp)
68{
69    int count = 0;
70    op_list_p tmp_entry = NULL;
71    qlist_for_each(tmp_entry, olp)
72    {
73        count++;
74    }
75    return (count);
76}
77
78
79/*
80 * op_list_new()
81 *
82 * creates a new operation list.
83 *
84 * returns pointer to an empty list or NULL on failure.
85 */
86op_list_p op_list_new(void)
87{
88    struct qlist_head *tmp_op_list = NULL;
89
90    tmp_op_list = (struct qlist_head *) malloc(sizeof(struct qlist_head));
91    if (tmp_op_list)
92    {
93        INIT_QLIST_HEAD(tmp_op_list);
94    }
95
96    return (tmp_op_list);
97}
98
99/*
100 * op_list_add()
101 *
102 * adds an operation to the list. 
103 *
104 * returns 0 on success, -1 on failure
105 */
106void op_list_add(op_list_p olp,
107                 method_op_p oip)
108{
109    /* note we are adding to tail:
110     * most modules will want to preserve FIFO ordering when searching
111     * through op_lists for work to do.
112     */
113    qlist_add_tail(&(oip->op_list_entry), olp);
114}
115
116/*
117 * op_list_cleanup()
118 *
119 * frees up the list and all data associated with it.
120 *
121 * no return values
122 */
123void op_list_cleanup(op_list_p olp)
124{
125    op_list_p iterator = NULL;
126    op_list_p scratch = NULL;
127    method_op_p tmp_method_op = NULL;
128
129    qlist_for_each_safe(iterator, scratch, olp)
130    {
131        tmp_method_op = qlist_entry(iterator, struct method_op,
132                                    op_list_entry);
133        bmi_dealloc_method_op(tmp_method_op);
134    }
135    free(olp);
136    olp = NULL;
137}
138
139/* op_list_empty()
140 *
141 * checks to see if the operation list is empty or not.
142 *
143 * returns 1 if empty, 0 if items are present.
144 */
145int op_list_empty(op_list_p olp)
146{
147    return (qlist_empty(olp));
148}
149
150
151/*
152 * op_list_remove()
153 *
154 * Removes the network operation from the given list.
155 * DOES NOT destroy the operation.
156 *
157 * returns 0 on success, -errno on failure.
158 */
159void op_list_remove(method_op_p oip)
160{
161    qlist_del(&(oip->op_list_entry));
162}
163
164
165/* op_list_search()
166 *
167 * Searches the operation list based on parameters in the
168 * op_list_search_key structure.  Returns first match.
169 *
170 * returns pointer to operation on success, NULL on failure.
171 */
172method_op_p op_list_search(op_list_p olp,
173                           struct op_list_search_key *key)
174{
175    op_list_p tmp_entry = NULL;
176    qlist_for_each(tmp_entry, olp)
177    {
178        if (!(op_list_cmp_key(key, qlist_entry(tmp_entry, struct method_op,
179                                               op_list_entry))))
180        {
181            return (qlist_entry(tmp_entry, struct method_op, op_list_entry));
182        }
183    }
184    return (NULL);
185}
186
187
188/* op_list_shownext()
189 *
190 * shows the next entry in an op list; does not remove the entry
191 *
192 * returns pointer to method op on success, NULL on failure
193 */
194method_op_p op_list_shownext(op_list_p olp)
195{
196    if (olp->next == olp)
197    {
198        return (NULL);
199    }
200    return (qlist_entry(olp->next, struct method_op, op_list_entry));
201}
202
203/****************************************************************
204 * Internal utility functions
205 */
206
207
208/*
209 * op_list_cmp_key()
210 *
211 * compares a key structure against an operation to see if they match. 
212 *
213 * returns 0 if match is found, 1 otherwise
214 */
215static int op_list_cmp_key(struct op_list_search_key *my_key,
216                           method_op_p my_op)
217{
218
219    if (my_key->msg_tag_yes && (my_key->msg_tag != my_op->msg_tag))
220    {
221        return (1);
222    }
223    if (my_key->op_id_yes && (my_key->op_id != my_op->op_id))
224    {
225        return (1);
226    }
227    if (my_key->method_addr_yes)
228    {
229        if(my_key->method_addr == my_op->addr)
230        {
231            /* normal case */
232        }
233        else if(my_op->addr->primary &&
234            my_key->method_addr == my_op->addr->primary)
235        {
236            /* swap address in the op to match addr we are using */
237            my_op->addr = my_op->addr->primary;
238        }
239        else if(my_op->addr->secondary &&
240            my_key->method_addr == my_op->addr->secondary)
241        {
242            /* swap address in the op to match addr we are using */
243            my_op->addr = my_op->addr->secondary;
244        }
245        else
246        {
247            return(1);
248        }
249    }
250    if (my_key->class_yes && (my_key->class != my_op->class))
251    {
252        return(1);
253    }
254    return (0);
255}
256
257
258static void gossip_print_op(method_op_p print_op)
259{
260
261    gossip_err("Operation:\n------------\n");
262    gossip_err("  op_id: %ld\n", (long) print_op->op_id);
263    gossip_err("  send_recv: %d\n", (int) print_op->send_recv);
264    gossip_err("  msg_tag: %d\n", (int) print_op->msg_tag);
265    gossip_err("  error_code: %d\n", (int) print_op->error_code);
266    gossip_err("  amt_complete: %ld\n", (long) print_op->amt_complete);
267    gossip_err("  buffer: %p\n", print_op->buffer);
268    gossip_err("  actual size: %ld\n", (long) print_op->actual_size);
269    gossip_err("  expected size: %ld\n", (long) print_op->expected_size);
270    gossip_err("  addr: %p\n", print_op->addr);
271    gossip_err("  mode: %d\n", (int) print_op->mode);
272
273    return;
274}
275
276/*
277 * Local variables:
278 *  c-indent-level: 4
279 *  c-basic-offset: 4
280 * End:
281 *
282 * vim: ts=8 sts=4 sw=4 expandtab
283 */
Note: See TracBrowser for help on using the browser.