View Javadoc
1   /**
2    * 
3    */
4   package org.melati.poem.test;
5   
6   import java.util.Enumeration;
7   import java.util.Random;
8   
9   import org.melati.poem.AccessToken;
10  import org.melati.poem.CachedSelection;
11  import org.melati.poem.PoemTask;
12  import org.melati.poem.PoemThread;
13  import org.melati.poem.Table;
14  import org.melati.poem.UnexpectedExceptionPoemException;
15  
16  /**
17   * @author timp
18   * @since 24 Jan 2007
19   * 
20   */
21  public class MultiThreadedCachedSelectionTest extends EverythingTestCase {
22  
23    private static String theResult;
24  
25    protected static EverythingDatabase db;
26  
27    public MultiThreadedCachedSelectionTest(String arg0) {
28      super(arg0);
29    }
30  
31    protected void setUp() throws Exception {
32      super.setUp();
33      db = (EverythingDatabase)getDb();
34    }
35  
36    protected void tearDown() throws Exception {
37      super.tearDown();
38    }
39  
40    abstract static class PoemTaskThread extends Thread {
41  
42      Table<?> table;
43  
44      PoemTaskThread(Table<?> table) {
45        this.table = table;
46      }
47  
48      abstract void run_() throws Exception;
49  
50      public void run() {
51        //System.err.println("MTCST thread name: "+ Thread.currentThread().getName());
52        table.getDatabase().inSession(AccessToken.root, new PoemTask() {
53          public void run() {
54            try {
55              run_();
56            } catch (Exception e) {
57              throw new UnexpectedExceptionPoemException(e);
58            }
59          }
60        });
61      }
62    }
63  
64    static class Setter extends PoemTaskThread {
65  
66      static class Signal {
67      }
68  
69      static final Signal 
70        set = new Signal(){ public String toString() {return "set";}}, 
71        add = new Signal(){ public String toString() {return "add";}},
72        delete = new Signal() { public String toString() {return "delete";}};
73  
74      static Signal[] theSignal = new Signal[1];
75  
76      int serial = 0;
77  
78      Setter(Table<?> table) {
79        super(table);
80      }
81  
82      void signal(Signal signal) {
83        System.err.println("Setter Signal changing from "
84                +theSignal[0] + " to " + signal);
85        synchronized (theSignal) {
86          theSignal[0] = signal;
87          theSignal.notifyAll();
88        }
89      }
90  
91      void run_() throws Exception {
92        System.err.println("Setter thread name: "+ (int)Thread.currentThread().getName().charAt(0));
93        for (;;) {
94          synchronized (theSignal) {
95            theSignal.wait();
96          }
97  
98          if (theSignal[0] == set) {
99            String fieldContent = "setWhatsit" + (serial++);
100           StringField t = (StringField)table.firstSelection(null);
101           if (t == null) {
102             System.out.println("\n*** setter: nothing to set\n");
103             synchronized (theResult) {
104               theResult += "\nNULL" + fieldContent;
105             }
106           } else {
107             System.out.println("\n*** setter: setting " + fieldContent);
108             t.setStringfield(fieldContent);
109             synchronized (theResult) {
110               theResult += "\n" + fieldContent;
111             }
112           }
113         } else if (theSignal[0] == add) {
114           String fieldContent = "addedWhatsit" + (serial++);
115           System.out.println("*** setter: adding " + fieldContent);
116           StringField t = (StringField)table.newPersistent();
117           t.setStringfield(fieldContent);
118           t.makePersistent();
119           synchronized (theResult) {
120             theResult += "\n" + fieldContent;
121           }
122         } else if (theSignal[0] == delete) {
123           StringField t = (StringField)table.firstSelection(null);
124           if (t == null) {
125             System.out.println("\n*** setter: nothing to delete");
126             synchronized (theResult) {
127               theResult += "\nempty delete";
128             }
129           } else {
130             System.out.println("*** setter: deleting");
131             t.delete_unsafe();
132             System.out.println("*** setter: done deleting");
133             synchronized (theResult) {
134               theResult += "\ndelete";
135             }
136           }
137         } else if (theSignal[0] == null) {
138           System.out.println("\n*** setter done");
139           break;
140         } else fail("WTF");
141 
142         PoemThread.commit();
143       }
144       PoemThread.commit();
145     }
146   }
147 
148   static class Getter extends PoemTaskThread {
149 
150     static Object[] theSignal = new Object[1];
151 
152     CachedSelection<?> cachedSelection;
153 
154     @SuppressWarnings({ "rawtypes", "unchecked" })
155     Getter(Table<?> table) {
156       super(table);
157       cachedSelection = new CachedSelection(table, null, null, null);
158     }
159 
160     void signal(Object signal) throws Exception {
161       System.err.println("Getter Signal changing from "
162               +theSignal[0] + " to " + signal);
163       synchronized (theSignal) {
164         theSignal[0] = signal;
165         theSignal.notifyAll();
166       }
167     }
168 
169     void run_() throws Exception {
170       System.err.println("Getter thread name: "+ (int)Thread.currentThread().getName().charAt(0));
171       for (;;) {
172         synchronized (theSignal) {
173           theSignal.wait();
174         }
175 
176         if (theSignal[0] == null) {
177           System.out.println("\n*** getter done\n");
178           signal("done");
179           break;
180         } else {
181           System.out.println("\n*** getter:");
182           Enumeration<?> them = cachedSelection.objects();
183 
184           System.out.print("** got\n");
185           synchronized (theResult) {
186             theResult += "\ngot";
187           }
188 
189           synchronized (theResult) {
190             while (them.hasMoreElements()) {
191               String s = " "
192                       + ((StringField)them.nextElement()).getStringfield();
193               theResult += s;
194               //System.out.print(s);
195             }
196           }
197           //System.out.println("\n");
198         }
199         PoemThread.commit();
200       }
201       PoemThread.commit();
202     }
203   }
204 
205   /**
206    * Setup threads and test them.
207    * @throws Exception 
208    */
209   public void testThem() throws Exception {
210     System.err.println("Start of test method");
211     theResult = "";
212 
213     Setter setter = new Setter(db.getStringFieldTable());
214     Getter getter = new Getter(db.getStringFieldTable());
215 
216     setter.start();
217     getter.start();
218 
219     try {
220       Thread.sleep(nap());
221       setter.signal(Setter.add);
222       Thread.sleep(nap());
223       getter.signal(Boolean.TRUE);
224       Thread.sleep(nap());
225       getter.signal(Boolean.TRUE);
226       Thread.sleep(nap());
227       setter.signal(Setter.set);
228       Thread.sleep(nap());
229       getter.signal(Boolean.TRUE);
230       Thread.sleep(nap());
231       getter.signal(Boolean.TRUE);
232       Thread.sleep(nap());
233       setter.signal(Setter.add);
234       Thread.sleep(nap());
235       getter.signal(Boolean.TRUE);
236       Thread.sleep(nap());
237       getter.signal(Boolean.TRUE);
238       Thread.sleep(nap());
239       setter.signal(Setter.delete);
240       Thread.sleep(nap());
241       getter.signal(Boolean.TRUE);
242       Thread.sleep(nap());
243       getter.signal(Boolean.TRUE);
244       Thread.sleep(nap());
245       setter.signal(Setter.delete);
246       Thread.sleep(nap());
247       getter.signal(Boolean.TRUE);
248       Thread.sleep(nap());
249       getter.signal(Boolean.TRUE);
250       Thread.sleep(nap());
251       
252       System.err.println(getDb().getFreeTransactionsCount() +  "!=" +  (getDb().transactionsMax() -1));
253       setter.signal(null);
254       getter.signal(null);
255       int max = getDb().transactionsMax() -1;
256       int trans = getDb().getFreeTransactionsCount();
257       while(trans != max) { 
258         Thread.sleep(1000);
259         System.err.println("Slept because free transactions = " + trans);
260         trans = getDb().getFreeTransactionsCount();
261       }
262     } catch (Exception e) {
263       e.printStackTrace();
264       fail();
265     }
266     System.err.println("End of test method");
267     // System.out.println(result);
268     /*
269     assertEquals("\naddedWhatsit0\n" + 
270                  "got addedWhatsit0\n" + 
271                  "got addedWhatsit0\n" + 
272                  "setWhatsit1\n" + 
273                  "got setWhatsit1\n" + 
274                  "got setWhatsit1\n" + 
275                  "addedWhatsit2\n" + 
276                  "got setWhatsit1 addedWhatsit2\n" + 
277                  "got setWhatsit1 addedWhatsit2\n" + 
278                  "delete\n" + 
279                  "got addedWhatsit2\n" + 
280                  "got addedWhatsit2\n" + 
281                  "delete\n" + 
282                  "got\n" + 
283                  "got",result);
284      */
285     // TODO think of an appropriate assertion
286   }
287 
288   private int nap() { 
289     Random generator = new Random();
290     int it = generator.nextInt(80);
291     //System.err.println(it);
292     return it;
293   }
294 }