]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/tools/bbatch.c
Backport of class based catalog backends into Branch-5.1.
[bacula/bacula] / bacula / src / tools / bbatch.c
1 /*
2  *
3  *  Program to test batch mode
4  *
5  *   Eric Bollengier, March 2007
6  *
7  *
8  *   Version $Id$
9  */
10 /*
11    Bacula® - The Network Backup Solution
12
13    Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
14
15    The main author of Bacula is Kern Sibbald, with contributions from
16    many others, a complete list can be found in the file AUTHORS.
17    This program is Free Software; you can redistribute it and/or
18    modify it under the terms of version three of the GNU Affero General Public
19    License as published by the Free Software Foundation and included
20    in the file LICENSE.
21
22    This program is distributed in the hope that it will be useful, but
23    WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25    General Public License for more details.
26
27    You should have received a copy of the GNU Affero General Public License
28    along with this program; if not, write to the Free Software
29    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30    02110-1301, USA.
31
32    Bacula® is a registered trademark of Kern Sibbald.
33    The licensor of Bacula is the Free Software Foundation Europe
34    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
35    Switzerland, email:ftf@fsfeurope.org.
36 */
37
38 /*
39   to create datafile
40  
41   for i in $(seq 10000 99999) ; do
42      j=$((($i % 1000) + 555))
43      echo "$i;/tmp/totabofds$j/fiddddle${j}$i;xxxLSTATxxxx;xxxxxxxMD5xxxxxx"
44   done  > dat1
45  
46   or
47
48   j=0
49   find / | while read a; do
50    j=$(($j+1))
51    echo "$j;$a;xxxLSTATxxxx;xxxxxxxMD5xxxxxx"
52   done > dat1
53  */
54
55 #include "bacula.h"
56 #include "stored/stored.h"
57 #include "findlib/find.h"
58 #include "cats/cats.h"
59 #include "cats/sql_glue.h"
60  
61 /* Forward referenced functions */
62 static void *do_batch(void *);
63
64
65 /* Local variables */
66 static B_DB *db;
67
68 static const char *db_name = "bacula";
69 static const char *db_user = "bacula";
70 static const char *db_password = "";
71 static const char *db_host = NULL;
72
73 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
74
75 static void usage()
76 {
77    fprintf(stderr, _(
78 PROG_COPYRIGHT
79 "\nVersion: %s (%s)\n"
80 "Example : bbatch -w /path/to/workdir -h localhost -f dat1 -f dat -f datx\n"
81 " will start 3 thread and load dat1, dat and datx in your catalog\n"
82 "See bbatch.c to generate datafile\n\n"
83 "Usage: bbatch [ options ] -w working/dir -f datafile\n"
84 "       -d <nn>           set debug level to <nn>\n"
85 "       -dt               print timestamp in debug output\n"
86 "       -n <name>         specify the database name (default bacula)\n"
87 "       -u <user>         specify database user name (default bacula)\n"
88 "       -P <password      specify database password (default none)\n"
89 "       -h <host>         specify database host (default NULL)\n"
90 "       -w <working>      specify working directory\n"
91 "       -r <jobids>       call restore code with given jobids\n"
92 "       -v                verbose\n"
93 "       -f <file>         specify data file\n"
94 "       -?                print this message\n\n"), 2001, VERSION, BDATE);
95    exit(1);
96 }
97
98 /* number of thread started */
99 int nb=0;
100
101 static int list_handler(void *ctx, int num_fields, char **row)
102 {
103    uint64_t *a = (uint64_t*) ctx;
104    (*a)++;
105    return 0;
106 }
107
108 int main (int argc, char *argv[])
109 {
110    int ch;
111    char *restore_list=NULL;
112    setlocale(LC_ALL, "");
113    bindtextdomain("bacula", LOCALEDIR);
114    textdomain("bacula");
115    init_stack_dump();
116    lmgr_init_thread();
117    
118    char **files = (char **) malloc (10 * sizeof(char *));
119    int i;
120    my_name_is(argc, argv, "bbatch");
121    init_msg(NULL, NULL);
122
123    OSDependentInit();
124
125    while ((ch = getopt(argc, argv, "h:c:d:n:P:Su:vf:w:r:?")) != -1) {
126       switch (ch) {
127       case 'r':
128          restore_list=bstrdup(optarg);
129          break;
130
131       case 'd':                    /* debug level */
132          if (*optarg == 't') {
133             dbg_timestamp = true;
134          } else {
135             debug_level = atoi(optarg);
136             if (debug_level <= 0) {
137                debug_level = 1;
138             }
139          }
140          break;
141
142       case 'h':
143          db_host = optarg;
144          break;
145
146       case 'n':
147          db_name = optarg;
148          break;
149
150       case 'w':
151          working_directory = optarg;
152          break;
153
154       case 'u':
155          db_user = optarg;
156          break;
157
158       case 'P':
159          db_password = optarg;
160          break;
161
162       case 'v':
163          verbose++;
164          break;
165
166       case 'f':
167          if (nb < 10 ) {
168             files[nb++] = optarg;
169          }
170          break;
171
172       case '?':
173       default:
174          usage();
175
176       }
177    }
178    argc -= optind;
179    argv += optind;
180
181    if (argc != 0) {
182       Pmsg0(0, _("Wrong number of arguments: \n"));
183       usage();
184    }
185
186    if (restore_list) {
187       uint64_t nb_file=0;
188       btime_t start, end;
189       /* To use the -r option, the catalog should already contains records */
190       
191       if ((db = db_init_database(NULL, NULL, db_name, db_user, db_password,
192                                  db_host, 0, NULL, false, false)) == NULL) {
193          Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n"));
194       }
195       if (!db_open_database(NULL, db)) {
196          Emsg0(M_ERROR_TERM, 0, db_strerror(db));
197       }
198
199       start = get_current_btime();
200       db_get_file_list(NULL, db, restore_list, false, false, list_handler, &nb_file);
201       end = get_current_btime();
202
203       Pmsg3(0, _("Computing file list for jobid=%s files=%lld secs=%d\n"), 
204             restore_list, nb_file, (uint32_t)btime_to_unix(end-start));
205       
206       free(restore_list);
207       return 0;
208    }
209
210 #ifdef HAVE_BATCH_FILE_INSERT
211    printf("With new Batch mode\n");
212 #else
213    printf("Without new Batch mode\n");
214 #endif
215    i = nb;
216    while (--i >= 0) {
217       pthread_t thid;
218       JCR *bjcr = new_jcr(sizeof(JCR), NULL);
219       bjcr->bsr = NULL;
220       bjcr->VolSessionId = 1;
221       bjcr->VolSessionTime = (uint32_t)time(NULL);
222       bjcr->NumReadVolumes = 0;
223       bjcr->NumWriteVolumes = 0;
224       bjcr->JobId = getpid();
225       bjcr->set_JobType(JT_CONSOLE);
226       bjcr->set_JobLevel(L_FULL);
227       bjcr->JobStatus = JS_Running;
228       bjcr->where = bstrdup(files[i]);
229       bjcr->job_name = get_pool_memory(PM_FNAME);
230       pm_strcpy(bjcr->job_name, "Dummy.Job.Name");
231       bjcr->client_name = get_pool_memory(PM_FNAME);
232       pm_strcpy(bjcr->client_name, "Dummy.Client.Name");
233       bstrncpy(bjcr->Job, "bbatch", sizeof(bjcr->Job));
234       bjcr->fileset_name = get_pool_memory(PM_FNAME);
235       pm_strcpy(bjcr->fileset_name, "Dummy.fileset.name");
236       bjcr->fileset_md5 = get_pool_memory(PM_FNAME);
237       pm_strcpy(bjcr->fileset_md5, "Dummy.fileset.md5");
238       
239       if ((db = db_init_database(NULL, NULL, db_name, db_user, db_password,
240                                  db_host, 0, NULL, false, false)) == NULL) {
241          Emsg0(M_ERROR_TERM, 0, _("Could not init Bacula database\n"));
242       }
243       if (!db_open_database(NULL, db)) {
244          Emsg0(M_ERROR_TERM, 0, db_strerror(db));
245       }
246       Dmsg0(200, "Database opened\n");
247       if (verbose) {
248          Pmsg2(000, _("Using Database: %s, User: %s\n"), db_name, db_user);
249       }
250       
251       bjcr->db = db;
252
253       pthread_create(&thid, NULL, do_batch, bjcr);
254    }
255
256    while (nb > 0) {
257       bmicrosleep(1,0);
258    }
259
260    return 0;
261 }
262
263 static void fill_attr(ATTR_DBR *ar, char *data)
264 {
265    char *p;
266    char *b;
267    int index=0;
268    ar->Stream = STREAM_UNIX_ATTRIBUTES;
269    ar->JobId = getpid();
270
271    for(p = b = data; *p; p++) {
272       if (*p == ';') {
273          *p = '\0';
274          switch (index) {
275          case 0:
276             ar->FileIndex = str_to_int64(b);
277             break;
278          case 1:
279             ar->fname = b;
280             break;
281          case 2:
282             ar->attr = b;
283             break;
284          case 3:
285             ar->Digest = b;
286             break;
287          }
288          index++;
289          b = ++p;
290       }
291    }
292 }
293
294 static void *do_batch(void *jcr)
295 {
296    JCR *bjcr = (JCR *)jcr;
297    char data[1024];
298    int lineno = 0;
299    struct ATTR_DBR ar;
300    memset(&ar, 0, sizeof(ar));
301    btime_t begin = get_current_btime();
302    char *datafile = bjcr->where;
303
304    FILE *fd = fopen(datafile, "r");
305    if (!fd) {
306       Emsg1(M_ERROR_TERM, 0, _("Error opening datafile %s\n"), datafile);
307    }
308    while (fgets(data, sizeof(data)-1, fd)) {
309       strip_trailing_newline(data);
310       lineno++;
311       if (verbose && ((lineno % 5000) == 1)) {
312          printf("\r%i", lineno);
313       }
314       fill_attr(&ar, data);
315       if (!db_create_file_attributes_record(bjcr, bjcr->db, &ar)) {
316          Emsg0(M_ERROR_TERM, 0, _("Error while inserting file\n"));
317       }
318    }
319    fclose(fd);
320    db_write_batch_file_records(bjcr);
321    btime_t end = get_current_btime();
322    
323    P(mutex);
324    char ed1[200], ed2[200];
325    printf("\rbegin = %s, end = %s\n", edit_int64(begin, ed1),edit_int64(end, ed2));
326    printf("Insert time = %sms\n", edit_int64((end - begin) / 10000, ed1));
327    printf("Create %u files at %.2f/s\n", lineno, 
328           (lineno / ((float)((end - begin) / 1000000))));
329    nb--;
330    V(mutex);
331    pthread_exit(NULL);
332    return NULL;
333 }