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

« back to all changes in this revision

Viewing changes to src/plugins/accounting_storage/mysql/mysql_jobacct_process.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
 
 *  mysql_jobacct_process.c - functions the processing of
3
 
 *                               information from the mysql jobacct
4
 
 *                               storage.
5
 
 *****************************************************************************
6
 
 *
7
 
 *  Copyright (C) 2008-2009 Lawrence Livermore National Security.
8
 
 *  Copyright (C) 2004-2007 The Regents of the University of California.
9
 
 *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
10
 
 *  Written by Danny Auble <da@llnl.gov>
11
 
 *
12
 
 *  This file is part of SLURM, a resource management program.
13
 
 *  For details, see <https://computing.llnl.gov/linux/slurm/>.
14
 
 *  Please also read the included file: DISCLAIMER.
15
 
 *
16
 
 *  SLURM is free software; you can redistribute it and/or modify it under
17
 
 *  the terms of the GNU General Public License as published by the Free
18
 
 *  Software Foundation; either version 2 of the License, or (at your option)
19
 
 *  any later version.
20
 
 *
21
 
 *  In addition, as a special exception, the copyright holders give permission
22
 
 *  to link the code of portions of this program with the OpenSSL library under
23
 
 *  certain conditions as described in each individual source file, and
24
 
 *  distribute linked combinations including the two. You must obey the GNU
25
 
 *  General Public License in all respects for all of the code used other than
26
 
 *  OpenSSL. If you modify file(s) with this exception, you may extend this
27
 
 *  exception to your version of the file(s), but you are not obligated to do
28
 
 *  so. If you do not wish to do so, delete this exception statement from your
29
 
 *  version.  If you delete this exception statement from all source files in
30
 
 *  the program, then also delete it here.
31
 
 *
32
 
 *  SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
33
 
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
34
 
 *  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
35
 
 *  details.
36
 
 *
37
 
 *  You should have received a copy of the GNU General Public License along
38
 
 *  with SLURM; if not, write to the Free Software Foundation, Inc.,
39
 
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
40
 
 *
41
 
 *  This file is patterned after jobcomp_linux.c, written by Morris Jette and
42
 
 *  Copyright (C) 2002 The Regents of the University of California.
43
 
\*****************************************************************************/
44
 
 
45
 
#include <stdlib.h>
46
 
#include "src/common/env.h"
47
 
#include "src/common/xstring.h"
48
 
#include "mysql_jobacct_process.h"
49
 
#include <fcntl.h>
50
 
 
51
 
static pthread_mutex_t local_file_lock = PTHREAD_MUTEX_INITIALIZER;
52
 
 
53
 
typedef struct {
54
 
        hostlist_t hl;
55
 
        time_t start;
56
 
        time_t end;
57
 
        bitstr_t *asked_bitmap;
58
 
} local_cluster_t;
59
 
 
60
 
static void _state_time_string(char **extra, uint32_t state,
61
 
                               uint32_t start, uint32_t end)
62
 
{
63
 
        int base_state = state & JOB_STATE_BASE;
64
 
 
65
 
        if(!start && !end) {
66
 
                xstrfmtcat(*extra, "t1.state='%u'", state);
67
 
                return;
68
 
        }
69
 
 
70
 
        switch(base_state) {
71
 
        case JOB_PENDING:
72
 
                if(start) {
73
 
                        if(!end) {
74
 
                                xstrfmtcat(*extra,
75
 
                                           "(t1.eligible && (!t1.start || "
76
 
                                           "(%d between "
77
 
                                           "t1.eligible and t1.start)))",
78
 
                                           start);
79
 
                        } else {
80
 
                                xstrfmtcat(*extra,
81
 
                                           "(t1.eligible && ((%d between "
82
 
                                           "t1.eligible and t1.start) || "
83
 
                                           "(t1.eligible between %d and %d)))",
84
 
                                           start, start,
85
 
                                           end);
86
 
                        }
87
 
                } else if (end) {
88
 
                        xstrfmtcat(*extra, "(t1.eligible && t1.eligible < %d)",
89
 
                                   end);
90
 
                }
91
 
                break;
92
 
        case JOB_SUSPENDED:
93
 
                /* FIX ME: this should do something with the suspended
94
 
                   table, but it doesn't right now. */
95
 
        case JOB_RUNNING:
96
 
                if(start) {
97
 
                        if(!end) {
98
 
                                xstrfmtcat(*extra,
99
 
                                           "(t1.start && (!t1.end || "
100
 
                                           "(%d between t1.start and t1.end)))",
101
 
                                           start);
102
 
                        } else {
103
 
                                xstrfmtcat(*extra,
104
 
                                           "(t1.start && "
105
 
                                           "((%d between t1.start and t1.end) "
106
 
                                           "|| (t1.start between %d and %d)))",
107
 
                                           start, start,
108
 
                                           end);
109
 
                        }
110
 
                } else if (end) {
111
 
                        xstrfmtcat(*extra, "(t1.start && t1.start < %d)", end);
112
 
                }
113
 
                break;
114
 
        case JOB_COMPLETE:
115
 
        case JOB_CANCELLED:
116
 
        case JOB_FAILED:
117
 
        case JOB_TIMEOUT:
118
 
        case JOB_NODE_FAIL:
119
 
        default:
120
 
                xstrfmtcat(*extra, "(t1.state='%u' && (t1.end && ", state);
121
 
                if(start) {
122
 
                        if(!end) {
123
 
                                xstrfmtcat(*extra, "(t1.end >= %d)))", start);
124
 
                        } else {
125
 
                                xstrfmtcat(*extra,
126
 
                                           "(t1.end between %d and %d)))",
127
 
                                           start, end);
128
 
                        }
129
 
                } else if(end) {
130
 
                        xstrfmtcat(*extra, "(t1.end <= %d)))", end);
131
 
                }
132
 
                break;
133
 
        }
134
 
 
135
 
        return;
136
 
}
137
 
 
138
 
static void _destroy_local_cluster(void *object)
139
 
{
140
 
        local_cluster_t *local_cluster = (local_cluster_t *)object;
141
 
        if(local_cluster) {
142
 
                if(local_cluster->hl)
143
 
                        hostlist_destroy(local_cluster->hl);
144
 
                FREE_NULL_BITMAP(local_cluster->asked_bitmap);
145
 
                xfree(local_cluster);
146
 
        }
147
 
}
148
 
 
149
 
static int _write_to_file(int fd, char *data)
150
 
{
151
 
        int pos = 0, nwrite = strlen(data), amount;
152
 
        int rc = SLURM_SUCCESS;
153
 
 
154
 
        while (nwrite > 0) {
155
 
                amount = write(fd, &data[pos], nwrite);
156
 
                if ((amount < 0) && (errno != EINTR)) {
157
 
                        error("Error writing file: %m");
158
 
                        rc = errno;
159
 
                        break;
160
 
                }
161
 
                nwrite -= amount;
162
 
                pos    += amount;
163
 
        }
164
 
        return rc;
165
 
}
166
 
 
167
 
static int _write_archive_file(MYSQL_RES *result, int start_col, int col_count,
168
 
                               time_t curr_end, char *arch_dir,
169
 
                               char *arch_type, char *insert,
170
 
                               bool with_deleted)
171
 
{
172
 
        time_t period_start = 0;
173
 
        int fd = 0;
174
 
        int rc = SLURM_SUCCESS;
175
 
        MYSQL_ROW row;
176
 
        struct tm time_tm;
177
 
        char *old_file = NULL, *new_file = NULL, *reg_file = NULL;
178
 
        char *values = NULL;
179
 
        char start_char[32];
180
 
        char end_char[32];
181
 
        int i=0;
182
 
 
183
 
        xassert(result);
184
 
 
185
 
        //START_TIMER;
186
 
        slurm_mutex_lock(&local_file_lock);
187
 
        while((row = mysql_fetch_row(result))) {
188
 
                if(period_start) {
189
 
                        xstrcat(values, ",\n(");
190
 
                } else {
191
 
                        period_start = atoi(row[start_col]);
192
 
                        localtime_r((time_t *)&period_start, &time_tm);
193
 
                        time_tm.tm_sec = 0;
194
 
                        time_tm.tm_min = 0;
195
 
                        time_tm.tm_hour = 0;
196
 
                        time_tm.tm_mday = 1;
197
 
                        snprintf(start_char, sizeof(start_char),
198
 
                                 "%4.4u-%2.2u-%2.2u"
199
 
                                 "T%2.2u:%2.2u:%2.2u",
200
 
                                 (time_tm.tm_year + 1900),
201
 
                                 (time_tm.tm_mon+1),
202
 
                                 time_tm.tm_mday,
203
 
                                 time_tm.tm_hour,
204
 
                                 time_tm.tm_min,
205
 
                                 time_tm.tm_sec);
206
 
 
207
 
                        localtime_r((time_t *)&curr_end, &time_tm);
208
 
                        snprintf(end_char, sizeof(end_char),
209
 
                                 "%4.4u-%2.2u-%2.2u"
210
 
                                 "T%2.2u:%2.2u:%2.2u",
211
 
                                 (time_tm.tm_year + 1900),
212
 
                                 (time_tm.tm_mon+1),
213
 
                                 time_tm.tm_mday,
214
 
                                 time_tm.tm_hour,
215
 
                                 time_tm.tm_min,
216
 
                                 time_tm.tm_sec);
217
 
 
218
 
                        /* write the buffer to file */
219
 
                        reg_file = xstrdup_printf(
220
 
                                "%s/%s_archive_%s_%s.sql",
221
 
                                arch_dir, arch_type,
222
 
                                start_char, end_char);
223
 
                        debug("Storing event archive at %s", reg_file);
224
 
                        old_file = xstrdup_printf("%s.old", reg_file);
225
 
                        new_file = xstrdup_printf("%s.new", reg_file);
226
 
 
227
 
                        fd = creat(new_file, 0600);
228
 
                        if (fd < 0) {
229
 
                                error("Can't save archive, "
230
 
                                      "create file %s error %m",
231
 
                                      new_file);
232
 
                                rc = errno;
233
 
                                xfree(insert);
234
 
                                break;
235
 
                        }
236
 
                        values = xstrdup_printf("%s\nvalues\n(", insert);
237
 
                }
238
 
 
239
 
                xstrfmtcat(values, "'%s'", row[0]);
240
 
                for(i=1; i<col_count; i++) {
241
 
                        xstrfmtcat(values, ", '%s'", row[i]);
242
 
                }
243
 
 
244
 
                if(with_deleted)
245
 
                        xstrcat(values, ", '1')");
246
 
                else
247
 
                        xstrcat(values, ")");
248
 
 
249
 
                if(!fd
250
 
                   || ((rc = _write_to_file(fd, values)) != SLURM_SUCCESS)) {
251
 
                        xfree(values);
252
 
                        break;
253
 
                }
254
 
                xfree(values);
255
 
        }
256
 
 
257
 
        if(with_deleted)
258
 
                rc = _write_to_file(fd,
259
 
                            " on duplicate key update deleted=1;");
260
 
        else
261
 
                rc = _write_to_file(fd,
262
 
                            " on duplicate key update "
263
 
                            "period_end=VALUES(period_end);");
264
 
//                      END_TIMER2("write file");
265
 
//                      info("write file took %s", TIME_STR);
266
 
 
267
 
        fsync(fd);
268
 
        close(fd);
269
 
 
270
 
        if (rc)
271
 
                (void) unlink(new_file);
272
 
        else {                  /* file shuffle */
273
 
                int ign;        /* avoid warning */
274
 
                (void) unlink(old_file);
275
 
                ign =  link(reg_file, old_file);
276
 
                (void) unlink(reg_file);
277
 
                ign =  link(new_file, reg_file);
278
 
                (void) unlink(new_file);
279
 
        }
280
 
        xfree(old_file);
281
 
        xfree(reg_file);
282
 
        xfree(new_file);
283
 
        slurm_mutex_unlock(&local_file_lock);
284
 
 
285
 
        return rc;
286
 
}
287
 
 
288
 
static int _archive_script(acct_archive_cond_t *arch_cond, time_t last_submit)
289
 
{
290
 
        char * args[] = {arch_cond->archive_script, NULL};
291
 
        const char *tmpdir;
292
 
        struct stat st;
293
 
        char **env = NULL;
294
 
        struct tm time_tm;
295
 
        time_t curr_end;
296
 
 
297
 
#ifdef _PATH_TMP
298
 
        tmpdir = _PATH_TMP;
299
 
#else
300
 
        tmpdir = "/tmp";
301
 
#endif
302
 
        if (stat(arch_cond->archive_script, &st) < 0) {
303
 
                errno = errno;
304
 
                error("mysql_jobacct_process_run_script: failed to stat %s: %m",
305
 
                      arch_cond->archive_script);
306
 
                return SLURM_ERROR;
307
 
        }
308
 
 
309
 
        if (!(st.st_mode & S_IFREG)) {
310
 
                errno = EACCES;
311
 
                error("mysql_jobacct_process_run_script: "
312
 
                      "%s isn't a regular file",
313
 
                      arch_cond->archive_script);
314
 
                return SLURM_ERROR;
315
 
        }
316
 
 
317
 
        if (access(arch_cond->archive_script, X_OK) < 0) {
318
 
                errno = EACCES;
319
 
                error("mysql_jobacct_process_run_script: "
320
 
                      "%s is not executable", arch_cond->archive_script);
321
 
                return SLURM_ERROR;
322
 
        }
323
 
 
324
 
        env = env_array_create();
325
 
 
326
 
        if(arch_cond->purge_event) {
327
 
                /* use localtime to avoid any daylight savings issues */
328
 
                if(!localtime_r(&last_submit, &time_tm)) {
329
 
                        error("Couldn't get localtime from "
330
 
                              "first event start %d",
331
 
                              last_submit);
332
 
                        return SLURM_ERROR;
333
 
                }
334
 
                time_tm.tm_mon -= arch_cond->purge_event;
335
 
                time_tm.tm_isdst = -1;
336
 
                curr_end = mktime(&time_tm);
337
 
                env_array_append_fmt(&env, "SLURM_ARCHIVE_EVENTS", "%u",
338
 
                                     arch_cond->archive_events);
339
 
                env_array_append_fmt(&env, "SLURM_ARCHIVE_LAST_EVENT", "%d",
340
 
                                     curr_end);
341
 
        }
342
 
 
343
 
        if(arch_cond->purge_job) {
344
 
                /* use localtime to avoid any daylight savings issues */
345
 
                if(!localtime_r(&last_submit, &time_tm)) {
346
 
                        error("Couldn't get localtime from first start %d",
347
 
                              last_submit);
348
 
                        return SLURM_ERROR;
349
 
                }
350
 
                time_tm.tm_mon -= arch_cond->purge_job;
351
 
                time_tm.tm_isdst = -1;
352
 
                curr_end = mktime(&time_tm);
353
 
 
354
 
                env_array_append_fmt(&env, "SLURM_ARCHIVE_JOBS", "%u",
355
 
                                     arch_cond->archive_jobs);
356
 
                env_array_append_fmt (&env, "SLURM_ARCHIVE_LAST_JOB", "%d",
357
 
                                      curr_end);
358
 
        }
359
 
 
360
 
        if(arch_cond->purge_step) {
361
 
                /* use localtime to avoid any daylight savings issues */
362
 
                if(!localtime_r(&last_submit, &time_tm)) {
363
 
                        error("Couldn't get localtime from first step start %d",
364
 
                              last_submit);
365
 
                        return SLURM_ERROR;
366
 
                }
367
 
                time_tm.tm_mon -= arch_cond->purge_step;
368
 
                time_tm.tm_isdst = -1;
369
 
                curr_end = mktime(&time_tm);
370
 
                env_array_append_fmt(&env, "SLURM_ARCHIVE_STEPS", "%u",
371
 
                                     arch_cond->archive_steps);
372
 
                env_array_append_fmt(&env, "SLURM_ARCHIVE_LAST_STEP", "%d",
373
 
                                     curr_end);
374
 
        }
375
 
 
376
 
        if(arch_cond->purge_suspend) {
377
 
                /* use localtime to avoid any daylight savings issues */
378
 
                if(!localtime_r(&last_submit, &time_tm)) {
379
 
                        error("Couldn't get localtime from first "
380
 
                              "suspend start %d",
381
 
                              last_submit);
382
 
                        return SLURM_ERROR;
383
 
                }
384
 
                time_tm.tm_mon -= arch_cond->purge_suspend;
385
 
                time_tm.tm_isdst = -1;
386
 
                curr_end = mktime(&time_tm);
387
 
                env_array_append_fmt(&env, "SLURM_ARCHIVE_SUSPEND", "%u",
388
 
                                     arch_cond->archive_steps);
389
 
                env_array_append_fmt(&env, "SLURM_ARCHIVE_LAST_SUSPEND", "%d",
390
 
                                     curr_end);
391
 
        }
392
 
 
393
 
#ifdef _PATH_STDPATH
394
 
        env_array_append (&env, "PATH", _PATH_STDPATH);
395
 
#else
396
 
        env_array_append (&env, "PATH", "/bin:/usr/bin");
397
 
#endif
398
 
        execve(arch_cond->archive_script, args, env);
399
 
 
400
 
        env_array_free(env);
401
 
 
402
 
        return SLURM_SUCCESS;
403
 
}
404
 
 
405
 
extern List setup_cluster_list_with_inx(mysql_conn_t *mysql_conn,
406
 
                                        acct_job_cond_t *job_cond,
407
 
                                        void **curr_cluster)
408
 
{
409
 
        List local_cluster_list = NULL;
410
 
        time_t now = time(NULL);
411
 
        MYSQL_RES *result = NULL;
412
 
        MYSQL_ROW row;
413
 
        hostlist_t temp_hl = NULL;
414
 
        hostlist_iterator_t h_itr = NULL;
415
 
        char *object = NULL;
416
 
        char *query = NULL;
417
 
 
418
 
        if(!job_cond || !job_cond->used_nodes)
419
 
                return NULL;
420
 
 
421
 
        if(!job_cond->cluster_list || list_count(job_cond->cluster_list) != 1) {
422
 
                error("If you are doing a query against nodes "
423
 
                      "you must only have 1 cluster "
424
 
                      "you are asking for.");
425
 
                return NULL;
426
 
        }
427
 
 
428
 
        temp_hl = hostlist_create(job_cond->used_nodes);
429
 
        if(!hostlist_count(temp_hl)) {
430
 
                error("we didn't get any real hosts to look for.");
431
 
                goto no_hosts;
432
 
        }
433
 
        h_itr = hostlist_iterator_create(temp_hl);
434
 
 
435
 
        query = xstrdup_printf("select cluster_nodes, period_start, "
436
 
                               "period_end from %s where node_name='' "
437
 
                               "&& cluster_nodes !=''",
438
 
                               event_table);
439
 
 
440
 
        if((object = list_peek(job_cond->cluster_list)))
441
 
                xstrfmtcat(query, " && cluster='%s'", object);
442
 
 
443
 
        if(job_cond->usage_start) {
444
 
                if(!job_cond->usage_end)
445
 
                        job_cond->usage_end = now;
446
 
 
447
 
                xstrfmtcat(query,
448
 
                           " && ((period_start < %d) "
449
 
                           "&& (period_end >= %d || period_end = 0))",
450
 
                           job_cond->usage_end, job_cond->usage_start);
451
 
        }
452
 
 
453
 
        debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query);
454
 
        if(!(result = mysql_db_query_ret(mysql_conn->db_conn, query, 0))) {
455
 
                xfree(query);
456
 
                hostlist_destroy(temp_hl);
457
 
                return NULL;
458
 
        }
459
 
        xfree(query);
460
 
 
461
 
        local_cluster_list = list_create(_destroy_local_cluster);
462
 
        while((row = mysql_fetch_row(result))) {
463
 
                char *host = NULL;
464
 
                int loc = 0;
465
 
                local_cluster_t *local_cluster =
466
 
                        xmalloc(sizeof(local_cluster_t));
467
 
                local_cluster->hl = hostlist_create(row[0]);
468
 
                local_cluster->start = atoi(row[1]);
469
 
                local_cluster->end   = atoi(row[2]);
470
 
                local_cluster->asked_bitmap =
471
 
                        bit_alloc(hostlist_count(local_cluster->hl));
472
 
                while((host = hostlist_next(h_itr))) {
473
 
                        if((loc = hostlist_find(
474
 
                                    local_cluster->hl, host)) != -1)
475
 
                                bit_set(local_cluster->asked_bitmap, loc);
476
 
                        free(host);
477
 
                }
478
 
                hostlist_iterator_reset(h_itr);
479
 
                if(bit_ffs(local_cluster->asked_bitmap) != -1) {
480
 
                        list_append(local_cluster_list, local_cluster);
481
 
                        if(local_cluster->end == 0) {
482
 
                                local_cluster->end = now;
483
 
                                (*curr_cluster) = local_cluster;
484
 
                        }
485
 
                } else
486
 
                        _destroy_local_cluster(local_cluster);
487
 
        }
488
 
        mysql_free_result(result);
489
 
        hostlist_iterator_destroy(h_itr);
490
 
        if(!list_count(local_cluster_list)) {
491
 
                hostlist_destroy(temp_hl);
492
 
                list_destroy(local_cluster_list);
493
 
                return NULL;
494
 
        }
495
 
no_hosts:
496
 
 
497
 
        hostlist_destroy(temp_hl);
498
 
 
499
 
        return local_cluster_list;
500
 
}
501
 
 
502
 
extern int good_nodes_from_inx(List local_cluster_list,
503
 
                               void **object, char *node_inx,
504
 
                               int submit)
505
 
{
506
 
        local_cluster_t **curr_cluster = (local_cluster_t **)object;
507
 
 
508
 
        /* check the bitmap to see if this is one of the jobs
509
 
           we are looking for */
510
 
        if(*curr_cluster) {
511
 
                bitstr_t *job_bitmap = NULL;
512
 
                if(!node_inx || !node_inx[0])
513
 
                        return 0;
514
 
                if((submit < (*curr_cluster)->start)
515
 
                   || (submit > (*curr_cluster)->end)) {
516
 
                        local_cluster_t *local_cluster = NULL;
517
 
 
518
 
                        ListIterator itr =
519
 
                                list_iterator_create(local_cluster_list);
520
 
                        while((local_cluster = list_next(itr))) {
521
 
                                if((submit >= local_cluster->start)
522
 
                                   && (submit <= local_cluster->end)) {
523
 
                                        *curr_cluster = local_cluster;
524
 
                                                break;
525
 
                                }
526
 
                        }
527
 
                        list_iterator_destroy(itr);
528
 
                        if(!local_cluster)
529
 
                                return 0;
530
 
                }
531
 
                job_bitmap = bit_alloc(hostlist_count((*curr_cluster)->hl));
532
 
                bit_unfmt(job_bitmap, node_inx);
533
 
                if(!bit_overlap((*curr_cluster)->asked_bitmap, job_bitmap)) {
534
 
                        FREE_NULL_BITMAP(job_bitmap);
535
 
                        return 0;
536
 
                }
537
 
                FREE_NULL_BITMAP(job_bitmap);
538
 
        }
539
 
        return 1;
540
 
}
541
 
 
542
 
extern int setup_job_cond_limits(mysql_conn_t *mysql_conn,
543
 
                                 acct_job_cond_t *job_cond, char **extra)
544
 
{
545
 
        int set = 0;
546
 
        ListIterator itr = NULL;
547
 
        char *object = NULL;
548
 
        char *table_level = "t2";
549
 
        jobacct_selected_step_t *selected_step = NULL;
550
 
 
551
 
        if(!job_cond)
552
 
                return 0;
553
 
 
554
 
        if(job_cond->associd_list && list_count(job_cond->associd_list)) {
555
 
                set = 0;
556
 
                if(*extra)
557
 
                        xstrcat(*extra, " && (");
558
 
                else
559
 
                        xstrcat(*extra, " where (");
560
 
                itr = list_iterator_create(job_cond->associd_list);
561
 
                while((object = list_next(itr))) {
562
 
                        if(set)
563
 
                                xstrcat(*extra, " || ");
564
 
                        xstrfmtcat(*extra, "t1.associd='%s'", object);
565
 
                        set = 1;
566
 
                }
567
 
                list_iterator_destroy(itr);
568
 
                xstrcat(*extra, ")");
569
 
        }
570
 
 
571
 
        if(job_cond->acct_list && list_count(job_cond->acct_list)) {
572
 
                set = 0;
573
 
                if(*extra)
574
 
                        xstrcat(*extra, " && (");
575
 
                else
576
 
                        xstrcat(*extra, " where (");
577
 
                itr = list_iterator_create(job_cond->acct_list);
578
 
                while((object = list_next(itr))) {
579
 
                        if(set)
580
 
                                xstrcat(*extra, " || ");
581
 
                        xstrfmtcat(*extra, "t1.account='%s'", object);
582
 
                        set = 1;
583
 
                }
584
 
                list_iterator_destroy(itr);
585
 
                xstrcat(*extra, ")");
586
 
        }
587
 
 
588
 
        if(job_cond->userid_list && list_count(job_cond->userid_list)) {
589
 
                set = 0;
590
 
                if(*extra)
591
 
                        xstrcat(*extra, " && (");
592
 
                else
593
 
                        xstrcat(*extra, " where (");
594
 
 
595
 
                itr = list_iterator_create(job_cond->userid_list);
596
 
                while((object = list_next(itr))) {
597
 
                        if(set)
598
 
                                xstrcat(*extra, " || ");
599
 
                        xstrfmtcat(*extra, "t1.uid='%s'", object);
600
 
                        set = 1;
601
 
                }
602
 
                list_iterator_destroy(itr);
603
 
                xstrcat(*extra, ")");
604
 
        }
605
 
 
606
 
        if(job_cond->groupid_list && list_count(job_cond->groupid_list)) {
607
 
                set = 0;
608
 
                if(*extra)
609
 
                        xstrcat(*extra, " && (");
610
 
                else
611
 
                        xstrcat(*extra, " where (");
612
 
                itr = list_iterator_create(job_cond->groupid_list);
613
 
                while((object = list_next(itr))) {
614
 
                        if(set)
615
 
                                xstrcat(*extra, " || ");
616
 
                        xstrfmtcat(*extra, "t1.gid='%s'", object);
617
 
                        set = 1;
618
 
                }
619
 
                list_iterator_destroy(itr);
620
 
                xstrcat(*extra, ")");
621
 
        }
622
 
 
623
 
        if(job_cond->partition_list && list_count(job_cond->partition_list)) {
624
 
                set = 0;
625
 
                if(*extra)
626
 
                        xstrcat(*extra, " && (");
627
 
                else
628
 
                        xstrcat(*extra, " where (");
629
 
                itr = list_iterator_create(job_cond->partition_list);
630
 
                while((object = list_next(itr))) {
631
 
                        if(set)
632
 
                                xstrcat(*extra, " || ");
633
 
                        xstrfmtcat(*extra, "t1.partition='%s'", object);
634
 
                        set = 1;
635
 
                }
636
 
                list_iterator_destroy(itr);
637
 
                xstrcat(*extra, ")");
638
 
        }
639
 
 
640
 
        /* this must be done before resvid_list since we set
641
 
           resvid_list up here */
642
 
        if(job_cond->resv_list && list_count(job_cond->resv_list)) {
643
 
                char *query = xstrdup_printf(
644
 
                        "select distinct id from %s where (", job_table);
645
 
                int my_set = 0;
646
 
                MYSQL_RES *result = NULL;
647
 
                MYSQL_ROW row;
648
 
 
649
 
                if(job_cond->cluster_list
650
 
                   && list_count(job_cond->cluster_list)) {
651
 
 
652
 
                        itr = list_iterator_create(job_cond->cluster_list);
653
 
                        while((object = list_next(itr))) {
654
 
                                if(my_set)
655
 
                                        xstrcat(query, " || ");
656
 
                                xstrfmtcat(query, "cluster='%s'", object);
657
 
                                my_set = 1;
658
 
                        }
659
 
                        list_iterator_destroy(itr);
660
 
                }
661
 
 
662
 
                if(my_set)
663
 
                        xstrcat(query, ") && (");
664
 
 
665
 
                itr = list_iterator_create(job_cond->resv_list);
666
 
                while((object = list_next(itr))) {
667
 
                        if(my_set)
668
 
                                xstrcat(query, " || ");
669
 
                        xstrfmtcat(query, "name='%s'", object);
670
 
                        my_set = 1;
671
 
                }
672
 
                list_iterator_destroy(itr);
673
 
                xstrcat(query, ")");
674
 
                if(!(result = mysql_db_query_ret(
675
 
                             mysql_conn->db_conn, query, 0))) {
676
 
                        xfree(query);
677
 
                        error("couldn't query the database");
678
 
                        goto no_resv;
679
 
                }
680
 
                xfree(query);
681
 
                if(!job_cond->resvid_list)
682
 
                        job_cond->resvid_list = list_create(slurm_destroy_char);
683
 
                while((row = mysql_fetch_row(result))) {
684
 
                        list_append(job_cond->resvid_list, xstrdup(row[0]));
685
 
                }
686
 
                mysql_free_result(result);
687
 
        }
688
 
        no_resv:
689
 
 
690
 
        if(job_cond->resvid_list && list_count(job_cond->resvid_list)) {
691
 
                set = 0;
692
 
                if(*extra)
693
 
                        xstrcat(*extra, " && (");
694
 
                else
695
 
                        xstrcat(*extra, " where (");
696
 
                itr = list_iterator_create(job_cond->resvid_list);
697
 
                while((object = list_next(itr))) {
698
 
                        if(set)
699
 
                                xstrcat(*extra, " || ");
700
 
                        xstrfmtcat(*extra, "t1.resvid='%s'", object);
701
 
                        set = 1;
702
 
                }
703
 
                list_iterator_destroy(itr);
704
 
                xstrcat(*extra, ")");
705
 
        }
706
 
 
707
 
        if(job_cond->step_list && list_count(job_cond->step_list)) {
708
 
                set = 0;
709
 
                if(*extra)
710
 
                        xstrcat(*extra, " && (");
711
 
                else
712
 
                        xstrcat(*extra, " where (");
713
 
                itr = list_iterator_create(job_cond->step_list);
714
 
                while((selected_step = list_next(itr))) {
715
 
                        if(set)
716
 
                                xstrcat(*extra, " || ");
717
 
                        xstrfmtcat(*extra, "t1.jobid=%u", selected_step->jobid);
718
 
                        set = 1;
719
 
                }
720
 
                list_iterator_destroy(itr);
721
 
                xstrcat(*extra, ")");
722
 
        }
723
 
 
724
 
        if(job_cond->cpus_min) {
725
 
                if(*extra)
726
 
                        xstrcat(*extra, " && (");
727
 
                else
728
 
                        xstrcat(*extra, " where (");
729
 
 
730
 
                if(job_cond->cpus_max) {
731
 
                        xstrfmtcat(*extra, "(t1.alloc_cpus between %u and %u))",
732
 
                                   job_cond->cpus_min, job_cond->cpus_max);
733
 
 
734
 
                } else {
735
 
                        xstrfmtcat(*extra, "(t1.alloc_cpus='%u'))",
736
 
                                   job_cond->cpus_min);
737
 
 
738
 
                }
739
 
        }
740
 
 
741
 
        if(job_cond->nodes_min) {
742
 
                if(*extra)
743
 
                        xstrcat(*extra, " && (");
744
 
                else
745
 
                        xstrcat(*extra, " where (");
746
 
 
747
 
                if(job_cond->nodes_max) {
748
 
                        xstrfmtcat(*extra,
749
 
                                   "(t1.alloc_nodes between %u and %u))",
750
 
                                   job_cond->nodes_min, job_cond->nodes_max);
751
 
 
752
 
                } else {
753
 
                        xstrfmtcat(*extra, "(t1.alloc_nodes='%u'))",
754
 
                                   job_cond->nodes_min);
755
 
 
756
 
                }
757
 
        }
758
 
        if(job_cond->state_list && list_count(job_cond->state_list)) {
759
 
                set = 0;
760
 
                if(*extra)
761
 
                        xstrcat(*extra, " && (");
762
 
                else
763
 
                        xstrcat(*extra, " where (");
764
 
 
765
 
                itr = list_iterator_create(job_cond->state_list);
766
 
                while((object = list_next(itr))) {
767
 
                        if(set)
768
 
                                xstrcat(*extra, " || ");
769
 
                        _state_time_string(extra, atoi(object),
770
 
                                           job_cond->usage_start,
771
 
                                           job_cond->usage_end);
772
 
                        set = 1;
773
 
                }
774
 
                list_iterator_destroy(itr);
775
 
                xstrcat(*extra, ")");
776
 
        } else {
777
 
                /* Only do this (default of all eligible jobs) if no
778
 
                   state is given */
779
 
                if(job_cond->usage_start) {
780
 
                        if(*extra)
781
 
                                xstrcat(*extra, " && (");
782
 
                        else
783
 
                                xstrcat(*extra, " where (");
784
 
 
785
 
                        if(!job_cond->usage_end)
786
 
                                xstrfmtcat(*extra,
787
 
                                           "(t1.end >= %d || t1.end = 0))",
788
 
                                           job_cond->usage_start);
789
 
                        else
790
 
                                xstrfmtcat(*extra,
791
 
                                           "(t1.eligible < %d "
792
 
                                           "&& (t1.end >= %d || t1.end = 0)))",
793
 
                                           job_cond->usage_end,
794
 
                                           job_cond->usage_start);
795
 
                } else if(job_cond->usage_end) {
796
 
                        if(*extra)
797
 
                                xstrcat(*extra, " && (");
798
 
                        else
799
 
                                xstrcat(*extra, " where (");
800
 
                        xstrfmtcat(*extra,
801
 
                                   "(t1.eligible < %d))", job_cond->usage_end);
802
 
                }
803
 
        }
804
 
 
805
 
        /* we need to put all the associations (t2) stuff together here */
806
 
        if(job_cond->cluster_list && list_count(job_cond->cluster_list)) {
807
 
                set = 0;
808
 
                if(*extra)
809
 
                        xstrcat(*extra, " && (");
810
 
                else
811
 
                        xstrcat(*extra, " where (");
812
 
 
813
 
                itr = list_iterator_create(job_cond->cluster_list);
814
 
                while((object = list_next(itr))) {
815
 
                        if(set)
816
 
                                xstrcat(*extra, " || ");
817
 
                        xstrfmtcat(*extra,
818
 
                                   "(t1.cluster='%s' || %s.cluster='%s')",
819
 
                                   object, table_level, object);
820
 
                        set = 1;
821
 
                }
822
 
                list_iterator_destroy(itr);
823
 
                xstrcat(*extra, ")");
824
 
        }
825
 
 
826
 
        if(job_cond->wckey_list && list_count(job_cond->wckey_list)) {
827
 
                set = 0;
828
 
                if(*extra)
829
 
                        xstrcat(*extra, " && (");
830
 
                else
831
 
                        xstrcat(*extra, " where (");
832
 
 
833
 
                itr = list_iterator_create(job_cond->wckey_list);
834
 
                while((object = list_next(itr))) {
835
 
                        if(set)
836
 
                                xstrcat(*extra, " || ");
837
 
                        xstrfmtcat(*extra, "t1.wckey='%s'", object);
838
 
                        set = 1;
839
 
                }
840
 
                list_iterator_destroy(itr);
841
 
                xstrcat(*extra, ")");
842
 
        }
843
 
        return set;
844
 
}
845
 
 
846
 
extern List mysql_jobacct_process_get_jobs(mysql_conn_t *mysql_conn, uid_t uid,
847
 
                                           acct_job_cond_t *job_cond)
848
 
{
849
 
 
850
 
        char *query = NULL;
851
 
        char *extra = NULL;
852
 
        char *tmp = NULL;
853
 
        jobacct_selected_step_t *selected_step = NULL;
854
 
        ListIterator itr = NULL;
855
 
        int set = 0, is_admin=1;
856
 
        char *table_level="t2";
857
 
        MYSQL_RES *result = NULL, *step_result = NULL;
858
 
        MYSQL_ROW row, step_row;
859
 
        int i, last_id = -1, curr_id = -1;
860
 
        jobacct_job_rec_t *job = NULL;
861
 
        jobacct_step_rec_t *step = NULL;
862
 
        time_t now = time(NULL);
863
 
        List job_list = list_create(destroy_jobacct_job_rec);
864
 
        uint16_t private_data = 0;
865
 
        acct_user_rec_t user;
866
 
        local_cluster_t *curr_cluster = NULL;
867
 
        List local_cluster_list = NULL;
868
 
        int only_pending = 0;
869
 
 
870
 
        /* if this changes you will need to edit the corresponding
871
 
         * enum below also t1 is job_table */
872
 
        char *job_req_inx[] = {
873
 
                "t1.id",
874
 
                "t1.jobid",
875
 
                "t1.associd",
876
 
                "t1.wckey",
877
 
                "t1.wckeyid",
878
 
                "t1.uid",
879
 
                "t1.gid",
880
 
                "t1.resvid",
881
 
                "t1.partition",
882
 
                "t1.blockid",
883
 
                "t1.cluster",
884
 
                "t1.account",
885
 
                "t1.eligible",
886
 
                "t1.submit",
887
 
                "t1.start",
888
 
                "t1.end",
889
 
                "t1.suspended",
890
 
                "t1.name",
891
 
                "t1.track_steps",
892
 
                "t1.state",
893
 
                "t1.comp_code",
894
 
                "t1.priority",
895
 
                "t1.req_cpus",
896
 
                "t1.alloc_cpus",
897
 
                "t1.alloc_nodes",
898
 
                "t1.nodelist",
899
 
                "t1.node_inx",
900
 
                "t1.kill_requid",
901
 
                "t1.timelimit",
902
 
                "t1.qos",
903
 
                "t2.user",
904
 
                "t2.cluster",
905
 
                "t2.acct",
906
 
                "t2.lft"
907
 
        };
908
 
 
909
 
        enum {
910
 
                JOB_REQ_ID,
911
 
                JOB_REQ_JOBID,
912
 
                JOB_REQ_ASSOCID,
913
 
                JOB_REQ_WCKEY,
914
 
                JOB_REQ_WCKEYID,
915
 
                JOB_REQ_UID,
916
 
                JOB_REQ_GID,
917
 
                JOB_REQ_RESVID,
918
 
                JOB_REQ_PARTITION,
919
 
                JOB_REQ_BLOCKID,
920
 
                JOB_REQ_CLUSTER1,
921
 
                JOB_REQ_ACCOUNT1,
922
 
                JOB_REQ_ELIGIBLE,
923
 
                JOB_REQ_SUBMIT,
924
 
                JOB_REQ_START,
925
 
                JOB_REQ_END,
926
 
                JOB_REQ_SUSPENDED,
927
 
                JOB_REQ_NAME,
928
 
                JOB_REQ_TRACKSTEPS,
929
 
                JOB_REQ_STATE,
930
 
                JOB_REQ_COMP_CODE,
931
 
                JOB_REQ_PRIORITY,
932
 
                JOB_REQ_REQ_CPUS,
933
 
                JOB_REQ_ALLOC_CPUS,
934
 
                JOB_REQ_ALLOC_NODES,
935
 
                JOB_REQ_NODELIST,
936
 
                JOB_REQ_NODE_INX,
937
 
                JOB_REQ_KILL_REQUID,
938
 
                JOB_REQ_TIMELIMIT,
939
 
                JOB_REQ_QOS,
940
 
                JOB_REQ_USER_NAME,
941
 
                JOB_REQ_CLUSTER,
942
 
                JOB_REQ_ACCOUNT,
943
 
                JOB_REQ_LFT,
944
 
                JOB_REQ_COUNT
945
 
        };
946
 
 
947
 
        /* if this changes you will need to edit the corresponding
948
 
         * enum below also t1 is step_table */
949
 
        char *step_req_inx[] = {
950
 
                "t1.stepid",
951
 
                "t1.start",
952
 
                "t1.end",
953
 
                "t1.suspended",
954
 
                "t1.name",
955
 
                "t1.nodelist",
956
 
                "t1.node_inx",
957
 
                "t1.state",
958
 
                "t1.kill_requid",
959
 
                "t1.comp_code",
960
 
                "t1.nodes",
961
 
                "t1.cpus",
962
 
                "t1.tasks",
963
 
                "t1.task_dist",
964
 
                "t1.user_sec",
965
 
                "t1.user_usec",
966
 
                "t1.sys_sec",
967
 
                "t1.sys_usec",
968
 
                "t1.max_vsize",
969
 
                "t1.max_vsize_task",
970
 
                "t1.max_vsize_node",
971
 
                "t1.ave_vsize",
972
 
                "t1.max_rss",
973
 
                "t1.max_rss_task",
974
 
                "t1.max_rss_node",
975
 
                "t1.ave_rss",
976
 
                "t1.max_pages",
977
 
                "t1.max_pages_task",
978
 
                "t1.max_pages_node",
979
 
                "t1.ave_pages",
980
 
                "t1.min_cpu",
981
 
                "t1.min_cpu_task",
982
 
                "t1.min_cpu_node",
983
 
                "t1.ave_cpu"
984
 
        };
985
 
 
986
 
        enum {
987
 
                STEP_REQ_STEPID,
988
 
                STEP_REQ_START,
989
 
                STEP_REQ_END,
990
 
                STEP_REQ_SUSPENDED,
991
 
                STEP_REQ_NAME,
992
 
                STEP_REQ_NODELIST,
993
 
                STEP_REQ_NODE_INX,
994
 
                STEP_REQ_STATE,
995
 
                STEP_REQ_KILL_REQUID,
996
 
                STEP_REQ_COMP_CODE,
997
 
                STEP_REQ_NODES,
998
 
                STEP_REQ_CPUS,
999
 
                STEP_REQ_TASKS,
1000
 
                STEP_REQ_TASKDIST,
1001
 
                STEP_REQ_USER_SEC,
1002
 
                STEP_REQ_USER_USEC,
1003
 
                STEP_REQ_SYS_SEC,
1004
 
                STEP_REQ_SYS_USEC,
1005
 
                STEP_REQ_MAX_VSIZE,
1006
 
                STEP_REQ_MAX_VSIZE_TASK,
1007
 
                STEP_REQ_MAX_VSIZE_NODE,
1008
 
                STEP_REQ_AVE_VSIZE,
1009
 
                STEP_REQ_MAX_RSS,
1010
 
                STEP_REQ_MAX_RSS_TASK,
1011
 
                STEP_REQ_MAX_RSS_NODE,
1012
 
                STEP_REQ_AVE_RSS,
1013
 
                STEP_REQ_MAX_PAGES,
1014
 
                STEP_REQ_MAX_PAGES_TASK,
1015
 
                STEP_REQ_MAX_PAGES_NODE,
1016
 
                STEP_REQ_AVE_PAGES,
1017
 
                STEP_REQ_MIN_CPU,
1018
 
                STEP_REQ_MIN_CPU_TASK,
1019
 
                STEP_REQ_MIN_CPU_NODE,
1020
 
                STEP_REQ_AVE_CPU,
1021
 
                STEP_REQ_COUNT
1022
 
        };
1023
 
 
1024
 
        memset(&user, 0, sizeof(acct_user_rec_t));
1025
 
        user.uid = uid;
1026
 
 
1027
 
        private_data = slurm_get_private_data();
1028
 
        if (private_data & PRIVATE_DATA_JOBS) {
1029
 
                /* This only works when running though the slurmdbd.
1030
 
                 * THERE IS NO AUTHENTICATION WHEN RUNNNING OUT OF THE
1031
 
                 * SLURMDBD!
1032
 
                 */
1033
 
                if(slurmdbd_conf) {
1034
 
                        is_admin = 0;
1035
 
                        /* we have to check the authentication here in the
1036
 
                         * plugin since we don't know what accounts are being
1037
 
                         * referenced until after the query.  Here we will
1038
 
                         * set if they are an operator or greater and then
1039
 
                         * check it below after the query.
1040
 
                         */
1041
 
                        if((uid == slurmdbd_conf->slurm_user_id || uid == 0)
1042
 
                           || assoc_mgr_get_admin_level(mysql_conn, uid)
1043
 
                           >= ACCT_ADMIN_OPERATOR)
1044
 
                                is_admin = 1;
1045
 
                        else {
1046
 
                                assoc_mgr_fill_in_user(mysql_conn, &user, 1,
1047
 
                                                       NULL);
1048
 
                        }
1049
 
                }
1050
 
        }
1051
 
 
1052
 
 
1053
 
        /* Here we set up environment to check used nodes of jobs.
1054
 
           Since we store the bitmap of the entire cluster we can use
1055
 
           that to set up a hostlist and set up the bitmap to make
1056
 
           things work.  This should go before the setup of conds
1057
 
           since we could update the start/end time.
1058
 
        */
1059
 
        if(job_cond && job_cond->used_nodes) {
1060
 
                local_cluster_list = setup_cluster_list_with_inx(
1061
 
                        mysql_conn, job_cond, (void **)&curr_cluster);
1062
 
                if(!local_cluster_list) {
1063
 
                        list_destroy(job_list);
1064
 
                        return NULL;
1065
 
                }
1066
 
        }
1067
 
 
1068
 
        if(job_cond->state_list && (list_count(job_cond->state_list) == 1)
1069
 
           && (atoi(list_peek(job_cond->state_list)) == JOB_PENDING))
1070
 
                only_pending = 1;
1071
 
 
1072
 
        setup_job_cond_limits(mysql_conn, job_cond, &extra);
1073
 
 
1074
 
        xfree(tmp);
1075
 
        xstrfmtcat(tmp, "%s", job_req_inx[0]);
1076
 
        for(i=1; i<JOB_REQ_COUNT; i++) {
1077
 
                xstrfmtcat(tmp, ", %s", job_req_inx[i]);
1078
 
        }
1079
 
 
1080
 
        /* This is here to make sure we are looking at only this user
1081
 
         * if this flag is set.  We also include any accounts they may be
1082
 
         * coordinator of.
1083
 
         */
1084
 
        if(!is_admin && (private_data & PRIVATE_DATA_JOBS)) {
1085
 
                query = xstrdup_printf("select lft from %s where user='%s'",
1086
 
                                       assoc_table, user.name);
1087
 
                if(user.coord_accts) {
1088
 
                        acct_coord_rec_t *coord = NULL;
1089
 
                        itr = list_iterator_create(user.coord_accts);
1090
 
                        while((coord = list_next(itr))) {
1091
 
                                xstrfmtcat(query, " || acct='%s'",
1092
 
                                           coord->name);
1093
 
                        }
1094
 
                        list_iterator_destroy(itr);
1095
 
                }
1096
 
                debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query);
1097
 
                if(!(result = mysql_db_query_ret(
1098
 
                             mysql_conn->db_conn, query, 0))) {
1099
 
                        xfree(extra);
1100
 
                        xfree(query);
1101
 
                        list_destroy(job_list);
1102
 
                        if(local_cluster_list)
1103
 
                                list_destroy(local_cluster_list);
1104
 
                        return NULL;
1105
 
                }
1106
 
                xfree(query);
1107
 
                set = 0;
1108
 
                while((row = mysql_fetch_row(result))) {
1109
 
                        if(set) {
1110
 
                                xstrfmtcat(extra,
1111
 
                                           " || (%s between %s.lft and %s.rgt)",
1112
 
                                           row[0], table_level, table_level);
1113
 
                        } else {
1114
 
                                set = 1;
1115
 
                                if(extra)
1116
 
                                        xstrfmtcat(extra,
1117
 
                                                   " && ((%s between %s.lft "
1118
 
                                                   "and %s.rgt)",
1119
 
                                                   row[0], table_level,
1120
 
                                                   table_level);
1121
 
                                else
1122
 
                                        xstrfmtcat(extra,
1123
 
                                                   " where ((%s between %s.lft "
1124
 
                                                   "and %s.rgt)",
1125
 
                                                   row[0], table_level,
1126
 
                                                   table_level);
1127
 
                        }
1128
 
                }
1129
 
                if(set)
1130
 
                        xstrcat(extra,")");
1131
 
                mysql_free_result(result);
1132
 
        }
1133
 
 
1134
 
        query = xstrdup_printf("select %s from %s as t1 left join %s as t2 "
1135
 
                               "on t1.associd=t2.id",
1136
 
                               tmp, job_table, assoc_table);
1137
 
        xfree(tmp);
1138
 
        if(extra) {
1139
 
                xstrcat(query, extra);
1140
 
                xfree(extra);
1141
 
        }
1142
 
 
1143
 
        /* Here we want to order them this way in such a way so it is
1144
 
           easy to look for duplicates
1145
 
        */
1146
 
        if(job_cond && !job_cond->duplicates)
1147
 
                xstrcat(query, " order by t1.cluster, jobid, submit desc");
1148
 
        else
1149
 
                xstrcat(query, " order by t1.cluster, submit desc");
1150
 
 
1151
 
        debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query);
1152
 
        if(!(result = mysql_db_query_ret(mysql_conn->db_conn, query, 0))) {
1153
 
                xfree(query);
1154
 
                list_destroy(job_list);
1155
 
                if(local_cluster_list)
1156
 
                        list_destroy(local_cluster_list);
1157
 
                return NULL;
1158
 
        }
1159
 
        xfree(query);
1160
 
 
1161
 
        while((row = mysql_fetch_row(result))) {
1162
 
                char *id = row[JOB_REQ_ID];
1163
 
                bool job_ended = 0;
1164
 
                int submit = atoi(row[JOB_REQ_SUBMIT]);
1165
 
 
1166
 
                curr_id = atoi(row[JOB_REQ_JOBID]);
1167
 
 
1168
 
                if(job_cond && !job_cond->duplicates && curr_id == last_id)
1169
 
                        continue;
1170
 
 
1171
 
                last_id = curr_id;
1172
 
 
1173
 
                /* check the bitmap to see if this is one of the jobs
1174
 
                   we are looking for */
1175
 
                if(!good_nodes_from_inx(local_cluster_list,
1176
 
                                        (void **)&curr_cluster,
1177
 
                                        row[JOB_REQ_NODE_INX], submit))
1178
 
                        continue;
1179
 
 
1180
 
                job = create_jobacct_job_rec();
1181
 
                list_append(job_list, job);
1182
 
 
1183
 
                job->state = atoi(row[JOB_REQ_STATE]);
1184
 
                job->alloc_cpus = atoi(row[JOB_REQ_ALLOC_CPUS]);
1185
 
                job->alloc_nodes = atoi(row[JOB_REQ_ALLOC_NODES]);
1186
 
                job->associd = atoi(row[JOB_REQ_ASSOCID]);
1187
 
                job->resvid = atoi(row[JOB_REQ_RESVID]);
1188
 
 
1189
 
                /* we want a blank wckey if the name is null */
1190
 
                if(row[JOB_REQ_WCKEY])
1191
 
                        job->wckey = xstrdup(row[JOB_REQ_WCKEY]);
1192
 
                else
1193
 
                        job->wckey = xstrdup("");
1194
 
                job->wckeyid = atoi(row[JOB_REQ_WCKEYID]);
1195
 
 
1196
 
                if(row[JOB_REQ_CLUSTER] && row[JOB_REQ_CLUSTER][0])
1197
 
                        job->cluster = xstrdup(row[JOB_REQ_CLUSTER]);
1198
 
                else if(row[JOB_REQ_CLUSTER1] && row[JOB_REQ_CLUSTER1][0])
1199
 
                        job->cluster = xstrdup(row[JOB_REQ_CLUSTER1]);
1200
 
 
1201
 
                if(row[JOB_REQ_USER_NAME])
1202
 
                        job->user = xstrdup(row[JOB_REQ_USER_NAME]);
1203
 
                else
1204
 
                        job->uid = atoi(row[JOB_REQ_UID]);
1205
 
 
1206
 
                if(row[JOB_REQ_LFT])
1207
 
                        job->lft = atoi(row[JOB_REQ_LFT]);
1208
 
 
1209
 
                if(row[JOB_REQ_ACCOUNT] && row[JOB_REQ_ACCOUNT][0])
1210
 
                        job->account = xstrdup(row[JOB_REQ_ACCOUNT]);
1211
 
                else if(row[JOB_REQ_ACCOUNT1] && row[JOB_REQ_ACCOUNT1][0])
1212
 
                        job->account = xstrdup(row[JOB_REQ_ACCOUNT1]);
1213
 
 
1214
 
                if(row[JOB_REQ_BLOCKID])
1215
 
                        job->blockid = xstrdup(row[JOB_REQ_BLOCKID]);
1216
 
 
1217
 
                job->eligible = atoi(row[JOB_REQ_ELIGIBLE]);
1218
 
                job->submit = submit;
1219
 
                job->start = atoi(row[JOB_REQ_START]);
1220
 
                job->end = atoi(row[JOB_REQ_END]);
1221
 
 
1222
 
                /* since the job->end could be set later end it here */
1223
 
                if(job->end) {
1224
 
                        job_ended = 1;
1225
 
                        if(!job->start || (job->start > job->end))
1226
 
                                job->start = job->end;
1227
 
                }
1228
 
 
1229
 
                if(job_cond && !job_cond->without_usage_truncation
1230
 
                   && job_cond->usage_start) {
1231
 
                        if(job->start && (job->start < job_cond->usage_start))
1232
 
                                job->start = job_cond->usage_start;
1233
 
 
1234
 
                        if(!job->end || job->end > job_cond->usage_end)
1235
 
                                job->end = job_cond->usage_end;
1236
 
 
1237
 
                        if(!job->start)
1238
 
                                job->start = job->end;
1239
 
 
1240
 
                        job->elapsed = job->end - job->start;
1241
 
 
1242
 
                        if(row[JOB_REQ_SUSPENDED]) {
1243
 
                                MYSQL_RES *result2 = NULL;
1244
 
                                MYSQL_ROW row2;
1245
 
                                /* get the suspended time for this job */
1246
 
                                query = xstrdup_printf(
1247
 
                                        "select start, end from %s where "
1248
 
                                        "(start < %d && (end >= %d "
1249
 
                                        "|| end = 0)) && id=%s "
1250
 
                                        "order by start",
1251
 
                                        suspend_table,
1252
 
                                        job_cond->usage_end,
1253
 
                                        job_cond->usage_start,
1254
 
                                        id);
1255
 
 
1256
 
                                debug4("%d(%d) query\n%s",
1257
 
                                       mysql_conn->conn, __LINE__, query);
1258
 
                                if(!(result2 = mysql_db_query_ret(
1259
 
                                             mysql_conn->db_conn,
1260
 
                                             query, 0))) {
1261
 
                                        list_destroy(job_list);
1262
 
                                        job_list = NULL;
1263
 
                                        break;
1264
 
                                }
1265
 
                                xfree(query);
1266
 
                                while((row2 = mysql_fetch_row(result2))) {
1267
 
                                        int local_start =
1268
 
                                                atoi(row2[0]);
1269
 
                                        int local_end =
1270
 
                                                atoi(row2[1]);
1271
 
 
1272
 
                                        if(!local_start)
1273
 
                                                continue;
1274
 
 
1275
 
                                        if(job->start > local_start)
1276
 
                                                local_start = job->start;
1277
 
                                        if(job->end < local_end)
1278
 
                                                local_end = job->end;
1279
 
 
1280
 
                                        if((local_end - local_start) < 1)
1281
 
                                                continue;
1282
 
 
1283
 
                                        job->elapsed -=
1284
 
                                                (local_end - local_start);
1285
 
                                        job->suspended +=
1286
 
                                                (local_end - local_start);
1287
 
                                }
1288
 
                                mysql_free_result(result2);
1289
 
 
1290
 
                        }
1291
 
                } else {
1292
 
                        job->suspended = atoi(row[JOB_REQ_SUSPENDED]);
1293
 
 
1294
 
                        /* fix the suspended number to be correct */
1295
 
                        if(job->state == JOB_SUSPENDED)
1296
 
                                job->suspended = now - job->suspended;
1297
 
                        if(!job->start) {
1298
 
                                job->elapsed = 0;
1299
 
                        } else if(!job->end) {
1300
 
                                job->elapsed = now - job->start;
1301
 
                        } else {
1302
 
                                job->elapsed = job->end - job->start;
1303
 
                        }
1304
 
 
1305
 
                        job->elapsed -= job->suspended;
1306
 
                }
1307
 
 
1308
 
                if((int)job->elapsed < 0)
1309
 
                        job->elapsed = 0;
1310
 
 
1311
 
                job->jobid = curr_id;
1312
 
                job->jobname = xstrdup(row[JOB_REQ_NAME]);
1313
 
                job->gid = atoi(row[JOB_REQ_GID]);
1314
 
                job->exitcode = atoi(row[JOB_REQ_COMP_CODE]);
1315
 
 
1316
 
                if(row[JOB_REQ_PARTITION])
1317
 
                        job->partition = xstrdup(row[JOB_REQ_PARTITION]);
1318
 
 
1319
 
                if(row[JOB_REQ_NODELIST])
1320
 
                        job->nodes = xstrdup(row[JOB_REQ_NODELIST]);
1321
 
 
1322
 
                if (!job->nodes || !strcmp(job->nodes, "(null)")) {
1323
 
                        xfree(job->nodes);
1324
 
                        job->nodes = xstrdup("(unknown)");
1325
 
                }
1326
 
 
1327
 
                job->track_steps = atoi(row[JOB_REQ_TRACKSTEPS]);
1328
 
                job->priority = atoi(row[JOB_REQ_PRIORITY]);
1329
 
                job->req_cpus = atoi(row[JOB_REQ_REQ_CPUS]);
1330
 
                job->requid = atoi(row[JOB_REQ_KILL_REQUID]);
1331
 
                job->timelimit = atoi(row[JOB_REQ_TIMELIMIT]);
1332
 
                job->qos = atoi(row[JOB_REQ_QOS]);
1333
 
                job->show_full = 1;
1334
 
 
1335
 
                if(only_pending || (job_cond && job_cond->without_steps))
1336
 
                        goto skip_steps;
1337
 
 
1338
 
                if(job_cond && job_cond->step_list
1339
 
                   && list_count(job_cond->step_list)) {
1340
 
                        set = 0;
1341
 
                        itr = list_iterator_create(job_cond->step_list);
1342
 
                        while((selected_step = list_next(itr))) {
1343
 
                                if(selected_step->jobid != job->jobid) {
1344
 
                                        continue;
1345
 
                                } else if (selected_step->stepid
1346
 
                                           == (uint32_t)NO_VAL) {
1347
 
                                        job->show_full = 1;
1348
 
                                        break;
1349
 
                                }
1350
 
 
1351
 
                                if(set)
1352
 
                                        xstrcat(extra, " || ");
1353
 
                                else
1354
 
                                        xstrcat(extra, " && (");
1355
 
 
1356
 
                                xstrfmtcat(extra, "t1.stepid=%u",
1357
 
                                           selected_step->stepid);
1358
 
                                set = 1;
1359
 
                                job->show_full = 0;
1360
 
                        }
1361
 
                        list_iterator_destroy(itr);
1362
 
                        if(set)
1363
 
                                xstrcat(extra, ")");
1364
 
                }
1365
 
                for(i=0; i<STEP_REQ_COUNT; i++) {
1366
 
                        if(i)
1367
 
                                xstrcat(tmp, ", ");
1368
 
                        xstrcat(tmp, step_req_inx[i]);
1369
 
                }
1370
 
                query = xstrdup_printf("select %s from %s t1 where t1.id=%s",
1371
 
                                       tmp, step_table, id);
1372
 
                xfree(tmp);
1373
 
 
1374
 
                if(extra) {
1375
 
                        xstrcat(query, extra);
1376
 
                        xfree(extra);
1377
 
                }
1378
 
 
1379
 
                //info("query = %s", query);
1380
 
                if(!(step_result = mysql_db_query_ret(
1381
 
                             mysql_conn->db_conn, query, 0))) {
1382
 
                        xfree(query);
1383
 
                        list_destroy(job_list);
1384
 
                        if(local_cluster_list)
1385
 
                                list_destroy(local_cluster_list);
1386
 
                        return NULL;
1387
 
                }
1388
 
                xfree(query);
1389
 
 
1390
 
                /* Querying the steps in the fashion was faster than
1391
 
                   doing only 1 query and then matching the steps up
1392
 
                   later with the job.
1393
 
                */
1394
 
                while ((step_row = mysql_fetch_row(step_result))) {
1395
 
                        /* check the bitmap to see if this is one of the steps
1396
 
                           we are looking for */
1397
 
                        if(!good_nodes_from_inx(local_cluster_list,
1398
 
                                                (void **)&curr_cluster,
1399
 
                                                step_row[STEP_REQ_NODE_INX],
1400
 
                                                submit))
1401
 
                                continue;
1402
 
 
1403
 
                        step = create_jobacct_step_rec();
1404
 
                        step->tot_cpu_sec = 0;
1405
 
                        step->tot_cpu_usec = 0;
1406
 
                        step->job_ptr = job;
1407
 
                        if(!job->first_step_ptr)
1408
 
                                job->first_step_ptr = step;
1409
 
                        list_append(job->steps, step);
1410
 
                        step->stepid = atoi(step_row[STEP_REQ_STEPID]);
1411
 
                        /* info("got step %u.%u", */
1412
 
/*                           job->header.jobnum, step->stepnum); */
1413
 
                        step->state = atoi(step_row[STEP_REQ_STATE]);
1414
 
                        step->exitcode = atoi(step_row[STEP_REQ_COMP_CODE]);
1415
 
                        step->ncpus = atoi(step_row[STEP_REQ_CPUS]);
1416
 
                        step->nnodes = atoi(step_row[STEP_REQ_NODES]);
1417
 
 
1418
 
                        step->ntasks = atoi(step_row[STEP_REQ_TASKS]);
1419
 
                        step->task_dist = atoi(step_row[STEP_REQ_TASKDIST]);
1420
 
                        if(!step->ntasks)
1421
 
                                step->ntasks = step->ncpus;
1422
 
 
1423
 
                        step->start = atoi(step_row[STEP_REQ_START]);
1424
 
 
1425
 
                        step->end = atoi(step_row[STEP_REQ_END]);
1426
 
                        /* if the job has ended end the step also */
1427
 
                        if(!step->end && job_ended) {
1428
 
                                step->end = job->end;
1429
 
                                step->state = job->state;
1430
 
                        }
1431
 
 
1432
 
                        if(job_cond && !job_cond->without_usage_truncation
1433
 
                           && job_cond->usage_start) {
1434
 
                                if(step->start
1435
 
                                   && (step->start < job_cond->usage_start))
1436
 
                                        step->start = job_cond->usage_start;
1437
 
 
1438
 
                                if(!step->start && step->end)
1439
 
                                        step->start = step->end;
1440
 
 
1441
 
                                if(!step->end
1442
 
                                   || (step->end > job_cond->usage_end))
1443
 
                                        step->end = job_cond->usage_end;
1444
 
                        }
1445
 
 
1446
 
                        /* figure this out by start stop */
1447
 
                        step->suspended = atoi(step_row[STEP_REQ_SUSPENDED]);
1448
 
                        if(!step->end) {
1449
 
                                step->elapsed = now - step->start;
1450
 
                        } else {
1451
 
                                step->elapsed = step->end - step->start;
1452
 
                        }
1453
 
                        step->elapsed -= step->suspended;
1454
 
 
1455
 
                        if((int)step->elapsed < 0)
1456
 
                                step->elapsed = 0;
1457
 
 
1458
 
                        step->user_cpu_sec = atoi(step_row[STEP_REQ_USER_SEC]);
1459
 
                        step->user_cpu_usec =
1460
 
                                atoi(step_row[STEP_REQ_USER_USEC]);
1461
 
                        step->sys_cpu_sec = atoi(step_row[STEP_REQ_SYS_SEC]);
1462
 
                        step->sys_cpu_usec = atoi(step_row[STEP_REQ_SYS_USEC]);
1463
 
                        step->tot_cpu_sec +=
1464
 
                                step->user_cpu_sec + step->sys_cpu_sec;
1465
 
                        step->tot_cpu_usec +=
1466
 
                                step->user_cpu_usec + step->sys_cpu_usec;
1467
 
                        step->sacct.max_vsize =
1468
 
                                atoi(step_row[STEP_REQ_MAX_VSIZE]);
1469
 
                        step->sacct.max_vsize_id.taskid =
1470
 
                                atoi(step_row[STEP_REQ_MAX_VSIZE_TASK]);
1471
 
                        step->sacct.ave_vsize =
1472
 
                                atof(step_row[STEP_REQ_AVE_VSIZE]);
1473
 
                        step->sacct.max_rss =
1474
 
                                atoi(step_row[STEP_REQ_MAX_RSS]);
1475
 
                        step->sacct.max_rss_id.taskid =
1476
 
                                atoi(step_row[STEP_REQ_MAX_RSS_TASK]);
1477
 
                        step->sacct.ave_rss =
1478
 
                                atof(step_row[STEP_REQ_AVE_RSS]);
1479
 
                        step->sacct.max_pages =
1480
 
                                atoi(step_row[STEP_REQ_MAX_PAGES]);
1481
 
                        step->sacct.max_pages_id.taskid =
1482
 
                                atoi(step_row[STEP_REQ_MAX_PAGES_TASK]);
1483
 
                        step->sacct.ave_pages =
1484
 
                                atof(step_row[STEP_REQ_AVE_PAGES]);
1485
 
                        step->sacct.min_cpu =
1486
 
                                atoi(step_row[STEP_REQ_MIN_CPU]);
1487
 
                        step->sacct.min_cpu_id.taskid =
1488
 
                                atoi(step_row[STEP_REQ_MIN_CPU_TASK]);
1489
 
                        step->sacct.ave_cpu = atof(step_row[STEP_REQ_AVE_CPU]);
1490
 
                        step->stepname = xstrdup(step_row[STEP_REQ_NAME]);
1491
 
                        step->nodes = xstrdup(step_row[STEP_REQ_NODELIST]);
1492
 
                        step->sacct.max_vsize_id.nodeid =
1493
 
                                atoi(step_row[STEP_REQ_MAX_VSIZE_NODE]);
1494
 
                        step->sacct.max_rss_id.nodeid =
1495
 
                                atoi(step_row[STEP_REQ_MAX_RSS_NODE]);
1496
 
                        step->sacct.max_pages_id.nodeid =
1497
 
                                atoi(step_row[STEP_REQ_MAX_PAGES_NODE]);
1498
 
                        step->sacct.min_cpu_id.nodeid =
1499
 
                                atoi(step_row[STEP_REQ_MIN_CPU_NODE]);
1500
 
 
1501
 
                        step->requid = atoi(step_row[STEP_REQ_KILL_REQUID]);
1502
 
                }
1503
 
                mysql_free_result(step_result);
1504
 
 
1505
 
                if(!job->track_steps) {
1506
 
                        /* If we don't have track_steps we want to see
1507
 
                           if we have multiple steps.  If we only have
1508
 
                           1 step check the job name against the step
1509
 
                           name in most all cases it will be
1510
 
                           different.  If it is different print out
1511
 
                           the step separate.
1512
 
                        */
1513
 
                        if(list_count(job->steps) > 1)
1514
 
                                job->track_steps = 1;
1515
 
                        else if(step && step->stepname && job->jobname) {
1516
 
                                if(strcmp(step->stepname, job->jobname))
1517
 
                                        job->track_steps = 1;
1518
 
                        }
1519
 
                }
1520
 
        skip_steps:
1521
 
                /* need to reset here to make the above test valid */
1522
 
                step = NULL;
1523
 
        }
1524
 
        mysql_free_result(result);
1525
 
        if(local_cluster_list)
1526
 
                list_destroy(local_cluster_list);
1527
 
 
1528
 
        return job_list;
1529
 
}
1530
 
 
1531
 
extern int mysql_jobacct_process_archive(mysql_conn_t *mysql_conn,
1532
 
                                         acct_archive_cond_t *arch_cond)
1533
 
{
1534
 
        int rc = SLURM_SUCCESS;
1535
 
        char *query = NULL;
1536
 
        time_t last_submit = time(NULL);
1537
 
        time_t curr_end;
1538
 
        char *tmp = NULL;
1539
 
        int i=0;
1540
 
        struct tm time_tm;
1541
 
 
1542
 
//      DEF_TIMERS;
1543
 
 
1544
 
        /* if this changes you will need to edit the corresponding
1545
 
         * enum below */
1546
 
        char *event_req_inx[] = {
1547
 
                "node_name",
1548
 
                "cluster",
1549
 
                "cpu_count",
1550
 
                "state",
1551
 
                "period_start",
1552
 
                "period_end",
1553
 
                "reason",
1554
 
                "cluster_nodes",
1555
 
        };
1556
 
 
1557
 
        /* if this changes you will need to edit the corresponding
1558
 
         * enum below */
1559
 
        char *job_req_inx[] = {
1560
 
                "id",
1561
 
                "jobid",
1562
 
                "associd",
1563
 
                "wckey",
1564
 
                "wckeyid",
1565
 
                "uid",
1566
 
                "gid",
1567
 
                "resvid",
1568
 
                "partition",
1569
 
                "blockid",
1570
 
                "cluster",
1571
 
                "account",
1572
 
                "eligible",
1573
 
                "submit",
1574
 
                "start",
1575
 
                "end",
1576
 
                "suspended",
1577
 
                "name",
1578
 
                "track_steps",
1579
 
                "state",
1580
 
                "comp_code",
1581
 
                "priority",
1582
 
                "req_cpus",
1583
 
                "alloc_cpus",
1584
 
                "alloc_nodes",
1585
 
                "nodelist",
1586
 
                "node_inx",
1587
 
                "kill_requid",
1588
 
                "timelimit",
1589
 
                "qos"
1590
 
        };
1591
 
 
1592
 
        /* if this changes you will need to edit the corresponding
1593
 
         * enum below */
1594
 
        char *step_req_inx[] = {
1595
 
                "id",
1596
 
                "stepid",
1597
 
                "start",
1598
 
                "end",
1599
 
                "suspended",
1600
 
                "name",
1601
 
                "nodelist",
1602
 
                "node_inx",
1603
 
                "state",
1604
 
                "kill_requid",
1605
 
                "comp_code",
1606
 
                "nodes",
1607
 
                "cpus",
1608
 
                "tasks",
1609
 
                "task_dist",
1610
 
                "user_sec",
1611
 
                "user_usec",
1612
 
                "sys_sec",
1613
 
                "sys_usec",
1614
 
                "max_vsize",
1615
 
                "max_vsize_task",
1616
 
                "max_vsize_node",
1617
 
                "ave_vsize",
1618
 
                "max_rss",
1619
 
                "max_rss_task",
1620
 
                "max_rss_node",
1621
 
                "ave_rss",
1622
 
                "max_pages",
1623
 
                "max_pages_task",
1624
 
                "max_pages_node",
1625
 
                "ave_pages",
1626
 
                "min_cpu",
1627
 
                "min_cpu_task",
1628
 
                "min_cpu_node",
1629
 
                "ave_cpu"
1630
 
        };
1631
 
 
1632
 
 
1633
 
        /* if this changes you will need to edit the corresponding
1634
 
         * enum below */
1635
 
        char *suspend_req_inx[] = {
1636
 
                "id",
1637
 
                "associd",
1638
 
                "start",
1639
 
                "end",
1640
 
        };
1641
 
 
1642
 
        enum {
1643
 
                EVENT_REQ_NODE,
1644
 
                EVENT_REQ_CLUSTER,
1645
 
                EVENT_REQ_CPUS,
1646
 
                EVENT_REQ_STATE,
1647
 
                EVENT_REQ_START,
1648
 
                EVENT_REQ_END,
1649
 
                EVENT_REQ_REASON,
1650
 
                EVENT_REQ_NODES,
1651
 
                EVENT_REQ_COUNT
1652
 
        };
1653
 
 
1654
 
        enum {
1655
 
                JOB_REQ_ID,
1656
 
                JOB_REQ_JOBID,
1657
 
                JOB_REQ_ASSOCID,
1658
 
                JOB_REQ_WCKEY,
1659
 
                JOB_REQ_WCKEYID,
1660
 
                JOB_REQ_UID,
1661
 
                JOB_REQ_GID,
1662
 
                JOB_REQ_RESVID,
1663
 
                JOB_REQ_PARTITION,
1664
 
                JOB_REQ_BLOCKID,
1665
 
                JOB_REQ_CLUSTER,
1666
 
                JOB_REQ_ACCOUNT,
1667
 
                JOB_REQ_ELIGIBLE,
1668
 
                JOB_REQ_SUBMIT,
1669
 
                JOB_REQ_START,
1670
 
                JOB_REQ_END,
1671
 
                JOB_REQ_SUSPENDED,
1672
 
                JOB_REQ_NAME,
1673
 
                JOB_REQ_TRACKSTEPS,
1674
 
                JOB_REQ_STATE,
1675
 
                JOB_REQ_COMP_CODE,
1676
 
                JOB_REQ_PRIORITY,
1677
 
                JOB_REQ_REQ_CPUS,
1678
 
                JOB_REQ_ALLOC_CPUS,
1679
 
                JOB_REQ_ALLOC_NODES,
1680
 
                JOB_REQ_NODELIST,
1681
 
                JOB_REQ_NODE_INX,
1682
 
                JOB_REQ_KILL_REQUID,
1683
 
                JOB_REQ_TIMELIMIT,
1684
 
                JOB_REQ_QOS,
1685
 
                JOB_REQ_COUNT
1686
 
        };
1687
 
 
1688
 
        enum {
1689
 
                STEP_REQ_ID,
1690
 
                STEP_REQ_STEPID,
1691
 
                STEP_REQ_START,
1692
 
                STEP_REQ_END,
1693
 
                STEP_REQ_SUSPENDED,
1694
 
                STEP_REQ_NAME,
1695
 
                STEP_REQ_NODELIST,
1696
 
                STEP_REQ_NODE_INX,
1697
 
                STEP_REQ_STATE,
1698
 
                STEP_REQ_KILL_REQUID,
1699
 
                STEP_REQ_COMP_CODE,
1700
 
                STEP_REQ_NODES,
1701
 
                STEP_REQ_CPUS,
1702
 
                STEP_REQ_TASKS,
1703
 
                STEP_REQ_TASKDIST,
1704
 
                STEP_REQ_USER_SEC,
1705
 
                STEP_REQ_USER_USEC,
1706
 
                STEP_REQ_SYS_SEC,
1707
 
                STEP_REQ_SYS_USEC,
1708
 
                STEP_REQ_MAX_VSIZE,
1709
 
                STEP_REQ_MAX_VSIZE_TASK,
1710
 
                STEP_REQ_MAX_VSIZE_NODE,
1711
 
                STEP_REQ_AVE_VSIZE,
1712
 
                STEP_REQ_MAX_RSS,
1713
 
                STEP_REQ_MAX_RSS_TASK,
1714
 
                STEP_REQ_MAX_RSS_NODE,
1715
 
                STEP_REQ_AVE_RSS,
1716
 
                STEP_REQ_MAX_PAGES,
1717
 
                STEP_REQ_MAX_PAGES_TASK,
1718
 
                STEP_REQ_MAX_PAGES_NODE,
1719
 
                STEP_REQ_AVE_PAGES,
1720
 
                STEP_REQ_MIN_CPU,
1721
 
                STEP_REQ_MIN_CPU_TASK,
1722
 
                STEP_REQ_MIN_CPU_NODE,
1723
 
                STEP_REQ_AVE_CPU,
1724
 
                STEP_REQ_COUNT
1725
 
        };
1726
 
 
1727
 
        enum {
1728
 
                SUSPEND_REQ_ID,
1729
 
                SUSPEND_REQ_ASSOCID,
1730
 
                SUSPEND_REQ_START,
1731
 
                SUSPEND_REQ_END,
1732
 
                SUSPEND_REQ_COUNT
1733
 
        };
1734
 
 
1735
 
        if(!arch_cond) {
1736
 
                error("No arch_cond was given to archive from.  returning");
1737
 
                return SLURM_ERROR;
1738
 
        }
1739
 
 
1740
 
        if(!localtime_r(&last_submit, &time_tm)) {
1741
 
                error("Couldn't get localtime from first start %d",
1742
 
                      last_submit);
1743
 
                return SLURM_ERROR;
1744
 
        }
1745
 
 
1746
 
        /* get to the beginning of the current month */
1747
 
        time_tm.tm_sec = 0;
1748
 
        time_tm.tm_min = 0;
1749
 
        time_tm.tm_hour = 0;
1750
 
        time_tm.tm_mday = 1;
1751
 
        time_tm.tm_isdst = -1;
1752
 
        last_submit = mktime(&time_tm);
1753
 
 
1754
 
        debug("archive: adjusted last submit is (%d)", last_submit);
1755
 
 
1756
 
        if(arch_cond->archive_script)
1757
 
                return _archive_script(arch_cond, last_submit);
1758
 
        else if(!arch_cond->archive_dir) {
1759
 
                error("No archive dir given, can't process");
1760
 
                return SLURM_ERROR;
1761
 
        }
1762
 
 
1763
 
        if(arch_cond->purge_event) {
1764
 
                /* remove all data from step table that was older than
1765
 
                 * period_start * arch_cond->purge_event.
1766
 
                 */
1767
 
                /* use localtime to avoid any daylight savings issues */
1768
 
                if(!localtime_r(&last_submit, &time_tm)) {
1769
 
                        error("Couldn't get localtime from first submit %d",
1770
 
                              last_submit);
1771
 
                        return SLURM_ERROR;
1772
 
                }
1773
 
                time_tm.tm_sec = 0;
1774
 
                time_tm.tm_min = 0;
1775
 
                time_tm.tm_hour = 0;
1776
 
                time_tm.tm_mday = 1;
1777
 
                time_tm.tm_mon -= arch_cond->purge_event;
1778
 
                time_tm.tm_isdst = -1;
1779
 
                curr_end = mktime(&time_tm);
1780
 
                curr_end--;
1781
 
 
1782
 
                debug4("from %d - %d months purging events from before %d",
1783
 
                       last_submit, arch_cond->purge_event, curr_end);
1784
 
 
1785
 
                if(arch_cond->archive_events) {
1786
 
                        char *insert = NULL;
1787
 
                        MYSQL_RES *result = NULL;
1788
 
 
1789
 
                        xfree(tmp);
1790
 
                        xstrfmtcat(tmp, "%s", event_req_inx[0]);
1791
 
                        for(i=1; i<EVENT_REQ_COUNT; i++) {
1792
 
                                xstrfmtcat(tmp, ", %s", event_req_inx[i]);
1793
 
                        }
1794
 
 
1795
 
                        /* get all the events started before this time
1796
 
                           listed */
1797
 
                        query = xstrdup_printf("select %s from %s where "
1798
 
                                               "period_start <= %d "
1799
 
                                               "&& period_end != 0 "
1800
 
                                               "order by period_start asc",
1801
 
                                               tmp, event_table, curr_end);
1802
 
 
1803
 
                        insert = xstrdup_printf("insert into %s (%s) ",
1804
 
                                                event_table, tmp);
1805
 
                        xfree(tmp);
1806
 
 
1807
 
//                      START_TIMER;
1808
 
                        debug3("%d(%d) query\n%s", mysql_conn->conn,
1809
 
                               __LINE__, query);
1810
 
                        if(!(result = mysql_db_query_ret(
1811
 
                                     mysql_conn->db_conn, query, 0))) {
1812
 
                                xfree(insert);
1813
 
                                xfree(query);
1814
 
                                return SLURM_ERROR;
1815
 
                        }
1816
 
                        xfree(query);
1817
 
//                      END_TIMER2("step query");
1818
 
//                      info("event query took %s", TIME_STR);
1819
 
 
1820
 
                        if(!mysql_num_rows(result)) {
1821
 
                                xfree(insert);
1822
 
                                mysql_free_result(result);
1823
 
                                goto exit_events;
1824
 
                        }
1825
 
 
1826
 
                        rc = _write_archive_file(
1827
 
                                result, EVENT_REQ_START, EVENT_REQ_COUNT,
1828
 
                                curr_end, arch_cond->archive_dir,
1829
 
                                "event", insert, false);
1830
 
 
1831
 
                        xfree(insert);
1832
 
                        mysql_free_result(result);
1833
 
 
1834
 
                        if(rc != SLURM_SUCCESS)
1835
 
                                return rc;
1836
 
                }
1837
 
                query = xstrdup_printf("delete from %s where "
1838
 
                                       "period_start <= %d && period_end != 0",
1839
 
                                       event_table, curr_end);
1840
 
                debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query);
1841
 
                rc = mysql_db_query(mysql_conn->db_conn, query);
1842
 
                xfree(query);
1843
 
                if(rc != SLURM_SUCCESS) {
1844
 
                        error("Couldn't remove old event data");
1845
 
                        return SLURM_ERROR;
1846
 
                }
1847
 
        }
1848
 
 
1849
 
exit_events:
1850
 
 
1851
 
        if(arch_cond->purge_suspend) {
1852
 
                /* remove all data from step table that was older than
1853
 
                 * period_start * arch_cond->purge_suspend.
1854
 
                 */
1855
 
                /* use localtime to avoid any daylight savings issues */
1856
 
                if(!localtime_r(&last_submit, &time_tm)) {
1857
 
                        error("Couldn't get localtime from first submit %d",
1858
 
                              last_submit);
1859
 
                        return SLURM_ERROR;
1860
 
                }
1861
 
                time_tm.tm_sec = 0;
1862
 
                time_tm.tm_min = 0;
1863
 
                time_tm.tm_hour = 0;
1864
 
                time_tm.tm_mday = 1;
1865
 
                time_tm.tm_mon -= arch_cond->purge_suspend;
1866
 
                time_tm.tm_isdst = -1;
1867
 
                curr_end = mktime(&time_tm);
1868
 
                curr_end--;
1869
 
 
1870
 
                debug4("from %d - %d months purging suspend from before %d",
1871
 
                       last_submit, arch_cond->purge_suspend, curr_end);
1872
 
 
1873
 
                if(arch_cond->archive_suspend) {
1874
 
                        char *insert = NULL;
1875
 
                        MYSQL_RES *result = NULL;
1876
 
 
1877
 
                        xfree(tmp);
1878
 
                        xstrfmtcat(tmp, "%s", suspend_req_inx[0]);
1879
 
                        for(i=1; i<SUSPEND_REQ_COUNT; i++) {
1880
 
                                xstrfmtcat(tmp, ", %s", suspend_req_inx[i]);
1881
 
                        }
1882
 
 
1883
 
                        /* get all the suspend started before this time
1884
 
                           listed */
1885
 
                        query = xstrdup_printf("select %s from %s where "
1886
 
                                               "start <= %d && end != 0 "
1887
 
                                               "order by start asc",
1888
 
                                               tmp, suspend_table, curr_end);
1889
 
 
1890
 
                        insert = xstrdup_printf("insert into %s (%s) ",
1891
 
                                                suspend_table, tmp);
1892
 
                        xfree(tmp);
1893
 
 
1894
 
//                      START_TIMER;
1895
 
                        debug3("%d(%d) query\n%s", mysql_conn->conn,
1896
 
                               __LINE__, query);
1897
 
                        if(!(result = mysql_db_query_ret(
1898
 
                                     mysql_conn->db_conn, query, 0))) {
1899
 
                                xfree(insert);
1900
 
                                xfree(query);
1901
 
                                return SLURM_ERROR;
1902
 
                        }
1903
 
                        xfree(query);
1904
 
//                      END_TIMER2("step query");
1905
 
//                      info("suspend query took %s", TIME_STR);
1906
 
 
1907
 
                        if(!mysql_num_rows(result)) {
1908
 
                                xfree(insert);
1909
 
                                mysql_free_result(result);
1910
 
                                goto exit_suspend;
1911
 
                        }
1912
 
 
1913
 
                        rc = _write_archive_file(
1914
 
                                result, SUSPEND_REQ_START, SUSPEND_REQ_COUNT,
1915
 
                                curr_end, arch_cond->archive_dir,
1916
 
                                "suspend", insert, false);
1917
 
 
1918
 
                        xfree(insert);
1919
 
                        mysql_free_result(result);
1920
 
 
1921
 
                        if(rc != SLURM_SUCCESS)
1922
 
                                return rc;
1923
 
                }
1924
 
                query = xstrdup_printf("delete from %s where start <= %d "
1925
 
                                       "&& end != 0",
1926
 
                                       suspend_table, curr_end);
1927
 
                debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query);
1928
 
                rc = mysql_db_query(mysql_conn->db_conn, query);
1929
 
                xfree(query);
1930
 
                if(rc != SLURM_SUCCESS) {
1931
 
                        error("Couldn't remove old suspend data");
1932
 
                        return SLURM_ERROR;
1933
 
                }
1934
 
        }
1935
 
 
1936
 
exit_suspend:
1937
 
 
1938
 
        if(arch_cond->purge_step) {
1939
 
                /* remove all data from step table that was older than
1940
 
                 * start * arch_cond->purge_step.
1941
 
                 */
1942
 
                /* use localtime to avoid any daylight savings issues */
1943
 
                if(!localtime_r(&last_submit, &time_tm)) {
1944
 
                        error("Couldn't get localtime from first start %d",
1945
 
                              last_submit);
1946
 
                        return SLURM_ERROR;
1947
 
                }
1948
 
                time_tm.tm_sec = 0;
1949
 
                time_tm.tm_min = 0;
1950
 
                time_tm.tm_hour = 0;
1951
 
                time_tm.tm_mday = 1;
1952
 
                time_tm.tm_mon -= arch_cond->purge_step;
1953
 
                time_tm.tm_isdst = -1;
1954
 
                curr_end = mktime(&time_tm);
1955
 
                curr_end--;
1956
 
 
1957
 
                debug4("from %d - %d months purging steps from before %d",
1958
 
                       last_submit, arch_cond->purge_step, curr_end);
1959
 
 
1960
 
                if(arch_cond->archive_steps) {
1961
 
                        char *insert = NULL;
1962
 
                        MYSQL_RES *result = NULL;
1963
 
 
1964
 
                        xfree(tmp);
1965
 
                        xstrfmtcat(tmp, "%s", step_req_inx[0]);
1966
 
                        for(i=1; i<STEP_REQ_COUNT; i++) {
1967
 
                                xstrfmtcat(tmp, ", %s", step_req_inx[i]);
1968
 
                        }
1969
 
 
1970
 
                        /* get all the steps submitted before this time
1971
 
                           listed */
1972
 
                        query = xstrdup_printf("select %s from %s where "
1973
 
                                               "start <= %d && end != 0 "
1974
 
                                               "&& !deleted "
1975
 
                                               "order by start asc",
1976
 
                                               tmp, step_table, curr_end);
1977
 
 
1978
 
                        xstrcat(tmp, ", deleted");
1979
 
                        insert = xstrdup_printf("insert into %s (%s) ",
1980
 
                                                step_table, tmp);
1981
 
                        xfree(tmp);
1982
 
 
1983
 
//                      START_TIMER;
1984
 
                        debug3("%d(%d) query\n%s", mysql_conn->conn,
1985
 
                               __LINE__, query);
1986
 
                        if(!(result = mysql_db_query_ret(
1987
 
                                     mysql_conn->db_conn, query, 0))) {
1988
 
                                xfree(insert);
1989
 
                                xfree(query);
1990
 
                                return SLURM_ERROR;
1991
 
                        }
1992
 
                        xfree(query);
1993
 
//                      END_TIMER2("step query");
1994
 
//                      info("step query took %s", TIME_STR);
1995
 
 
1996
 
                        if(!mysql_num_rows(result)) {
1997
 
                                xfree(insert);
1998
 
                                mysql_free_result(result);
1999
 
                                goto exit_steps;
2000
 
                        }
2001
 
 
2002
 
                        rc = _write_archive_file(
2003
 
                                result, STEP_REQ_START, STEP_REQ_COUNT,
2004
 
                                curr_end, arch_cond->archive_dir,
2005
 
                                "step", insert, true);
2006
 
 
2007
 
                        xfree(insert);
2008
 
                        mysql_free_result(result);
2009
 
 
2010
 
                        if(rc != SLURM_SUCCESS)
2011
 
                                return rc;
2012
 
                }
2013
 
 
2014
 
                query = xstrdup_printf("delete from %s where start <= %d "
2015
 
                                       "&& end != 0",
2016
 
                                       step_table, curr_end);
2017
 
                debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query);
2018
 
                rc = mysql_db_query(mysql_conn->db_conn, query);
2019
 
                xfree(query);
2020
 
                if(rc != SLURM_SUCCESS) {
2021
 
                        error("Couldn't remove old step data");
2022
 
                        return SLURM_ERROR;
2023
 
                }
2024
 
        }
2025
 
exit_steps:
2026
 
 
2027
 
        if(arch_cond->purge_job) {
2028
 
                /* remove all data from step table that was older than
2029
 
                 * last_submit * arch_cond->purge_job.
2030
 
                 */
2031
 
                /* use localtime to avoid any daylight savings issues */
2032
 
                if(!localtime_r(&last_submit, &time_tm)) {
2033
 
                        error("Couldn't get localtime from first submit %d",
2034
 
                              last_submit);
2035
 
                        return SLURM_ERROR;
2036
 
                }
2037
 
                time_tm.tm_sec = 0;
2038
 
                time_tm.tm_min = 0;
2039
 
                time_tm.tm_hour = 0;
2040
 
                time_tm.tm_mday = 1;
2041
 
                time_tm.tm_mon -= arch_cond->purge_job;
2042
 
                time_tm.tm_isdst = -1;
2043
 
                curr_end = mktime(&time_tm);
2044
 
                curr_end--;
2045
 
 
2046
 
                debug4("from %d - %d months purging jobs from before %d",
2047
 
                       last_submit, arch_cond->purge_job, curr_end);
2048
 
 
2049
 
                if(arch_cond->archive_jobs) {
2050
 
                        char *insert = NULL;
2051
 
                        MYSQL_RES *result = NULL;
2052
 
 
2053
 
                        xfree(tmp);
2054
 
                        xstrfmtcat(tmp, "%s", job_req_inx[0]);
2055
 
                        for(i=1; i<JOB_REQ_COUNT; i++) {
2056
 
                                xstrfmtcat(tmp, ", %s", job_req_inx[i]);
2057
 
                        }
2058
 
                        /* get all the jobs submitted before this time
2059
 
                           listed */
2060
 
                        query = xstrdup_printf("select %s from %s where "
2061
 
                                               "submit < %d && end != 0 "
2062
 
                                               "&& !deleted "
2063
 
                                               "order by submit asc",
2064
 
                                               tmp, job_table, curr_end);
2065
 
 
2066
 
                        xstrcat(tmp, ", deleted");
2067
 
                        insert = xstrdup_printf("insert into %s (%s) ",
2068
 
                                                job_table, tmp);
2069
 
                        xfree(tmp);
2070
 
 
2071
 
//                      START_TIMER;
2072
 
                        debug3("%d(%d) query\n%s", mysql_conn->conn,
2073
 
                               __LINE__, query);
2074
 
                        if(!(result = mysql_db_query_ret(
2075
 
                                     mysql_conn->db_conn, query, 0))) {
2076
 
                                xfree(insert);
2077
 
                                xfree(query);
2078
 
                                return SLURM_ERROR;
2079
 
                        }
2080
 
                        xfree(query);
2081
 
//                      END_TIMER2("job query");
2082
 
//                      info("job query took %s", TIME_STR);
2083
 
 
2084
 
                        if(!mysql_num_rows(result)) {
2085
 
                                xfree(insert);
2086
 
                                mysql_free_result(result);
2087
 
                                goto exit_jobs;
2088
 
                        }
2089
 
 
2090
 
                        rc = _write_archive_file(
2091
 
                                result, JOB_REQ_SUBMIT, JOB_REQ_COUNT,
2092
 
                                curr_end, arch_cond->archive_dir,
2093
 
                                "job", insert, true);
2094
 
 
2095
 
                        xfree(insert);
2096
 
                        mysql_free_result(result);
2097
 
 
2098
 
                        if(rc != SLURM_SUCCESS)
2099
 
                                return rc;
2100
 
                }
2101
 
 
2102
 
                query = xstrdup_printf("delete from %s where submit <= %d "
2103
 
                                       "&& end != 0",
2104
 
                                       job_table, curr_end);
2105
 
                debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, query);
2106
 
                rc = mysql_db_query(mysql_conn->db_conn, query);
2107
 
                xfree(query);
2108
 
                if(rc != SLURM_SUCCESS) {
2109
 
                        error("Couldn't remove old job data");
2110
 
                        return SLURM_ERROR;
2111
 
                }
2112
 
        }
2113
 
exit_jobs:
2114
 
 
2115
 
        return SLURM_SUCCESS;
2116
 
}
2117
 
 
2118
 
extern int mysql_jobacct_process_archive_load(mysql_conn_t *mysql_conn,
2119
 
                                              acct_archive_rec_t *arch_rec)
2120
 
{
2121
 
        char *data = NULL;
2122
 
        int error_code = SLURM_SUCCESS;
2123
 
 
2124
 
        if(!arch_rec) {
2125
 
                error("We need a acct_archive_rec to load anything.");
2126
 
                return SLURM_ERROR;
2127
 
        }
2128
 
 
2129
 
        if(arch_rec->insert) {
2130
 
                data = xstrdup(arch_rec->insert);
2131
 
        } else if(arch_rec->archive_file) {
2132
 
                uint32_t data_size = 0;
2133
 
                int data_allocated, data_read = 0;
2134
 
                int state_fd = open(arch_rec->archive_file, O_RDONLY);
2135
 
                if (state_fd < 0) {
2136
 
                        info("No archive file (%s) to recover",
2137
 
                             arch_rec->archive_file);
2138
 
                        error_code = ENOENT;
2139
 
                } else {
2140
 
                        data_allocated = BUF_SIZE;
2141
 
                        data = xmalloc(data_allocated);
2142
 
                        while (1) {
2143
 
                                data_read = read(state_fd, &data[data_size],
2144
 
                                                 BUF_SIZE);
2145
 
                                if (data_read < 0) {
2146
 
                                        if (errno == EINTR)
2147
 
                                                continue;
2148
 
                                        else {
2149
 
                                                error("Read error on %s: %m",
2150
 
                                                      arch_rec->archive_file);
2151
 
                                                break;
2152
 
                                        }
2153
 
                                } else if (data_read == 0)      /* eof */
2154
 
                                        break;
2155
 
                                data_size      += data_read;
2156
 
                                data_allocated += data_read;
2157
 
                                xrealloc(data, data_allocated);
2158
 
                        }
2159
 
                        close(state_fd);
2160
 
                }
2161
 
                if(error_code != SLURM_SUCCESS) {
2162
 
                        xfree(data);
2163
 
                        return error_code;
2164
 
                }
2165
 
        } else {
2166
 
                error("Nothing was set in your "
2167
 
                      "acct_archive_rec so I am unable to process.");
2168
 
                return SLURM_ERROR;
2169
 
        }
2170
 
 
2171
 
        if(!data) {
2172
 
                error("It doesn't appear we have anything to load.");
2173
 
                return SLURM_ERROR;
2174
 
        }
2175
 
 
2176
 
        debug3("%d(%d) query\n%s", mysql_conn->conn, __LINE__, data);
2177
 
        error_code = mysql_db_query_check_after(mysql_conn->db_conn, data);
2178
 
        xfree(data);
2179
 
        if(error_code != SLURM_SUCCESS) {
2180
 
                error("Couldn't load old data");
2181
 
                return SLURM_ERROR;
2182
 
        }
2183
 
 
2184
 
        return SLURM_SUCCESS;
2185
 
}