1 21 22 package org.apache.derbyTesting.functionTests.tests.store; 23 24 import java.sql.Connection ; 25 import java.sql.ResultSet ; 26 import java.sql.SQLException ; 27 import java.sql.Statement ; 28 29 import java.util.BitSet ; 30 import java.util.Enumeration ; 31 import java.util.HashMap ; 32 import java.util.Vector ; 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 59 public class TestDiskHashtable 60 { 61 private TransactionController tc; 62 private int failed = 0; 63 64 public static void main( String args[]) 65 { 66 int failed = 1; 67 68 REPORT("Test DiskHashtable starting"); 69 try 70 { 71 ij.getPropertyArg(args); 74 Connection conn = ij.startJBMS(); 75 Statement 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 rs = stmt.executeQuery( "values( testDiskHashtable())"); 78 if( rs.next()) 79 failed = rs.getInt(1); 80 stmt.close(); 81 conn.close(); 82 } 83 catch( SQLException e) 84 { 85 TestUtil.dumpSQLExceptions( e); 86 failed = 1; 87 } 88 catch( Throwable 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 msg) 98 { 99 failed = 1; 100 REPORT( msg); 101 } 102 103 private static void REPORT(String msg) 104 { 105 System.out.println( msg); 106 } 107 108 public static int runTests() throws SQLException 109 { 110 TestDiskHashtable tester = new TestDiskHashtable(); 111 return tester.doIt(); 112 } 113 114 private TestDiskHashtable() throws SQLException 115 { 116 LanguageConnectionContext lcc = ConnectionUtil.getCurrentLCC(); 117 if( lcc == null) 118 throw new SQLException ( "Cannot get the LCC"); 119 tc = lcc.getTransactionExecute(); 120 } 121 122 private int doIt() throws SQLException 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 } 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 simpleHash = new HashMap ( 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 key = KeyHasher.buildHashKey( rows[i], keyCols); 184 Vector al = (Vector ) simpleHash.get( key); 185 isDuplicate[i] = (al != null); 186 if( al == null) 187 { 188 al = new Vector (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 for( int i = 0; i < rows.length; i++) 208 { 209 Object 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 } 222 private void testLargeTable( DiskHashtable dht, 223 int[] keyCols, 224 DataValueDescriptor[] aRow) 225 throws StandardException 226 { 227 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 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 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 found = new BitSet (key0Count * key1Count); 271 Enumeration elements = dht.elements(); 272 while( elements.hasMoreElements()) 273 { 274 Object 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 } 308 private void testElements( boolean removeDups, 309 DiskHashtable dht, 310 int[] keyCols, 311 int rowCount, 312 DataValueDescriptor[][] rows, 313 HashMap 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 e = dht.elements(); e.hasMoreElements();) 322 { 323 Object 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 ) 332 { 333 Vector v = (Vector ) 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 } 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 } 383 private boolean rowsEqual( Object r1, Object 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 ) 395 { 396 Vector v2 = (Vector ) 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 ) 416 { 417 if( !(r2 instanceof Vector )) 418 return false; 419 Vector v1 = (Vector ) r1; 420 Vector v2 = (Vector ) 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 return r1.equals( r2); 432 } } 434 | Popular Tags |