]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/cats.h
acd88ff22e38c965d2c6864aefbaddd1545a4a56
[bacula/bacula] / bacula / src / cats / cats.h
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Catalog DB header file
21  *
22  *  Written by Kern E. Sibbald
23  *
24  *  Anyone who accesses the database will need to include
25  *   this file.
26  */
27
28 #ifndef __CATS_H_
29 #define __CATS_H_ 1
30
31 /*
32    Here is how database versions work.
33
34    While I am working on a new release with database changes, the
35    update scripts are in the src/cats directory under the names
36    update_xxx_tables.in.  Most of the time, I make database updates
37    in one go and immediately update the version, but not always.  If
38    there are going to be several updates as is the case with version
39    1.37, then I will often forgo changing the version until the last
40    update otherwise I will end up with too many versions and a lot
41    of confusion.
42
43    When I am pretty sure there will be no more updates, I will
44    change the version from 8 to 9 (in the present case), and when I
45    am 100% sure there will be no more changes, the update script
46    will be copied to the updatedb directory with the correct name
47    (in the present case 8 to 9).
48  */
49
50 /* Current database version number for all drivers */
51 #define BDB_VERSION 16
52
53 typedef void (DB_LIST_HANDLER)(void *, const char *);
54 typedef int (DB_RESULT_HANDLER)(void *, int, char **);
55
56 /* What kind of database we have */
57 typedef enum {
58    SQL_TYPE_MYSQL      = 0,
59    SQL_TYPE_POSTGRESQL = 1,
60    SQL_TYPE_SQLITE3    = 2,
61    SQL_TYPE_UNKNOWN    = 99
62 } SQL_DBTYPE;
63
64 /* What kind of driver we have */
65 typedef enum {
66    SQL_DRIVER_TYPE_MYSQL      = 0,
67    SQL_DRIVER_TYPE_POSTGRESQL = 1,
68    SQL_DRIVER_TYPE_SQLITE3    = 2
69 } SQL_DRIVER;
70
71
72 /* ==============================================================
73  *
74  *  What follows are definitions that are used "globally" for all
75  *   the different SQL engines and both inside and external to the
76  *   cats directory.
77  */
78
79 #define faddr_t long
80
81 /*
82  * Generic definition of a sql_row.
83  */
84 typedef char **SQL_ROW;
85
86 /*
87  * Generic definition of a a sql_field.
88  */
89 typedef struct sql_field {
90    char *name;                        /* name of column */
91    int max_length;                    /* max length */
92    uint32_t type;                     /* type */
93    uint32_t flags;                    /* flags */
94 } SQL_FIELD;
95
96
97 /*
98  * Structure used when calling db_get_query_ids()
99  *  allows the subroutine to return a list of ids.
100  */
101 class dbid_list : public SMARTALLOC {
102 public:
103    DBId_t *DBId;                      /* array of DBIds */
104    char *PurgedFiles;                 /* Array of PurgedFile flags */
105    int num_ids;                       /* num of ids actually stored */
106    int max_ids;                       /* size of id array */
107    int num_seen;                      /* number of ids processed */
108    int tot_ids;                       /* total to process */
109
110    dbid_list();                       /* in sql.c */
111    ~dbid_list();                      /* in sql.c */
112 };
113
114 /* Job information passed to create job record and update
115  * job record at end of job. Note, although this record
116  * contains all the fields found in the Job database record,
117  * it also contains fields found in the JobMedia record.
118  */
119 /* Job record */
120 struct JOB_DBR {
121    JobId_t JobId;
122    char Job[MAX_NAME_LENGTH];         /* Job unique name */
123    char Name[MAX_NAME_LENGTH];        /* Job base name */
124    int JobType;                       /* actually char(1) */
125    int JobLevel;                      /* actually char(1) */
126    int JobStatus;                     /* actually char(1) */
127    DBId_t ClientId;                   /* Id of client */
128    DBId_t PoolId;                     /* Id of pool */
129    DBId_t FileSetId;                  /* Id of FileSet */
130    DBId_t PriorJobId;                 /* Id of migrated (prior) job */
131    time_t SchedTime;                  /* Time job scheduled */
132    time_t StartTime;                  /* Job start time */
133    time_t EndTime;                    /* Job termination time of orig job */
134    time_t RealEndTime;                /* Job termination time of this job */
135    utime_t JobTDate;                  /* Backup time/date in seconds */
136    uint32_t VolSessionId;
137    uint32_t VolSessionTime;
138    uint32_t JobFiles;
139    uint32_t JobErrors;
140    uint32_t JobMissingFiles;
141    uint64_t JobBytes;
142    uint64_t ReadBytes;
143    int PurgedFiles;
144    int HasBase;
145
146    /* Note, FirstIndex, LastIndex, Start/End File and Block
147     * are only used in the JobMedia record.
148     */
149    uint32_t FirstIndex;               /* First index this Volume */
150    uint32_t LastIndex;                /* Last index this Volume */
151    uint32_t StartFile;
152    uint32_t EndFile;
153    uint32_t StartBlock;
154    uint32_t EndBlock;
155
156    char cSchedTime[MAX_TIME_LENGTH];
157    char cStartTime[MAX_TIME_LENGTH];
158    char cEndTime[MAX_TIME_LENGTH];
159    char cRealEndTime[MAX_TIME_LENGTH];
160    /* Extra stuff not in DB */
161    int     order;                     /* 0 ASC, 1 DESC */
162    int     limit;                     /* limit records to display */
163    faddr_t rec_addr;
164    uint32_t FileIndex;                /* added during Verify */
165
166    int     CorrNbJob;                 /* used by dbd_get_job_statistics() */
167    int     CorrJobBytes;              /* used by dbd_get_job_statistics() */
168    int     CorrJobFiles;              /* used by dbd_get_job_statistics() */
169 };
170
171 /* Job Media information used to create the media records
172  * for each Volume used for the job.
173  */
174 /* JobMedia record */
175 struct JOBMEDIA_DBR {
176    DBId_t JobMediaId;                 /* record id */
177    JobId_t  JobId;                    /* JobId */
178    DBId_t MediaId;                    /* MediaId */
179    uint32_t FirstIndex;               /* First index this Volume */
180    uint32_t LastIndex;                /* Last index this Volume */
181    uint32_t StartFile;                /* File for start of data */
182    uint32_t EndFile;                  /* End file on Volume */
183    uint32_t StartBlock;               /* start block on tape */
184    uint32_t EndBlock;                 /* last block */
185 };
186
187
188 /* Volume Parameter structure */
189 struct VOL_PARAMS {
190    char VolumeName[MAX_NAME_LENGTH];  /* Volume name */
191    char MediaType[MAX_NAME_LENGTH];   /* Media Type */
192    char Storage[MAX_NAME_LENGTH];     /* Storage name */
193    uint32_t VolIndex;                 /* Volume seqence no. */
194    uint32_t FirstIndex;               /* First index this Volume */
195    uint32_t LastIndex;                /* Last index this Volume */
196    int32_t Slot;                      /* Slot */
197    uint64_t StartAddr;                /* Start address */
198    uint64_t EndAddr;                  /* End address */
199    int32_t InChanger;                 /* InChanger flag */
200 };
201
202
203 /* Attributes record -- NOT same as in database because
204  *  in general, this "record" creates multiple database
205  *  records (e.g. pathname, filename, fileattributes).
206  */
207 struct ATTR_DBR {
208    char *fname;                       /* full path & filename */
209    char *link;                        /* link if any */
210    char *attr;                        /* attributes statp */
211    uint32_t FileIndex;
212    uint32_t Stream;
213    uint32_t FileType;
214    uint32_t DeltaSeq;
215    JobId_t  JobId;
216    DBId_t ClientId;
217    DBId_t PathId;
218    DBId_t FilenameId;
219    FileId_t FileId;
220    char *Digest;
221    int DigestType;
222 };
223
224 struct ROBJECT_DBR {
225    char *object_name;
226    char *object;
227    char *plugin_name;
228    char *JobIds;
229    uint32_t object_len;
230    uint32_t object_full_len;
231    uint32_t object_index;
232    int32_t  object_compression;
233    uint32_t FileIndex;
234    uint32_t Stream;
235    uint32_t FileType;
236    JobId_t  JobId;
237    DBId_t RestoreObjectId;
238 };
239
240
241 /* File record -- same format as database */
242 struct FILE_DBR {
243    FileId_t FileId;
244    uint32_t FileIndex;
245    JobId_t  JobId;
246    DBId_t FilenameId;
247    DBId_t PathId;
248    JobId_t  MarkId;
249    uint32_t DeltaSeq;
250    char LStat[256];
251    char Digest[BASE64_SIZE(CRYPTO_DIGEST_MAX_SIZE)];
252    int DigestType;                    /* NO_SIG/MD5_SIG/SHA1_SIG */
253 };
254
255 /* Pool record -- same format as database */
256 struct POOL_DBR {
257    DBId_t PoolId;
258    char Name[MAX_NAME_LENGTH];        /* Pool name */
259    uint32_t NumVols;                  /* total number of volumes */
260    uint32_t MaxVols;                  /* max allowed volumes */
261    int32_t LabelType;                 /* Bacula/ANSI/IBM */
262    int32_t UseOnce;                   /* set to use once only */
263    int32_t UseCatalog;                /* set to use catalog */
264    int32_t AcceptAnyVolume;           /* set to accept any volume sequence */
265    int32_t AutoPrune;                 /* set to prune automatically */
266    int32_t Recycle;                   /* default Vol recycle flag */
267    uint32_t ActionOnPurge;            /* action on purge, e.g. truncate the disk volume */
268    utime_t  VolRetention;             /* retention period in seconds */
269    utime_t  CacheRetention;           /* cache retention period in seconds */   
270    utime_t  VolUseDuration;           /* time in secs volume can be used */
271    uint32_t MaxVolJobs;               /* Max Jobs on Volume */
272    uint32_t MaxVolFiles;              /* Max files on Volume */
273    uint64_t MaxVolBytes;              /* Max bytes on Volume */
274    DBId_t RecyclePoolId;              /* RecyclePool destination when media is purged */
275    DBId_t ScratchPoolId;              /* ScratchPool source when media is needed */
276    char PoolType[MAX_NAME_LENGTH];
277    char LabelFormat[MAX_NAME_LENGTH];
278    /* Extra stuff not in DB */
279    faddr_t rec_addr;
280 };
281
282 class DEVICE_DBR {
283 public:
284    DBId_t DeviceId;
285    char Name[MAX_NAME_LENGTH];        /* Device name */
286    DBId_t MediaTypeId;                /* MediaType */
287    DBId_t StorageId;                  /* Storage id if autochanger */
288    uint32_t DevMounts;                /* Number of times mounted */
289    uint32_t DevErrors;                /* Number of read/write errors */
290    uint64_t DevReadBytes;             /* Number of bytes read */
291    uint64_t DevWriteBytes;            /* Number of bytew written */
292    uint64_t DevReadTime;              /* time spent reading volume */
293    uint64_t DevWriteTime;             /* time spent writing volume */
294    uint64_t DevReadTimeSincCleaning;  /* read time since cleaning */
295    uint64_t DevWriteTimeSincCleaning; /* write time since cleaning */
296    time_t   CleaningDate;             /* time last cleaned */
297    utime_t  CleaningPeriod;           /* time between cleanings */
298 };
299
300 class STORAGE_DBR {
301 public:
302    DBId_t StorageId;
303    char Name[MAX_NAME_LENGTH];        /* Device name */
304    int AutoChanger;                   /* Set if autochanger */
305
306    /* Not in database */
307    bool created;                      /* set if created by db_create ... */
308 };
309
310 class MEDIATYPE_DBR {
311 public:
312    DBId_t MediaTypeId;
313    char MediaType[MAX_NAME_LENGTH];   /* MediaType string */
314    int ReadOnly;                      /* Set if read-only */
315 };
316
317 /* Media record -- same as the database */
318 class MEDIA_DBR {
319 public:
320    MEDIA_DBR() { memset(this, 0, sizeof(MEDIA_DBR)); };
321    ~MEDIA_DBR() {  };
322    void clear() { memset(this, 0, sizeof(MEDIA_DBR)); };
323    void copy(MEDIA_DBR *omr) { memcpy(this, omr, sizeof(MEDIA_DBR)); sid_group = NULL; };
324
325    DBId_t MediaId;                    /* Unique volume id */
326    char VolumeName[MAX_NAME_LENGTH];  /* Volume name */
327    char MediaType[MAX_NAME_LENGTH];   /* Media type */
328    DBId_t PoolId;                     /* Pool id */
329    time_t   FirstWritten;             /* Time Volume first written this usage */
330    time_t   LastWritten;              /* Time Volume last written */
331    time_t   LabelDate;                /* Date/Time Volume labeled */
332    time_t   InitialWrite;             /* Date/Time Volume first written */
333    int32_t  LabelType;                /* Label (Bacula/ANSI/IBM) */
334    uint32_t VolJobs;                  /* number of jobs on this medium */
335    uint32_t VolFiles;                 /* Number of files */
336    uint32_t VolBlocks;                /* Number of blocks */
337    uint32_t VolParts;                 /* Number of cache parts */
338    uint32_t VolCloudParts;            /* Number of cloud parts */
339    uint32_t VolMounts;                /* Number of times mounted */
340    uint32_t VolErrors;                /* Number of read/write errors */
341    uint64_t VolWrites;                /* Number of writes */
342    uint64_t VolReads;                 /* Number of reads */
343    uint64_t VolBytes;                 /* Number of bytes written */
344    uint64_t VolABytes;                /* Size of aligned volume */
345    uint64_t VolHoleBytes;             /* The size of Holes */
346    uint32_t VolHoles;                 /* Number of holes */
347    uint32_t VolType;                  /* Device type of where Volume labeled */
348    uint64_t MaxVolBytes;              /* Max bytes to write to Volume */
349    uint64_t VolCapacityBytes;         /* capacity estimate */
350    uint64_t LastPartBytes;            /* Bytes in last part */
351    uint64_t VolReadTime;              /* time spent reading volume */
352    uint64_t VolWriteTime;             /* time spent writing volume */
353    utime_t  VolRetention;             /* Volume retention in seconds */
354    utime_t  CacheRetention;           /* Cache retention period in second */
355    utime_t  VolUseDuration;           /* time in secs volume can be used */
356    uint32_t ActionOnPurge;            /* action on purge, e.g. truncate the disk volume */
357    uint32_t MaxVolJobs;               /* Max Jobs on Volume */
358    uint32_t MaxVolFiles;              /* Max files on Volume */
359    int32_t  Recycle;                  /* recycle yes/no */
360    int32_t  Slot;                     /* slot in changer */
361    int32_t  Enabled;                  /* 0=disabled, 1=enabled, 2=archived */
362    int32_t  InChanger;                /* Volume currently in changer */
363    DBId_t   StorageId;                /* Storage record Id */
364    uint32_t EndFile;                  /* Last file on volume */
365    uint32_t EndBlock;                 /* Last block on volume */
366    uint32_t RecycleCount;             /* Number of times recycled */
367    char     VolStatus[20];            /* Volume status */
368    DBId_t   DeviceId;                 /* Device where Vol last written */
369    DBId_t   LocationId;               /* Where Volume is -- user defined */
370    DBId_t   ScratchPoolId;            /* Where to move if scratch */
371    DBId_t   RecyclePoolId;            /* Where to move when recycled */
372    /* Extra stuff not in DB */
373    faddr_t rec_addr;                  /* found record address */
374    /* Since the database returns times as strings, this is how we pass
375     *   them back.
376     */
377    char    cFirstWritten[MAX_TIME_LENGTH]; /* FirstWritten returned from DB */
378    char    cLastWritten[MAX_TIME_LENGTH];  /* LastWritten returned from DB */
379    char    cLabelDate[MAX_TIME_LENGTH];    /* LabelData returned from DB */
380    char    cInitialWrite[MAX_TIME_LENGTH]; /* InitialWrite returned from DB */
381    char   *exclude_list;                   /* Optionnal exclude list for db_find_next_volume() */
382    char   *sid_group;                 /* Storageid group string */
383    char    sid[30];                   /* edited StorageId */
384    bool    set_first_written;
385    bool    set_label_date;
386 };
387
388 /* Client record -- same as the database */
389 struct CLIENT_DBR {
390    DBId_t ClientId;                   /* Unique Client id */
391    int AutoPrune;
392    utime_t FileRetention;
393    utime_t JobRetention;
394    char Name[MAX_NAME_LENGTH];        /* Client name */
395    char Uname[256];                   /* Uname for client */
396 };
397
398 /* Counter record as in database */
399 struct COUNTER_DBR {
400    char Counter[MAX_NAME_LENGTH];
401    int32_t MinValue;
402    int32_t MaxValue;
403    int32_t CurrentValue;
404    char WrapCounter[MAX_NAME_LENGTH];
405 };
406
407
408 /* FileSet record -- same as the database */
409 struct FILESET_DBR {
410    DBId_t FileSetId;                  /* Unique FileSet id */
411    char FileSet[MAX_NAME_LENGTH];     /* FileSet name */
412    char MD5[50];                      /* MD5 signature of include/exclude */
413    time_t CreateTime;                 /* date created */
414    /*
415     * This is where we return CreateTime
416     */
417    char cCreateTime[MAX_TIME_LENGTH]; /* CreateTime as returned from DB */
418    /* Not in DB but returned by db_create_fileset() */
419    bool created;                      /* set when record newly created */
420 };
421
422 class SNAPSHOT_DBR {
423 public:
424    SNAPSHOT_DBR() {
425       memset(this, 0, sizeof(SNAPSHOT_DBR));
426    };
427    ~SNAPSHOT_DBR() {
428       reset();
429    };
430    void debug(int level) {
431       Dmsg8(DT_SNAPSHOT|level,
432             "Snapshot      %s:\n"
433             "  Volume:     %s\n"
434             "  Device:     %s\n"
435             "  Id:         %d\n"
436             "  FileSet:    %s\n"
437             "  CreateDate: %s\n"
438             "  Client:     %s\n"
439             "  Type:       %s\n",
440             Name, NPRT(Volume), NPRT(Device), SnapshotId,
441             FileSet, CreateDate, Client, Type);
442    };
443    char *as_arg(POOLMEM **out) {
444       bash_spaces(Name);
445       bash_spaces(Type);
446
447       if (Volume) {
448          bash_spaces(Volume);
449       }
450       if (Device) {
451          bash_spaces(Device);
452       }
453
454       Mmsg(out, "name=%s volume=%s device=%s tdate=%d type=%s",
455            Name, NPRTB(Volume), NPRTB(Device), CreateTDate, Type);
456
457       unbash_spaces(Name);
458       unbash_spaces(Type);
459       if (Volume) {
460          unbash_spaces(Volume);
461       }
462       if (Device) {
463          unbash_spaces(Device);
464       }
465       return *out;
466    };
467    void reset() {
468       if (need_to_free) {
469          if (Volume) {
470             free(Volume);
471          }
472          if (Device) {
473             free(Device);
474          }
475          if (errmsg) {
476             free(errmsg);
477          }
478          errmsg = Volume = Device = NULL;
479       }
480       need_to_free = false;
481    };
482    bool    need_to_free;             /* Need to free the internal memory */
483    /* Used when searching snapshots */
484    char    created_after[MAX_TIME_LENGTH];
485    char    created_before[MAX_TIME_LENGTH];
486    bool    expired;                 /* Look for CreateTDate > (NOW - Retention) */
487    bool    sorted_client;           /* Results sorted by Client, SnapshotId */
488    int     status;                  /* Status of the snapshot */
489
490    DBId_t  SnapshotId;              /* Unique Snapshot ID */
491    DBId_t  JobId;                   /* Related JobId */
492    DBId_t  FileSetId;               /* FileSetId if any */
493    DBId_t  ClientId;                /* From which client this snapshot comes */
494    char    Name[MAX_NAME_LENGTH];   /* Snapshot Name */
495    char    FileSet[MAX_NAME_LENGTH];/* FileSet name if any */
496    char    Client[MAX_NAME_LENGTH]; /* Client name */
497    char    Type[MAX_NAME_LENGTH];   /* zfs, btrfs, lvm, netapp, */
498    char    Comment[MAX_NAME_LENGTH];/* Comment */
499    char    CreateDate[MAX_TIME_LENGTH]; /* Create date as string */
500    time_t  CreateTDate;             /* Create TDate (in sec, since epoch) */
501    char   *Volume;                  /* Volume taken in snapshot */
502    char   *Device;                  /* Device, Pool, Directory, ...  */
503    char   *errmsg;                  /* Error associated with a snapshot */
504    utime_t Retention;               /* Number of second before pruning the snapshot */
505    uint64_t Size;                   /* Snapshot Size */
506 };
507
508 /* Call back context for getting a 32/64 bit value from the database */
509 class db_int64_ctx {
510 public:
511    int64_t value;                     /* value returned */
512    int count;                         /* number of values seen */
513
514    db_int64_ctx() : value(0), count(0) {};
515    ~db_int64_ctx() {};
516 private:
517    db_int64_ctx(const db_int64_ctx&);            /* prohibit pass by value */
518    db_int64_ctx &operator=(const db_int64_ctx&); /* prohibit class assignment */
519 };
520
521 /* Call back context for getting a list of comma separated strings from the
522  * database
523  */
524 class db_list_ctx {
525 public:
526    POOLMEM *list;                     /* list */
527    int count;                         /* number of values seen */
528
529    db_list_ctx() { list = get_pool_memory(PM_FNAME); reset(); }
530    ~db_list_ctx() { free_pool_memory(list); list = NULL; }
531    void reset() { *list = 0; count = 0;}
532    void add(const db_list_ctx &str) {
533       if (str.count > 0) {
534          if (*list) {
535             pm_strcat(list, ",");
536          }
537          pm_strcat(list, str.list);
538          count += str.count;
539       }
540    }
541    void add(const char *str) {
542       if (count > 0) {
543          pm_strcat(list, ",");
544       }
545       pm_strcat(list, str);
546       count++;
547    }
548 private:
549    db_list_ctx(const db_list_ctx&);            /* prohibit pass by value */
550    db_list_ctx &operator=(const db_list_ctx&); /* prohibit class assignment */
551 };
552
553 /* sql_query flags */
554 #define QF_STORE_RESULT 0x01
555  
556 /* sql_list.c */
557 enum e_list_type {
558    HORZ_LIST,                   /* list */
559    VERT_LIST,                   /* llist */
560    ARG_LIST,                    /* key1=v1 key2=v2 key3=v3 */
561    FAILED_JOBS,
562    INCOMPLETE_JOBS
563 };
564  
565 #include "bdb.h"
566 #include "protos.h"
567 #include "jcr.h"
568 #include "sql_cmds.h"
569
570
571 /* Object used in db_list_xxx function */
572 class LIST_CTX {
573 public:
574    char line[256];              /* Used to print last dash line */
575    int32_t num_rows;
576
577    e_list_type type;            /* Vertical/Horizontal */
578    DB_LIST_HANDLER *send;       /* send data back */
579    bool once;                   /* Used to print header one time */
580    void *ctx;                   /* send() user argument */
581    BDB *mdb;
582    JCR *jcr;
583
584    void empty() {
585       once = false;
586       line[0] = '\0';
587    }
588
589    void send_dashes() {
590       if (*line) {
591          send(ctx, line);
592       }
593    }
594
595    LIST_CTX(JCR *j, BDB *m, DB_LIST_HANDLER *h, void *c, e_list_type t) {
596       line[0] = '\0';
597       once = false;
598       num_rows = 0;
599       type = t;
600       send = h;
601       ctx = c;
602       jcr = j;
603       mdb = m;
604    }
605 };
606
607 /* Functions exported by sql.c for use within the cats directory. */
608 int list_result(void *vctx, int cols, char **row);
609 int list_result(JCR *jcr, BDB *mdb, DB_LIST_HANDLER *send, void *ctx, e_list_type type);
610 int get_sql_record_max(JCR *jcr, BDB *mdb);
611 void list_dashes(BDB *mdb, DB_LIST_HANDLER *send, void *ctx);
612
613 void print_dashes(BDB *mdb);
614 void print_result(BDB *mdb);
615 int QueryDB(const char *file, int line, JCR *jcr, BDB *db, char *select_cmd);
616 int InsertDB(const char *file, int line, JCR *jcr, BDB *db, char *select_cmd);
617 int DeleteDB(const char *file, int line, JCR *jcr, BDB *db, char *delete_cmd);
618 void split_path_and_file(JCR *jcr, BDB *mdb, const char *fname);
619
620 #endif  /* __CATS_H_ */