]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/bdb.c
ebl Add ClientId in db_create_job_record
[bacula/bacula] / bacula / src / cats / bdb.c
1 /*
2  * Bacula Catalog Database routines written specifically
3  *  for Bacula.  Note, these routines are VERY dumb and
4  *  do not provide all the functionality of an SQL database.
5  *  The purpose of these routines is to ensure that Bacula
6  *  can limp along if no real database is loaded on the
7  *  system.
8  *
9  *    Kern Sibbald, January MMI
10  *
11  *    Version $Id$
12  *
13  */
14 /*
15    Bacula® - The Network Backup Solution
16
17    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
18
19    The main author of Bacula is Kern Sibbald, with contributions from
20    many others, a complete list can be found in the file AUTHORS.
21    This program is Free Software; you can redistribute it and/or
22    modify it under the terms of version two of the GNU General Public
23    License as published by the Free Software Foundation plus additions
24    that are listed in the file LICENSE.
25
26    This program is distributed in the hope that it will be useful, but
27    WITHOUT ANY WARRANTY; without even the implied warranty of
28    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
29    General Public License for more details.
30
31    You should have received a copy of the GNU General Public License
32    along with this program; if not, write to the Free Software
33    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34    02110-1301, USA.
35
36    Bacula® is a registered trademark of John Walker.
37    The licensor of Bacula is the Free Software Foundation Europe
38    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
39    Switzerland, email:ftf@fsfeurope.org.
40 */
41
42
43 /* The following is necessary so that we do not include
44  * the dummy external definition of DB.
45  */
46 #define __SQL_C                       /* indicate that this is sql.c */
47
48 #include "bacula.h"
49 #include "cats.h"
50
51 #ifdef HAVE_BACULA_DB
52
53 uint32_t bacula_db_version = 0;
54
55 /* List of open databases */
56 static BQUEUE db_list = {&db_list, &db_list};
57 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
58
59 /* -----------------------------------------------------------------------
60  *
61  *   Bacula specific defines and subroutines
62  *
63  * -----------------------------------------------------------------------
64  */
65
66
67 #define DB_CONTROL_FILENAME  "control.db"
68 #define DB_JOBS_FILENAME     "jobs.db"
69 #define DB_POOLS_FILENAME    "pools.db"
70 #define DB_MEDIA_FILENAME    "media.db"
71 #define DB_JOBMEDIA_FILENAME "jobmedia.db"
72 #define DB_CLIENT_FILENAME   "client.db"
73 #define DB_FILESET_FILENAME  "fileset.db"
74
75 static POOLMEM *make_filename(B_DB *mdb, char *name)
76 {
77    char sep;
78    POOLMEM *dbf;
79
80    dbf = get_pool_memory(PM_FNAME);
81    if (IsPathSeparator(working_directory[strlen(working_directory)-1])) {
82       sep = 0;
83    } else {
84       sep = '/';
85    }
86    Mmsg(dbf, "%s%c%s-%s", working_directory, sep, mdb->db_name, name);
87    return dbf;
88 }
89
90 int bdb_write_control_file(B_DB *mdb)
91 {
92    mdb->control.time = time(NULL);
93    lseek(mdb->cfd, 0, SEEK_SET);
94    if (write(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
95       Mmsg1(&mdb->errmsg, "Error writing control file. ERR=%s\n", strerror(errno));
96       Emsg0(M_FATAL, 0, mdb->errmsg);
97       return 0;
98    }
99    return 1;
100 }
101
102 /*
103  * Retrieve database type
104  */
105 const char *
106 db_get_type(void)
107 {
108    return "Internal";
109 }
110
111 /*
112  * Initialize database data structure. In principal this should
113  * never have errors, or it is really fatal.
114  */
115 B_DB *
116 db_init_database(JCR *jcr, char const *db_name, char const *db_user, char const *db_password,
117                  char const *db_address, int db_port, char const *db_socket,
118                  int mult_db_connections)
119 {
120    B_DB *mdb;
121    P(mutex);                          /* lock DB queue */
122    /* Look to see if DB already open */
123    for (mdb=NULL; (mdb=(B_DB *)qnext(&db_list, &mdb->bq)); ) {
124       if (strcmp(mdb->db_name, db_name) == 0) {
125          Dmsg2(200, "DB REopen %d %s\n", mdb->ref_count, db_name);
126          mdb->ref_count++;
127          V(mutex);
128          return mdb;                  /* already open */
129       }
130    }
131
132    Dmsg0(200, "db_open first time\n");
133    mdb = (B_DB *)malloc(sizeof(B_DB));
134    memset(mdb, 0, sizeof(B_DB));
135    Dmsg0(200, "DB struct init\n");
136    mdb->db_name = bstrdup(db_name);
137    mdb->errmsg = get_pool_memory(PM_EMSG);
138    *mdb->errmsg = 0;
139    mdb->cmd = get_pool_memory(PM_EMSG);  /* command buffer */
140    mdb->ref_count = 1;
141    mdb->cached_path = get_pool_memory(PM_FNAME);
142    mdb->cached_path_id = 0;
143    qinsert(&db_list, &mdb->bq);       /* put db in list */
144    Dmsg0(200, "Done db_open_database()\n");
145    mdb->cfd = -1;
146    V(mutex);
147    Jmsg(jcr, M_WARNING, 0, _("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"));
148    Jmsg(jcr, M_WARNING, 0, _("WARNING!!!! The Internal Database is NOT OPERATIONAL!\n"));
149    Jmsg(jcr, M_WARNING, 0, _("You should use SQLite, PostgreSQL, or MySQL\n"));
150
151    return mdb;
152 }
153
154 /*
155  * Now actually open the database.  This can generate errors,
156  * which are returned in the errmsg
157  */
158 int
159 db_open_database(JCR *jcr, B_DB *mdb)
160 {
161    char *dbf;
162    int fd, badctl;
163    off_t filend;
164    int errstat;
165
166    Dmsg1(200, "db_open_database() %s\n", mdb->db_name);
167
168    P(mutex);
169
170    if ((errstat=rwl_init(&mdb->lock)) != 0) {
171       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"), strerror(errstat));
172       V(mutex);
173       return 0;
174    }
175
176    Dmsg0(200, "make_filename\n");
177    dbf = make_filename(mdb, DB_CONTROL_FILENAME);
178    mdb->cfd = open(dbf, O_CREAT|O_RDWR, 0600);
179    free_memory(dbf);
180    if (mdb->cfd < 0) {
181       Mmsg2(&mdb->errmsg, _("Unable to open Catalog DB control file %s: ERR=%s\n"),
182          dbf, strerror(errno));
183       V(mutex);
184       return 0;
185    }
186    Dmsg0(200, "DB open\n");
187    /* See if the file was previously written */
188    filend = lseek(mdb->cfd, 0, SEEK_END);
189    if (filend == 0) {                 /* No, initialize everything */
190       Dmsg0(200, "Init DB files\n");
191       memset(&mdb->control, 0, sizeof(mdb->control));
192       mdb->control.bdb_version = BDB_VERSION;
193       bdb_write_control_file(mdb);
194
195       /* Create Jobs File */
196       dbf = make_filename(mdb, DB_JOBS_FILENAME);
197       fd = open(dbf, O_CREAT|O_RDWR, 0600);
198       free_memory(dbf);
199       close(fd);
200
201       /* Create Pools File */
202       dbf = make_filename(mdb, DB_POOLS_FILENAME);
203       fd = open(dbf, O_CREAT|O_RDWR, 0600);
204       free_memory(dbf);
205       close(fd);
206
207       /* Create Media File */
208       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
209       fd = open(dbf, O_CREAT|O_RDWR, 0600);
210       free_memory(dbf);
211       close(fd);
212
213       /* Create JobMedia File */
214       dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
215       fd = open(dbf, O_CREAT|O_RDWR, 0600);
216       free_memory(dbf);
217       close(fd);
218
219       /* Create Client File */
220       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
221       fd = open(dbf, O_CREAT|O_RDWR, 0600);
222       free_memory(dbf);
223       close(fd);
224
225       /* Create FileSet File */
226       dbf = make_filename(mdb, DB_FILESET_FILENAME);
227       fd = open(dbf, O_CREAT|O_RDWR, 0600);
228       free_memory(dbf);
229       close(fd);
230    }
231
232    Dmsg0(200, "Read control file\n");
233    badctl = 0;
234    lseek(mdb->cfd, 0, SEEK_SET);      /* seek to begining of control file */
235    if (read(mdb->cfd, &mdb->control, sizeof(mdb->control)) != sizeof(mdb->control)) {
236       Mmsg1(&mdb->errmsg, _("Error reading catalog DB control file. ERR=%s\n"), strerror(errno));
237       badctl = 1;
238    } else if (mdb->control.bdb_version != BDB_VERSION) {
239       Mmsg2(&mdb->errmsg, _("Error, catalog DB control file wrong version. "
240 "Wanted %d, got %d\n"
241 "Please reinitialize the working directory.\n"),
242          BDB_VERSION, mdb->control.bdb_version);
243       badctl = 1;
244    }
245    bacula_db_version = mdb->control.bdb_version;
246    if (badctl) {
247       V(mutex);
248       return 0;
249    }
250    V(mutex);
251    return 1;
252 }
253
254 void db_close_database(JCR *jcr, B_DB *mdb)
255 {
256    P(mutex);
257    mdb->ref_count--;
258    if (mdb->ref_count == 0) {
259       qdchain(&mdb->bq);
260       /*  close file descriptors */
261       if (mdb->cfd >= 0) {
262          close(mdb->cfd);
263       }
264       free(mdb->db_name);
265       if (mdb->jobfd) {
266          fclose(mdb->jobfd);
267       }
268       if (mdb->poolfd) {
269          fclose(mdb->poolfd);
270       }
271       if (mdb->mediafd) {
272          fclose(mdb->mediafd);
273       }
274       if (mdb->jobmediafd) {
275          fclose(mdb->jobmediafd);
276       }
277       if (mdb->clientfd) {
278          fclose(mdb->clientfd);
279       }
280       if (mdb->filesetfd) {
281          fclose(mdb->filesetfd);
282       }
283       rwl_destroy(&mdb->lock);
284       free_pool_memory(mdb->errmsg);
285       free_pool_memory(mdb->cmd);
286       free_pool_memory(mdb->cached_path);
287       free(mdb);
288    }
289    V(mutex);
290 }
291
292
293 void db_escape_string(char *snew, char *old, int len)
294 {
295    memset(snew, 0, len);
296    bstrncpy(snew, old, len);
297 }
298
299 char *db_strerror(B_DB *mdb)
300 {
301    return mdb->errmsg;
302 }
303
304 int db_sql_query(B_DB *mdb, char const *query, DB_RESULT_HANDLER *result_handler, void *ctx)
305 {
306    return 1;
307 }
308
309 /*
310  * Open the Jobs file for reading/writing
311  */
312 int bdb_open_jobs_file(B_DB *mdb)
313 {
314    char *dbf;
315
316    if (!mdb->jobfd) {
317       dbf = make_filename(mdb, DB_JOBS_FILENAME);
318       mdb->jobfd = fopen(dbf, "r+b");
319       if (!mdb->jobfd) {
320          Mmsg2(&mdb->errmsg, "Error opening DB Jobs file %s: ERR=%s\n",
321             dbf, strerror(errno));
322          Emsg0(M_FATAL, 0, mdb->errmsg);
323          free_memory(dbf);
324          return 0;
325       }
326       free_memory(dbf);
327    }
328    return 1;
329 }
330
331 /*
332  * Open the JobMedia file for reading/writing
333  */
334 int bdb_open_jobmedia_file(B_DB *mdb)
335 {
336    char *dbf;
337
338    if (!mdb->jobmediafd) {
339       dbf = make_filename(mdb, DB_JOBMEDIA_FILENAME);
340       mdb->jobmediafd = fopen(dbf, "r+b");
341       if (!mdb->jobmediafd) {
342          Mmsg2(&mdb->errmsg, "Error opening DB JobMedia file %s: ERR=%s\n",
343             dbf, strerror(errno));
344          Emsg0(M_FATAL, 0, mdb->errmsg);
345          free_memory(dbf);
346          return 0;
347       }
348       free_memory(dbf);
349    }
350    return 1;
351 }
352
353
354 /*
355  * Open the Pools file for reading/writing
356  */
357 int bdb_open_pools_file(B_DB *mdb)
358 {
359    char *dbf;
360
361    if (!mdb->poolfd) {
362       dbf = make_filename(mdb, DB_POOLS_FILENAME);
363       mdb->poolfd = fopen(dbf, "r+b");
364       if (!mdb->poolfd) {
365          Mmsg2(&mdb->errmsg, "Error opening DB Pools file %s: ERR=%s\n",
366             dbf, strerror(errno));
367          Emsg0(M_FATAL, 0, mdb->errmsg);
368          free_memory(dbf);
369          return 0;
370       }
371       Dmsg1(200, "Opened pool file %s\n", dbf);
372       free_memory(dbf);
373    }
374    return 1;
375 }
376
377 /*
378  * Open the Client file for reading/writing
379  */
380 int bdb_open_client_file(B_DB *mdb)
381 {
382    char *dbf;
383
384    if (!mdb->clientfd) {
385       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
386       mdb->clientfd = fopen(dbf, "r+b");
387       if (!mdb->clientfd) {
388          Mmsg2(&mdb->errmsg, "Error opening DB Clients file %s: ERR=%s\n",
389             dbf, strerror(errno));
390          Emsg0(M_FATAL, 0, mdb->errmsg);
391          free_memory(dbf);
392          return 0;
393       }
394       free_memory(dbf);
395    }
396    return 1;
397 }
398
399 /*
400  * Open the FileSet file for reading/writing
401  */
402 int bdb_open_fileset_file(B_DB *mdb)
403 {
404    char *dbf;
405
406    if (!mdb->filesetfd) {
407       dbf = make_filename(mdb, DB_CLIENT_FILENAME);
408       mdb->filesetfd = fopen(dbf, "r+b");
409       if (!mdb->filesetfd) {
410          Mmsg2(&mdb->errmsg, "Error opening DB FileSet file %s: ERR=%s\n",
411             dbf, strerror(errno));
412          Emsg0(M_FATAL, 0, mdb->errmsg);
413          free_memory(dbf);
414          return 0;
415       }
416       free_memory(dbf);
417    }
418    return 1;
419 }
420
421
422
423 /*
424  * Open the Media file for reading/writing
425  */
426 int bdb_open_media_file(B_DB *mdb)
427 {
428    char *dbf;
429
430    if (!mdb->mediafd) {
431       dbf = make_filename(mdb, DB_MEDIA_FILENAME);
432       mdb->mediafd = fopen(dbf, "r+b");
433       if (!mdb->mediafd) {
434          Mmsg2(&mdb->errmsg, "Error opening DB Media file %s: ERR=%s\n",
435             dbf, strerror(errno));
436          free_memory(dbf);
437          return 0;
438       }
439       free_memory(dbf);
440    }
441    return 1;
442 }
443
444
445 void _db_lock(const char *file, int line, B_DB *mdb)
446 {
447    int errstat;
448    if ((errstat=rwl_writelock(&mdb->lock)) != 0) {
449       e_msg(file, line, M_ABORT, 0, "rwl_writelock failure. ERR=%s\n",
450            strerror(errstat));
451    }
452 }
453
454 void _db_unlock(const char *file, int line, B_DB *mdb)
455 {
456    int errstat;
457    if ((errstat=rwl_writeunlock(&mdb->lock)) != 0) {
458       e_msg(file, line, M_ABORT, 0, "rwl_writeunlock failure. ERR=%s\n",
459            strerror(errstat));
460    }
461 }
462
463 /*
464  * Start a transaction. This groups inserts and makes things
465  *  much more efficient. Usually started when inserting
466  *  file attributes.
467  */
468 void db_start_transaction(JCR *jcr, B_DB *mdb)
469 {
470 }
471
472 void db_end_transaction(JCR *jcr, B_DB *mdb)
473 {
474 }
475
476 bool db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
477 { return true; }
478
479 void
480 db_list_pool_records(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr, 
481                      DB_LIST_HANDLER *sendit, void *ctx, e_list_type type)
482 { }
483
484 int db_int64_handler(void *ctx, int num_fields, char **row)
485 { return 0; }
486
487
488 #endif /* HAVE_BACULA_DB */