1 /*****************************************************************************
2  *  Copyright (C) 2004 The Regents of the University of California.
3  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
4  *  Written by Jim Garlick <garlick@llnl.gov>
5  *  UCRL-CODE-2002-008.
6  *
7  *  This file is part of PowerMan, a remote power management program.
8  *  For details, see http://code.google.com/p/powerman/
9  *
10  *  PowerMan is free software; you can redistribute it and/or modify it under
11  *  the terms of the GNU General Public License as published by the Free
12  *  Software Foundation; either version 2 of the License, or (at your option)
13  *  any later version.
14  *
15  *  PowerMan is distributed in the hope that it will be useful, but WITHOUT
16  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18  *  for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with PowerMan; if not, write to the Free Software Foundation, Inc.,
22  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
23 \*****************************************************************************/
24 
25 /* Args used to be stored in a List, but gprof showed that very large
26  * configurations spent a lot of time doing linear search of arg list for
27  * each arg->state update.  The List was traded for a hash, but as we still
28  * want to iterate through args in the client in order, we keep the hostlist
29  * representation of the nodes in the ArgList, and use it to implement an
30  * 'iterator' interface.
31  */
32 
33 #if HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 #include <errno.h>
37 #include <sys/time.h>
38 #include <time.h>
39 #include <fcntl.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <stdarg.h>
43 #include <assert.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 
48 #include "list.h"
49 #include "xmalloc.h"
50 #include "hostlist.h"
51 #include "hash.h"
52 #include "arglist.h"
53 
54 struct arglist_iterator {
55     hostlist_iterator_t itr;
56     ArgList arglist;
57 };
58 
59 struct arglist {
60     hash_t args;
61     hostlist_t hl;
62     int refcount;               /* free when refcount == 0 */
63 };
64 
_destroy_arg(Arg * arg)65 static void _destroy_arg(Arg * arg)
66 {
67     assert(arg != NULL);
68     assert(arg->node != NULL);
69     xfree(arg->node);
70     if (arg->val)
71         xfree(arg->val);
72     xfree(arg);
73 }
74 
_create_arg(char * node)75 static Arg *_create_arg(char *node)
76 {
77     Arg *arg = (Arg *) xmalloc(sizeof(Arg));
78 
79     arg->node = xstrdup(node);
80     arg->state = ST_UNKNOWN;
81     arg->val = NULL;
82 
83     return arg;
84 }
85 
arglist_create(hostlist_t hl)86 ArgList arglist_create(hostlist_t hl)
87 {
88     ArgList new = (ArgList) xmalloc(sizeof(struct arglist));
89     hostlist_iterator_t itr;
90     char *node;
91     int hash_size;
92 
93     new->refcount = 1;
94     hash_size = hostlist_count(hl); /* reasonable? */
95     new->args = hash_create(hash_size, (hash_key_f)hash_key_string,
96             (hash_cmp_f)strcmp, (hash_del_f)_destroy_arg);
97 
98     if ((itr = hostlist_iterator_create(hl)) == NULL) {
99         arglist_unlink(new);
100         return NULL;
101     }
102     while ((node = hostlist_next(itr)) != NULL) {
103         Arg *arg = _create_arg(node);
104 
105         hash_insert(new->args, arg->node, arg);
106         free(node); /* hostlist_next strdups returned string */
107     }
108     hostlist_iterator_destroy(itr);
109     new->hl = hostlist_copy(hl);
110 
111     return new;
112 }
113 
arglist_unlink(ArgList arglist)114 void arglist_unlink(ArgList arglist)
115 {
116     if (--arglist->refcount == 0) {
117         hash_destroy(arglist->args);
118         hostlist_destroy(arglist->hl);
119         xfree(arglist);
120     }
121 }
122 
arglist_link(ArgList arglist)123 ArgList arglist_link(ArgList arglist)
124 {
125     arglist->refcount++;
126 
127     return arglist;
128 }
129 
arglist_find(ArgList arglist,char * node)130 Arg *arglist_find(ArgList arglist, char *node)
131 {
132     Arg *arg = NULL;
133 
134     if (node != NULL)
135         arg = hash_find(arglist->args, node);
136 
137     return arg;
138 }
139 
arglist_iterator_create(ArgList arglist)140 ArgListIterator arglist_iterator_create(ArgList arglist)
141 {
142     ArgListIterator itr = (ArgListIterator)xmalloc(sizeof(struct arglist_iterator));
143 
144     itr->arglist = arglist;
145     itr->itr = hostlist_iterator_create(arglist->hl);
146 
147     return itr;
148 }
149 
arglist_iterator_destroy(ArgListIterator itr)150 void arglist_iterator_destroy(ArgListIterator itr)
151 {
152     hostlist_iterator_destroy(itr->itr);
153     xfree(itr);
154 }
155 
arglist_next(ArgListIterator itr)156 Arg *arglist_next(ArgListIterator itr)
157 {
158     Arg *arg = NULL;
159     char *node;
160 
161     node = hostlist_next(itr->itr);
162     if (node != NULL) {
163         arg = hash_find(itr->arglist->args, node);
164         free(node); /* hostlist_next strdups returned string */
165     }
166 
167     return arg;
168 }
169 
170 /*
171  * vi:tabstop=4 shiftwidth=4 expandtab
172  */
173