KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > controller > backup > backupers > PostgreSQLTarBackuper


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2005 Emic Networks
4  * Contact: sequoia@continuent.org
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * Initial developer(s): Emmanuel Cecchet.
19  * Contributor(s): Dylan Hansen, Mathieu Peltier, Olivier Fambon.
20  */

21
22 package org.continuent.sequoia.controller.backup.backupers;
23
24 import java.io.File JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Date JavaDoc;
28
29 import org.continuent.sequoia.common.exceptions.BackupException;
30 import org.continuent.sequoia.common.log.Trace;
31 import org.continuent.sequoia.controller.backend.DatabaseBackend;
32 import org.continuent.sequoia.controller.backup.BackupManager;
33 import org.continuent.sequoia.controller.backup.DumpTransferInfo;
34
35 /**
36  * This class defines a Backuper for PostgreSQL databases. This backuper creates
37  * dumps in the tar format, using the "--format=t" switch on pg_dump.
38  * <p>
39  * Supported URLs are:
40  * <ul>
41  * <li>jdbc:postgresql://host:port/dbname?param1=foo,param2=bar</li>
42  * <li>jdbc:postgresql://host/dbname?param1=foo,param2=bar</li>
43  * <li>jdbc:postgresql:dbname?param1=foo,param2=bar</li>
44  * </ul>
45  *
46  * @author <a HREF="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet</a>
47  * @author <a HREF="mailto:dhansen@h2st.com">Dylan Hansen</a>
48  * @author <a HREF="mailto:mathieu.peltier@emicnetworks.com">Mathieu Peltier</a>
49  * @author <a HREF="mailto:olivier.fambon@emicnetworks.com">Olivier Fambon</a>
50  * @version 1.0
51  */

52 public class PostgreSQLTarBackuper extends AbstractPostgreSQLBackuper
53 {
54   // Logger
55
static Trace logger = Trace
56                                              .getLogger(PostgreSQLTarBackuper.class
57                                                  .getName());
58
59   /**
60    * The dump format for this (family of) backuper.
61    */

62   public static final String JavaDoc DUMP_FORMAT = "PostgreSQL Tar Dump";
63
64   /**
65    * @see org.continuent.sequoia.controller.backup.Backuper#getDumpFormat()
66    */

67   public String JavaDoc getDumpFormat()
68   {
69     return DUMP_FORMAT;
70   }
71
72   /**
73    * @see org.continuent.sequoia.controller.backup.Backuper#backup(DatabaseBackend,
74    * String, String, String, String, ArrayList)
75    */

76   public Date JavaDoc backup(DatabaseBackend backend, String JavaDoc login, String JavaDoc password,
77       String JavaDoc dumpName, String JavaDoc path, ArrayList JavaDoc tables) throws BackupException
78   {
79     // Parse the URL for the connection information
80
String JavaDoc url = backend.getURL();
81     PostgreSQLUrlInfo info = new AbstractPostgreSQLBackuper.PostgreSQLUrlInfo(
82         url);
83
84     if (logger.isDebugEnabled())
85       logger.debug("Backing up database '" + info.getDbName() + "' on host '"
86           + info.getHost() + ":" + info.getPort() + "'");
87
88     try
89     {
90       // Create the path, if it does not already exist
91
File JavaDoc pathDir = new File JavaDoc(path);
92       if (!pathDir.exists())
93       {
94         pathDir.mkdirs();
95         pathDir.mkdir();
96       }
97       String JavaDoc fullPath = getDumpPhysicalPath(path, dumpName) + ".tar";
98
99       int exitValue = -1;
100       String JavaDoc dumpOptions = "";
101       if (pgDumpFlags != null)
102       {
103         if (pgDumpFlags.indexOf("-F") >= 0
104             || pgDumpFlags.indexOf("--format=") >= 0)
105         {
106           logger.error("Invalid option in pgDumpFlags \"" + pgDumpFlags
107               + "\". You are not allowed to set the format of the dump!");
108         }
109         else
110         {
111           dumpOptions = " " + pgDumpFlags + " ";
112         }
113       }
114       if (useAuthentication)
115       {
116         if (logger.isDebugEnabled())
117           logger.debug("Performing backup using authentication");
118         int timeout = -1;
119         if (dumpTimeout != null)
120         {
121           try
122           {
123             timeout = Integer.parseInt(dumpTimeout);
124           }
125           catch (NumberFormatException JavaDoc e)
126           {
127             logger.error("\"" + dumpTimeout
128                 + "\" is not a valid dump-timeout value!");
129             timeout = -1;
130           }
131         }
132         String JavaDoc[] expectFeed = makeExpectDialogueWithAuthentication("pg_dump",
133             info, " --format=t -f " + fullPath + dumpOptions, login, password,
134             timeout);
135
136         String JavaDoc[] cmd = makeExpectCommandReadingStdin();
137
138         exitValue = executeNativeCommand(expectFeed, cmd);
139       }
140       else
141       {
142         if (pgDumpFlags != null)
143         {
144           if (pgDumpFlags.indexOf("-U") >= 0 || pgDumpFlags.indexOf("-W") >= 0)
145           {
146             logger
147                 .error("Invalid option in pgDumpFlags \""
148                     + pgDumpFlags
149                     + "\". Set \"authentication=true\" if you want to use authentication!");
150           }
151           else
152           {
153             dumpOptions = " " + pgDumpFlags + " ";
154           }
155         }
156
157         String JavaDoc cmd = makeCommand("pg_dump", info, " --format=t -f " + fullPath
158             + dumpOptions, login);
159         exitValue = executeNativeCommand(cmd);
160       }
161
162       if (exitValue != 0)
163       {
164         printErrors();
165         throw new BackupException(
166             "pg_dump execution did not complete successfully!");
167       }
168
169     }
170     catch (Exception JavaDoc e)
171     {
172       String JavaDoc msg = "Error while performing backup";
173       logger.error(msg, e);
174       throw new BackupException(msg, e);
175     }
176
177     return new Date JavaDoc(System.currentTimeMillis());
178   }
179
180   /**
181    * @see org.continuent.sequoia.controller.backup.Backuper#restore(DatabaseBackend,
182    * String, String, String, String, ArrayList)
183    */

184   public void restore(DatabaseBackend backend, String JavaDoc login, String JavaDoc password,
185       String JavaDoc dumpName, String JavaDoc path, ArrayList JavaDoc tables) throws BackupException
186   {
187     // Parse the URL for the connection information
188
String JavaDoc url = backend.getURL();
189     PostgreSQLUrlInfo info = new AbstractPostgreSQLBackuper.PostgreSQLUrlInfo(
190         url);
191
192     if (logger.isDebugEnabled())
193       logger.debug("Restoring database '" + info.getDbName() + "' on host '"
194           + info.getHost() + ":" + info.getPort() + "'");
195
196     // Check to see if the given path + dumpName exists
197
String JavaDoc fullPath = getDumpPhysicalPath(path, dumpName) + ".tar";
198     File JavaDoc dump = new File JavaDoc(fullPath);
199     if (!dump.exists())
200       throw new BackupException("Backup '" + fullPath + "' does not exist!");
201
202     try
203     {
204       if (useAuthentication)
205       {
206         if (logger.isInfoEnabled())
207           logger.info("Performing database operations using authentication");
208
209         // Drop the database if it already exists
210
if (logger.isDebugEnabled())
211           logger.debug("Dropping database '" + info.getDbName() + "'");
212
213         String JavaDoc[] expectFeed = makeExpectDialogueWithAuthentication("dropdb",
214             info, "", login, password, 60); // 1 minute timeout
215

216         String JavaDoc[] cmd = makeExpectCommandReadingStdin();
217
218         if (executeNativeCommand(expectFeed, cmd) != 0)
219         {
220           printErrors();
221           throw new BackupException(
222               "dropdb execution did not complete successfully!");
223         }
224
225         // Re-create the database, use the specified encoding if provided
226
if (logger.isDebugEnabled())
227           logger.debug("Re-creating '" + info.getDbName() + "'");
228
229         expectFeed = makeExpectDialogueWithAuthentication("createdb", info,
230             encoding != null ? "--encoding=" + encoding + " " : "", login,
231             password, 60); // 1 minute timeout
232

233         cmd = makeExpectCommandReadingStdin();
234
235         if (executeNativeCommand(expectFeed, cmd) != 0)
236         {
237           printErrors();
238           throw new BackupException(
239               "createdb execution did not complete successfully!");
240         }
241
242         // Run a pre-restore script, if specified
243
if (preRestoreScript != null)
244         {
245           if (logger.isDebugEnabled())
246             logger.debug("Running pre-restore script '" + preRestoreScript
247                 + "' on '" + info.getDbName() + "'");
248
249           expectFeed = makeExpectDialogueWithAuthentication("psql", info,
250               "--pset pager -f " + preRestoreScript, login, password, 300); // 5
251
// minutes
252
// timeout
253

254           cmd = makeExpectCommandReadingStdin();
255
256           if (executeNativeCommand(expectFeed, cmd) != 0)
257           {
258             printErrors();
259             throw new BackupException(
260                 "psql execution did not complete successfully!");
261           }
262         }
263
264         // Use the pg_restore command to rebuild the database
265
if (logger.isDebugEnabled())
266           logger.debug("Rebuilding '" + info.getDbName() + "' from dump '"
267               + dumpName + "'");
268
269         int timeout = -1;
270         if (restoreTimeout != null)
271         {
272           try
273           {
274             timeout = Integer.parseInt(restoreTimeout);
275           }
276           catch (NumberFormatException JavaDoc e)
277           {
278             logger.error("\"" + restoreTimeout
279                 + "\" is not a valid restore-timeout value!");
280             timeout = -1;
281           }
282         }
283
284         expectFeed = makeExpectDialogueWithAuthentication("pg_restore", info,
285             "--format=t -d " + info.getDbName() + " " + fullPath, login,
286             password, timeout); // 30 minutes timeout
287

288         cmd = makeExpectCommandReadingStdin();
289
290         if (executeNativeCommand(expectFeed, cmd) != 0)
291         {
292           printErrors();
293           throw new BackupException(
294               "pg_restore execution did not complete successfully!");
295         }
296         
297         // Run a post-restore script, if specified
298
if (postRestoreScript != null)
299         {
300           if (logger.isDebugEnabled())
301             logger.debug("Running post-restore script '" + postRestoreScript
302                 + "' on '" + info.getDbName() + "'");
303
304           expectFeed = makeExpectDialogueWithAuthentication("psql", info,
305               "--pset pager -f " + postRestoreScript, login, password, 300); // 5
306
// minutes
307
// timeout
308

309           cmd = makeExpectCommandReadingStdin();
310
311           if (executeNativeCommand(expectFeed, cmd) != 0)
312           {
313             printErrors();
314             throw new BackupException(
315                 "psql execution did not complete successfully!");
316           }
317         }
318         
319       }
320       else
321       // No authentication
322
{
323         // Drop the database if it already exists
324
if (logger.isDebugEnabled())
325           logger.debug("Dropping database '" + info.getDbName() + "'");
326
327         String JavaDoc dropCmd = makeCommand("dropdb", info, "", login);
328         if (executeNativeCommand(dropCmd) != 0)
329         {
330           printErrors();
331           throw new BackupException(
332               "dropdb execution did not complete successfully!");
333         }
334
335         // Re-create the database, use the specified encoding if provided
336
if (logger.isDebugEnabled())
337           logger.debug("Re-creating '" + info.getDbName() + "'");
338
339         String JavaDoc createCmd = makeCommand("createdb", info, encoding != null
340             ? "--encoding=" + encoding + " "
341             : "", login);
342         if (executeNativeCommand(createCmd) != 0)
343         {
344           printErrors();
345           throw new BackupException(
346               "createdb execution did not complete successfully!");
347         }
348
349         // Run a pre-restore script, if specified
350
if (preRestoreScript != null)
351         {
352           if (logger.isDebugEnabled())
353             logger.debug("Running pre-restore script '" + preRestoreScript
354                 + "' on '" + info.getDbName() + "'");
355
356           String JavaDoc preRestoreCmd = makeCommand("psql", info, "--pset pager -f "
357               + preRestoreScript, login);
358           if (executeNativeCommand(preRestoreCmd) != 0)
359           {
360             printErrors();
361             throw new BackupException(
362                 "psql execution did not complete successfully!");
363           }
364         }
365
366         // Use the psql command to rebuild the database
367
if (logger.isDebugEnabled())
368           logger.debug("Rebuilding '" + info.getDbName() + "' from dump '"
369               + dumpName + "'");
370
371         String JavaDoc replayCmd = makeCommand("pg_restore", info, "--format=t -d "
372             + info.getDbName() + " " + fullPath, login);
373         if (executeNativeCommand(replayCmd) != 0)
374         {
375           printErrors();
376           throw new BackupException(
377               "pg_restore execution did not complete successfully!");
378         }
379         
380         // Run a post-restore script, if specified
381
if (postRestoreScript != null)
382         {
383           if (logger.isDebugEnabled())
384             logger.debug("Running post-restore script '" + postRestoreScript
385                 + "' on '" + info.getDbName() + "'");
386
387           String JavaDoc postRestoreCmd = makeCommand("psql", info, "--pset pager -f "
388               + postRestoreScript, login);
389           if (executeNativeCommand(postRestoreCmd) != 0)
390           {
391             printErrors();
392             throw new BackupException(
393                 "psql execution did not complete successfully!");
394           }
395         }
396         
397       }
398     }
399     catch (Exception JavaDoc e)
400     {
401       String JavaDoc msg = "Error while performing backup";
402       logger.error(msg, e);
403       throw new BackupException(msg, e);
404     }
405   }
406
407   /**
408    * @see org.continuent.sequoia.controller.backup.Backuper#fetchDump(org.continuent.sequoia.controller.backup.DumpTransferInfo,
409    * java.lang.String, java.lang.String)
410    */

411   public void fetchDump(DumpTransferInfo dumpTransferInfo, String JavaDoc path,
412       String JavaDoc dumpName) throws BackupException, IOException JavaDoc
413   {
414     BackupManager.fetchDumpFile(dumpTransferInfo, path, dumpName + ".tar");
415   }
416
417   /**
418    * @see org.continuent.sequoia.controller.backup.Backuper#deleteDump(java.lang.String,
419    * java.lang.String)
420    */

421   public void deleteDump(String JavaDoc path, String JavaDoc dumpName) throws BackupException
422   {
423     super.deleteDump(path, dumpName + ".tar");
424   }
425
426 }
427
Popular Tags