]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.acorn/src/org/simantics/acorn/internal/AcornDatabase.java
Merge commit '5da68e7'
[simantics/platform.git] / bundles / org.simantics.acorn / src / org / simantics / acorn / internal / AcornDatabase.java
1 package org.simantics.acorn.internal;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.RandomAccessFile;
6 import java.nio.channels.FileLock;
7 import java.nio.file.DirectoryStream;
8 import java.nio.file.FileVisitOption;
9 import java.nio.file.FileVisitResult;
10 import java.nio.file.Files;
11 import java.nio.file.Path;
12 import java.nio.file.SimpleFileVisitor;
13 import java.nio.file.attribute.BasicFileAttributes;
14 import java.util.EnumSet;
15 import java.util.Properties;
16
17 import org.simantics.acorn.GraphClientImpl2;
18 import org.simantics.db.Database;
19 import org.simantics.db.DatabaseUserAgent;
20 import org.simantics.db.ServiceLocator;
21 import org.simantics.db.common.utils.Logger;
22 import org.simantics.db.server.ProCoreException;
23
24 /**
25  * @author Tuukka Lehtonen
26  */
27 public class AcornDatabase implements Database {
28
29     private final Path folder;
30
31     private DatabaseUserAgent userAgent;
32
33     private RandomAccessFile raLockFile;
34
35     private FileLock lock;
36
37     private boolean isRunning;
38
39     public AcornDatabase(Path folder) {
40         this.folder = folder;
41     }
42
43     @Override
44     public DatabaseUserAgent getUserAgent() {
45         return userAgent;
46     }
47
48     @Override
49     public void setUserAgent(DatabaseUserAgent dbUserAgent) {
50         userAgent = dbUserAgent;
51     }
52
53     @Override
54     public Status getStatus() {
55         return Status.Local;
56     }
57
58     @Override
59     public File getFolder() {
60         return folder.toFile();
61     }
62
63     @Override
64     public boolean isFolderOk() {
65         return isFolderOk(folder.toFile());
66     }
67
68     @Override
69     public boolean isFolderOk(File aFolder) {
70         if (!aFolder.isDirectory())
71             return false;
72         return true;
73     }
74
75     @Override
76     public boolean isFolderEmpty() {
77         return isFolderEmpty(folder.toFile());
78     }
79
80     @Override
81     public boolean isFolderEmpty(File aFolder) {
82         Path path = aFolder.toPath();
83         if (!Files.isDirectory(path))
84             return false;
85         try (DirectoryStream<Path> folderStream = Files.newDirectoryStream(path)) {
86             return !folderStream.iterator().hasNext();
87         } catch (IOException e) {
88             Logger.defaultLogError("Failed to open folder stream. folder=" + path, e);
89             return false;
90         }
91     }
92
93     @Override
94     public void initFolder(Properties properties) throws ProCoreException {
95         try {
96             Files.createDirectories(folder);
97         } catch (IOException e) {
98             throw new ProCoreException(e);
99         }
100     }
101
102     @Override
103     public void deleteFiles() throws ProCoreException {
104         deleteTree(folder);
105     }
106
107     @Override
108     public void start() throws ProCoreException {
109         Path lockFile = folder.resolve("lock");
110         try {
111             if (!Files.exists(lockFile))
112                 Files.createFile(lockFile);
113             
114             raLockFile = new RandomAccessFile(lockFile.toFile(), "rw");
115             lock = raLockFile.getChannel().tryLock();
116             if (lock == null) {
117                 throw new ProCoreException("The database in folder " + folder.toAbsolutePath() + " is already in use!");
118             }
119             
120             isRunning = true;
121             
122         } catch (IOException e) {
123             e.printStackTrace();
124         }
125     }
126
127     @Override
128     public boolean isRunning() throws ProCoreException {
129         return isRunning;
130     }
131
132     @Override
133     public boolean tryToStop() throws ProCoreException {
134         try {
135             lock.release();
136             raLockFile.close();
137             
138             Files.deleteIfExists(folder.resolve("lock"));
139             
140             isRunning = false;
141             
142         } catch (IOException e) {
143             e.printStackTrace();
144         }
145         
146         return true;
147     }
148
149     @Override
150     public void connect() throws ProCoreException {
151     }
152
153     @Override
154     public boolean isConnected() throws ProCoreException {
155         return isRunning;
156     }
157
158     @Override
159     public String execute(String command) throws ProCoreException {
160         throw new UnsupportedOperationException("execute(" + command + ")");
161     }
162
163     @Override
164     public void disconnect() throws ProCoreException {
165     }
166
167     @Override
168     public void clone(File to, int revision, boolean saveHistory) throws ProCoreException {
169         // TODO: implement
170         throw new UnsupportedOperationException();
171     }
172
173     @Override
174     public Path createFromChangeSets(int revision) throws ProCoreException {
175         // TODO: implement
176         throw new UnsupportedOperationException();
177     }
178
179     @Override
180     public void deleteGuard() throws ProCoreException {
181         // TODO: implement
182         throw new UnsupportedOperationException();
183     }
184
185     @Override
186     public Path dumpChangeSets() throws ProCoreException {
187         // TODO: implement
188         throw new UnsupportedOperationException();
189     }
190
191     @Override
192     public void purgeDatabase() throws ProCoreException {
193         // TODO: implement
194         throw new UnsupportedOperationException();
195     }
196
197     @Override
198     public long serverGetTailChangeSetId() throws ProCoreException {
199         // "We have it all"
200         // But after purging we don't so beware.
201         // TODO: beware for purge
202         return 1;
203     }
204
205     @Override
206     public Session newSession(ServiceLocator locator) throws ProCoreException {
207         try {
208             return new GraphClientImpl2(this, folder, locator);
209         } catch (IOException e) {
210             throw new ProCoreException(e);
211         }
212     }
213
214     @Override
215     public Journal getJournal() throws ProCoreException {
216         // TODO: implement
217         throw new UnsupportedOperationException();
218     }
219
220     private static void deleteTree(Path path) throws ProCoreException {
221         if (!Files.exists(path))
222             return;
223
224         class Visitor extends SimpleFileVisitor<Path> {
225             @Override
226             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
227                 try {
228                     Files.delete(file);
229                 } catch (IOException ioe) {
230                     ioe.printStackTrace();
231                     throw ioe;
232                 }
233                 return FileVisitResult.CONTINUE;
234             }
235             @Override
236             public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
237                 if (e == null) {
238                     try {
239                         Files.delete(dir);
240                     } catch (IOException ioe) {
241                         ioe.printStackTrace();
242                         throw ioe;
243                     }
244                     return FileVisitResult.CONTINUE;
245                 }
246                 throw e;
247             }
248         }
249         try {
250             Visitor v = new Visitor();
251             EnumSet<FileVisitOption> opts = EnumSet.noneOf(FileVisitOption.class);
252             Files.walkFileTree(path, opts, Integer.MAX_VALUE, v);
253         } catch (IOException e) {
254             throw new ProCoreException("Could not delete " + path, e);
255         }
256     }
257
258         @Override
259         public String getCompression() {
260                 return "LZ4";
261         }
262
263 }