KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > util > DbBackup


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: DbBackup.java,v 1.9 2006/10/30 21:14:28 bostic Exp $
7  */

8
9 package com.sleepycat.je.util;
10
11 import com.sleepycat.je.DatabaseException;
12 import com.sleepycat.je.DbInternal;
13 import com.sleepycat.je.Environment;
14 import com.sleepycat.je.dbi.EnvironmentImpl;
15 import com.sleepycat.je.log.FileManager;
16 import com.sleepycat.je.utilint.DbLsn;
17
18
19 /**
20  * DbBackup is a helper class for stopping and restarting JE background
21  * activity in an open environment in order to simplify backup operations. It
22  * also lets the application create a backup which can support restoring the
23  * environment to a specific point in time.
24  * <p>
25  * <b>Backing up without DbBackup:</b>
26  * Because JE has an append only log file architecture, it is always possible
27  * to do a hot backup without the use of DbBackup by copying all log files
28  * (.jdb files) to your archival location. As long as the log files are copied
29  * in alphabetical order, (numerical in effect) <i>and</i> all log files are
30  * copied, the environment can be successfully backed up without any need to
31  * stop database operations or background activity. This means that your
32  * backup operation must do a loop to check for the creation of new log files
33  * before deciding that the backup is finished. For example:
34  * <pre>
35  * time files in activity
36  * environment
37  *
38  * t0 000000001.jdb Backup starts copying file 1
39  * 000000003.jdb
40  * 000000004.jdb
41  *
42  * t1 000000001.jdb JE log cleaner migrates portion of file 3 to newly
43  * 000000004.jdb created file 5 and deletes file 3. Backup finishes
44  * 000000005.jdb file 1, starts copying file 4. Backup MUST include
45  * file 5 for a consistent backup!
46  *
47  * t2 000000001.jdb Backup finishes copying file 4, starts and finishes
48  * 000000004.jdb file 5, has caught up. Backup ends.
49  * 000000005.jdb
50  *</pre>
51  * <p>
52  * In the example above, the backup operation must be sure to copy file 5,
53  * which came into existence after the backup had started. If the backup
54  * stopped operations at file 4, the backup set would include only file 1 and
55  * 4, omitting file 3, which would be an inconsistent set.
56  * <p>
57  * Also note that log file 5 may not have filled up before it was copied to
58  * archival storage. On the next backup, there might be a newer, larger version
59  * of file 5, and that newer version should replace the older file 5 in archive
60  * storage.
61  * <p>
62  * <b>Backup up with DbBackup</b>
63  * <p>
64  * DbBackup helps simplify application backup by defining the set of files that
65  * must be copied for each backup operation. If the environment directory has
66  * read/write protection, the application must pass DbBackup an open,
67  * read/write environment handle.
68  * <p>
69  * When entering backup mode, JE
70  * determines the set of log files needed for a consistent backup, and freezes
71  * all changes to those files. The application can copy that defined set of
72  * files and finish operation without checking for the ongoing creation of new
73  * files. Also, there will be no need to check for a newer version of the last
74  * file on the next backup.
75  * <p>
76  * In the example above, if DbBackupHelper was used at t0, the application
77  * would only have to copy files 1, 3 and 4 to back up. On a subsequent backup,
78  * the application could start its copying at file 5. There would be no need
79  * to check for a newer version of file 4.
80  * <p>
81  * An example usage:
82  * <pre>
83  *
84  * Environment env = new Environment(...);
85  * DbBackup backupHelper = new DbBackup(env);
86  *
87  * // Find the file number of the last file in the previous backup
88  * // persistently, by either checking the backup archive, or saving
89  * // state in a persistent file.
90  * long lastFileCopiedInPrevBackup = ...
91  *
92  * // Start backup, find out what needs to be copied.
93  * backupHelper.startBackup();
94  * try {
95  * String[] filesForBackup =
96  * backupHelper.getLogFilesInBackupSet(lastFileCopiedInPrevBackup);
97  *
98  * // Copy the files to archival storage.
99  * myApplicationCopyMethod(filesForBackup)
100
101  * // Update our knowlege of the last file saved in the backup set,
102  * // so we can copy less on the next backup
103  * lastFileCopiedInPrevBackup = backupHelper.getLastFileInBackupSet();
104  * myApplicationSaveLastFile(lastFileCopiedInBackupSet);
105  * }
106  * finally {
107  * // Remember to exit backup mode, or all log files won't be cleaned
108  * // and disk usage will bloat.
109  * backupHelper.endBackup();
110  * }
111  */

112 public class DbBackup {
113
114     private EnvironmentImpl envImpl;
115     private boolean backupStarted;
116     private long lastFileInBackupSet = -1;
117     private boolean envIsReadOnly;
118
119     /**
120      * DbBackup must be created with an open, valid environment handle.
121      * If the environment directory has read/write permissions, the environment
122      * handle must be configured for read/write.
123      */

124     public DbBackup(Environment env)
125         throws DatabaseException {
126
127         /* Check that the Environment is open. */
128         env.checkHandleIsValid();
129         envImpl = DbInternal.envGetEnvironmentImpl(env);
130         FileManager fileManager = envImpl.getFileManager();
131
132         /*
133          * If the environment is writable, we need a r/w environment handle
134          * in order to flip the file.
135          */

136         envIsReadOnly = fileManager.checkEnvHomePermissions(true);
137         if ((!envIsReadOnly) && envImpl.isReadOnly()) {
138             throw new DatabaseException(this.getClass().getName() +
139                                 " requires a read/write Environment handle");
140         }
141     }
142
143     /**
144      * Start backup mode in order to determine the definitive backup set needed
145      * for this point in time. After calling this method, log cleaning will be
146      * disabled until endBackup() is called. Be sure to call endBackup() to
147      * re-enable log cleaning or disk space usage will bloat.
148      */

149     public synchronized void startBackup()
150         throws DatabaseException {
151     
152         if (backupStarted) {
153             throw new DatabaseException(this.getClass().getName() +
154                                          ".startBackup was already called");
155         }
156
157         backupStarted = true;
158
159         try {
160             /* Prevent any file deletions. */
161             envImpl.getCleaner().setDeleteProhibited();
162
163             FileManager fileManager = envImpl.getFileManager();
164         
165             /*
166              * Flip the log so that we can know that the list of files
167              * corresponds to a given point.
168              */

169             if (envIsReadOnly) {
170                 lastFileInBackupSet = fileManager.getLastFileNum().longValue();
171             } else {
172                 long newFileNum = envImpl.forceLogFileFlip();
173                 lastFileInBackupSet = DbLsn.getFileNumber(newFileNum) - 1;
174             }
175         } catch (DatabaseException e) {
176             backupStarted = false;
177             throw e;
178         }
179     }
180
181     /**
182      * End backup mode, thereby re-enabling normal JE log cleaning.
183      */

184     public synchronized void endBackup()
185         throws DatabaseException {
186     
187         checkBackupStarted();
188         
189         try {
190             envImpl.getCleaner().clearDeleteProhibited();
191         } finally {
192             backupStarted = false;
193         }
194     }
195
196     /**
197      * Can only be called in backup mode, after startBackup() has been called.
198      *
199      * @return the file number of the last file in the current backup set.
200      * Save this value to reduce the number of files that must be copied at
201      * the next backup session.
202      */

203     public synchronized long getLastFileInBackupSet()
204         throws DatabaseException {
205     
206         checkBackupStarted();
207         return lastFileInBackupSet;
208     }
209
210     /**
211      * Get the list of all files that are needed for the environment at the
212      * point of time when backup mode started. Can only be called in backup
213      * mode, after startBackup() has been called.
214      *
215      * @return the names of all files in the backup set, sorted in alphabetical
216      * order.
217      */

218     public synchronized String JavaDoc[] getLogFilesInBackupSet()
219         throws DatabaseException {
220
221         checkBackupStarted();
222         return envImpl.getFileManager().listFiles(0, lastFileInBackupSet);
223     }
224
225     /**
226      * Get the minimum list of files that must be copied for this backup. This
227      * consists of the set of backup files that are greater than the last file
228      * copied in the previous backup session. Can only be called in backup
229      * mode, after startBackup() has been called.
230      *
231      * @param lastFileCopiedInPrevBackup file number of last file copied in the
232      * last backup session, obtained from getLastFileInBackupSet().
233      *
234      * @return the names of all the files in the backup set that come after
235      * lastFileCopiedInPrevBackup.
236      */

237     public synchronized
238         String JavaDoc[] getLogFilesInBackupSet(long lastFileCopiedInPrevBackup)
239         throws DatabaseException {
240     
241         checkBackupStarted();
242         FileManager fileManager = envImpl.getFileManager();
243         return fileManager.listFiles(lastFileCopiedInPrevBackup + 1,
244                                       lastFileInBackupSet);
245     }
246
247     private void checkBackupStarted()
248         throws DatabaseException {
249
250         if (!backupStarted) {
251             throw new DatabaseException( this.getClass().getName() +
252                                          ".startBackup was not called");
253         }
254     }
255 }
256
Popular Tags