001: /**
002: * Sequoia: Database clustering technology.
003: * Copyright (C) 2002-2004 French National Institute For Research In Computer
004: * Science And Control (INRIA).
005: * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
006: * Contact: sequoia@continuent.org
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: * Initial developer(s): Emmanuel Cecchet.
021: * Contributor(s): Nicolas Modrzyk.
022: */package org.continuent.sequoia.controller.backup.backupers;
023:
024: import java.io.BufferedReader;
025: import java.io.BufferedWriter;
026: import java.io.File;
027: import java.io.FileNotFoundException;
028: import java.io.FileReader;
029: import java.io.FileWriter;
030: import java.io.IOException;
031: import java.io.PrintStream;
032: import java.util.ArrayList;
033: import java.util.Date;
034: import java.util.Hashtable;
035: import java.util.StringTokenizer;
036:
037: import org.apache.log4j.Category;
038: import org.apache.log4j.Priority;
039: import org.continuent.sequoia.common.exceptions.BackupException;
040: import org.continuent.sequoia.common.exceptions.OctopusException;
041: import org.continuent.sequoia.common.i18n.Translate;
042: import org.continuent.sequoia.common.log.Trace;
043: import org.continuent.sequoia.common.sql.schema.DatabaseTable;
044: import org.continuent.sequoia.common.util.FileManagement;
045: import org.continuent.sequoia.common.util.LoggingOutputStream;
046: import org.continuent.sequoia.controller.backend.DatabaseBackend;
047: import org.continuent.sequoia.controller.backup.BackupManager;
048: import org.continuent.sequoia.controller.backup.Backuper;
049: import org.continuent.sequoia.controller.backup.DumpTransferInfo;
050: import org.webdocwf.util.loader.Loader;
051: import org.webdocwf.util.loader.generator.LoaderGenerator;
052:
053: /**
054: * This class defines a Backuper based on Octopus v3.4.1.
055: * <p>
056: * The options supported by this Backuper must be separated by commas (default
057: * is 'zip=true,redirectOutput=false'). The options are defined as follows:
058: * <p>
059: * zip=[true,false]: defines if the dump directory must be compressed in a zip
060: * file. Default is true.
061: * <p>
062: * redirectOutput=[true,false]: redirect Octopus output directly in the logger
063: * instead of dumping everything on the standard console (may not work on some
064: * systems). Default is false.
065: *
066: * @author <a href="mailto:emmanuel.cecchet@emicnetworks.com">Emmanuel Cecchet
067: * </a>
068: * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
069: * @version 1.0
070: */
071: public class OctopusBackuper implements Backuper {
072: static Trace logger = Trace.getLogger(OctopusBackuper.class
073: .getName());
074: private boolean redirectOutput = false;
075: private boolean zipBackupFiles = true;
076:
077: static {
078: String sequoiaHome = System.getProperty("sequoia.home");
079: if (sequoiaHome != null)
080: System.setProperty("OCTOPUS_HOME", sequoiaHome
081: + File.separator + "lib" + File.separator
082: + "octopus" + File.separator + "xml");
083: }
084:
085: //
086: // Octopus constants
087: //
088:
089: private static final int DB_NAME = 0;
090: private static final int DRIVER = 1;
091: private static final int FULL_NAME = 2;
092: private static final int PREFIX_URL = 3;
093:
094: // four values ... this is REALLY dirty but I see no other way to deal with
095: // octopus constants ...
096: // 1. If we parse the url, what can describe the db we're dealing with
097: // 2. In octopus specific conf file, <Driver name="hsql">
098: // 3. In octopus general vendors file, what driver are we using ...
099: // 4. the part of the url, octopus adds up automatically, from conf file
100:
101: private static final String[] HSQL = { "hsqldb", "hsql",
102: "HypersonicSQL", "jdbc:hsqldb:" };
103: private static final String[] CSV = { "csv", "csv", "Csv",
104: "jdbc:relique:csv:" };
105: private static final String[] MYSQL = { "mysql", "mm", "MySQL",
106: "jdbc:mysql://" };
107: private static final String[] POSTGRESQL = { "postgresql",
108: "postgresql", "PostgreSQL", "jdbc:postgresql://" };
109: private static final String[] ORACLE = { "oracle", "oracle",
110: "Oracle", "jdbc:oracle:thin:" };
111: private static final String[] JTURBO = { "jTurbo", "jTurbo",
112: "MSQL", "jdbc:JTurbo://" };
113: private static final String[] MSSQL = { "microsoft", "microsoft",
114: "MSQL", "jdbc:microsoft:sqlserver://" };
115:
116: static final Hashtable TYPES;
117: static {
118: TYPES = new Hashtable();
119: TYPES.put(HSQL[DB_NAME], HSQL);
120: TYPES.put(CSV[DB_NAME], CSV);
121: TYPES.put(MYSQL[DB_NAME], MYSQL);
122: TYPES.put(ORACLE[DB_NAME], ORACLE);
123: TYPES.put(POSTGRESQL[DB_NAME], POSTGRESQL);
124: TYPES.put(JTURBO[DB_NAME], JTURBO);
125: TYPES.put(MSSQL[DB_NAME], MSSQL);
126: }
127:
128: //
129: // OctopusBackuper interface implementation
130: //
131:
132: /**
133: * Creates a new <code>OctopusBackuper</code> object
134: */
135: public OctopusBackuper() {
136: }
137:
138: /**
139: * @see org.continuent.sequoia.controller.backup.Backuper#getDumpFormat()
140: */
141: public String getDumpFormat() {
142: if (zipBackupFiles)
143: return "Octopus v3.4.1 database neutral dump compressed";
144: else
145: return "Octopus v3.4.1 database neutral dump";
146: }
147:
148: /**
149: * @see org.continuent.sequoia.controller.backup.Backuper#backup(org.continuent.sequoia.controller.backend.DatabaseBackend,
150: * java.lang.String, java.lang.String, java.lang.String,
151: * java.lang.String, java.util.ArrayList)
152: */
153: public Date backup(DatabaseBackend backend, String login,
154: String password, String dumpName, String path,
155: ArrayList tables) throws BackupException {
156: logger.info(Translate.get("backup.manager.backuping.backend",
157: new String[] { backend.getName(), dumpName }));
158:
159: if (logger.isDebugEnabled())
160: logger.debug("Creating directory for backup");
161:
162: // The dump will be located in a sub-directory with the same name
163: String octopusDir = createOctopusDir(path, dumpName);
164:
165: String type = getDatabaseType(backend.getURL());
166: String sourceType = getOctopusType(type);
167: String sourceUrl = backend.getURL().substring(
168: getUrlPrefix(type).length());
169: String sourceDriver = getOctopusDriver(type);
170: String targetType = getOctopusType(TYPE_CSV);
171: String targetDriver = getOctopusDriver(TYPE_CSV);
172: String targetUrl = createCsvDir(octopusDir);
173: String targetUser = "";
174: String targetPassword = "";
175:
176: PrintStream oldStream = null;
177: if (redirectOutput) {
178: if (logger.isDebugEnabled())
179: logger.debug("Redirecting Octopus output streams");
180:
181: // Prevent Octopus from dumping everything on the standard output
182: oldStream = redirectOutputStream();
183: }
184:
185: try {
186: // Generate metadata
187: if (logger.isDebugEnabled())
188: logger.debug("### Generating Octopus metadata ###");
189: callOctopusLoader(sourceType, sourceUrl, sourceDriver,
190: login, password, targetType, targetDriver,
191: targetUrl, targetUser, targetPassword, true, true,
192: octopusDir);
193:
194: // Generate loader job
195: if (logger.isDebugEnabled())
196: logger.debug("### Generating loader job ###");
197: callOctopusLoader(sourceType, sourceUrl, sourceDriver,
198: login, password, targetType, targetDriver,
199: targetUrl, targetUser, targetPassword, true, false,
200: octopusDir);
201:
202: if (logger.isDebugEnabled()) {
203: logger.debug("=======================================");
204: logger.debug("Using the following Octopus settings:");
205: logger.debug("Octopus dump directory=" + octopusDir);
206: logger.debug("Target URL=" + targetUrl);
207: logger.debug("Loader job file="
208: + getLoaderJobFile(octopusDir));
209: logger.debug("Compress backup=" + zipBackupFiles);
210: logger.debug("OCTOPUS HOME:"
211: + System.getProperty("OCTOPUS_HOME"));
212: logger.debug("=======================================");
213: }
214:
215: // Perform the backup
216: launchOctopus(octopusDir, dumpName, tables);
217:
218: if (redirectOutput) {
219: // Restore previous output stream
220: System.setOut(oldStream);
221: }
222: } catch (Exception e) {
223: if (redirectOutput) {
224: // Restore previous output stream
225: System.setOut(oldStream);
226: }
227: String msg = "Error while performing backup for backend "
228: + backend.getName();
229: logger.error(msg, e);
230: throw new BackupException(msg, e);
231: }
232:
233: // Check if we need to compress the backup
234: if (zipBackupFiles) {
235: try {
236: if (logger.isDebugEnabled())
237: logger.debug("Compressing dump");
238: Zipper.zip(path + File.separator + dumpName
239: + Zipper.ZIP_EXT, octopusDir,
240: Zipper.STORE_PATH_FROM_ZIP_ROOT);
241: if (logger.isDebugEnabled())
242: logger.debug("Cleaning uncompressed dump files");
243: cleanUp(octopusDir);
244: } catch (Exception e) {
245: String msg = "Error while compressing dump";
246: logger.error(msg, e);
247: throw new BackupException(msg, e);
248: }
249: }
250:
251: return new Date(System.currentTimeMillis());
252: }
253:
254: /**
255: * @see org.continuent.sequoia.controller.backup.Backuper#restore(org.continuent.sequoia.controller.backend.DatabaseBackend,
256: * java.lang.String, java.lang.String, java.lang.String,
257: * java.lang.String, java.util.ArrayList)
258: */
259: public void restore(DatabaseBackend backend, String login,
260: String password, String dumpName, String path,
261: ArrayList tables) throws BackupException {
262: logger.info(Translate.get("backup.manager.restoring.backend",
263: new String[] { backend.getName(), dumpName }));
264:
265: // The dump will be located in a sub-directory with the same name
266: String octopusDir = createOctopusDir(path, dumpName);
267:
268: if (zipBackupFiles) {
269: try {
270: if (logger.isDebugEnabled())
271: logger.debug("Uncompressing dump");
272: Zipper.unzip(path + File.separator + dumpName
273: + Zipper.ZIP_EXT, octopusDir);
274: } catch (Exception e) {
275: String msg = "Error while uncompressing dump";
276: logger.error(msg, e);
277: throw new BackupException(msg, e);
278: }
279: }
280:
281: String type = getDatabaseType(backend.getURL());
282: String targetType = getOctopusType(type);
283: String targetUrl = backend.getURL().substring(
284: getUrlPrefix(type).length());
285: String targetDriver = getOctopusDriver(type);
286: String sourceType = getOctopusType(TYPE_CSV);
287: String sourceDriver = getOctopusDriver(TYPE_CSV);
288: String sourceUrl = createCsvDir(octopusDir);
289: String sourceUser = "";
290: String sourcePassword = "";
291:
292: PrintStream oldStream = null;
293: if (redirectOutput) {
294: if (logger.isDebugEnabled())
295: logger.debug("Redirecting Octopus output streams");
296:
297: // Prevent Octopus from dumping everything on the standard output
298: oldStream = redirectOutputStream();
299: }
300:
301: try {
302: // Generate loader job
303: if (logger.isDebugEnabled())
304: logger.debug("### Generating loader job ###");
305: callOctopusLoader(sourceType, sourceUrl, sourceDriver,
306: sourceUser, sourcePassword, targetType,
307: targetDriver, targetUrl, login, password, false,
308: false, octopusDir);
309:
310: setOctopusLoaderJob(octopusDir, sourceType);
311:
312: if (logger.isDebugEnabled()) {
313: logger.debug("=======================================");
314: logger.debug("Using the following Octopus settings:");
315: logger.debug("Octopus dump directory=" + octopusDir);
316: logger.debug("Source URL=" + sourceUrl);
317: logger.debug("Target URL=" + targetUrl);
318: logger.debug("Loader job file="
319: + getLoaderJobFile(octopusDir));
320: logger.debug("Compress backup=" + zipBackupFiles);
321: logger.debug("OCTOPUS HOME:"
322: + System.getProperty("OCTOPUS_HOME"));
323: logger.debug("=======================================");
324: }
325:
326: // Perform the backup
327: launchOctopus(octopusDir, dumpName, tables);
328:
329: if (zipBackupFiles) {
330: if (logger.isDebugEnabled())
331: logger.debug("Cleaning backup files");
332: cleanUp(octopusDir);
333: }
334:
335: if (redirectOutput) {
336: // Restore previous output stream
337: System.setOut(oldStream);
338: }
339: } catch (Exception e) {
340: if (redirectOutput) {
341: // Restore previous output stream
342: System.setOut(oldStream);
343: }
344: String msg = "Error while performing restore operation on backend "
345: + backend.getName();
346: logger.error(msg, e);
347: throw new BackupException(msg, e);
348: }
349: }
350:
351: /**
352: * @see org.continuent.sequoia.controller.backup.Backuper#deleteDump(java.lang.String,
353: * java.lang.String)
354: */
355: public void deleteDump(String path, String dumpName)
356: throws BackupException {
357: if (zipBackupFiles) {
358: File toRemove = new File(path + File.separator + dumpName
359: + Zipper.ZIP_EXT);
360: if (logger.isDebugEnabled())
361: logger.debug("Deleting compressed dump " + toRemove);
362: toRemove.delete();
363: } else {
364: if (logger.isDebugEnabled())
365: logger.debug("Deleting dump directory " + path
366: + File.separator + dumpName);
367: cleanUp(path + File.separator + dumpName);
368: }
369: }
370:
371: //
372: // Octopus wrappers
373: //
374:
375: private static final String TYPE_CSV = "csv";
376: private static final String COPY_MODE = "copy";
377: private static final String OCTOPUS_INCLUDE_HREF = "<include href=\"sql/";
378:
379: private void callOctopusLoader(String sourceType, String sourceUrl,
380: String sourceDriver, String sourceUser,
381: String sourcePassword, String targetType,
382: String targetDriver, String targetUrl, String targetUser,
383: String targetPassword, boolean backup,
384: boolean generateAllVendors, String octopusDir)
385: throws OctopusException {
386: try {
387: if (logger.isDebugEnabled()) {
388: logger.debug("Source Type:" + sourceType);
389: logger.debug("Source Driver:" + sourceDriver);
390: logger.debug("Source URL :" + sourceUrl);
391: logger.debug("Source User :" + sourceUser);
392: logger.debug("Target Type:" + targetType);
393: logger.debug("Target Driver:" + targetDriver);
394: logger.debug("Target URL:" + targetUrl);
395: logger.debug("Target User :" + targetUser);
396: logger.debug("Generate SQL for all vendors :"
397: + generateAllVendors);
398: }
399: LoaderGenerator loader = new LoaderGenerator(sourceType, // sourceType
400: sourceUrl, // sourceDatabase Url?
401: COPY_MODE, // valueMode
402: octopusDir, // generatorOutput
403: sourceDriver, // sourceDriverName
404: targetDriver, // TargetDriverName
405: targetUrl, // targetDataBase
406: targetType, // TargetType
407: sourceUser, // sourceUser
408: sourcePassword, // sourcePassword
409: targetUser, // targetUser
410: targetPassword, // targetPassword
411: "", // domlPath
412: "org.webdoc.util.loader", // package name
413: "true", // generate drop table stmt
414: "true", // generate drop integrity statement
415: "true", // generate create table stmt
416: "true", // generate create pk statement
417: "true", // generate create fk statement
418: "true", // generate create index stmt
419: String.valueOf(generateAllVendors), // generate sql for all vendors
420: String.valueOf(!generateAllVendors), // generate xml
421: "false", // generate doml
422: String.valueOf(!generateAllVendors), // full mode ??
423: String.valueOf(!backup), // restore mode
424: null, // convertTablesToSemicolonSeparatedList(database.getTables()),
425: // tables list
426: null // Jar file structure
427: );
428: loader.generate();
429: } catch (Exception e) {
430: throw new OctopusException(e);
431: }
432: }
433:
434: /**
435: * This start octopus with previously generated LoaderJob file
436: *
437: * @param octopusDir the working directory
438: * @param tables the list of tables to backup, null means all tables
439: * @throws OctopusException if octopus fails
440: */
441: private void launchOctopus(String octopusDir, String dumpName,
442: ArrayList tables) throws OctopusException {
443: try {
444: Loader myOctopus;
445: String loaderLogging;
446: if (logger.isDebugEnabled())
447: loaderLogging = Loader.LOGMODE_FULL;
448: else if (!logger.isFatalEnabled()) // Logger is OFF
449: loaderLogging = Loader.LOGMODE_NONE;
450: else
451: loaderLogging = Loader.LOGMODE_NORMAL;
452:
453: if (tables == null) {
454: // Copy everything
455: myOctopus = new Loader(getLoaderJobFile(octopusDir),
456: loaderLogging, "sequoia", octopusDir, "Octopus"
457: + dumpName + ".log", true, null, null,
458: true, null, 0, 100);
459: } else {
460: // Copy only the tables we want
461: myOctopus = new Loader(getLoaderJobFile(octopusDir),
462: loaderLogging, "sequoia", octopusDir, "Octopus"
463: + dumpName + ".log", true, null, null,
464: true, null, 0, 100,
465: convertTablesToArray(tables));
466: }
467: try {
468: myOctopus.load();
469: } catch (Exception e) {
470: logger.error("Failed to load octopus", e);
471: throw new OctopusException(Translate.get(
472: "controller.octopus.load.failed", e));
473: }
474: }
475: // I am doing this because Octopus throws NullPointerException
476: // all the time so it is impossible to know which failed
477: catch (OctopusException oe) {
478: // This is thrown only by the above.
479: throw oe;
480: } catch (Exception e) {
481: throw new OctopusException(Translate
482: .get("controller.octopus.instance.failed"));
483: }
484: }
485:
486: private void cleanUp(String octopusDir) {
487: if (logger.isDebugEnabled())
488: logger.debug("Cleaning up temporary backup files...");
489: File toRemove = new File(octopusDir);
490: FileManagement.deleteDir(toRemove);
491: }
492:
493: private String[] convertTablesToArray(ArrayList tablesList) {
494: int length = tablesList.size();
495: String[] result = new String[length];
496: for (int i = 0; i < length; i++)
497: result[i] = ((DatabaseTable) tablesList.get(i)).getName();
498: return result;
499: }
500:
501: private String createOctopusDir(String path, String dumpName)
502: throws BackupException {
503: // Create main octopus directory
504: String octopusDir = path + File.separator + dumpName;
505:
506: File octopusd = new File(octopusDir);
507: octopusd.mkdirs();
508: octopusd.mkdir();
509:
510: if (!octopusd.exists())
511: throw new BackupException(
512: "backup.directory.cannot.be.created");
513:
514: return octopusDir;
515: }
516:
517: private String createCsvDir(String octopusDir)
518: throws BackupException {
519: // Create Csv directory
520: String csvDir = TYPE_CSV;
521: File csvd = new File(octopusDir + File.separator + csvDir);
522: csvDir = csvd.getAbsolutePath();
523: csvd.mkdirs();
524: csvd.mkdir();
525:
526: if (!csvd.exists())
527: throw new BackupException(
528: "backup.directory.cannot.be.created");
529:
530: return csvDir;
531: }
532:
533: private String getDatabaseType(String url) throws BackupException {
534: if (url == null)
535: throw new BackupException("Invalid null source url");
536: int index = url.indexOf(':');
537: int index2 = url.indexOf(':', index + 1);
538: if (index == -1 || index2 == -1 || index > index2)
539: throw new BackupException("Invalid source url format");
540: String type = url.substring(index + 1, index2);
541: return type;
542: }
543:
544: private String getLoaderJobFile(String octopusDir) {
545: return octopusDir + File.separator + "LoaderJob.olj";
546: }
547:
548: private PrintStream redirectOutputStream() {
549: PrintStream previousOut = System.out;
550: System.setOut(new PrintStream(
551: new LoggingOutputStream(Category.getInstance(this
552: .getClass().getName()), Priority.DEBUG), true));
553: return previousOut;
554: }
555:
556: private void setOctopusLoaderJob(String octopusDir,
557: String sourceType) throws OctopusException {
558: String onErrorContinueEqualFalse = "onErrorContinue=\"false\"";
559: String onErrorContinueEqualTrue = "onErrorContinue=\"true\"";
560: BufferedReader br = null;
561: BufferedWriter bw = null;
562:
563: try {
564: br = new BufferedReader(new FileReader(
565: getLoaderJobFile(octopusDir)));
566: String line = "";
567: StringBuffer buffer = new StringBuffer();
568:
569: while ((line = br.readLine()) != null) {
570: /* Give the metadata location */
571: int idx = line.indexOf(OCTOPUS_INCLUDE_HREF);
572: if (idx != -1) {
573: idx += OCTOPUS_INCLUDE_HREF.length();
574: // -4 = Skip "sql/"
575: line = line.substring(0, idx - 4) + ".."
576: + File.separator + octopusDir
577: + File.separator + "SQLForAllVendors"
578: + File.separator + sourceType
579: + File.separator + "sql" + File.separator
580: + line.substring(idx);
581: }
582:
583: /* Force on error continue */
584: int index7 = line.indexOf(onErrorContinueEqualFalse);
585: if (index7 != -1) {
586: line = line.substring(0, index7)
587: + onErrorContinueEqualTrue
588: + line.substring(index7
589: + onErrorContinueEqualFalse
590: .length());
591: }
592: buffer.append(line
593: + System.getProperty("line.separator"));
594: }
595: br.close();
596: if (logger.isDebugEnabled()) {
597: logger.debug("Octopus file updated with success");
598: }
599:
600: bw = new BufferedWriter(new FileWriter(
601: getLoaderJobFile(octopusDir)));
602: bw.write(buffer.toString());
603: bw.close();
604: } catch (FileNotFoundException fie) {
605: // loader job was not generated properly
606: logger.warn(Translate
607: .get("controller.octopus.loader.job.not.found"));
608: throw new OctopusException(fie.getMessage());
609: } catch (IOException e) {
610: // Error while reading file
611: logger.warn(Translate
612: .get("controller.octopus.loader.io.problem"));
613: } finally {
614: // close the open streams
615: if (bw != null)
616: try {
617: bw.close();
618: } catch (IOException e1) {
619:
620: }
621: if (br != null)
622: try {
623: br.close();
624: } catch (IOException e2) {
625: }
626: }
627: }
628:
629: /**
630: * Get octopus type.
631: *
632: * @param type from url
633: * @return value from hashtable or null
634: * @throws BackupException if the type is not supported
635: */
636: private String getOctopusType(String type) throws BackupException {
637: if (type == null)
638: return null;
639:
640: // SEQUOIA-700 fix
641: if (!TYPES.containsKey(type))
642: throw new BackupException(
643: "OctopusBackuper does not support this database type.");
644:
645: return ((String[]) TYPES.get(type))[OctopusBackuper.FULL_NAME];
646: }
647:
648: /**
649: * Get octopus driver.
650: *
651: * @param type from url
652: * @return value from hashtable or null
653: */
654: private String getOctopusDriver(String type) {
655: if (type == null)
656: return null;
657: return ((String[]) TYPES.get(type))[OctopusBackuper.DRIVER];
658: }
659:
660: /**
661: * Get Octopus url prefix
662: *
663: * @param type from url
664: * @return value from hashtable or null
665: */
666: private String getUrlPrefix(String type) {
667: if (type == null)
668: return null;
669: return ((String[]) TYPES.get(type))[OctopusBackuper.PREFIX_URL];
670: }
671:
672: //
673: // Octopus Backuper options
674: //
675:
676: /**
677: * @see org.continuent.sequoia.controller.backup.Backuper#getOptions()
678: */
679: public String getOptions() {
680: return "zip=" + String.valueOf(zipBackupFiles);
681: }
682:
683: /**
684: * @see org.continuent.sequoia.controller.backup.Backuper#setOptions(java.lang.String)
685: */
686: public void setOptions(String options) {
687: if (options != null) {
688: StringTokenizer strTok = new StringTokenizer(options, ",");
689: String option = null;
690: String name = null;
691: String value = null;
692:
693: // Parse the string of options, add them to the HashMap
694: while (strTok.hasMoreTokens()) {
695: option = strTok.nextToken();
696: name = option.substring(0, option.indexOf("="));
697: value = option.substring(option.indexOf("=") + 1,
698: option.length());
699:
700: if ("zip".equals(name)) {
701: try {
702: zipBackupFiles = !"false".equals(value);
703: } catch (RuntimeException e) {
704: zipBackupFiles = true;
705: logger
706: .warn("Invalid zip value for OctopusBackuper, available option is 'zip=[true,false]' ("
707: + option + ")");
708: }
709: } else if ("redirectOutput".equals(name)) {
710: try {
711: redirectOutput = "true".equals(value);
712: } catch (RuntimeException e) {
713: redirectOutput = false;
714: logger
715: .warn("Invalid redirectOutput value for OctopusBackuper, available option is 'redirectOutput=[true,false]' ("
716: + option + ")");
717: }
718: } else {
719: logger.warn("Unsupported option '" + option
720: + "' for OctopusBackuper");
721: }
722: }
723: }
724: logger.info("OctopusBackuper backup compression is set to "
725: + zipBackupFiles);
726: }
727:
728: /**
729: * @see org.continuent.sequoia.controller.backup.Backuper#fetchDump(org.continuent.sequoia.controller.backup.DumpTransferInfo,
730: * java.lang.String, java.lang.String)
731: */
732: public void fetchDump(DumpTransferInfo dumpTransferInfo,
733: String path, String dumpName) throws BackupException,
734: IOException {
735: BackupManager.fetchDumpFile(dumpTransferInfo, path, dumpName
736: + Zipper.ZIP_EXT);
737: }
738:
739: /**
740: * @see org.continuent.sequoia.controller.backup.Backuper#setupDumpServer()
741: */
742: public DumpTransferInfo setupDumpServer() throws IOException {
743: return BackupManager.setupDumpFileServer();
744: }
745: }
|