Mercurial > hg > Database > jungle-network
comparison src/main/java/app/bbs/PersistentJungleBulletinBoard.java @ 124:dacfa7eba841
To select persistent mode "-persistent"
author | one |
---|---|
date | Sat, 11 Jan 2014 06:33:54 +0900 |
parents | |
children | 6104702a1880 |
comparison
equal
deleted
inserted
replaced
123:495ac60d7f5f | 124:dacfa7eba841 |
---|---|
1 package app.bbs; | |
2 | |
3 import java.io.File; | |
4 import java.io.FileNotFoundException; | |
5 import java.io.IOException; | |
6 import java.nio.ByteBuffer; | |
7 import java.util.Date; | |
8 import java.util.concurrent.atomic.AtomicInteger; | |
9 | |
10 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.Jungle; | |
11 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree; | |
12 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTreeEditor; | |
13 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Children; | |
14 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Node; | |
15 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeList; | |
16 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeListReader; | |
17 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNodePath; | |
18 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultTreeEditor; | |
19 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.EditableNode; | |
20 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.NodeEditor; | |
21 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.DefaultTraverser; | |
22 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.DefaultEither; | |
23 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either; | |
24 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error; | |
25 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.IterableConverter; | |
26 import alice.jungle.core.NetworkDefaultJungle; | |
27 import alice.jungle.persistent.PersistentJournal; | |
28 import alice.jungle.transaction.JungleUpdater; | |
29 | |
30 public class PersistentJungleBulletinBoard implements NetworkBulletinBoard | |
31 { | |
32 private final Jungle jungle; | |
33 private final PersistentJournal journal; | |
34 private final String LOG_DIR = "./log"; | |
35 | |
36 public PersistentJungleBulletinBoard(String _uuid) throws FileNotFoundException | |
37 { | |
38 journal = new PersistentJournal(); | |
39 jungle = new NetworkDefaultJungle(journal, _uuid,new DefaultTreeEditor(new DefaultTraverser())); | |
40 BullentInBoardJungleManager.setJungle(jungle); | |
41 } | |
42 | |
43 public void init() { | |
44 checkAndCreateLogDirectory(); | |
45 try { | |
46 commitLogRecover(); | |
47 } catch (IOException e) { | |
48 e.printStackTrace(); | |
49 } | |
50 } | |
51 | |
52 public void checkAndCreateLogDirectory() { | |
53 File logFile = new File(LOG_DIR); | |
54 if(!logFile.exists()) { | |
55 logFile.mkdir(); | |
56 return; | |
57 } | |
58 if (logFile.isFile()) { | |
59 logFile.delete(); | |
60 logFile.mkdir(); | |
61 } | |
62 } | |
63 | |
64 public void commitLogRecover() throws IOException { | |
65 File[] logFiles = new File(LOG_DIR).listFiles(); | |
66 for(File logFile : logFiles) { | |
67 commitLogRecover(logFile); | |
68 logFile.delete(); | |
69 } | |
70 if(jungle.getTreeByName("boards") == null) { | |
71 jungle.createNewTree("boards"); | |
72 } | |
73 } | |
74 | |
75 private void commitLogRecover(File logFile) throws IOException { | |
76 journal.setInputFile(logFile); | |
77 ChangeListReader reader = journal.getReader(); | |
78 if (reader == null) return; | |
79 for (ChangeList chList : reader) { | |
80 String treeName = chList.getTreeName(); | |
81 JungleTree tree = jungle.getTreeByName(treeName); | |
82 if(tree == null) { | |
83 tree = jungle.createNewTree(treeName); | |
84 } | |
85 JungleTreeEditor editor = tree.getLocalTreeEditor(); | |
86 Either<Error, JungleTreeEditor> either = JungleUpdater.edit(editor, chList); | |
87 editor = either.b(); | |
88 if(either.isA()) { | |
89 throw new IOException("Failed commit log recovery"); | |
90 } | |
91 editor.success(); | |
92 } | |
93 } | |
94 | |
95 public Iterable<String> getBoards() | |
96 { | |
97 JungleTree tree = jungle.getTreeByName("boards"); | |
98 Node node = tree.getRootNode(); | |
99 Children<Node> chs = node.getChildren(); | |
100 | |
101 IterableConverter.Converter<String,Node> converter = new IterableConverter.Converter<String,Node>(){ | |
102 public String conv(Node _b) { | |
103 ByteBuffer e = _b.getAttributes().get("name"); | |
104 return new String(e.array()); | |
105 } | |
106 }; | |
107 | |
108 return new IterableConverter<String,Node>(chs,converter); | |
109 } | |
110 | |
111 public void createBoards(final String _name,final String _author,final String _initMessage,final String _editKey) | |
112 { | |
113 if(null == jungle.createNewTree(_name)){ | |
114 throw new IllegalStateException(); | |
115 } | |
116 | |
117 JungleTree tree = jungle.getTreeByName("boards"); | |
118 JungleTreeEditor editor = tree.getTreeEditor(); | |
119 DefaultNodePath root = new DefaultNodePath(); | |
120 Either<Error,JungleTreeEditor> either = editor.addNewChildAt(root,0); | |
121 if(either.isA()){ | |
122 throw new IllegalStateException(); | |
123 } | |
124 editor = either.b(); | |
125 | |
126 either = editor.putAttribute(root.add(0),"name",ByteBuffer.wrap(_name.getBytes())); | |
127 if(either.isA()){ | |
128 throw new IllegalStateException(); | |
129 } | |
130 editor = either.b(); | |
131 Either<Error,JungleTreeEditor> result = editor.success(); | |
132 if(result.isA()){ | |
133 throw new IllegalStateException(); | |
134 } | |
135 final long timestamp = new Date().getTime(); | |
136 | |
137 | |
138 tree = jungle.getTreeByName(_name); | |
139 editor = tree.getTreeEditor(); | |
140 either = editor.addNewChildAt(root,0); | |
141 if(either.isA()){ | |
142 throw new IllegalStateException(); | |
143 } | |
144 editor = either.b(); | |
145 | |
146 NodeEditor e = new NodeEditor(){ | |
147 public <T extends EditableNode<T>> Either<Error, T> edit(T _e){ | |
148 _e = _e.getAttributes().put("author",ByteBuffer.wrap(_author.getBytes())).b(); | |
149 _e = _e.getAttributes().put("mes",ByteBuffer.wrap(_initMessage.getBytes())).b(); | |
150 _e = _e.getAttributes().put("key",ByteBuffer.wrap(_editKey.getBytes())).b(); | |
151 ByteBuffer tBuffer = ByteBuffer.allocate(16); | |
152 _e = _e.getAttributes().put("timestamp",tBuffer.putLong(timestamp)).b(); | |
153 return DefaultEither.newB(_e); | |
154 } | |
155 }; | |
156 | |
157 either = editor.edit(root.add(0),e); | |
158 if(either.isA()){ | |
159 throw new IllegalStateException(); | |
160 } | |
161 editor = either.b(); | |
162 editor.success(); | |
163 } | |
164 | |
165 public void createBoardMessage(final String _board,final String _author,final String _message,final String _editKey) | |
166 { | |
167 JungleTree tree = jungle.getTreeByName(_board); | |
168 if(tree == null){ | |
169 throw new IllegalStateException(); | |
170 } | |
171 | |
172 Either<Error, JungleTreeEditor> either; | |
173 do{ | |
174 Node node = tree.getRootNode(); | |
175 int size = node.getChildren().size(); | |
176 DefaultNodePath path = new DefaultNodePath(); | |
177 | |
178 JungleTreeEditor editor = tree.getTreeEditor(); | |
179 either = editor.addNewChildAt(path,size); | |
180 if(either.isA()){ | |
181 throw new IllegalStateException(); | |
182 } | |
183 editor = either.b(); | |
184 final long timestamp = new Date().getTime(); | |
185 NodeEditor e = new NodeEditor(){ | |
186 public <T extends EditableNode<T>> Either<Error, T> edit(T _e){ | |
187 _e = _e.getAttributes().put("author",ByteBuffer.wrap(_author.getBytes())).b(); | |
188 _e = _e.getAttributes().put("mes",ByteBuffer.wrap(_message.getBytes())).b(); | |
189 _e = _e.getAttributes().put("key",ByteBuffer.wrap(_editKey.getBytes())).b(); | |
190 ByteBuffer tBuffer = ByteBuffer.allocate(16); | |
191 _e = _e.getAttributes().put("timestamp",tBuffer.putLong(timestamp)).b(); | |
192 return DefaultEither.newB(_e); | |
193 } | |
194 }; | |
195 path = path.add(size); | |
196 either = editor.edit(path,e); | |
197 if(either.isA()){ | |
198 throw new IllegalStateException(); | |
199 } | |
200 editor = either.b(); | |
201 either = editor.success(); | |
202 | |
203 }while(either.isA()); | |
204 } | |
205 | |
206 public void editMessage(String _board,String _uuid,final String _author,final String _message,final String _editKey) | |
207 { | |
208 for(;;) { | |
209 DefaultNodePath path = new DefaultNodePath(); | |
210 path = path.add(Integer.parseInt(_uuid)); | |
211 | |
212 JungleTree tree = jungle.getTreeByName(_board); | |
213 JungleTreeEditor editor = tree.getTreeEditor(); | |
214 final long timestamp = new Date().getTime(); | |
215 NodeEditor e = new NodeEditor(){ | |
216 public <T extends EditableNode<T>> Either<Error, T> edit(T _e){ | |
217 _e = _e.getAttributes().put("author",ByteBuffer.wrap(_author.getBytes())).b(); | |
218 _e = _e.getAttributes().put("mes",ByteBuffer.wrap(_message.getBytes())).b(); | |
219 _e = _e.getAttributes().put("key",ByteBuffer.wrap(_editKey.getBytes())).b(); | |
220 ByteBuffer tBuffer = ByteBuffer.allocate(16); | |
221 _e = _e.getAttributes().put("timestamp",tBuffer.putLong(timestamp)).b(); | |
222 return DefaultEither.newB(_e); | |
223 } | |
224 }; | |
225 | |
226 Either<Error, JungleTreeEditor> either = editor.edit(path,e); | |
227 if(either.isA()){ | |
228 throw new IllegalStateException(); | |
229 } | |
230 editor = either.b(); | |
231 either = editor.success(); | |
232 if(!either.isA()) { | |
233 return; | |
234 } | |
235 } | |
236 | |
237 } | |
238 | |
239 public Iterable<BoardMessage> getMessages(String _boardName) | |
240 { | |
241 JungleTree tree = jungle.getTreeByName(_boardName); | |
242 Node node = tree.getRootNode(); | |
243 Children<Node> chs = node.getChildren(); | |
244 | |
245 final AtomicInteger counter = new AtomicInteger(0); | |
246 IterableConverter.Converter<BoardMessage,Node> converter = new IterableConverter.Converter<BoardMessage,Node>(){ | |
247 public BoardMessage conv(Node _b) { | |
248 String uuid = Integer.toString(counter.get()); | |
249 String author = new String(_b.getAttributes().get("author").array()); | |
250 String message = new String(_b.getAttributes().get("mes").array()); | |
251 counter.incrementAndGet(); | |
252 return new BoardMessageImpl(author,message,uuid); | |
253 } | |
254 }; | |
255 return new IterableConverter<BoardMessage,Node>(chs,converter); | |
256 } | |
257 | |
258 | |
259 | |
260 private static class BoardMessageImpl implements BoardMessage | |
261 { | |
262 private final String author; | |
263 private final String message; | |
264 private final String uuid; | |
265 | |
266 public BoardMessageImpl(String _author,String _message,String _uuid) | |
267 { | |
268 author = _author; | |
269 message = _message; | |
270 uuid = _uuid; | |
271 } | |
272 | |
273 public String getAuthor() | |
274 { | |
275 return author; | |
276 } | |
277 | |
278 public String getMessage() | |
279 { | |
280 return message; | |
281 } | |
282 | |
283 public String getUUID() | |
284 { | |
285 return uuid; | |
286 } | |
287 } | |
288 | |
289 | |
290 | |
291 } |