1 24 25 package com.mckoi.database; 26 27 import java.io.*; 28 import java.util.ArrayList ; 29 import com.mckoi.util.IntegerVector; 30 import com.mckoi.util.IntegerIterator; 31 import com.mckoi.util.IndexComparator; 32 import com.mckoi.util.BlockIntegerList; 33 import com.mckoi.debug.*; 34 35 57 58 final class RIDList { 59 60 63 private TransactionSystem system; 64 65 68 private MasterTableDataSource master_table; 69 70 73 private TableName table_name; 74 75 78 private String column_name; 79 80 83 private int column; 84 85 89 private BlockIntegerList set_list; 90 91 94 private IntegerVector rid_list; 95 96 100 private int hash_rid_difference; 101 102 106 private IndexComparator set_comparator; 107 108 111 private boolean is_built; 112 113 121 private int build_state = 0; 122 123 126 private IntegerVector concurrent_modification_info; 127 private ArrayList concurrent_modification_data; 128 private Object modification_lock = new Object (); 129 130 133 private boolean request_processing = false; 134 135 138 RIDList(MasterTableDataSource master_table, int column) { 139 this.master_table = master_table; 141 this.system = master_table.getSystem(); 142 this.column = column; 143 144 DataTableDef table_def = master_table.getDataTableDef(); 145 table_name = table_def.getTableName(); 146 column_name = table_def.columnAt(column).getName(); 147 148 is_built = false; 149 setupComparator(); 150 } 151 152 155 public final DebugLogger Debug() { 156 return master_table.Debug(); 157 } 158 159 163 private void setupComparator() { 164 set_comparator = new IndexComparator() { 165 166 private int internalCompare(int index, TObject cell2) { 167 TObject cell1 = getCellContents(index); 168 return cell1.compareTo(cell2); 169 } 170 171 public int compare(int index, Object val) { 172 return internalCompare(index, (TObject) val); 173 } 174 public int compare(int index1, int index2) { 175 TObject cell = getCellContents(index2); 176 return internalCompare(index1, cell); 177 } 178 }; 179 } 180 181 184 private TObject getCellContents(int row) { 185 return master_table.getCellContents(column, row); 186 } 187 188 192 private void calcHashRIDDifference(int size) { 193 if (size == 0) { 194 hash_rid_difference = 32; 195 } 196 else { 197 hash_rid_difference = (65536 * 4096) / size; 198 if (hash_rid_difference > 16384) { 199 hash_rid_difference = 16384; 200 } 201 else if (hash_rid_difference < 8) { 202 hash_rid_difference = 8; 203 } 204 } 205 206 } 209 210 211 216 private int rehashRIDList(int old_rid_place) { 217 calcHashRIDDifference(set_list.size()); 218 219 int new_rid_place = -1; 220 221 int cur_rid = 0; 222 int old_rid = 0; 223 IntegerIterator iterator = set_list.iterator(); 224 225 while (iterator.hasNext()) { 226 int row_index = iterator.next(); 227 if (row_index >= 0 && row_index < rid_list.size()) { 228 int old_value = rid_list.intAt(row_index); 229 int new_value; 230 231 if (old_value == 0) { 232 cur_rid += hash_rid_difference; 233 new_rid_place = cur_rid; 234 } 235 else { 236 if (old_value != old_rid) { 237 old_rid = old_value; 238 cur_rid += hash_rid_difference; 239 new_value = cur_rid; 240 } 241 else { 242 new_value = cur_rid; 243 } 244 rid_list.placeIntAt(new_value, row_index); 245 } 246 } 247 } 248 249 if (new_rid_place == -1) { 250 throw new Error ( 251 "Post condition not correct - new_rid_place shouldn't be -1"); 252 } 253 254 system.stats().increment("RIDList.rehash_rid_table"); 255 256 return new_rid_place; 257 } 258 259 260 270 void insertRID(TObject cell, int row) { 271 274 synchronized (modification_lock) { 275 276 if (build_state > 0 && build_state < 4) { 278 concurrent_modification_info.addInt(1); 279 concurrent_modification_info.addInt(row); 280 concurrent_modification_data.add(cell); 281 return; 282 } 283 284 if (rid_list == null) { 286 return; 287 } 288 289 } 290 291 rid_list.placeIntAt(0, row); 293 294 set_list.insertSort(cell, row, set_comparator); 296 297 int given_rid = -1; 298 TObject previous_cell; 299 300 int set_index = set_list.searchLast(cell, set_comparator); 302 303 if (set_list.get(set_index) != row) { 304 throw new Error ( 305 "set_list.searchLast(cell) didn't turn up expected row."); 306 } 307 308 int next_set_index = set_index + 1; 309 if (next_set_index >= set_list.size()) { 310 next_set_index = -1; 311 } 312 int previous_set_index = set_index - 1; 313 314 int next_rid; 315 if (next_set_index > -1) { 316 next_rid = rid_list.intAt(set_list.get(next_set_index)); 317 } 318 else { 319 if (previous_set_index > -1) { 320 next_rid = rid_list.intAt(set_list.get(previous_set_index)) + 323 (hash_rid_difference * 2); 324 } 325 else { 326 next_rid = (hash_rid_difference * 2); 327 } 328 } 329 int previous_rid; 330 if (previous_set_index > -1) { 331 previous_rid = rid_list.intAt(set_list.get(previous_set_index)); 332 } 333 else { 334 previous_rid = 0; 335 } 336 337 if (previous_set_index > -1) { 339 previous_cell = getCellContents(set_list.get(previous_set_index)); 340 if (previous_cell.compareTo(cell) == 0) { 341 given_rid = previous_rid; 342 } 343 } 344 345 if (given_rid == -1) { 347 if (previous_rid + 1 == next_rid) { 348 given_rid = rehashRIDList(next_rid); 350 } 351 else { 352 given_rid = ((next_rid + 1) + (previous_rid - 1)) / 2; 353 } 354 } 355 356 rid_list.placeIntAt(given_rid, row); 358 359 } 360 361 369 void removeRID(int row) { 370 373 synchronized (modification_lock) { 374 375 if (build_state > 0 && build_state < 4) { 377 concurrent_modification_info.addInt(2); 378 concurrent_modification_info.addInt(row); 379 return; 380 } 381 382 if (rid_list == null) { 384 return; 385 } 386 387 } 388 389 try { 390 TObject cell = getCellContents(row); 392 int removed = set_list.removeSort(cell, row, set_comparator); 393 } 394 catch (Error e) { 395 System.err.println("RIDList: " + table_name + "." + column_name); 396 throw e; 397 } 398 399 } 400 401 405 void requestBuildRIDList() { 406 if (!isBuilt()) { 407 if (!request_processing) { 408 request_processing = true; 409 system.postEvent(10000, system.createEvent(new Runnable () { 411 public void run() { 412 createRIDCache(); 413 } 414 })); 415 } 416 } 417 } 418 419 425 private void createRIDCache() { 426 427 try { 428 429 if (master_table.isClosed()) { 432 return; 433 } 434 435 long time_start = System.currentTimeMillis(); 436 long time_took; 437 int rid_list_size; 438 439 int set_size; 440 441 synchronized (master_table) { 442 synchronized (modification_lock) { 443 444 if (is_built) { 445 return; 446 } 447 448 build_state = 1; 450 concurrent_modification_info = new IntegerVector(); 451 concurrent_modification_data = new ArrayList (); 452 453 set_size = master_table.rawRowCount(); 455 set_list = new BlockIntegerList(); 456 for (int r = 0; r < set_size; ++r) { 458 if (!master_table.recordDeleted(r)) { 459 TObject cell = getCellContents(r); 460 set_list.insertSort(cell, r, set_comparator); 461 } 462 } 463 466 master_table.addRootLock(); 468 469 } } 472 try { 473 474 478 calcHashRIDDifference(set_size); 479 480 rid_list = new IntegerVector(set_size + 128); 481 482 if (set_list.size() > 0) { int cur_rid = hash_rid_difference; 486 IntegerIterator iterator = set_list.iterator(); 487 int row_index = iterator.next(); 488 TObject last_cell = getCellContents(row_index); 489 rid_list.placeIntAt(cur_rid, row_index); 490 491 while (iterator.hasNext()) { 492 row_index = iterator.next(); 493 TObject cur_cell = getCellContents(row_index); 494 int cmp = cur_cell.compareTo(last_cell); 495 if (cmp > 0) { 496 cur_rid += hash_rid_difference; 497 } 498 else if (cmp < 0) { throw new Error ("Internal Database Error: Index is corrupt " + 502 " - InsertSearch list is not sorted."); 503 } 504 rid_list.placeIntAt(cur_rid, row_index); 505 506 last_cell = cur_cell; 507 } 508 } 509 510 synchronized (master_table) { 514 synchronized (modification_lock) { 515 build_state = 4; 516 517 int mod_size = concurrent_modification_info.size(); 520 int i = 0; 521 int m_data = 0; 522 int insert_count = 0; 523 int remove_count = 0; 524 while (i < mod_size) { 525 int type = concurrent_modification_info.intAt(i); 526 int row = concurrent_modification_info.intAt(i + 1); 527 if (type == 1) { 529 TObject cell = 530 (TObject) concurrent_modification_data.get(m_data); 531 insertRID(cell, row); 532 ++m_data; 533 ++insert_count; 534 } 535 else if (type == 2) { 537 removeRID(row); 538 ++remove_count; 539 } 540 else { 541 throw new Error ("Unknown modification type."); 542 } 543 544 i += 2; 545 } 546 547 if (remove_count > 0) { 548 Debug().write(Lvl.ERROR, this, 549 "Assertion failed: It should not be possible to remove " + 550 "rows during a root lock when building a RID list."); 551 } 552 553 concurrent_modification_info = null; 554 concurrent_modification_data = null; 555 556 time_took = System.currentTimeMillis() - time_start; 558 rid_list_size = rid_list.size(); 559 560 is_built = true; 561 562 } 563 } 565 } 566 finally { 567 master_table.removeRootLock(); 569 } 570 571 Debug().write(Lvl.MESSAGE, this, 572 "RID List " + table_name.toString() + "." + column_name + 573 " Initial Size = " + rid_list_size); 574 Debug().write(Lvl.MESSAGE, this, 575 "RID list built in " + time_took + "ms."); 576 577 system.stats().increment( 579 "{session} RIDList.rid_caches_created"); 580 system.stats().add(rid_list_size, 582 "{session} RIDList.rid_indices"); 583 584 } 585 catch (IOException e) { 586 throw new Error ("IO Error: " + e.getMessage()); 587 } 588 589 } 590 591 594 boolean isBuilt() { 595 synchronized (modification_lock) { 596 return is_built; 597 } 598 } 599 600 609 BlockIntegerList sortedSet(final IntegerVector row_set) { 610 611 int row_set_length = row_set.size(); 613 614 BlockIntegerList new_set = new BlockIntegerList(); 617 618 IndexComparator comparator = new IndexComparator() { 620 public int compare(int index, Object val) { 621 int rid_val = rid_list.intAt(row_set.intAt(index)); 622 int rid_val2 = ((Integer ) val).intValue(); 623 return rid_val - rid_val2; 624 } 625 public int compare(int index1, int index2) { 626 throw new Error ("Shouldn't be called!"); 627 } 628 }; 629 630 synchronized (master_table) { 636 637 for (int i = 0; i < row_set_length; ++i) { 639 Integer rid_val = 640 new Integer (rid_list.intAt(row_set.intAt(i))); 641 new_set.insertSort(rid_val, i, comparator); 642 } 643 644 return new_set; 645 646 } 648 } 649 650 651 } 652 653 | Popular Tags |