1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
17 
18 #ifndef _BOINC_DB_
19 #define _BOINC_DB_
20 
21 // Structures corresponding to database records.
22 // Some of these types have counterparts in client/types.h,
23 // but don't be deceived - client and server have different variants.
24 
25 // The parse and write functions are for use in scheduler RPC.
26 // They don't necessarily serialize the entire records.
27 
28 #include <cstdio>
29 #include <vector>
30 #include <string.h>
31 
32 #include "db_base.h"
33 #include "boinc_db_types.h"
34 
35 extern DB_CONN boinc_db;
36 
37 struct TRANSITIONER_ITEM {
38     DB_ID_TYPE id; // WARNING: this is the WU ID
39     char name[256];
40     DB_ID_TYPE appid;
41     int min_quorum;
42     bool need_validate;
43     DB_ID_TYPE canonical_resultid;
44     int transition_time;
45     int delay_bound;
46     int error_mask;
47     int max_error_results;
48     int max_total_results;
49     int file_delete_state;
50     int assimilate_state;
51     int target_nresults;
52     char result_template_file[64];
53     int priority;
54     int hr_class;
55     int batch;
56     DB_ID_TYPE app_version_id;
57     int transitioner_flags;
58     int size_class;
59     DB_ID_TYPE res_id; // This is the RESULT ID
60     char res_name[256];
61     int res_report_deadline;
62     int res_server_state;
63     int res_outcome;
64     int res_validate_state;
65     int res_file_delete_state;
66     int res_sent_time;
67     DB_ID_TYPE res_hostid;
68     int res_received_time;
69     DB_ID_TYPE res_app_version_id;
70     int res_exit_status;
71 
72     void clear();
73     void parse(MYSQL_ROW&);
74 };
75 
76 struct DB_HOST_APP_VERSION : public DB_BASE, public HOST_APP_VERSION {
77     DB_HOST_APP_VERSION(DB_CONN* p=0);
78     void db_print(char*);
79     void db_parse(MYSQL_ROW &row);
80     int update_scheduler(DB_HOST_APP_VERSION&);
81     int update_validator(DB_HOST_APP_VERSION&);
82 };
83 
84 struct DB_USER_SUBMIT : public DB_BASE, public USER_SUBMIT {
85     DB_USER_SUBMIT(DB_CONN* p=0);
86     void db_print(char*);
87     void db_parse(MYSQL_ROW &row);
88 };
89 
90 struct STATE_COUNTS {
91     DB_ID_TYPE appid;
92     int last_update_time;
93     int result_server_state_2;
94     int result_server_state_4;
95     int result_file_delete_state_1;
96     int result_file_delete_state_2;
97     int result_server_state_5_and_file_delete_state_0;
98     int workunit_need_validate_1;
99     int workunit_assimilate_state_1;
100     int workunit_file_delete_state_1;
101     int workunit_file_delete_state_2;
102 
103     void clear();
104 };
105 
106 struct DB_STATE_COUNTS : public DB_BASE, public STATE_COUNTS {
107     DB_STATE_COUNTS(DB_CONN* p=0);
108     DB_ID_TYPE get_id();
109     void db_print(char *);
110     void db_parse(MYSQL_ROW &row);
111 };
112 
113 struct VALIDATOR_ITEM {
114     WORKUNIT wu;
115     RESULT res;
116 
117     void clear();
118     void parse(MYSQL_ROW&);
119 };
120 
121 class DB_PLATFORM : public DB_BASE, public PLATFORM {
122 public:
123     DB_PLATFORM(DB_CONN* p=0);
124     DB_ID_TYPE get_id();
125     void db_print(char*);
126     void db_parse(MYSQL_ROW &row);
127 };
128 
129 class DB_APP : public DB_BASE, public APP {
130 public:
131     DB_APP(DB_CONN* p=0);
132     DB_ID_TYPE get_id();
133     void db_print(char*);
134     void db_parse(MYSQL_ROW &row);
135 };
136 
137 class DB_APP_VERSION : public DB_BASE, public APP_VERSION {
138 public:
139     DB_APP_VERSION(DB_CONN* p=0);
140     DB_ID_TYPE get_id();
141     void db_print(char*);
142     void db_parse(MYSQL_ROW &row);
143     void operator=(APP_VERSION& w) {APP_VERSION::operator=(w);}
144 };
145 
146 class DB_USER : public DB_BASE, public USER {
147 public:
148     DB_USER(DB_CONN* p=0);
149     DB_ID_TYPE get_id();
150     void db_print(char*);
151     void db_parse(MYSQL_ROW &row);
152     void operator=(USER& r) {USER::operator=(r);}
153 };
154 
155 class DB_TEAM : public DB_BASE, public TEAM {
156 public:
157     DB_TEAM(DB_CONN* p=0);
158     DB_ID_TYPE get_id();
159     void db_print(char*);
160     void db_parse(MYSQL_ROW &row);
161 };
162 
163 class DB_HOST : public DB_BASE, public HOST {
164 public:
165     DB_HOST(DB_CONN* p=0);
166     DB_ID_TYPE get_id();
167     int update_diff_sched(HOST&);
168     int update_diff_validator(HOST&);
169     int fpops_percentile(double percentile, double& fpops);
170         // return the given percentile of p_fpops
171     int fpops_mean(double& mean);
172     int fpops_stddev(double& stddev);
173     void db_print(char*);
174     void db_parse(MYSQL_ROW &row);
175     void operator=(HOST& r) {HOST::operator=(r);}
176 };
177 
178 class DB_RESULT : public DB_BASE, public RESULT {
179 public:
180     DB_RESULT(DB_CONN* p=0);
181     DB_ID_TYPE get_id();
182     int mark_as_sent(int old_server_state, int report_grace_period);
183     void db_print(char*);
184     void db_print_values(char*);
185     void db_parse(MYSQL_ROW &row);
186     void operator=(RESULT& r) {RESULT::operator=(r);}
187     int get_unsent_counts(APP&, int* unsent, int count_max);
188     int make_unsent(
189         APP&, int size_class, int n, const char* order_clause, int& nchanged
190     );
191 };
192 
193 class DB_WORKUNIT : public DB_BASE, public WORKUNIT {
194 public:
195     DB_WORKUNIT(DB_CONN* p=0);
196     DB_ID_TYPE get_id();
197     void db_print(char*);
198     void db_print_values(char*);
199     void db_parse(MYSQL_ROW &row);
200     void operator=(WORKUNIT& w) {WORKUNIT::operator=(w);}
201 };
202 
203 class DB_CREDITED_JOB : public DB_BASE, public CREDITED_JOB {
204 public:
205     DB_CREDITED_JOB(DB_CONN* p=0);
206     void db_print(char*);
207     void db_parse(MYSQL_ROW &row);
208     void operator=(CREDITED_JOB& wh) {CREDITED_JOB::operator=(wh);}
209 };
210 
211 class DB_MSG_FROM_HOST : public DB_BASE, public MSG_FROM_HOST {
212 public:
213     DB_MSG_FROM_HOST(DB_CONN* p=0);
214     DB_ID_TYPE get_id();
215     void db_print(char*);
216     void db_parse(MYSQL_ROW &row);
217 };
218 
219 class DB_MSG_TO_HOST : public DB_BASE, public MSG_TO_HOST {
220 public:
221     DB_MSG_TO_HOST(DB_CONN* p=0);
222     DB_ID_TYPE get_id();
223     void db_print(char*);
224     void db_parse(MYSQL_ROW &row);
225 };
226 
227 class DB_ASSIGNMENT : public DB_BASE, public ASSIGNMENT {
228 public:
229     DB_ASSIGNMENT(DB_CONN* p=0);
230     DB_ID_TYPE get_id();
231     void db_print(char*);
232     void db_parse(MYSQL_ROW& row);
233 };
234 
235 // The transitioner uses this to get (WU, result) pairs efficiently.
236 // Each call to enumerate() returns a list of the pairs for a single WU
237 //
238 class DB_TRANSITIONER_ITEM_SET : public DB_BASE_SPECIAL {
239 public:
240     DB_TRANSITIONER_ITEM_SET(DB_CONN* p=0);
241     TRANSITIONER_ITEM last_item;
242     int nitems_this_query;
243 
244     int enumerate(
245         int transition_time,
246         int nresult_limit,
247         int wu_id_modulus,
248         int wu_id_remainder,
249         std::vector<TRANSITIONER_ITEM>& items
250     );
251     int update_result(TRANSITIONER_ITEM&);
252     int update_workunit(TRANSITIONER_ITEM&, TRANSITIONER_ITEM&);
253 };
254 
255 // The validator uses this to get (WU, result) pairs efficiently.
256 // Each call to enumerate() returns a list of the pairs for a single WU
257 //
258 class DB_VALIDATOR_ITEM_SET : public DB_BASE_SPECIAL {
259 public:
260     DB_VALIDATOR_ITEM_SET(DB_CONN* p=0);
261     VALIDATOR_ITEM last_item;
262     int nitems_this_query;
263 
264     int enumerate(
265         DB_ID_TYPE appid,
266         int nresult_limit,
267         int wu_id_modulus,
268         int wu_id_remainder,
269         DB_ID_TYPE wu_id_min,
270         DB_ID_TYPE wu_id_max,
271         std::vector<VALIDATOR_ITEM>& items
272     );
273     int update_result(RESULT&);
274     int update_workunit(WORKUNIT&);
275 };
276 
277 
278 // used by the feeder and scheduler for outgoing work
279 //
280 struct WORK_ITEM {
281     DB_ID_TYPE res_id;
282     int res_priority;
283     int res_server_state;
284     double res_report_deadline;
285     WORKUNIT wu;
286     void parse(MYSQL_ROW& row);
287 };
288 
289 class DB_WORK_ITEM : public WORK_ITEM, public DB_BASE_SPECIAL {
290     DB_ID_TYPE start_id;
291         // when enumerate_all is used, keeps track of which ID to start from
292 public:
293     DB_WORK_ITEM(DB_CONN* p=0);
294     int enumerate(
295         int limit, const char* select_clause, const char* order_clause
296     );
297         // used by feeder
298     int enumerate_all(
299         int limit, const char* select_clause
300     );
301         // used by feeder when HR is used.
302         // Successive calls cycle through all results.
303     int read_result();
304         // used by scheduler to read result server state
305     int update();
306         // used by scheduler to update WU transition time
307         // and various result fields
308 };
309 
310 // Used by the scheduler to send <result_abort> or <result_abort_if_not_started>
311 // messages if the result is no longer needed.
312 //
313 struct IN_PROGRESS_RESULT {
314 	char result_name[256];
315 	int assimilate_state;
316 	int error_mask;
317 	int server_state;
318 	int outcome;
319     void parse(MYSQL_ROW& row);
320 };
321 
322 class DB_IN_PROGRESS_RESULT : public IN_PROGRESS_RESULT, public DB_BASE_SPECIAL {
323 public:
324     DB_IN_PROGRESS_RESULT(DB_CONN* p=0);
325     int enumerate(DB_ID_TYPE hostid, const char* result_names);
326 };
327 
328 // Used by the scheduler to handle results reported by clients
329 // The read and the update of these results are combined
330 // into single SQL queries.
331 
332 struct SCHED_RESULT_ITEM {
333     char queried_name[256];     // name as reported by client
334     DB_ID_TYPE id;
335     char name[256];
336     DB_ID_TYPE workunitid;
337     DB_ID_TYPE appid;
338     int server_state;
339     int client_state;
340     int validate_state;
341     int outcome;
342     DB_ID_TYPE hostid;
343     DB_ID_TYPE userid;
344     DB_ID_TYPE teamid;
345     int sent_time;
346     int received_time;
347     double cpu_time;
348     char xml_doc_out[BLOB_SIZE];
349     char stderr_out[BLOB_SIZE];
350     int app_version_num;
351     int exit_status;
352     int file_delete_state;
353     double elapsed_time;
354     DB_ID_TYPE app_version_id;
355     double peak_working_set_size;
356     double peak_swap_size;
357     double peak_disk_usage;
358 
359     void clear();
360     void parse(MYSQL_ROW& row);
361 };
362 
363 class DB_SCHED_RESULT_ITEM_SET : public DB_BASE_SPECIAL {
364 public:
365     DB_SCHED_RESULT_ITEM_SET(DB_CONN* p=0);
366     std::vector<SCHED_RESULT_ITEM> results;
367 
368     int add_result(char* result_name);
369 
370     int enumerate();
371         // using a single SQL query, look up all the reported results,
372         // (based on queried_name)
373         // and fill in the rest of the entries in the results vector
374 
375     int lookup_result(char* result_name, SCHED_RESULT_ITEM** result);
376 
377     int update_result(SCHED_RESULT_ITEM& result);
378     int update_workunits();
379 };
380 
381 struct FILE_ITEM {
382     DB_ID_TYPE id;
383     char name[254];
384     char md5sum[34];
385     double size;
386 
387     void clear();
388 };
389 
390 class DB_FILE : public DB_BASE, public FILE_ITEM {
391 public:
392     DB_FILE(DB_CONN* p=0);
393     DB_ID_TYPE get_id();
394     void db_print(char*);
395     void db_parse(MYSQL_ROW &row);
396     void operator=(FILE_ITEM& f) {FILE_ITEM::operator=(f);}
397 };
398 
399 struct FILESET_ITEM {
400     DB_ID_TYPE id;
401     char name[254];
402 
403     void clear();
404 };
405 
406 class DB_FILESET : public DB_BASE, public FILESET_ITEM {
407 public:
408     DB_FILESET(DB_CONN* p=0);
409     DB_ID_TYPE get_id();
410     void db_print(char*);
411     void db_parse(MYSQL_ROW &row);
412     void operator=(FILESET_ITEM& f) {FILESET_ITEM::operator=(f);}
413 
414     // retrieve fileset instance (populate object)
415     int select_by_name(const char* name);
416 };
417 
418 struct FILESET_FILE_ITEM {
419     DB_ID_TYPE fileset_id;
420     DB_ID_TYPE file_id;
421 
422     void clear();
423 };
424 
425 class DB_FILESET_FILE : public DB_BASE, public FILESET_FILE_ITEM {
426 public:
427     DB_FILESET_FILE(DB_CONN* p=0);
428     void db_print(char*);
429     void db_parse(MYSQL_ROW &row);
430     void operator=(FILESET_FILE_ITEM& tf) {FILESET_FILE_ITEM::operator=(tf);}
431 };
432 
433 struct SCHED_TRIGGER_ITEM {
434     DB_ID_TYPE id;
435     DB_ID_TYPE fileset_id;
436     bool need_work;
437     bool work_available;
438     bool no_work_available;
439     bool working_set_removal;
440 
441     void clear();
442 };
443 
444 class DB_SCHED_TRIGGER : public DB_BASE, public SCHED_TRIGGER_ITEM {
445 public:
446     DB_SCHED_TRIGGER(DB_CONN* p=0);
447     DB_ID_TYPE get_id();
448     void db_print(char*);
449     void db_parse(MYSQL_ROW &row);
450     void operator=(SCHED_TRIGGER_ITEM& t) {SCHED_TRIGGER_ITEM::operator=(t);}
451 
452     typedef enum {
453         none                         = 0,
454         state_need_work              = 1,
455         state_work_available         = 2,
456         state_no_work_available      = 3,
457         state_working_set_removal    = 4
458     } STATE;
459 
460     // retrieve trigger instance (populate object)
461     int select_unique_by_fileset_name(const char* fileset_name);
462     // set single trigger state
463     int update_single_state(const DB_SCHED_TRIGGER::STATE state, const bool value);
464 };
465 
466 struct FILESET_SCHED_TRIGGER_ITEM {
467     FILESET_ITEM fileset;
468     SCHED_TRIGGER_ITEM trigger;
469 
470     void clear();
471 };
472 
473 class DB_FILESET_SCHED_TRIGGER_ITEM : public DB_BASE_SPECIAL, public FILESET_SCHED_TRIGGER_ITEM {
474 public:
475     DB_FILESET_SCHED_TRIGGER_ITEM(DB_CONN* p=0);
476     void db_parse(MYSQL_ROW &row);
477     void operator=(FILESET_SCHED_TRIGGER_ITEM& fst) {FILESET_SCHED_TRIGGER_ITEM::operator=(fst);}
478 };
479 
480 class DB_FILESET_SCHED_TRIGGER_ITEM_SET : public DB_BASE_SPECIAL {
481 public:
482     DB_FILESET_SCHED_TRIGGER_ITEM_SET(DB_CONN* p=0);
483 
484     // select available triggers based on name and/or state
485     // -> name filter optional (set string, default NULL)
486     // -> pattern search optional (set use_regexp to true, default false))
487     // -> state filter optional (set state, default none)
488     // -> state_value (default true)
489     int select_by_name_state(
490             const char* fileset_name,
491             const bool use_regexp,
492             const DB_SCHED_TRIGGER::STATE state,
493             const bool state_value);
494 
495     // check if given trigger (fileset name) is part of set and return position (1-indexed)
496     int contains_trigger(const char* fileset_name);
497 
498     // storage vector
499     std::vector<DB_FILESET_SCHED_TRIGGER_ITEM> items;
500 };
501 
502 struct DB_VDA_FILE : public DB_BASE, public VDA_FILE {
503     DB_VDA_FILE(DB_CONN* p=0);
504     DB_ID_TYPE get_id();
505     void db_print(char*);
506     void db_parse(MYSQL_ROW &row);
507 };
508 
509 struct DB_VDA_CHUNK_HOST : public DB_BASE, public VDA_CHUNK_HOST {
510     DB_VDA_CHUNK_HOST(DB_CONN* p=0);
511     void db_print(char*);
512     void db_parse(MYSQL_ROW &row);
513 };
514 
515 struct DB_BADGE : public DB_BASE, public BADGE {
516     DB_BADGE(DB_CONN* p=0);
get_idDB_BADGE517     DB_ID_TYPE get_id() {return id;};
db_printDB_BADGE518     void db_print(char*){};
519     void db_parse(MYSQL_ROW&);
520 };
521 
522 struct DB_BADGE_USER : public DB_BASE, public BADGE_USER {
523     DB_BADGE_USER(DB_CONN* p=0);
db_printDB_BADGE_USER524     void db_print(char*){};
525     void db_parse(MYSQL_ROW&);
526 };
527 
528 struct DB_BADGE_TEAM : public DB_BASE, public BADGE_TEAM {
529     DB_BADGE_TEAM(DB_CONN* p=0);
db_printDB_BADGE_TEAM530     void db_print(char*){};
531     void db_parse(MYSQL_ROW&);
532 };
533 
534 struct DB_CREDIT_USER : public DB_BASE, public CREDIT_USER {
535     DB_CREDIT_USER(DB_CONN* p=0);
536     void db_print(char*);
537     void db_parse(MYSQL_ROW&);
538 };
539 
540 struct DB_CREDIT_TEAM : public DB_BASE, public CREDIT_TEAM {
541     DB_CREDIT_TEAM(DB_CONN* p=0);
542     void db_print(char*);
543     void db_parse(MYSQL_ROW&);
544 };
545 
546 #endif
547