]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.common/src/org/simantics/db/common/processor/MergingGraphRequestProcessor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.common / src / org / simantics / db / common / processor / MergingGraphRequestProcessor.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.db.common.processor;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.Collection;\r
16 import java.util.HashMap;\r
17 import java.util.HashSet;\r
18 import java.util.LinkedList;\r
19 import java.util.Set;\r
20 import java.util.UUID;\r
21 import java.util.concurrent.Semaphore;\r
22 \r
23 import org.simantics.db.AsyncReadGraph;\r
24 import org.simantics.db.AsyncRequestProcessor;\r
25 import org.simantics.db.ReadGraph;\r
26 import org.simantics.db.RequestProcessor;\r
27 import org.simantics.db.Resource;\r
28 import org.simantics.db.Session;\r
29 import org.simantics.db.VirtualGraph;\r
30 import org.simantics.db.WriteGraph;\r
31 import org.simantics.db.common.procedure.adapter.AsyncMultiProcedureAdapter;\r
32 import org.simantics.db.common.procedure.adapter.ProcedureAdapter;\r
33 import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure;\r
34 import org.simantics.db.common.request.ReadRequest;\r
35 import org.simantics.db.common.request.WriteRequest;\r
36 import org.simantics.db.common.utils.Logger;\r
37 import org.simantics.db.exception.CancelTransactionException;\r
38 import org.simantics.db.exception.DatabaseException;\r
39 import org.simantics.db.procedure.AsyncListener;\r
40 import org.simantics.db.procedure.AsyncMultiListener;\r
41 import org.simantics.db.procedure.AsyncMultiProcedure;\r
42 import org.simantics.db.procedure.AsyncProcedure;\r
43 import org.simantics.db.procedure.Listener;\r
44 import org.simantics.db.procedure.MultiListener;\r
45 import org.simantics.db.procedure.MultiProcedure;\r
46 import org.simantics.db.procedure.Procedure;\r
47 import org.simantics.db.procedure.SyncListener;\r
48 import org.simantics.db.procedure.SyncMultiListener;\r
49 import org.simantics.db.procedure.SyncMultiProcedure;\r
50 import org.simantics.db.procedure.SyncProcedure;\r
51 import org.simantics.db.request.AsyncMultiRead;\r
52 import org.simantics.db.request.AsyncRead;\r
53 import org.simantics.db.request.DelayedWrite;\r
54 import org.simantics.db.request.DelayedWriteResult;\r
55 import org.simantics.db.request.ExternalRead;\r
56 import org.simantics.db.request.MultiRead;\r
57 import org.simantics.db.request.Read;\r
58 import org.simantics.db.request.ReadInterface;\r
59 import org.simantics.db.request.UndoTraits;\r
60 import org.simantics.db.request.Write;\r
61 import org.simantics.db.request.WriteInterface;\r
62 import org.simantics.db.request.WriteOnly;\r
63 import org.simantics.db.request.WriteOnlyResult;\r
64 import org.simantics.db.request.WriteResult;\r
65 import org.simantics.utils.DataContainer;\r
66 import org.simantics.utils.datastructures.Callback;\r
67 import org.simantics.utils.datastructures.Pair;\r
68 \r
69 public class MergingGraphRequestProcessor implements RequestProcessor {\r
70 \r
71     private static class SyncWriteRequestAdapter implements Write {\r
72 \r
73         private Semaphore semaphore = new Semaphore(0);\r
74         private Object request;\r
75         private Throwable exception;\r
76         SyncWriteRequestAdapter(Write r) {\r
77             this.request = r;\r
78         }\r
79         SyncWriteRequestAdapter(WriteOnly r) {\r
80             this.request = r;\r
81         }\r
82 //        @Override\r
83 //        public GraphRequestStatus perform(Graph g) throws Exception {\r
84 //            return perform((ReadGraph)g);\r
85 //        }\r
86         @Override\r
87         public void perform(WriteGraph g) throws DatabaseException, CancelTransactionException {\r
88             if(request instanceof Write) {\r
89                 ((Write)request).perform(g);\r
90             } else if(request instanceof DelayedWrite) {\r
91                     ((DelayedWrite)request).perform(g);\r
92             } else {\r
93                 ((WriteOnly)request).perform(g);\r
94             }\r
95         }\r
96 //        @Override\r
97 //        public String getId() {\r
98 //            if(request instanceof WriteGraphRequest) {\r
99 //                return ((WriteGraphRequest)request).getId();\r
100 //            } else {\r
101 //                return null;\r
102 //            }\r
103 //        }\r
104 //        @Override\r
105 //        public void requestCompleted(GraphRequestStatus status) {\r
106 //            if(request instanceof WriteGraphRequest) {\r
107 //                ((WriteGraphRequest)request).requestCompleted(status);\r
108 //            } else {\r
109 //            }\r
110 //        }\r
111 //        @Override\r
112 //        public void handleException(Throwable e) {\r
113 //            this.exception = e;\r
114 //            if(request instanceof WriteGraphRequest) {\r
115 //                ((WriteGraphRequest)request).handleException(e);\r
116 //            }\r
117 //        }\r
118 \r
119         public void throwOrWrapException() {\r
120             if (exception == null)\r
121                 return;\r
122             if (exception instanceof RuntimeException)\r
123                 throw (RuntimeException) exception;\r
124             if (exception instanceof Error)\r
125                 throw (Error) exception;\r
126             throw new RuntimeException("See cause for the real exception.", exception);\r
127         }\r
128 \r
129         @Override\r
130         public VirtualGraph getProvider() {\r
131             return null;\r
132         }\r
133 \r
134 //        @Override\r
135 //        public void fillMetadata(Map<String, String> metadata) {\r
136 //        }\r
137 \r
138         public void acquire() {\r
139             try {\r
140                 semaphore.acquire();\r
141             } catch (InterruptedException e) {\r
142                         Logger.defaultLogError(e);\r
143             }\r
144         }\r
145 \r
146         public void release() {\r
147             semaphore.release();\r
148         }\r
149 \r
150         @Override\r
151         public UndoTraits getUndoTraits() {\r
152             return null;\r
153         }\r
154         \r
155         @Override\r
156         public String toString() {\r
157             return "SyncWriteRequestAdapter " + request;\r
158         }\r
159 \r
160     }\r
161 \r
162     long transactionKeepalivePeriod;\r
163 \r
164     /**\r
165      * Synchronization object for implementing {@link #synchronize()}.\r
166      * {@link Object#notifyAll()} is invoked for this lock object every time a\r
167      * single transaction is completed, thereby releasing all waiters in\r
168      * {@link #synchronize()}.\r
169      */\r
170     Object barrier = new Object();\r
171 \r
172     Set<Pair<Object, Object>> requestSet = new HashSet<Pair<Object, Object>>();\r
173     LinkedList<Pair<Object, Object>> requestQueue = new LinkedList<Pair<Object, Object>>();\r
174     boolean hasAlreadyRequest = false;\r
175 \r
176     /**\r
177      * A set of requests which {@link #synchronize()} is depending on at the\r
178      * moment. Every time a request within this set is completed, some thread in\r
179      * {@link #synchronize()} should be released.\r
180      */\r
181 //    Set<Object> barrierRequests = new HashSet<Object>();\r
182     Set<Object> syncRequests = new HashSet<Object>();\r
183 \r
184     private String name;\r
185 \r
186     private AsyncRequestProcessor processor;\r
187 \r
188     public MergingGraphRequestProcessor(String name, AsyncRequestProcessor processor, long transactionKeepalivePeriod) {\r
189         this.name = name;\r
190         this.processor = processor;\r
191         this.transactionKeepalivePeriod = transactionKeepalivePeriod;\r
192     }\r
193 \r
194     public MergingGraphRequestProcessor(AsyncRequestProcessor processor, long transactionKeepalivePeriod) {\r
195         this.name = "MergingGraphRequestProcessor" + UUID.randomUUID().toString();\r
196         this.processor = processor;\r
197         this.transactionKeepalivePeriod = transactionKeepalivePeriod;\r
198     }\r
199 \r
200     @SuppressWarnings({"unchecked", "rawtypes"})\r
201     protected class MergedRead extends ReadRequest {\r
202 \r
203         Pair<Object, Object> currentRequest;\r
204 \r
205 //        RunnerReadGraphRequest(GraphRequestProcessor processor) {\r
206 //            super(processor);\r
207 //        }\r
208 //\r
209 //        @Override\r
210 //        public void completed(boolean value) {\r
211 ////            System.out.println(this + "MGRP read completed");\r
212 ////            synchronized (MergingGraphRequestProcessor.this) {\r
213 ////                if (requestQueue.isEmpty())\r
214 ////                    hasAlreadyRequest = false;\r
215 ////                else\r
216 ////                    newTransaction();\r
217 ////            }\r
218 //        }\r
219 \r
220         @Override\r
221         public void run(ReadGraph graph) {\r
222 \r
223 //            System.out.println(MergingGraphRequestProcessor.this + " reads");\r
224 \r
225             while (true) {\r
226 \r
227                 synchronized (MergingGraphRequestProcessor.this) {\r
228 \r
229                     // Release #synchronize() invokers if necessary.\r
230 //                    if (currentRequest != null && barrierRequests.contains(currentRequest)) {\r
231 //                        synchronized (barrier) {\r
232 //                            barrier.notifyAll();\r
233 //                        }\r
234 //                    }\r
235 \r
236                     if(requestQueue.isEmpty()) {\r
237                         if (transactionKeepalivePeriod > 0) {\r
238 //                            System.out.println("MGRP [" + MergingGraphRequestProcessor.this + "] waits " + transactionKeepalivePeriod + " ms. in " + Thread.currentThread() );\r
239                             try {\r
240                                 MergingGraphRequestProcessor.this.wait(transactionKeepalivePeriod);\r
241                             } catch (InterruptedException e) {\r
242                                         Logger.defaultLogError(e);\r
243                             }\r
244                             if (requestQueue.isEmpty())\r
245                                 break;\r
246                         } else\r
247                             break;\r
248                     }\r
249 \r
250                     Object nextRequest = requestQueue.peekFirst().first;\r
251                     if(nextRequest instanceof Write || nextRequest instanceof DelayedWrite) {\r
252                         break;\r
253                     }\r
254 \r
255                     currentRequest = requestQueue.remove(0);\r
256                     requestSet.remove(currentRequest);\r
257 \r
258                 }\r
259 \r
260 //                ReadGraphRequest req = (ReadGraphRequest)currentRequest.first;\r
261 \r
262                 if( syncRequests.contains(currentRequest.first)) {\r
263 \r
264                     try {\r
265 \r
266                         if(currentRequest.second instanceof AsyncProcedure<?>) {\r
267                             if(currentRequest.first instanceof Read) {\r
268                                 Read req = (Read)currentRequest.first;\r
269                                 graph.syncRequest(req, (AsyncProcedure<?>)currentRequest.second);\r
270                             } else {\r
271                                 AsyncRead req = (AsyncRead)currentRequest.first;\r
272                                 graph.syncRequest(req, (AsyncProcedure<?>)currentRequest.second);\r
273                             }\r
274                         } else {\r
275                             AsyncMultiRead req = (AsyncMultiRead)currentRequest.first;\r
276                             graph.syncRequest(req, (AsyncMultiProcedure<?>)currentRequest.second);\r
277                         }\r
278 \r
279                     } catch(Throwable t) {\r
280 \r
281                                 Logger.defaultLogError(t);\r
282 \r
283                         if(currentRequest.second instanceof AsyncProcedure<?>) {\r
284                             ((AsyncProcedure<?>)currentRequest.second).exception(graph, t);\r
285                         } else {\r
286                             ((AsyncMultiProcedure<?>)currentRequest.second).exception(graph, t);\r
287                         }\r
288 \r
289                     }\r
290 \r
291                     synchronized (currentRequest.first) {\r
292                         syncRequests.remove(currentRequest.first);\r
293 //                      System.out.println("notifying " + currentRequest.first);\r
294                         currentRequest.first.notify();\r
295                     }\r
296 \r
297 \r
298                 } else {\r
299 \r
300                     try{\r
301 \r
302                         if(currentRequest.second instanceof AsyncProcedure<?>) {\r
303                             if(currentRequest.first instanceof AsyncRead) {\r
304                                 AsyncRead req = (AsyncRead)currentRequest.first;\r
305                                 graph.asyncRequest(req, (AsyncProcedure<?>)currentRequest.second);\r
306                             } else {\r
307                                 Read req = (Read)currentRequest.first;\r
308                                 graph.asyncRequest(req, (AsyncProcedure<?>)currentRequest.second);\r
309                             }\r
310                         } else {\r
311                             AsyncMultiRead req = (AsyncMultiRead)currentRequest.first;\r
312                             graph.asyncRequest(req, (AsyncMultiProcedure<?>)currentRequest.second);\r
313                         }\r
314 \r
315                     } catch(Throwable t) {\r
316 \r
317                                 Logger.defaultLogError(t);\r
318 \r
319                         if(currentRequest.second instanceof AsyncProcedure<?>) {\r
320                             ((AsyncProcedure<?>)currentRequest.second).exception(graph, t);\r
321                         } else {\r
322                             ((AsyncMultiProcedure<?>)currentRequest.second).exception(graph, t);\r
323                         }\r
324 \r
325                     }\r
326                 }\r
327 \r
328             }\r
329 \r
330 //            System.out.println(MergingGraphRequestProcessor.this + " read completed");\r
331 \r
332             synchronized (MergingGraphRequestProcessor.this) {\r
333                 if (requestQueue.isEmpty())\r
334                     hasAlreadyRequest = false;\r
335                 else\r
336                     newTransaction();\r
337             }\r
338 \r
339         }\r
340 \r
341         @Override\r
342         public String toString() {\r
343             return "MergedRead[" + requestQueue.size() + " requests]";\r
344         }\r
345 \r
346     }\r
347 \r
348     protected class RunnerWriteGraphRequest extends WriteRequest {\r
349 \r
350         Pair<Object, Object> currentRequest;\r
351         HashMap<String, String> metadata = new HashMap<String, String>();\r
352 \r
353         @Override\r
354         public void perform(WriteGraph graph) throws DatabaseException {\r
355 \r
356 //            System.out.println(MergingGraphRequestProcessor.this + " writes");\r
357 \r
358             while (true) {\r
359 \r
360                 synchronized (MergingGraphRequestProcessor.this) {\r
361 \r
362                     // Release #synchronize() invokers if necessary.\r
363 //                    if (currentRequest != null && barrierRequests.contains(currentRequest)) {\r
364 //                        synchronized (barrier) {\r
365 //                            barrier.notifyAll();\r
366 //                        }\r
367 //                    }\r
368 \r
369                     if(requestQueue.isEmpty()) {\r
370                         if (transactionKeepalivePeriod > 0) {\r
371                             try {\r
372                                 MergingGraphRequestProcessor.this.wait(transactionKeepalivePeriod);\r
373                             } catch (InterruptedException e) {\r
374                                         Logger.defaultLogError(e);\r
375                             }\r
376                             if (requestQueue.isEmpty())\r
377                                 break;\r
378                         } else\r
379                             break;\r
380                     }\r
381 \r
382                     Object nextRequest = requestQueue.peekFirst().first;\r
383                     if(nextRequest instanceof AsyncMultiRead || nextRequest instanceof AsyncRead || nextRequest instanceof Read) {\r
384                         break;\r
385                     }\r
386 \r
387                     currentRequest = requestQueue.remove(0);\r
388                     requestSet.remove(currentRequest);\r
389 \r
390                 }\r
391 \r
392                 @SuppressWarnings("unchecked")\r
393                 Callback<Throwable> callback = (Callback<Throwable>)currentRequest.second;\r
394 \r
395                 if (currentRequest.first.getClass().equals(SyncWriteRequestAdapter.class)) {\r
396 \r
397                     SyncWriteRequestAdapter adapter = (SyncWriteRequestAdapter)currentRequest.first;\r
398 \r
399                     try {\r
400 //                        System.out.println("merg.sync " + adapter);\r
401                         graph.syncRequest(adapter);\r
402                         if(callback != null) callback.run(null);\r
403                     } catch(Throwable t) {\r
404                                 Logger.defaultLogError(t);\r
405                         if(callback != null) callback.run(t);\r
406                     }\r
407 \r
408                     adapter.release();\r
409 //                    System.out.println("merg.sync.release " + adapter);\r
410 \r
411                 } else {\r
412 \r
413                     try {\r
414                         if(currentRequest.first instanceof Write) graph.syncRequest((Write)currentRequest.first); \r
415                         else if(currentRequest.first instanceof DelayedWrite) graph.syncRequest((DelayedWrite)currentRequest.first); \r
416                         if(callback != null) callback.run(null);\r
417                     } catch(Throwable t) {\r
418                                 Logger.defaultLogError(t);\r
419                         if(callback != null) callback.run(t);\r
420                     }\r
421 \r
422                 }\r
423 \r
424             }\r
425 \r
426 //            System.out.println(MergingGraphRequestProcessor.this + " write completed");\r
427 \r
428             synchronized (MergingGraphRequestProcessor.this) {\r
429                 if (requestQueue.isEmpty())\r
430                     hasAlreadyRequest = false;\r
431                 else\r
432                     newTransaction();\r
433             }\r
434 \r
435         }\r
436 \r
437     }\r
438 \r
439     private void newTransaction() {\r
440 \r
441         boolean write = false;\r
442 \r
443         synchronized (MergingGraphRequestProcessor.this) {\r
444             assert(!requestQueue.isEmpty());\r
445             Object nextRequest = requestQueue.peekFirst().first;\r
446             write = (nextRequest instanceof Write || nextRequest instanceof DelayedWrite);\r
447         }\r
448 \r
449         if(write) {\r
450             processor.asyncRequest(new RunnerWriteGraphRequest(), null);\r
451         } else {\r
452             processor.asyncRequest(new MergedRead());\r
453         }\r
454 \r
455     }\r
456 \r
457     @Override\r
458     public <T> void asyncRequest(AsyncMultiRead<T> request, AsyncMultiProcedure<T> procedure) {\r
459 \r
460 //        System.out.println(this + " asyncRequest(ReadGraphRequest<QueryProcedure4<T>> request, QueryProcedure4<T> procedure)");\r
461 \r
462         if (requestSet.contains(request))\r
463             return;\r
464 \r
465         Pair<Object, Object> pair = new Pair<Object, Object>(request, procedure);\r
466         requestQueue.add(pair);\r
467         requestSet.add(pair);\r
468 \r
469         if (!hasAlreadyRequest) {\r
470             newTransaction();\r
471             hasAlreadyRequest = true;\r
472         } else {\r
473             notify();\r
474         }\r
475 \r
476     }\r
477 \r
478     @Override\r
479     public synchronized <T> void asyncRequest(AsyncRead<T> request, AsyncProcedure<T> procedure) {\r
480 \r
481 //        System.out.println(this + " asyncRequest(ReadGraphRequest<SingleQueryProcedure4<T>> request, SingleQueryProcedure4<T> procedure) " + this);\r
482 \r
483         if (requestSet.contains(request))\r
484             return;\r
485 \r
486         Pair<Object, Object> pair = new Pair<Object, Object>(request, procedure);\r
487         requestQueue.add(pair);\r
488         requestSet.add(pair);\r
489 \r
490         if (!hasAlreadyRequest) {\r
491             newTransaction();\r
492             hasAlreadyRequest = true;\r
493         } else {\r
494 //            System.out.println("notify " + this);\r
495             notify();\r
496         }\r
497 \r
498     }\r
499 \r
500     @Override\r
501     public synchronized void asyncRequest(Write request, Callback<DatabaseException> callback) {\r
502 \r
503 //        System.out.println(this + " asyncRequest(WriteGraphRequest request)");\r
504 \r
505         if (requestSet.contains(request))\r
506             return;\r
507 \r
508         Pair<Object, Object> pair = new Pair<Object, Object>(request, callback);\r
509         requestQueue.add(pair);\r
510         requestSet.add(pair);\r
511 \r
512         if (!hasAlreadyRequest) {\r
513 //            System.out.println("new transaction");\r
514             newTransaction();\r
515             hasAlreadyRequest = true;\r
516         } else {\r
517 //            System.out.println("notify");\r
518             notify();\r
519         }\r
520 \r
521     }\r
522 \r
523     @Override\r
524     public synchronized void asyncRequest(DelayedWrite request, Callback<DatabaseException> callback) {\r
525 \r
526 //        System.out.println(this + " asyncRequest(WriteGraphRequest request)");\r
527 \r
528         if (requestSet.contains(request))\r
529             return;\r
530 \r
531         Pair<Object, Object> pair = new Pair<Object, Object>(request, callback);\r
532         requestQueue.add(pair);\r
533         requestSet.add(pair);\r
534 \r
535         if (!hasAlreadyRequest) {\r
536 //            System.out.println("new transaction");\r
537             newTransaction();\r
538             hasAlreadyRequest = true;\r
539         } else {\r
540 //            System.out.println("notify");\r
541             notify();\r
542         }\r
543 \r
544     }\r
545 \r
546     @Override\r
547     public synchronized void asyncRequest(WriteOnly request, Callback<DatabaseException> callback) {\r
548 \r
549 //        System.out.println(this + " asyncRequest(WriteGraphRequest request)");\r
550 \r
551         if (requestSet.contains(request))\r
552             return;\r
553 \r
554         Pair<Object, Object> pair = new Pair<Object, Object>(request, callback);\r
555         requestQueue.add(pair);\r
556         requestSet.add(pair);\r
557 \r
558         if (!hasAlreadyRequest) {\r
559 //            System.out.println("new transaction");\r
560             newTransaction();\r
561             hasAlreadyRequest = true;\r
562         } else {\r
563 //            System.out.println("notify");\r
564             notify();\r
565         }\r
566 \r
567     }\r
568 \r
569     @Override\r
570     public <T> Collection<T> syncRequest(AsyncMultiRead<T> request, final AsyncMultiProcedure<T> procedure) {\r
571 \r
572         final DataContainer<Throwable> throwable = new DataContainer<Throwable>(null);\r
573 \r
574         // Queue the adapter up for execution.\r
575         synchronized (request) {\r
576             syncRequests.add(request);\r
577             asyncRequest(request, procedure);\r
578             if(syncRequests.contains(request)) {\r
579                 try {\r
580                     //                  System.out.println("waiting " + request);\r
581                     request.wait();\r
582                 } catch (InterruptedException e) {\r
583                     throw new Error(e);\r
584                 }\r
585             }\r
586         }\r
587 \r
588         Throwable t = throwable.get();\r
589 \r
590         if(t != null) {\r
591                 Logger.defaultLogError(t);\r
592             throw new RuntimeException(t.getMessage());\r
593         }\r
594         \r
595         return null;\r
596 \r
597     }\r
598 \r
599     @Override\r
600     public <T> T syncRequest(AsyncRead<T> request, final AsyncProcedure<T> procedure) {\r
601 \r
602 //        System.out.println("syncRequest(ReadGraphRequest<SingleQueryProcedure4<T>> request, SingleQueryProcedure4<T> procedure)");\r
603 \r
604         final DataContainer<T> result = new DataContainer<T>(null);\r
605         final DataContainer<Throwable> throwable = new DataContainer<Throwable>(null);\r
606 \r
607         // Queue the adapter up for execution.\r
608         synchronized (request) {\r
609 \r
610             syncRequests.add(request);\r
611             asyncRequest(request, new AsyncProcedure<T>() {\r
612 \r
613                 public void execute(AsyncReadGraph graph, T t) {\r
614                     synchronized(result) {\r
615                         result.set(t);\r
616                     }\r
617                     procedure.execute(graph, t);\r
618                 };\r
619 \r
620                 @Override\r
621                 public void exception(AsyncReadGraph graph, Throwable t) {\r
622                     throwable.set(t);\r
623                 }\r
624 \r
625                 @Override\r
626                 public String toString() {\r
627                     return procedure.toString();\r
628                 }\r
629 \r
630             });\r
631             if(syncRequests.contains(request)) {\r
632                 try {\r
633                     //                  System.out.println("waiting " + request);\r
634                     request.wait();\r
635                 } catch (InterruptedException e) {\r
636                     throw new Error(e);\r
637                 }\r
638             }\r
639         }\r
640 \r
641         Throwable t = throwable.get();\r
642 \r
643         if(t != null) {\r
644                 Logger.defaultLogError(t);\r
645             throw new RuntimeException(t.getMessage());\r
646         }\r
647         \r
648         return result.get();\r
649 \r
650         //return result.get();\r
651 \r
652     }\r
653 \r
654 \r
655     @Override\r
656     public void syncRequest(Write request) {\r
657 \r
658 //        System.out.println(MergingGraphRequestProcessor.this + " syncRequest(WriteGraphRequest)");\r
659 \r
660         SyncWriteRequestAdapter adapter = new SyncWriteRequestAdapter(request);\r
661 \r
662         asyncRequest(adapter, null);\r
663 \r
664         adapter.acquire();\r
665 \r
666         // Throw exception if one occurred.\r
667         adapter.throwOrWrapException();\r
668 \r
669     }\r
670 \r
671     @Override\r
672     public void syncRequest(WriteOnly request) {\r
673 \r
674 //        System.out.println(MergingGraphRequestProcessor.this + " syncRequest(WriteGraphRequest)");\r
675 \r
676         SyncWriteRequestAdapter adapter = new SyncWriteRequestAdapter(request);\r
677 \r
678         // Queue the adapter up for execution.\r
679         synchronized (adapter) {\r
680             asyncRequest(adapter, null);\r
681             try {\r
682                 adapter.wait();\r
683             } catch (InterruptedException e) {\r
684                 throw new Error(e);\r
685             }\r
686         }\r
687 \r
688         // Throw exception if one occurred.\r
689         adapter.throwOrWrapException();\r
690 \r
691     }\r
692 \r
693     @Override\r
694     public Session getSession() {\r
695         return processor.getSession();\r
696     }\r
697 \r
698     @Override\r
699     public String toString() {\r
700         return "MergingGraphRequestProcessor[" + name + "]@" + System.identityHashCode(this) + " (based on " + processor + ")";\r
701     }\r
702 \r
703     @Override\r
704     public <T> void asyncRequest(AsyncRead<T> request) {\r
705 \r
706         asyncRequest(request, new ProcedureAdapter<T>() {\r
707 \r
708             @Override\r
709             public void exception(Throwable t) {\r
710                         Logger.defaultLogError(t);\r
711             }\r
712 \r
713         });\r
714 \r
715     }\r
716 \r
717     @Override\r
718     public <T> void asyncRequest(AsyncRead<T> request, Procedure<T> procedure) {\r
719         asyncRequest(request, new NoneToAsyncProcedure<T>(procedure));\r
720     }\r
721 \r
722     @Override\r
723     public <T> void asyncRequest(AsyncMultiRead<T> request) {\r
724         throw new UnsupportedOperationException("Not implemented.");\r
725     }\r
726 \r
727     @Override\r
728     public <T> void asyncRequest(AsyncMultiRead<T> request,\r
729             MultiProcedure<T> procedure) {\r
730         throw new UnsupportedOperationException("Not implemented.");\r
731     }\r
732 \r
733     @Override\r
734     public <T> T syncRequest(AsyncRead<T> request) {\r
735 \r
736         final DataContainer<Throwable> throwable = new DataContainer<Throwable>(null);\r
737         final DataContainer<T> result = new DataContainer<T>();\r
738 \r
739         syncRequest(request, new AsyncProcedure<T>() {\r
740 \r
741             public void execute(AsyncReadGraph graph, T t) {\r
742                 result.set(t);\r
743             }\r
744 \r
745             @Override\r
746             public void exception(AsyncReadGraph graph, Throwable t) {\r
747                 throwable.set(t);\r
748             }\r
749 \r
750         });\r
751 \r
752         Throwable t = throwable.get();\r
753 \r
754         if(t != null) {\r
755                 Logger.defaultLogError(t);\r
756             throw new RuntimeException(t.getMessage());\r
757         }\r
758 \r
759         return result.get();\r
760 \r
761     }\r
762 \r
763     @Override\r
764     public <T> T syncRequest(AsyncRead<T> request,\r
765             Procedure<T> procedure) {\r
766         throw new UnsupportedOperationException("Not implemented.");\r
767     }\r
768 \r
769     @Override\r
770     public <T> Collection<T> syncRequest(AsyncMultiRead<T> request) {\r
771 \r
772         final DataContainer<Throwable> throwable = new DataContainer<Throwable>(null);\r
773         final ArrayList<T> result = new ArrayList<T>();\r
774 \r
775         syncRequest(request, new AsyncMultiProcedureAdapter<T>() {\r
776 \r
777             @Override\r
778             public void execute(AsyncReadGraph graph, T t) {\r
779                 synchronized(result) {\r
780                     result.add(t);\r
781                 }\r
782             };\r
783 \r
784             @Override\r
785             public void exception(AsyncReadGraph graph, Throwable t) {\r
786                 throwable.set(t);\r
787             }\r
788 \r
789         });\r
790 \r
791         Throwable t = throwable.get();\r
792 \r
793         if(t != null) {\r
794                 Logger.defaultLogError(t);\r
795             throw new RuntimeException(t.getMessage());\r
796         }\r
797 \r
798         return result;\r
799 \r
800     }\r
801 \r
802     @Override\r
803     public <T> Collection<T> syncRequest(AsyncMultiRead<T> request,\r
804             MultiProcedure<T> procedure) {\r
805         throw new Error("Not implemented.");\r
806     }\r
807 \r
808     @Override\r
809     public <T> T syncRequest(Read<T> request) {\r
810 \r
811         final DataContainer<Throwable> throwable = new DataContainer<Throwable>(null);\r
812         final DataContainer<T> result = new DataContainer<T>();\r
813 \r
814 \r
815         syncRequest(request, new Procedure<T>() {\r
816 \r
817             public void execute(T t) {\r
818                 result.set(t);\r
819             }\r
820 \r
821             @Override\r
822             public void exception(Throwable t) {\r
823                 throwable.set(t);\r
824             }\r
825 \r
826         });\r
827 \r
828         Throwable t = throwable.get();\r
829 \r
830         if(t != null) {\r
831             throw new Error(t.getMessage());\r
832         }\r
833 \r
834 \r
835         return result.get();\r
836 \r
837     }\r
838 \r
839     @Override\r
840     public <T> T syncRequest(Read<T> request,\r
841             final AsyncProcedure<T> procedure) {\r
842 \r
843         final DataContainer<T> result = new DataContainer<T>(null);\r
844         final DataContainer<Throwable> throwable = new DataContainer<Throwable>(null);\r
845 \r
846         // Queue the adapter up for execution.\r
847         synchronized (request) {\r
848 \r
849             syncRequests.add(request);\r
850             asyncRequest(request, new AsyncProcedure<T>() {\r
851 \r
852                 public void execute(AsyncReadGraph graph, T t) {\r
853                     synchronized(result) {\r
854                         result.set(t);\r
855                     }\r
856                     procedure.execute(graph, t);\r
857                 };\r
858 \r
859                 @Override\r
860                 public void exception(AsyncReadGraph graph, Throwable t) {\r
861                     throwable.set(t);\r
862                 }\r
863 \r
864                 @Override\r
865                 public String toString() {\r
866                     return procedure.toString();\r
867                 }\r
868 \r
869             });\r
870             if(syncRequests.contains(request)) {\r
871                 try {\r
872                     //                  System.out.println("waiting " + request);\r
873                     request.wait();\r
874                 } catch (InterruptedException e) {\r
875                     throw new Error(e);\r
876                 }\r
877             }\r
878         }\r
879 \r
880         Throwable t = throwable.get();\r
881 \r
882         if(t != null) {\r
883             throw new RuntimeException("Unexpected exception in MergingGraphRequestProcessor.syncRequest(Read, AsyncProcedure)", t);\r
884         }\r
885         \r
886         return result.get();\r
887 \r
888     }\r
889 \r
890     @Override\r
891     public <T> void asyncRequest(Read<T> request) {\r
892 \r
893         asyncRequest(request, new ProcedureAdapter<T>() {\r
894 \r
895             @Override\r
896             public void exception(Throwable t) {\r
897                 Logger.defaultLogError(t);\r
898             }\r
899 \r
900         });\r
901 \r
902     }\r
903 \r
904     @Override\r
905     public synchronized <T> void asyncRequest(Read<T> request,\r
906             AsyncProcedure<T> procedure) {\r
907 \r
908         if (requestSet.contains(request))\r
909             return;\r
910 \r
911         Pair<Object, Object> pair = new Pair<Object, Object>(request, procedure);\r
912         requestQueue.add(pair);\r
913         requestSet.add(pair);\r
914 \r
915         if (!hasAlreadyRequest) {\r
916             newTransaction();\r
917             hasAlreadyRequest = true;\r
918         } else {\r
919             notify();\r
920         }\r
921 \r
922     }\r
923 \r
924     @Override\r
925     public <T> T syncRequest(Read<T> request, Procedure<T> procedure) {\r
926         return syncRequest(request, new NoneToAsyncProcedure<T>(procedure));\r
927     }\r
928 \r
929     @Override\r
930     public <T> Collection<T> syncRequest(final MultiRead<T> request) throws DatabaseException {\r
931         assert(request != null);\r
932 \r
933         final ArrayList<T> result = new ArrayList<T>();\r
934         final DataContainer<Throwable> exception = new DataContainer<Throwable>();\r
935 \r
936         syncRequest(request, new AsyncMultiProcedureAdapter<T>() {\r
937 \r
938             @Override\r
939             public void execute(AsyncReadGraph graph, T t) {\r
940                 synchronized(result) {\r
941                     result.add(t);\r
942                 }\r
943             }\r
944 \r
945             @Override\r
946             public void exception(AsyncReadGraph graph, Throwable t) {\r
947                 exception.set(t);\r
948             }\r
949 \r
950             @Override\r
951             public String toString() {\r
952                 return "syncRequest(MultiRead) -> " + request;\r
953             }\r
954 \r
955         });\r
956 \r
957         Throwable t = exception.get();\r
958         if(t != null) {\r
959             if(t instanceof DatabaseException) throw (DatabaseException)t;\r
960             else throw new DatabaseException("Unexpected exception in ReadGraph.syncRequest(Read)", t);\r
961         }\r
962 \r
963         return result;\r
964     }\r
965 \r
966     @Override\r
967     public <T> Collection<T> syncRequest(MultiRead<T> request, AsyncMultiProcedure<T> procedure)  {\r
968         throw new UnsupportedOperationException("Not implemented");\r
969     }\r
970 \r
971     @Override\r
972     public <T> Collection<T> syncRequest(MultiRead<T> request, MultiProcedure<T> procedure) {\r
973         throw new UnsupportedOperationException("Not implemented");\r
974     }\r
975 \r
976     @Override\r
977     public <T> void asyncRequest(Read<T> request, Procedure<T> procedure) {\r
978         asyncRequest(request, new NoneToAsyncProcedure<T>(procedure));\r
979     }\r
980 \r
981     @Override\r
982     public <T> void asyncRequest(MultiRead<T> request) {\r
983         throw new UnsupportedOperationException("Not implemented");\r
984     }\r
985 \r
986     @Override\r
987     public <T> void asyncRequest(MultiRead<T> request, AsyncMultiProcedure<T> procedure) {\r
988         throw new UnsupportedOperationException("Not implemented");\r
989     }\r
990 \r
991     @Override\r
992     public <T> void asyncRequest(MultiRead<T> request, MultiProcedure<T> procedure) {\r
993         throw new UnsupportedOperationException("Not implemented");\r
994     }\r
995 \r
996     @Override\r
997     public void asyncRequest(Write r) {\r
998         asyncRequest(r, null);\r
999     }\r
1000 \r
1001     @Override\r
1002     public void asyncRequest(DelayedWrite r) {\r
1003         asyncRequest(r, null);\r
1004     }\r
1005 \r
1006     @Override\r
1007     public void asyncRequest(WriteOnly r) {\r
1008         asyncRequest(r, null);\r
1009     }\r
1010 \r
1011     @Override\r
1012     public <T> T getService(Class<T> api) {\r
1013         return getSession().getService(api);\r
1014     }\r
1015 \r
1016     @Override\r
1017     public <T> T peekService(Class<T> api) {\r
1018         return getSession().peekService(api);\r
1019     }\r
1020 \r
1021     @Override\r
1022     public boolean hasService(Class<?> api) {\r
1023         return getSession().hasService(api);\r
1024     }\r
1025 \r
1026     @Override\r
1027     public <T> void registerService(Class<T> api, T service) {\r
1028         getSession().registerService(api, service);\r
1029     }\r
1030 \r
1031 //    @Override\r
1032 //    public <T> T syncRequest(Read<T> arg0, AsyncListener<T> arg1) {\r
1033 //        throw new UnsupportedOperationException("Not implemented.");\r
1034 //    }\r
1035 \r
1036     @Override\r
1037     public <T> T syncRequest(Read<T> arg0, SyncListener<T> arg1) {\r
1038         throw new UnsupportedOperationException("Not implemented.");\r
1039     }\r
1040 \r
1041     @Override\r
1042     public <T> T syncRequest(Read<T> arg0, Listener<T> arg1) {\r
1043         throw new UnsupportedOperationException("Not implemented.");\r
1044     }\r
1045 \r
1046     @Override\r
1047     public <T> T syncRequest(Read<T> arg0, SyncProcedure<T> arg1) {\r
1048         throw new UnsupportedOperationException("Not implemented.");\r
1049     }\r
1050 \r
1051     @Override\r
1052     public <T> T syncRequest(AsyncRead<T> arg0, AsyncListener<T> arg1) {\r
1053         throw new UnsupportedOperationException("Not implemented.");\r
1054     }\r
1055 \r
1056     @Override\r
1057     public <T> T syncRequest(AsyncRead<T> arg0, SyncListener<T> arg1) {\r
1058         throw new UnsupportedOperationException("Not implemented.");\r
1059 \r
1060     }\r
1061 \r
1062     @Override\r
1063     public <T> T syncRequest(AsyncRead<T> arg0, Listener<T> arg1) {\r
1064         throw new UnsupportedOperationException("Not implemented.");\r
1065 \r
1066     }\r
1067 \r
1068     @Override\r
1069     public <T> T syncRequest(AsyncRead<T> arg0, SyncProcedure<T> arg1) {\r
1070         throw new UnsupportedOperationException("Not implemented.");\r
1071 \r
1072     }\r
1073 \r
1074     @Override\r
1075     public <T> void asyncRequest(Read<T> arg0, AsyncListener<T> arg1) {\r
1076         throw new UnsupportedOperationException("Not implemented.");\r
1077 \r
1078     }\r
1079 \r
1080     @Override\r
1081     public <T> void asyncRequest(Read<T> arg0, SyncListener<T> arg1) {\r
1082         throw new UnsupportedOperationException("Not implemented.");\r
1083 \r
1084     }\r
1085 \r
1086     @Override\r
1087     public <T> void asyncRequest(Read<T> arg0, Listener<T> arg1) {\r
1088         throw new UnsupportedOperationException("Not implemented.");\r
1089 \r
1090     }\r
1091 \r
1092     @Override\r
1093     public <T> void asyncRequest(Read<T> arg0, SyncProcedure<T> arg1) {\r
1094         throw new UnsupportedOperationException("Not implemented.");\r
1095 \r
1096     }\r
1097 \r
1098     @Override\r
1099     public <T> void asyncRequest(AsyncRead<T> arg0, AsyncListener<T> arg1) {\r
1100         throw new UnsupportedOperationException("Not implemented.");\r
1101 \r
1102     }\r
1103 \r
1104     @Override\r
1105     public <T> void asyncRequest(AsyncRead<T> arg0, SyncListener<T> arg1) {\r
1106         throw new UnsupportedOperationException("Not implemented.");\r
1107 \r
1108     }\r
1109 \r
1110     @Override\r
1111     public <T> void asyncRequest(AsyncRead<T> arg0, Listener<T> arg1) {\r
1112         throw new UnsupportedOperationException("Not implemented.");\r
1113 \r
1114     }\r
1115 \r
1116     @Override\r
1117     public <T> void asyncRequest(AsyncRead<T> arg0, SyncProcedure<T> arg1) {\r
1118         throw new UnsupportedOperationException("Not implemented.");\r
1119 \r
1120     }\r
1121 \r
1122     @Override\r
1123     public <T> Collection<T> syncRequest(MultiRead<T> arg0, AsyncMultiListener<T> arg1) {\r
1124         throw new UnsupportedOperationException("Not implemented.");\r
1125 \r
1126     }\r
1127 \r
1128     @Override\r
1129     public <T> Collection<T> syncRequest(MultiRead<T> arg0, SyncMultiListener<T> arg1) {\r
1130         throw new UnsupportedOperationException("Not implemented.");\r
1131 \r
1132     }\r
1133 \r
1134     @Override\r
1135     public <T> Collection<T> syncRequest(MultiRead<T> arg0, MultiListener<T> arg1) {\r
1136         throw new UnsupportedOperationException("Not implemented.");\r
1137 \r
1138     }\r
1139 \r
1140     @Override\r
1141     public <T> Collection<T> syncRequest(MultiRead<T> arg0, SyncMultiProcedure<T> arg1) {\r
1142         throw new UnsupportedOperationException("Not implemented.");\r
1143 \r
1144     }\r
1145 \r
1146     @Override\r
1147     public <T> Collection<T> syncRequest(AsyncMultiRead<T> arg0,\r
1148             AsyncMultiListener<T> arg1) {\r
1149         throw new UnsupportedOperationException("Not implemented.");\r
1150 \r
1151     }\r
1152 \r
1153     @Override\r
1154     public <T> Collection<T> syncRequest(AsyncMultiRead<T> arg0, SyncMultiListener<T> arg1) {\r
1155         throw new UnsupportedOperationException("Not implemented.");\r
1156 \r
1157     }\r
1158 \r
1159     @Override\r
1160     public <T> Collection<T> syncRequest(AsyncMultiRead<T> arg0,\r
1161             MultiListener<T> arg1) {\r
1162         throw new UnsupportedOperationException("Not implemented.");\r
1163 \r
1164     }\r
1165 \r
1166     @Override\r
1167     public <T> Collection<T> syncRequest(AsyncMultiRead<T> arg0, SyncMultiProcedure<T> arg1) {\r
1168         throw new UnsupportedOperationException("Not implemented.");\r
1169 \r
1170     }\r
1171 \r
1172     @Override\r
1173     public <T> void asyncRequest(MultiRead<T> arg0, AsyncMultiListener<T> arg1) {\r
1174         throw new UnsupportedOperationException("Not implemented.");\r
1175 \r
1176     }\r
1177 \r
1178     @Override\r
1179     public <T> void asyncRequest(MultiRead<T> arg0, SyncMultiListener<T> arg1) {\r
1180         throw new UnsupportedOperationException("Not implemented.");\r
1181 \r
1182     }\r
1183 \r
1184     @Override\r
1185     public <T> void asyncRequest(MultiRead<T> arg0, MultiListener<T> arg1) {\r
1186         throw new UnsupportedOperationException("Not implemented.");\r
1187 \r
1188     }\r
1189 \r
1190     @Override\r
1191     public <T> void asyncRequest(MultiRead<T> arg0, SyncMultiProcedure<T> arg1) {\r
1192         throw new UnsupportedOperationException("Not implemented.");\r
1193 \r
1194     }\r
1195 \r
1196     @Override\r
1197     public <T> void asyncRequest(AsyncMultiRead<T> arg0,\r
1198             AsyncMultiListener<T> arg1) {\r
1199         throw new UnsupportedOperationException("Not implemented.");\r
1200     }\r
1201 \r
1202     @Override\r
1203     public <T> void asyncRequest(AsyncMultiRead<T> arg0, SyncMultiListener<T> arg1) {\r
1204         throw new UnsupportedOperationException("Not implemented.");\r
1205 \r
1206     }\r
1207 \r
1208     @Override\r
1209     public <T> void asyncRequest(AsyncMultiRead<T> arg0,\r
1210             MultiListener<T> arg1) {\r
1211         throw new UnsupportedOperationException("Not implemented.");\r
1212 \r
1213     }\r
1214 \r
1215     @Override\r
1216     public <T> void asyncRequest(AsyncMultiRead<T> arg0, SyncMultiProcedure<T> arg1) {\r
1217         throw new UnsupportedOperationException("Not implemented.");\r
1218     }\r
1219 \r
1220     @Override\r
1221     public <T> void asyncRequest(ExternalRead<T> request, Procedure<T> procedure) {\r
1222         throw new UnsupportedOperationException("Not implemented.");\r
1223     }\r
1224 \r
1225     @Override\r
1226     public <T> T syncRequest(ExternalRead<T> request) {\r
1227         throw new UnsupportedOperationException("Not implemented.");\r
1228     }\r
1229 \r
1230     @Override\r
1231     public <T> T syncRequest(ExternalRead<T> request, Listener<T> procedure) {\r
1232         throw new UnsupportedOperationException("Not implemented.");\r
1233     }\r
1234 \r
1235     @Override\r
1236     public <T> T syncRequest(ExternalRead<T> request, Procedure<T> procedure) {\r
1237         throw new UnsupportedOperationException("Not implemented.");\r
1238     }\r
1239 \r
1240     @Override\r
1241     public <T> void asyncRequest(ExternalRead<T> request) {\r
1242         throw new UnsupportedOperationException("Not implemented.");\r
1243     }\r
1244 \r
1245     @Override\r
1246     public <T> void asyncRequest(ExternalRead<T> request, Listener<T> procedure) {\r
1247         throw new UnsupportedOperationException("Not implemented.");\r
1248     }\r
1249 \r
1250     @Override\r
1251     public void syncRequest(DelayedWrite request) throws DatabaseException {\r
1252         throw new UnsupportedOperationException("Not implemented.");\r
1253     }\r
1254 \r
1255         @Override\r
1256         public <T> T syncRequest(WriteResult<T> request) throws DatabaseException {\r
1257                 throw new UnsupportedOperationException();\r
1258         }\r
1259 \r
1260         @Override\r
1261         public <T> T syncRequest(DelayedWriteResult<T> request)\r
1262                         throws DatabaseException {\r
1263                 throw new UnsupportedOperationException();\r
1264         }\r
1265 \r
1266         @Override\r
1267         public <T> T syncRequest(WriteOnlyResult<T> r) throws DatabaseException {\r
1268                 throw new UnsupportedOperationException();\r
1269         }\r
1270 \r
1271         @Override\r
1272         public <T> void asyncRequest(WriteResult<T> r, Procedure<T> procedure) {\r
1273                 throw new UnsupportedOperationException();\r
1274         }\r
1275 \r
1276         @Override\r
1277         public <T> void asyncRequest(DelayedWriteResult<T> r, Procedure<T> procedure) {\r
1278                 throw new UnsupportedOperationException();\r
1279         }\r
1280 \r
1281         @Override\r
1282         public <T> void asyncRequest(WriteOnlyResult<T> r, Procedure<T> procedure) {\r
1283                 throw new UnsupportedOperationException();\r
1284         }\r
1285         \r
1286         @Override\r
1287         public Resource getRootLibrary() {\r
1288                 return processor.getRootLibrary();\r
1289         }\r
1290 \r
1291         @Override\r
1292         public <T> void async(ReadInterface<T> r, Procedure<T> procedure) {\r
1293                 throw new UnsupportedOperationException();\r
1294         }\r
1295 \r
1296         @Override\r
1297         public <T> void async(ReadInterface<T> r, AsyncProcedure<T> procedure) {\r
1298                 throw new UnsupportedOperationException();\r
1299         }\r
1300 \r
1301         @Override\r
1302         public <T> void async(ReadInterface<T> r, SyncProcedure<T> procedure) {\r
1303                 throw new UnsupportedOperationException();\r
1304         }\r
1305 \r
1306         @Override\r
1307         public <T> void async(ReadInterface<T> r, Listener<T> procedure) {\r
1308                 throw new UnsupportedOperationException();\r
1309         }\r
1310 \r
1311         @Override\r
1312         public <T> void async(ReadInterface<T> r, AsyncListener<T> procedure) {\r
1313                 throw new UnsupportedOperationException();\r
1314         }\r
1315 \r
1316         @Override\r
1317         public <T> void async(ReadInterface<T> r, SyncListener<T> procedure) {\r
1318                 throw new UnsupportedOperationException();\r
1319         }\r
1320         \r
1321         @Override\r
1322         public <T> T sync(ReadInterface<T> r) throws DatabaseException {\r
1323                 throw new UnsupportedOperationException();\r
1324         }\r
1325         \r
1326         @Override\r
1327         public <T> T sync(WriteInterface<T> r) throws DatabaseException {\r
1328                 throw new UnsupportedOperationException();\r
1329         }\r
1330         \r
1331         @Override\r
1332         public <T> void async(WriteInterface<T> r, Procedure<T> procedure) {\r
1333                 throw new UnsupportedOperationException();\r
1334         }\r
1335 \r
1336         @Override\r
1337         public <T> void async(WriteInterface<T> r) {\r
1338                 throw new UnsupportedOperationException();\r
1339         }\r
1340         \r
1341         @Override\r
1342         public Object getModificationCounter() {\r
1343                 throw new UnsupportedOperationException();\r
1344         }\r
1345         \r
1346 }\r