c9c99958a2859b4d1913da1803036278648b9c3c
[BackupPC.git] / dbxml / convert_pgsql_xmldb.pl
1 #!/usr/bin/perl -w
2
3 # Dumps database structure into XML to fill SleepyCat's XMLDB
4
5
6 use strict;
7 use warnings;
8 use Sleepycat::DbXml 'simple';
9 use DBI;
10 use XML::Simple;
11 use Data::Dumper;
12 use Term::ProgressBar;
13
14
15
16 my $xmldb_path = './dbxml';     # -h option for tools
17 my $xmldb_container = 'backuppc.dbxml';
18
19 my $connect = "DBI:Pg:dbname=backuppc";
20
21 my $commit_every = 100;
22
23 my $bar = Term::ProgressBar->new({
24         count => 100,
25 #       fh    => \*STDOUT,
26 #       name  => 'thingy',
27         ETA     => 'linear',
28 });
29
30 sub _debug {
31         $bar->message(join(" ",@_));
32         $bar->update();
33         return;
34 }
35
36 _debug("connecting to $connect\n");
37 my $dbh = DBI->connect($connect,"","") || die $DBI::errstr;
38 _debug("connected");
39
40 # open a container in the db environment
41 my $env = new DbEnv(0);
42 $env->set_cachesize(0, 64 * 1024, 1);
43
44 $env->open($xmldb_path,
45             Db::DB_INIT_MPOOL|Db::DB_CREATE|Db::DB_INIT_LOCK|Db::DB_INIT_LOG|Db::DB_INIT_TXN);
46 my $theMgr = new XmlManager($env);
47
48 my $containerTxn = $theMgr->createTransaction();
49 _debug("openContainer $xmldb_container\n");
50 my $container = $theMgr->openContainer($containerTxn, $xmldb_container);
51 _debug("commit");
52 $containerTxn->commit();
53
54 #  Get an XmlUpdateContext. Useful from a performance perspective.
55 my $updateContext = $theMgr->createUpdateContext();
56
57 # myDbEnv and myXmlContainer open with transactions. All subsequent
58 # writes to them must also be performed inside a transaction.
59
60 # Get a transaction
61 my $txn = $theMgr->createTransaction();
62
63 # Add the documents
64 my $myXMLDoc = $theMgr->createDocument();
65
66 my $sql = qq{
67 select
68         files.id as unique_id,
69         hosts.name as host,
70         shares.name as share,
71         backupnum as num,
72         backups.date as backup_date,
73         backups.type as type,
74         files.path as path,
75         files.date as date,
76         files.size as size,
77         backups.size as backup_size
78 from files
79 join shares on files.shareid = shares.id
80 join hosts on shares.hostid = hosts.id
81 join backups on shares.hostid = backups.hostid
82         and files.backupnum = backups.num
83         and shares.id = backups.shareid
84 order by backups.date
85 limit 1000
86 };
87
88 _debug("prepare");
89 my $sth = $dbh->prepare($sql) || die $dbh->errstr();
90 _debug("execute");
91 $sth->execute() || die $sth->errstr();
92
93 _debug( $sth->rows . ' rows returned');
94 $bar->target( $sth->rows );
95 my $i = 1;
96 my $next_update = 0;
97
98 while (my $row = $sth->fetchrow_hashref() ) {
99
100         my $xml = XMLout( $row, NoAttr => 1, RootName => 'file' );
101         if ($xml) {
102                 # Set the XmlDocument to the relevant string and then put it 
103                 #  into the container.
104                 $myXMLDoc->setContent( "$xml" );
105                 $container->putDocument($txn, $myXMLDoc, $updateContext, DbXml::DBXML_GEN_NAME);
106         } else {
107                 _debug("skip $i: ".Dumper($row));
108         }
109
110         $i++;
111         $next_update = $bar->update( $i ) if ( $i > $next_update );
112
113         if ($i % $commit_every == 0) {
114                 _debug("commit");
115                 $txn->commit();
116                 $txn = $theMgr->createTransaction();
117                 $bar->message(Dumper($xml));
118         }
119
120 }
121
122 # Normally we would use a try/catch block to trap any exceptions.
123 #  In the catch, we should call txn->abort() to avoid leaving the
124 #  database in an indeterminate state in the event of an error.
125 #  However, this simple example avoids error handling so as to 
126 #  highlite basic concepts, so that step if omitted here as well.
127
128 # Commit the writes. This causes the container write operations
129 #   to be saved to the container.
130 _debug("final commit");
131 $txn->commit();
132