~ubuntu-branches/ubuntu/precise/slurm-llnl/precise

« back to all changes in this revision

Viewing changes to src/db_api/cluster_report_functions.c

  • Committer: Bazaar Package Importer
  • Author(s): Gennaro Oliva
  • Date: 2011-04-08 11:21:17 UTC
  • mfrom: (3.3.16 sid)
  • Revision ID: james.westby@ubuntu.com-20110408112117-nfnyq9dtm55hqoaw
Tags: 2.2.4-1
* New upstream releases 
* Cleaning spare file and directories, not belonging to the sources
  generated by the building process and not removed by distclean.
  Added debian/clean with spare files and rm -rf inside debian/rules
  for directories.
* Added new packages libslurm-perl, libslurmdb-perl, slurm-llnl-torque
  (Closes: #575822) thanks to Julien Blache

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************\
 
2
 *  cluster_report_functions.c - Interface to functions dealing with cluster
 
3
 *                               reports.
 
4
 ******************************************************************************
 
5
 *  Copyright (C) 2010 Lawrence Livermore National Security.
 
6
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
 
7
 *  Written by Danny Auble da@llnl.gov, et. al.
 
8
 *  CODE-OCEC-09-009. All rights reserved.
 
9
 *
 
10
 *  This file is part of SLURM, a resource management program.
 
11
 *  For details, see <https://computing.llnl.gov/linux/slurm/>.
 
12
 *  Please also read the included file: DISCLAIMER.
 
13
 *
 
14
 *  SLURM is free software; you can redistribute it and/or modify it under
 
15
 *  the terms of the GNU General Public License as published by the Free
 
16
 *  Software Foundation; either version 2 of the License, or (at your option)
 
17
 *  any later version.
 
18
 *
 
19
 *  In addition, as a special exception, the copyright holders give permission
 
20
 *  to link the code of portions of this program with the OpenSSL library under
 
21
 *  certain conditions as described in each individual source file, and
 
22
 *  distribute linked combinations including the two. You must obey the GNU
 
23
 *  General Public License in all respects for all of the code used other than
 
24
 *  OpenSSL. If you modify file(s) with this exception, you may extend this
 
25
 *  exception to your version of the file(s), but you are not obligated to do
 
26
 *  so. If you do not wish to do so, delete this exception statement from your
 
27
 *  version.  If you delete this exception statement from all source files in
 
28
 *  the program, then also delete it here.
 
29
 *
 
30
 *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
 
31
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
32
 *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 
33
 *  details.
 
34
 *
 
35
 *  You should have received a copy of the GNU General Public License along
 
36
 *  with SLURM; if not, write to the Free Software Foundation, Inc.,
 
37
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
 
38
\*****************************************************************************/
 
39
 
 
40
#ifdef HAVE_CONFIG_H
 
41
#  include "config.h"
 
42
#endif
 
43
 
 
44
#include <slurm/slurm.h>
 
45
#include <slurm/slurm_errno.h>
 
46
 
 
47
#include "src/common/slurmdb_defs.h"
 
48
#include "src/common/slurm_accounting_storage.h"
 
49
#include "src/common/xstring.h"
 
50
 
 
51
typedef enum {
 
52
        CLUSTER_REPORT_UA,
 
53
        CLUSTER_REPORT_AU,
 
54
        CLUSTER_REPORT_UW,
 
55
        CLUSTER_REPORT_WU
 
56
} cluster_report_t;
 
57
 
 
58
static void _process_ua(List user_list, slurmdb_association_rec_t *assoc)
 
59
{
 
60
        ListIterator itr = NULL;
 
61
        slurmdb_report_user_rec_t *slurmdb_report_user = NULL;
 
62
        slurmdb_accounting_rec_t *accting = NULL;
 
63
 
 
64
        /* make sure we add all associations to this
 
65
           user rec because we could have some in
 
66
           partitions which would create another
 
67
           record otherwise
 
68
        */
 
69
        itr = list_iterator_create(user_list);
 
70
        while((slurmdb_report_user = list_next(itr))) {
 
71
                if(!strcmp(slurmdb_report_user->name, assoc->user)
 
72
                   && !strcmp(slurmdb_report_user->acct, assoc->acct))
 
73
                        break;
 
74
        }
 
75
        list_iterator_destroy(itr);
 
76
 
 
77
        if(!slurmdb_report_user) {
 
78
                struct passwd *passwd_ptr = NULL;
 
79
                uid_t uid = NO_VAL;
 
80
                passwd_ptr = getpwnam(assoc->user);
 
81
                if(passwd_ptr)
 
82
                        uid = passwd_ptr->pw_uid;
 
83
                /* In this report we are using the slurmdb_report user
 
84
                   structure to store the information we want
 
85
                   since it is already available and will do
 
86
                   pretty much what we want.
 
87
                */
 
88
                slurmdb_report_user =
 
89
                        xmalloc(sizeof(slurmdb_report_user_rec_t));
 
90
                slurmdb_report_user->name = xstrdup(assoc->user);
 
91
                slurmdb_report_user->uid = uid;
 
92
                slurmdb_report_user->acct = xstrdup(assoc->acct);
 
93
 
 
94
                list_append(user_list, slurmdb_report_user);
 
95
        }
 
96
        /* get the amount of time this assoc used
 
97
           during the time we are looking at */
 
98
        itr = list_iterator_create(assoc->accounting_list);
 
99
        while((accting = list_next(itr))) {
 
100
                slurmdb_report_user->cpu_secs +=
 
101
                        (uint64_t)accting->alloc_secs;
 
102
        }
 
103
        list_iterator_destroy(itr);
 
104
}
 
105
 
 
106
static void _process_au(List assoc_list, slurmdb_association_rec_t *assoc)
 
107
{
 
108
        slurmdb_report_assoc_rec_t *slurmdb_report_assoc =
 
109
                xmalloc(sizeof(slurmdb_report_assoc_rec_t));
 
110
        ListIterator itr = NULL;
 
111
        slurmdb_accounting_rec_t *accting = NULL;
 
112
 
 
113
        list_append(assoc_list, slurmdb_report_assoc);
 
114
 
 
115
        slurmdb_report_assoc->acct = xstrdup(assoc->acct);
 
116
        slurmdb_report_assoc->cluster = xstrdup(assoc->cluster);
 
117
        slurmdb_report_assoc->parent_acct = xstrdup(assoc->parent_acct);
 
118
        slurmdb_report_assoc->user = xstrdup(assoc->user);
 
119
 
 
120
        /* get the amount of time this assoc used
 
121
           during the time we are looking at */
 
122
        itr = list_iterator_create(assoc->accounting_list);
 
123
        while((accting = list_next(itr))) {
 
124
                slurmdb_report_assoc->cpu_secs +=
 
125
                        (uint64_t)accting->alloc_secs;
 
126
        }
 
127
        list_iterator_destroy(itr);
 
128
 
 
129
}
 
130
 
 
131
static void _process_uw(List user_list, slurmdb_wckey_rec_t *wckey)
 
132
{
 
133
        ListIterator itr = NULL;
 
134
        slurmdb_report_user_rec_t *slurmdb_report_user = NULL;
 
135
        slurmdb_accounting_rec_t *accting = NULL;
 
136
        struct passwd *passwd_ptr = NULL;
 
137
        uid_t uid = NO_VAL;
 
138
 
 
139
        passwd_ptr = getpwnam(wckey->user);
 
140
        if(passwd_ptr)
 
141
                uid = passwd_ptr->pw_uid;
 
142
        /* In this report we are using the slurmdb_report user
 
143
           structure to store the information we want
 
144
           since it is already available and will do
 
145
           pretty much what we want.
 
146
        */
 
147
        slurmdb_report_user =
 
148
                xmalloc(sizeof(slurmdb_report_user_rec_t));
 
149
        slurmdb_report_user->name = xstrdup(wckey->user);
 
150
        slurmdb_report_user->uid = uid;
 
151
        slurmdb_report_user->acct = xstrdup(wckey->name);
 
152
 
 
153
        list_append(user_list, slurmdb_report_user);
 
154
 
 
155
        /* get the amount of time this wckey used
 
156
           during the time we are looking at */
 
157
        itr = list_iterator_create(wckey->accounting_list);
 
158
        while((accting = list_next(itr))) {
 
159
                slurmdb_report_user->cpu_secs +=
 
160
                        (uint64_t)accting->alloc_secs;
 
161
        }
 
162
        list_iterator_destroy(itr);
 
163
}
 
164
 
 
165
static void _process_wu(List assoc_list, slurmdb_wckey_rec_t *wckey)
 
166
{
 
167
        slurmdb_report_assoc_rec_t *slurmdb_report_assoc = NULL,
 
168
                *parent_assoc = NULL;
 
169
        ListIterator itr = NULL;
 
170
        slurmdb_accounting_rec_t *accting = NULL;
 
171
 
 
172
        /* find the parent */
 
173
        itr = list_iterator_create(assoc_list);
 
174
        while((parent_assoc = list_next(itr))) {
 
175
                if(!parent_assoc->user
 
176
                   && !strcmp(parent_assoc->acct, wckey->name))
 
177
                        break;
 
178
        }
 
179
        list_iterator_destroy(itr);
 
180
        if(!parent_assoc) {
 
181
                parent_assoc = xmalloc(sizeof(slurmdb_report_assoc_rec_t));
 
182
 
 
183
                list_append(assoc_list,
 
184
                            parent_assoc);
 
185
                parent_assoc->acct = xstrdup(wckey->name);
 
186
        }
 
187
 
 
188
        /* now add one for the user */
 
189
        slurmdb_report_assoc = xmalloc(sizeof(slurmdb_report_assoc_rec_t));
 
190
        list_append(assoc_list, slurmdb_report_assoc);
 
191
 
 
192
        slurmdb_report_assoc->acct = xstrdup(wckey->name);
 
193
        slurmdb_report_assoc->user = xstrdup(wckey->user);
 
194
 
 
195
        /* get the amount of time this wckey used
 
196
           during the time we are looking at */
 
197
        itr = list_iterator_create(wckey->accounting_list);
 
198
        while((accting = list_next(itr))) {
 
199
                slurmdb_report_assoc->cpu_secs +=
 
200
                        (uint64_t)accting->alloc_secs;
 
201
                parent_assoc->cpu_secs +=
 
202
                        (uint64_t)accting->alloc_secs;
 
203
        }
 
204
        list_iterator_destroy(itr);
 
205
}
 
206
 
 
207
static void _process_assoc_type(
 
208
        ListIterator itr,
 
209
        slurmdb_report_cluster_rec_t *slurmdb_report_cluster,
 
210
        char *cluster_name,
 
211
        cluster_report_t type)
 
212
{
 
213
        slurmdb_association_rec_t *assoc = NULL;
 
214
 
 
215
        /* now add the associations of interest here by user */
 
216
        while((assoc = list_next(itr))) {
 
217
                if(!assoc->accounting_list
 
218
                   || !list_count(assoc->accounting_list)
 
219
                   || ((type == CLUSTER_REPORT_UA) && !assoc->user)) {
 
220
                        list_delete_item(itr);
 
221
                        continue;
 
222
                }
 
223
 
 
224
                if(strcmp(cluster_name, assoc->cluster))
 
225
                        continue;
 
226
 
 
227
                if(type == CLUSTER_REPORT_UA)
 
228
                        _process_ua(slurmdb_report_cluster->user_list,
 
229
                                    assoc);
 
230
                else if(type == CLUSTER_REPORT_AU)
 
231
                        _process_au(slurmdb_report_cluster->assoc_list,
 
232
                                    assoc);
 
233
 
 
234
                list_delete_item(itr);
 
235
        }
 
236
}
 
237
 
 
238
static void _process_wckey_type(
 
239
        ListIterator itr,
 
240
        slurmdb_report_cluster_rec_t *slurmdb_report_cluster,
 
241
        char *cluster_name,
 
242
        cluster_report_t type)
 
243
{
 
244
        slurmdb_wckey_rec_t *wckey = NULL;
 
245
 
 
246
        /* now add the wckeyiations of interest here by user */
 
247
        while((wckey = list_next(itr))) {
 
248
                if(!wckey->accounting_list
 
249
                   || !list_count(wckey->accounting_list)
 
250
                   || ((type == CLUSTER_REPORT_UW) && !wckey->user)) {
 
251
                        list_delete_item(itr);
 
252
                        continue;
 
253
                }
 
254
 
 
255
                if(strcmp(cluster_name, wckey->cluster))
 
256
                        continue;
 
257
 
 
258
                if(type == CLUSTER_REPORT_UW)
 
259
                        _process_uw(slurmdb_report_cluster->user_list,
 
260
                                    wckey);
 
261
                else if(type == CLUSTER_REPORT_WU)
 
262
                        _process_wu(slurmdb_report_cluster->assoc_list,
 
263
                                    wckey);
 
264
 
 
265
                list_delete_item(itr);
 
266
        }
 
267
}
 
268
 
 
269
static List _process_util_by_report(void *db_conn, char *calling_name,
 
270
                                    void *cond, cluster_report_t type)
 
271
{       ListIterator itr = NULL;
 
272
        ListIterator itr2 = NULL;
 
273
        ListIterator type_itr = NULL;
 
274
        slurmdb_cluster_cond_t cluster_cond;
 
275
        List type_list = NULL;
 
276
        List cluster_list = NULL;
 
277
        List first_list = NULL;
 
278
        slurmdb_cluster_rec_t *cluster = NULL;
 
279
        slurmdb_report_cluster_rec_t *slurmdb_report_cluster = NULL;
 
280
        time_t start_time, end_time;
 
281
 
 
282
        int exit_code = 0;
 
283
 
 
284
        uid_t my_uid = getuid();
 
285
        List ret_list = list_create(slurmdb_destroy_report_cluster_rec);
 
286
 
 
287
        slurmdb_init_cluster_cond(&cluster_cond, 0);
 
288
 
 
289
        cluster_cond.with_deleted = 1;
 
290
        cluster_cond.with_usage = 1;
 
291
        if((type == CLUSTER_REPORT_UA) || (type == CLUSTER_REPORT_AU)) {
 
292
                start_time = ((slurmdb_association_cond_t *)cond)->usage_start;
 
293
                end_time = ((slurmdb_association_cond_t *)cond)->usage_end;
 
294
 
 
295
                cluster_cond.cluster_list =
 
296
                        ((slurmdb_association_cond_t *)cond)->cluster_list;
 
297
        } else if((type == CLUSTER_REPORT_UW) || (type == CLUSTER_REPORT_WU)) {
 
298
                start_time = ((slurmdb_wckey_cond_t *)cond)->usage_start;
 
299
                end_time = ((slurmdb_wckey_cond_t *)cond)->usage_end;
 
300
 
 
301
                cluster_cond.cluster_list =
 
302
                        ((slurmdb_wckey_cond_t *)cond)->cluster_list;
 
303
        } else {
 
304
                error("unknown report type %d", type);
 
305
                return NULL;
 
306
        }
 
307
 
 
308
        /* This needs to be done on some systems to make sure
 
309
           cluster_cond isn't messed.  This has happened on some 64
 
310
           bit machines and this is here to be on the safe side.
 
311
        */
 
312
        slurmdb_report_set_start_end_time(&start_time, &end_time);
 
313
        cluster_cond.usage_end = end_time;
 
314
        cluster_cond.usage_start = start_time;
 
315
 
 
316
 
 
317
        cluster_list = acct_storage_g_get_clusters(
 
318
                db_conn, my_uid, &cluster_cond);
 
319
 
 
320
        if(!cluster_list) {
 
321
                exit_code=1;
 
322
                fprintf(stderr, "%s: Problem with cluster query.\n",
 
323
                        calling_name);
 
324
                goto end_it;
 
325
        }
 
326
 
 
327
        if((type == CLUSTER_REPORT_UA) || (type == CLUSTER_REPORT_AU)) {
 
328
                ((slurmdb_association_cond_t *)cond)->usage_start = start_time;
 
329
                ((slurmdb_association_cond_t *)cond)->usage_end = end_time;
 
330
                type_list = acct_storage_g_get_associations(
 
331
                        db_conn, my_uid, cond);
 
332
        } else if((type == CLUSTER_REPORT_UW) || (type == CLUSTER_REPORT_WU)) {
 
333
                ((slurmdb_wckey_cond_t *)cond)->usage_start = start_time;
 
334
                ((slurmdb_wckey_cond_t *)cond)->usage_end = end_time;
 
335
                type_list = acct_storage_g_get_wckeys(
 
336
                        db_conn, my_uid, cond);
 
337
        }
 
338
 
 
339
        if(!type_list) {
 
340
                exit_code=1;
 
341
                fprintf(stderr, "%s: Problem with get query.\n", calling_name);
 
342
                goto end_it;
 
343
        }
 
344
 
 
345
        if((type == CLUSTER_REPORT_UA) || (type == CLUSTER_REPORT_AU)) {
 
346
                first_list = type_list;
 
347
                type_list = slurmdb_get_hierarchical_sorted_assoc_list(
 
348
                        first_list);
 
349
        }
 
350
 
 
351
        /* set up the structures for easy retrieval later */
 
352
        itr = list_iterator_create(cluster_list);
 
353
        type_itr = list_iterator_create(type_list);
 
354
        while((cluster = list_next(itr))) {
 
355
                slurmdb_cluster_accounting_rec_t *accting = NULL;
 
356
 
 
357
                /* check to see if this cluster is around during the
 
358
                   time we are looking at */
 
359
                if(!cluster->accounting_list
 
360
                   || !list_count(cluster->accounting_list))
 
361
                        continue;
 
362
 
 
363
                slurmdb_report_cluster =
 
364
                        xmalloc(sizeof(slurmdb_report_cluster_rec_t));
 
365
 
 
366
                list_append(ret_list, slurmdb_report_cluster);
 
367
 
 
368
                slurmdb_report_cluster->name = xstrdup(cluster->name);
 
369
                if((type == CLUSTER_REPORT_UA) || (type == CLUSTER_REPORT_UW))
 
370
                        slurmdb_report_cluster->user_list =
 
371
                                list_create(slurmdb_destroy_report_user_rec);
 
372
                else if((type == CLUSTER_REPORT_AU)
 
373
                        || (type == CLUSTER_REPORT_WU))
 
374
                        slurmdb_report_cluster->assoc_list =
 
375
                                list_create(slurmdb_destroy_report_assoc_rec);
 
376
 
 
377
                /* get the amount of time and the average cpu count
 
378
                   during the time we are looking at */
 
379
                itr2 = list_iterator_create(cluster->accounting_list);
 
380
                while((accting = list_next(itr2))) {
 
381
                        slurmdb_report_cluster->cpu_secs += accting->alloc_secs
 
382
                                + accting->down_secs + accting->idle_secs
 
383
                                + accting->resv_secs;
 
384
                        slurmdb_report_cluster->cpu_count += accting->cpu_count;
 
385
                }
 
386
                list_iterator_destroy(itr2);
 
387
 
 
388
                slurmdb_report_cluster->cpu_count /=
 
389
                        list_count(cluster->accounting_list);
 
390
                if((type == CLUSTER_REPORT_UA) || (type == CLUSTER_REPORT_AU))
 
391
                        _process_assoc_type(type_itr, slurmdb_report_cluster,
 
392
                                            cluster->name, type);
 
393
                else if((type == CLUSTER_REPORT_UW)
 
394
                        || (type == CLUSTER_REPORT_WU))
 
395
                        _process_wckey_type(type_itr, slurmdb_report_cluster,
 
396
                                            cluster->name, type);
 
397
                list_iterator_reset(type_itr);
 
398
        }
 
399
        list_iterator_destroy(type_itr);
 
400
        list_iterator_destroy(itr);
 
401
 
 
402
end_it:
 
403
 
 
404
        if(type_list) {
 
405
                list_destroy(type_list);
 
406
                type_list = NULL;
 
407
        }
 
408
 
 
409
        if(first_list) {
 
410
                list_destroy(first_list);
 
411
                first_list = NULL;
 
412
        }
 
413
 
 
414
        if(cluster_list) {
 
415
                list_destroy(cluster_list);
 
416
                cluster_list = NULL;
 
417
        }
 
418
 
 
419
        if(exit_code) {
 
420
                if(ret_list) {
 
421
                        list_destroy(ret_list);
 
422
                        ret_list = NULL;
 
423
                }
 
424
        }
 
425
 
 
426
        return ret_list;
 
427
}
 
428
 
 
429
 
 
430
extern List slurmdb_report_cluster_account_by_user(void *db_conn,
 
431
        slurmdb_association_cond_t *assoc_cond)
 
432
{
 
433
        return _process_util_by_report(db_conn,
 
434
                                       "slurmdb_report_cluster_account_by_user",
 
435
                                       assoc_cond, CLUSTER_REPORT_AU);
 
436
}
 
437
 
 
438
extern List slurmdb_report_cluster_user_by_account(void *db_conn,
 
439
        slurmdb_association_cond_t *assoc_cond)
 
440
{
 
441
        return _process_util_by_report(db_conn,
 
442
                                       "slurmdb_report_cluster_user_by_account",
 
443
                                       assoc_cond, CLUSTER_REPORT_UA);
 
444
}
 
445
 
 
446
extern List slurmdb_report_cluster_wckey_by_user(void *db_conn,
 
447
        slurmdb_wckey_cond_t *wckey_cond)
 
448
{
 
449
        return _process_util_by_report(db_conn,
 
450
                                       "slurmdb_report_cluster_wckey_by_user",
 
451
                                       wckey_cond, CLUSTER_REPORT_WU);
 
452
}
 
453
 
 
454
extern List slurmdb_report_cluster_user_by_wckey(void *db_conn,
 
455
        slurmdb_wckey_cond_t *wckey_cond)
 
456
{
 
457
        return _process_util_by_report(db_conn,
 
458
                                       "slurmdb_report_cluster_user_by_wckey",
 
459
                                       wckey_cond, CLUSTER_REPORT_UW);
 
460
}