KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > functionTests > tests > store > TestDiskHashtable


1 /*
2
3    Derby - Class org.apache.derbyTesting.functionTests.tests.store.TestDiskHashtable
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.functionTests.tests.store;
23
24 import java.sql.Connection JavaDoc;
25 import java.sql.ResultSet JavaDoc;
26 import java.sql.SQLException JavaDoc;
27 import java.sql.Statement JavaDoc;
28
29 import java.util.BitSet JavaDoc;
30 import java.util.Enumeration JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.Vector JavaDoc;
33
34 import org.apache.derby.iapi.error.PublicAPI;
35 import org.apache.derby.iapi.error.StandardException;
36 import org.apache.derby.iapi.sql.conn.ConnectionUtil;
37 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
38 import org.apache.derby.iapi.store.access.DiskHashtable;
39 import org.apache.derby.iapi.store.access.KeyHasher;
40 import org.apache.derby.iapi.store.access.TransactionController;
41 import org.apache.derby.iapi.types.DataValueDescriptor;
42 import org.apache.derby.iapi.types.Orderable;
43 import org.apache.derby.iapi.types.SQLInteger;
44 import org.apache.derby.iapi.types.SQLLongint;
45 import org.apache.derby.iapi.types.SQLVarchar;
46 import org.apache.derby.tools.ij;
47 import org.apache.derbyTesting.functionTests.util.TestUtil;
48
49 /**
50  * This program tests the org.apache.derby.iapi.store.access.DiskHashtable class.
51  * The unit test interface is not used because that is undocumented and very difficult to decipher.
52  * Furthermore it is difficult to diagnose problems when using the unit test interface.
53  *
54  * Created: Wed Feb 09 15:44:12 2005
55  *
56  * @author <a HREF="mailto:klebanof@us.ibm.com">Jack Klebanoff</a>
57  * @version 1.0
58  */

59 public class TestDiskHashtable
60 {
61     private TransactionController tc;
62     private int failed = 0;
63     
64     public static void main( String JavaDoc args[])
65     {
66         int failed = 1;
67
68         REPORT("Test DiskHashtable starting");
69         try
70         {
71             // use the ij utility to read the property file and
72
// make the initial connection.
73
ij.getPropertyArg(args);
74             Connection JavaDoc conn = ij.startJBMS();
75             Statement JavaDoc stmt = conn.createStatement();
76             stmt.execute("CREATE FUNCTION testDiskHashtable() returns INTEGER EXTERNAL NAME 'org.apache.derbyTesting.functionTests.tests.store.TestDiskHashtable.runTests' LANGUAGE JAVA PARAMETER STYLE JAVA");
77             ResultSet JavaDoc rs = stmt.executeQuery( "values( testDiskHashtable())");
78             if( rs.next())
79                 failed = rs.getInt(1);
80             stmt.close();
81             conn.close();
82         }
83         catch( SQLException JavaDoc e)
84         {
85             TestUtil.dumpSQLExceptions( e);
86             failed = 1;
87         }
88         catch( Throwable JavaDoc t)
89         {
90             REPORT("FAIL -- unexpected exception:" + t.toString());
91             failed = 1;
92         }
93         REPORT( (failed == 0) ? "OK" : "FAILED");
94         System.exit( (failed == 0) ? 0 : 1);
95     }
96
97     private void REPORT_FAILURE(String JavaDoc msg)
98     {
99         failed = 1;
100         REPORT( msg);
101     }
102     
103     private static void REPORT(String JavaDoc msg)
104     {
105         System.out.println( msg);
106     }
107     
108     public static int runTests() throws SQLException JavaDoc
109     {
110         TestDiskHashtable tester = new TestDiskHashtable();
111         return tester.doIt();
112     }
113
114     private TestDiskHashtable() throws SQLException JavaDoc
115     {
116         LanguageConnectionContext lcc = ConnectionUtil.getCurrentLCC();
117         if( lcc == null)
118             throw new SQLException JavaDoc( "Cannot get the LCC");
119         tc = lcc.getTransactionExecute();
120     }
121
122     private int doIt() throws SQLException JavaDoc
123     {
124         try {
125
126
127             REPORT( "Starting single key, keep duplicates test");
128             testOneVariant( tc, false, singleKeyTemplate, singleKeyCols, singleKeyRows);
129             REPORT( "Starting single key, remove duplicates test");
130             testOneVariant( tc, true, singleKeyTemplate, singleKeyCols, singleKeyRows);
131             REPORT( "Starting multiple key, keep duplicates test");
132             testOneVariant( tc, false, multiKeyTemplate, multiKeyCols, multiKeyRows);
133             REPORT( "Starting multiple key, remove duplicates test");
134             testOneVariant( tc, true, multiKeyTemplate, multiKeyCols, multiKeyRows);
135
136             tc.commit();
137         }
138         catch (StandardException se)
139         {
140             throw PublicAPI.wrapStandardException( se);
141         }
142         return failed;
143     } // end of doIt
144

145     private static final DataValueDescriptor[] singleKeyTemplate = { new SQLInteger(), new SQLVarchar()};
146     private static final int[] singleKeyCols = {0};
147     private static final DataValueDescriptor[][] singleKeyRows =
148     {
149         {new SQLInteger(1), new SQLVarchar("abcd")},
150         {new SQLInteger(2), new SQLVarchar("abcd")},
151         {new SQLInteger(3), new SQLVarchar("e")},
152         {new SQLInteger(1), new SQLVarchar("zz")}
153     };
154
155     private static final DataValueDescriptor[] multiKeyTemplate = { new SQLLongint(), new SQLVarchar(), new SQLInteger()};
156     private static final int[] multiKeyCols = {1, 0};
157     private static final DataValueDescriptor[][] multiKeyRows =
158     {
159         {new SQLLongint(1), new SQLVarchar( "aa"), multiKeyTemplate[2].getNewNull()},
160         {new SQLLongint(2), new SQLVarchar( "aa"), new SQLInteger(1)},
161         {new SQLLongint(2), new SQLVarchar( "aa"), new SQLInteger(2)},
162         {new SQLLongint(2), new SQLVarchar( "b"), new SQLInteger(1)}
163     };
164
165     private static final int LOTS_OF_ROWS_COUNT = 50000;
166     
167     private void testOneVariant( TransactionController tc,
168                                  boolean removeDups,
169                                  DataValueDescriptor[] template,
170                                  int[] keyCols,
171                                  DataValueDescriptor[][] rows)
172         throws StandardException
173     {
174         DiskHashtable dht = new DiskHashtable(tc, template, keyCols, removeDups, false);
175         boolean[] isDuplicate = new boolean[ rows.length];
176         boolean[] found = new boolean[ rows.length];
177         HashMap JavaDoc simpleHash = new HashMap JavaDoc( rows.length);
178
179         testElements( removeDups, dht, keyCols, 0, rows, simpleHash, isDuplicate, found);
180
181         for( int i = 0; i < rows.length; i++)
182         {
183             Object JavaDoc key = KeyHasher.buildHashKey( rows[i], keyCols);
184             Vector JavaDoc al = (Vector JavaDoc) simpleHash.get( key);
185             isDuplicate[i] = (al != null);
186             if( al == null)
187             {
188                 al = new Vector JavaDoc(4);
189                 simpleHash.put( key, al);
190             }
191             if( (!removeDups) || !isDuplicate[i])
192                 al.add( rows[i]);
193             
194             if( dht.put( key, rows[i]) != (removeDups ? (!isDuplicate[i]) : true))
195                 REPORT_FAILURE( " put returned wrong value on row " + i);
196
197             for( int j = 0; j <= i; j++)
198             {
199                 key = KeyHasher.buildHashKey( rows[j], keyCols);
200                 if( ! rowsEqual( dht.get( key), simpleHash.get( key)))
201                     REPORT_FAILURE( " get returned wrong value on key " + j);
202             }
203
204             testElements( removeDups, dht, keyCols, i+1, rows, simpleHash, isDuplicate, found);
205         }
206         // Remove them
207
for( int i = 0; i < rows.length; i++)
208         {
209             Object JavaDoc key = KeyHasher.buildHashKey( rows[i], keyCols);
210             if( ! rowsEqual( dht.remove( key), simpleHash.get( key)))
211                 REPORT_FAILURE( " remove returned wrong value on key " + i);
212             simpleHash.remove( key);
213             if( dht.get( key) != null)
214                 REPORT_FAILURE( " remove did not delete key " + i);
215         }
216         testElements( removeDups, dht, keyCols, 0, rows, simpleHash, isDuplicate, found);
217
218         testLargeTable( dht, keyCols, rows[0]);
219         dht.close();
220     } // end of testOneVariant
221

222     private void testLargeTable( DiskHashtable dht,
223                                  int[] keyCols,
224                                  DataValueDescriptor[] aRow)
225         throws StandardException
226     {
227         // Add a lot of elements
228
// If there are two or more key columns then we will vary the first two key columns, using an approximately
229
// square matrix of integer key values. Because the hash generator is commutative key (i,j) hashes into the
230
// same bucket as key (j,i), testing the case where different keys hash into the same bucket.
231
int key1Count = (keyCols.length > 1) ? ((int) Math.round( Math.sqrt( (double) LOTS_OF_ROWS_COUNT))) : 1;
232         int key0Count = (LOTS_OF_ROWS_COUNT + key1Count - 1)/key1Count;
233
234         DataValueDescriptor[] row = new DataValueDescriptor[ aRow.length];
235         for( int i = 0; i < row.length; i++)
236             row[i] = aRow[i].getClone();
237         
238         for( int key0Idx = 0; key0Idx < key0Count; key0Idx++)
239         {
240             row[ keyCols[0]].setValue( key0Idx);
241             for( int key1Idx = 0; key1Idx < key1Count; key1Idx++)
242             {
243                 if( keyCols.length > 1)
244                     row[ keyCols[1]].setValue( key1Idx);
245                 Object JavaDoc key = KeyHasher.buildHashKey( row, keyCols);
246                 if( ! dht.put( key, row))
247                 {
248                     REPORT_FAILURE( " put returned wrong value for key(" + key0Idx + "," + key1Idx + ")");
249                     key0Idx = key0Count;
250                     break;
251                 }
252             }
253         }
254         for( int key0Idx = 0; key0Idx < key0Count; key0Idx++)
255         {
256             row[ keyCols[0]].setValue( key0Idx);
257             for( int key1Idx = 0; key1Idx < key1Count; key1Idx++)
258             {
259                 if( keyCols.length > 1)
260                     row[ keyCols[1]].setValue( key1Idx);
261                 Object JavaDoc key = KeyHasher.buildHashKey( row, keyCols);
262                 if( ! rowsEqual( dht.get( key), row))
263                 {
264                     REPORT_FAILURE( " large table get returned wrong value for key(" + key0Idx + "," + key1Idx + ")");
265                     key0Idx = key0Count;
266                     break;
267                 }
268             }
269         }
270         BitSet JavaDoc found = new BitSet JavaDoc(key0Count * key1Count);
271         Enumeration JavaDoc elements = dht.elements();
272         while( elements.hasMoreElements())
273         {
274             Object JavaDoc el = elements.nextElement();
275             if( ! (el instanceof DataValueDescriptor[]))
276             {
277                 REPORT_FAILURE( " large table enumeration returned wrong element type");
278                 break;
279             }
280             DataValueDescriptor[] fetchedRow = (DataValueDescriptor[]) el;
281             
282             int i = fetchedRow[ keyCols[0]].getInt() * key1Count;
283             if( keyCols.length > 1)
284                 i += fetchedRow[ keyCols[1]].getInt();
285             if( i >= key0Count * key1Count)
286             {
287                 REPORT_FAILURE( " large table enumeration returned invalid element");
288                 break;
289             }
290                 
291             if( found.get(i))
292             {
293                 REPORT_FAILURE( " large table enumeration returned same element twice");
294                 break;
295             }
296             found.set(i);
297         }
298         for( int i = key0Count * key1Count - 1; i >= 0; i--)
299         {
300             if( !found.get(i))
301             {
302                 REPORT_FAILURE( " large table enumeration missed at least one element");
303                 break;
304             }
305         }
306     } // end of testLargeTable
307

308     private void testElements( boolean removeDups,
309                                DiskHashtable dht,
310                                int[] keyCols,
311                                int rowCount,
312                                DataValueDescriptor[][] rows,
313                                HashMap JavaDoc simpleHash,
314                                boolean[] isDuplicate,
315                                boolean[] found)
316         throws StandardException
317     {
318         for( int i = 0; i < rowCount; i++)
319             found[i] = false;
320         
321         for( Enumeration JavaDoc e = dht.elements(); e.hasMoreElements();)
322         {
323             Object JavaDoc el = e.nextElement();
324             if( el == null)
325             {
326                 REPORT_FAILURE( " table enumeration returned a null element");
327                 return;
328             }
329             if( el instanceof DataValueDescriptor[])
330                 checkElement( (DataValueDescriptor[]) el, rowCount, rows, found);
331             else if( el instanceof Vector JavaDoc)
332             {
333                 Vector JavaDoc v = (Vector JavaDoc) el;
334                 for( int i = 0; i < v.size(); i++)
335                     checkElement( (DataValueDescriptor[]) v.get(i), rowCount, rows, found);
336             }
337             else if( el == null)
338             {
339                 REPORT_FAILURE( " table enumeration returned an incorrect element type");
340                 return;
341             }
342         }
343         for( int i = 0; i < rowCount; i++)
344         {
345             if( (removeDups && isDuplicate[i]))
346             {
347                 if( found[i])
348                 {
349                     REPORT_FAILURE( " table enumeration did not remove duplicates");
350                     return;
351                 }
352             }
353             else if( ! found[i])
354             {
355                 REPORT_FAILURE( " table enumeration missed at least one element");
356                 return;
357             }
358         }
359     } // end of testElements
360

361     private void checkElement( DataValueDescriptor[] fetchedRow,
362                                int rowCount,
363                                DataValueDescriptor[][] rows,
364                                boolean[] found)
365         throws StandardException
366     {
367         for( int i = 0; i < rowCount; i++)
368         {
369             if( rowsEqual( fetchedRow, rows[i]))
370             {
371                 if( found[i])
372                 {
373                     REPORT_FAILURE( " table enumeration returned the same element twice");
374                     return;
375                 }
376                 found[i] = true;
377                 return;
378             }
379         }
380         REPORT_FAILURE( " table enumeration returned an incorrect element");
381     } // end of checkElement
382

383     private boolean rowsEqual( Object JavaDoc r1, Object JavaDoc r2)
384         throws StandardException
385     {
386         if( r1 == null)
387             return r2 == null;
388
389         if( r1 instanceof DataValueDescriptor[])
390         {
391             DataValueDescriptor[] row1 = (DataValueDescriptor[]) r1;
392             DataValueDescriptor[] row2;
393             
394             if( r2 instanceof Vector JavaDoc)
395             {
396                 Vector JavaDoc v2 = (Vector JavaDoc) r2;
397                 if( v2.size() != 1)
398                     return false;
399                 row2 = (DataValueDescriptor[]) v2.elementAt(0);
400             }
401             else if( r2 instanceof DataValueDescriptor[])
402                 row2 = (DataValueDescriptor[]) r2;
403             else
404                 return false;
405             
406             if( row1.length != row2.length)
407                 return false;
408             for( int i = 0; i < row1.length; i++)
409             {
410                 if( ! row1[i].compare( Orderable.ORDER_OP_EQUALS, row2[i], true, true))
411                     return false;
412             }
413             return true;
414         }
415         if( r1 instanceof Vector JavaDoc)
416         {
417             if( !(r2 instanceof Vector JavaDoc))
418                 return false;
419             Vector JavaDoc v1 = (Vector JavaDoc) r1;
420             Vector JavaDoc v2 = (Vector JavaDoc) r2;
421             if( v1.size() != v2.size())
422                 return false;
423             for( int i = v1.size() - 1; i >= 0; i--)
424             {
425                 if( ! rowsEqual( v1.elementAt( i), v2.elementAt(i)))
426                     return false;
427             }
428             return true;
429         }
430         // What is it then?
431
return r1.equals( r2);
432     } // end of rowsEqual
433
}
434
Popular Tags