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 }