1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.store; |
7 | |
8 | import java.io.IOException; |
9 | import java.nio.channels.FileChannel; |
10 | import java.sql.SQLException; |
11 | import java.util.ArrayList; |
12 | import java.util.List; |
13 | |
14 | import org.h2.api.ErrorCode; |
15 | import org.h2.engine.Constants; |
16 | import org.h2.message.DbException; |
17 | import org.h2.message.TraceSystem; |
18 | import org.h2.store.fs.FilePath; |
19 | import org.h2.store.fs.FileUtils; |
20 | import org.h2.util.New; |
21 | |
22 | /** |
23 | * Utility class to list the files of a database. |
24 | */ |
25 | public class FileLister { |
26 | |
27 | private FileLister() { |
28 | // utility class |
29 | } |
30 | |
31 | /** |
32 | * Try to lock the database, and then unlock it. If this worked, the |
33 | * .lock.db file will be removed. |
34 | * |
35 | * @param files the database files to check |
36 | * @param message the text to include in the error message |
37 | * @throws SQLException if it failed |
38 | */ |
39 | public static void tryUnlockDatabase(List<String> files, String message) |
40 | throws SQLException { |
41 | for (String fileName : files) { |
42 | if (fileName.endsWith(Constants.SUFFIX_LOCK_FILE)) { |
43 | FileLock lock = new FileLock(new TraceSystem(null), fileName, |
44 | Constants.LOCK_SLEEP); |
45 | try { |
46 | lock.lock(FileLock.LOCK_FILE); |
47 | lock.unlock(); |
48 | } catch (DbException e) { |
49 | throw DbException.get( |
50 | ErrorCode.CANNOT_CHANGE_SETTING_WHEN_OPEN_1, |
51 | message).getSQLException(); |
52 | } |
53 | } else if (fileName.endsWith(Constants.SUFFIX_MV_FILE)) { |
54 | FileChannel f = null; |
55 | try { |
56 | f = FilePath.get(fileName).open("r"); |
57 | java.nio.channels.FileLock lock = f.tryLock(0, Long.MAX_VALUE, true); |
58 | lock.release(); |
59 | } catch (Exception e) { |
60 | throw DbException.get( |
61 | ErrorCode.CANNOT_CHANGE_SETTING_WHEN_OPEN_1, e, |
62 | message).getSQLException(); |
63 | } finally { |
64 | if (f != null) { |
65 | try { |
66 | f.close(); |
67 | } catch (IOException e) { |
68 | // ignore |
69 | } |
70 | } |
71 | } |
72 | } |
73 | } |
74 | } |
75 | |
76 | /** |
77 | * Normalize the directory name. |
78 | * |
79 | * @param dir the directory (null for the current directory) |
80 | * @return the normalized directory name |
81 | */ |
82 | public static String getDir(String dir) { |
83 | if (dir == null || dir.equals("")) { |
84 | return "."; |
85 | } |
86 | return FileUtils.toRealPath(dir); |
87 | } |
88 | |
89 | /** |
90 | * Get the list of database files. |
91 | * |
92 | * @param dir the directory (must be normalized) |
93 | * @param db the database name (null for all databases) |
94 | * @param all if true, files such as the lock, trace, and lob |
95 | * files are included. If false, only data, index, log, |
96 | * and lob files are returned |
97 | * @return the list of files |
98 | */ |
99 | public static ArrayList<String> getDatabaseFiles(String dir, String db, |
100 | boolean all) { |
101 | ArrayList<String> files = New.arrayList(); |
102 | // for Windows, File.getCanonicalPath("...b.") returns just "...b" |
103 | String start = db == null ? null : (FileUtils.toRealPath(dir + "/" + db) + "."); |
104 | for (String f : FileUtils.newDirectoryStream(dir)) { |
105 | boolean ok = false; |
106 | if (f.endsWith(Constants.SUFFIX_LOBS_DIRECTORY)) { |
107 | if (start == null || f.startsWith(start)) { |
108 | files.addAll(getDatabaseFiles(f, null, all)); |
109 | ok = true; |
110 | } |
111 | } else if (f.endsWith(Constants.SUFFIX_LOB_FILE)) { |
112 | ok = true; |
113 | } else if (f.endsWith(Constants.SUFFIX_PAGE_FILE)) { |
114 | ok = true; |
115 | } else if (f.endsWith(Constants.SUFFIX_MV_FILE)) { |
116 | ok = true; |
117 | } else if (all) { |
118 | if (f.endsWith(Constants.SUFFIX_LOCK_FILE)) { |
119 | ok = true; |
120 | } else if (f.endsWith(Constants.SUFFIX_TEMP_FILE)) { |
121 | ok = true; |
122 | } else if (f.endsWith(Constants.SUFFIX_TRACE_FILE)) { |
123 | ok = true; |
124 | } |
125 | } |
126 | if (ok) { |
127 | if (db == null || f.startsWith(start)) { |
128 | String fileName = f; |
129 | files.add(fileName); |
130 | } |
131 | } |
132 | } |
133 | return files; |
134 | } |
135 | |
136 | } |