1 2 12 package com.versant.core.jdo.tools.ant; 13 14 import com.versant.core.jdo.QueryDetails; 15 import com.versant.core.common.*; 16 import com.versant.core.common.config.ConfigInfo; 17 import com.versant.core.common.config.ConfigParser; 18 import com.versant.core.jdbc.JdbcConfig; 19 import com.versant.core.metadata.*; 20 import com.versant.core.common.NewObjectOID; 21 import com.versant.core.logging.LogEventStore; 22 import com.versant.core.server.*; 23 import com.versant.core.jdbc.*; 24 import com.versant.core.jdbc.query.JdbcCompiledQuery; 25 import com.versant.core.jdbc.metadata.JdbcLinkCollectionField; 26 import com.versant.core.jdbc.metadata.JdbcTable; 27 import com.versant.core.jdbc.metadata.JdbcClass; 28 import com.versant.core.jdbc.sql.SqlDriver; 29 import com.versant.core.util.CharBuf; 30 31 import java.io.PrintStream ; 32 import java.io.PrintWriter ; 33 import java.sql.*; 34 import java.text.SimpleDateFormat ; 35 import java.util.*; 36 import java.util.Date ; 37 38 import com.versant.core.common.BindingSupportImpl; 39 import com.versant.core.storagemanager.DummyApplicationContext; 40 import com.versant.core.storagemanager.StorageManagerFactoryBuilder; 41 import com.versant.core.logging.LogEventStore; 42 43 47 public class CopyDatabaseBean { 48 49 private Properties srcProps; 50 private String datastore; 51 private Properties destProps; 52 private String db; 53 private String url; 54 private String driver; 55 private String user; 56 private String password; 57 private String properties; 58 private boolean dropTables = true; 59 private boolean createTables = true; 60 private PrintStream out = System.out; 61 private PrintWriter outw; 62 private boolean stopFlag; 63 private ClassLoader loader = getClass().getClassLoader(); 64 private int rowsPerTransaction = 1000; 65 private String logEvents = LogEventStore.LOG_EVENTS_ERRORS; 66 private boolean logEventsToSysOut = true; 67 68 private MiniServer dest; 69 private MiniServer src; 70 71 private static final SimpleDateFormat DATE_FORMAT = 72 new SimpleDateFormat ("dd MMM yyyy HH:mm:ss"); 73 74 private static final int DOTS_PER_LINE = 70; 75 76 private static final DummyKeyGen DUMMY_KEY_GEN = new DummyKeyGen(); 77 78 public CopyDatabaseBean() { 79 } 80 81 public Properties getSrcProps() { 82 return srcProps; 83 } 84 85 public void setSrcProps(Properties srcProps) { 86 this.srcProps = srcProps; 87 } 88 89 public String getDatastore() { 90 return datastore; 91 } 92 93 public void setDatastore(String datastore) { 94 this.datastore = datastore; 95 } 96 97 public Properties getDestProps() { 98 return destProps; 99 } 100 101 public void setDestProps(Properties destProps) { 102 this.destProps = destProps; 103 } 104 105 public String getDb() { 106 return db; 107 } 108 109 public void setDb(String db) { 110 this.db = db; 111 } 112 113 public String getUrl() { 114 return url; 115 } 116 117 public void setUrl(String url) { 118 this.url = url; 119 } 120 121 public String getDriver() { 122 return driver; 123 } 124 125 public void setDriver(String driver) { 126 this.driver = driver; 127 } 128 129 public String getUser() { 130 return user; 131 } 132 133 public void setUser(String user) { 134 this.user = user; 135 } 136 137 public String getPassword() { 138 return password; 139 } 140 141 public void setPassword(String password) { 142 this.password = password; 143 } 144 145 public String getProperties() { 146 return properties; 147 } 148 149 public void setProperties(String properties) { 150 this.properties = properties; 151 } 152 153 public boolean isCreateTables() { 154 return createTables; 155 } 156 157 public void setCreateTables(boolean createTables) { 158 this.createTables = createTables; 159 } 160 161 public boolean isDropTables() { 162 return dropTables; 163 } 164 165 public void setDropTables(boolean dropTables) { 166 this.dropTables = dropTables; 167 } 168 169 public PrintStream getOut() { 170 return out; 171 } 172 173 public void setOut(PrintStream out) { 174 this.out = out; 175 } 176 177 public boolean isStopFlag() { 178 return stopFlag; 179 } 180 181 public void setStopFlag(boolean stopFlag) { 182 this.stopFlag = stopFlag; 183 } 184 185 public String getLogEvents() { 186 return logEvents; 187 } 188 189 public void setLogEvents(String logEvents) { 190 this.logEvents = logEvents; 191 } 192 193 public boolean isLogEventsToSysOut() { 194 return logEventsToSysOut; 195 } 196 197 public void setLogEventsToSysOut(boolean logEventsToSysOut) { 198 this.logEventsToSysOut = logEventsToSysOut; 199 } 200 201 public ClassLoader getLoader() { 202 return loader; 203 } 204 205 public void setLoader(ClassLoader loader) { 206 this.loader = loader; 207 } 208 209 public int getRowsPerTransaction() { 210 return rowsPerTransaction; 211 } 212 213 public void setRowsPerTransaction(int rowsPerTransaction) { 214 this.rowsPerTransaction = rowsPerTransaction; 215 } 216 217 private void checkStopFlag() { 218 if (stopFlag) throw new StoppedException(); 219 } 220 221 224 private void prepare() { 225 if (srcProps == null) { 226 throw BindingSupportImpl.getInstance().illegalArgument("srcProps property not set"); 227 } 228 229 if (destProps == null) destProps = (Properties)srcProps.clone(); 230 231 232 if (db != null) destProps.setProperty(ConfigParser.STORE_DB, db); 233 if (driver != null) { 234 destProps.setProperty(ConfigParser.STD_CON_DRIVER_NAME, driver); 235 } 236 if (url != null) { 237 destProps.setProperty(ConfigParser.STD_CON_URL, 238 url); 239 } 240 if (user != null) { 241 destProps.setProperty(ConfigParser.STD_CON_USER_NAME, user); 242 } 243 if (password != null) { 244 destProps.setProperty(ConfigParser.STD_CON_PASSWORD, password); 245 } 246 if (properties != null) { 247 properties = properties.trim().replace('\n', ';'); 248 destProps.setProperty(ConfigParser.STORE_PROPERTIES, 249 properties); 250 } 251 252 outw = new PrintWriter (out, true); 253 } 254 255 258 public void copyDatabase() throws Exception { 259 prepare(); 260 long start = System.currentTimeMillis(); 261 out.println("Started copy at " + DATE_FORMAT.format(new Date (start)) + 262 "\n"); 263 src = dest = null; 264 try { 265 dest = new MiniServer(destProps); 266 checkStopFlag(); 267 src = new MiniServer(srcProps); 268 checkStopFlag(); 269 270 if (dropTables) dest.dropAllTables(); 271 if (createTables) dest.createAllTables(); 272 273 ClassMetaData[] srcClasses = src.getStoreClasses(); 274 ClassMetaData[] destClasses = dest.getStoreClasses(); 275 276 out.println("=== Copying main table for each class (one dot = " + 277 rowsPerTransaction + " rows) ===\n"); 278 long mainStart = System.currentTimeMillis(); 279 int mainTotRows = 0; 280 int numClasses = srcClasses.length; 281 for (int i = 0; i < numClasses; i++) { 282 mainTotRows += copyClassMainTable(srcClasses[i], 283 destClasses[i]); 284 checkStopFlag(); 285 } 286 int mainTime = (int)(System.currentTimeMillis() - mainStart); 287 out.println(); 288 289 out.println("=== Copying link tables for each class (one dot = " + 290 rowsPerTransaction + " rows) ===\n"); 291 long linkStart = System.currentTimeMillis(); 292 int linkTotRows = 0; 293 for (int i = 0; i < numClasses; i++) { 294 ClassMetaData sc = srcClasses[i]; 295 for (int j = 0; j < sc.fields.length; j++) { 296 FieldMetaData sfmd = sc.fields[j]; 297 if (sfmd.storeField instanceof JdbcLinkCollectionField) { 298 JdbcLinkCollectionField srcField = 299 (JdbcLinkCollectionField)sfmd.storeField; 300 if (!srcField.readOnly) { 301 linkTotRows += copyLinkTable(srcField, 302 (JdbcLinkCollectionField)destClasses[i].fields[j].storeField); 303 checkStopFlag(); 304 } 305 } 306 } 307 } 308 int linkTime = (int)(System.currentTimeMillis() - linkStart); 309 out.println(); 310 311 if (createTables) { 312 dest.createAllIndexes(); 313 dest.createAllConstraints(); 314 } 315 316 out.println("Copied " + mainTotRows + " main table rows " + 317 "in " + fmtSec(mainTime) + " secs (" + 318 perSec(mainTotRows, mainTime) + " per second)"); 319 320 out.println("Copied " + linkTotRows + " link table rows " + 321 "in " + fmtSec(linkTime) + " secs (" + 322 perSec(linkTotRows, linkTime) + " per second)"); 323 324 } catch (StoppedException x) { 325 out.println("\n*** Copy aborted ***"); 326 } finally { 327 if (src != null) src.shutdown(); 328 if (dest != null) dest.shutdown(); 329 src = dest = null; 330 out.println("\nFinished at " + DATE_FORMAT.format(new Date ())); 331 } 332 } 333 334 private String fmtSec(int ms) { 335 StringBuffer s = new StringBuffer (); 336 s.append(ms / 1000); 337 s.append('.'); 338 ms = ms % 1000; 339 if (ms < 10) s.append("00"); 340 if (ms < 100) s.append('0'); 341 s.append(ms); 342 return s.toString(); 343 } 344 345 private String perSec(int rows, int ms) { 346 float f = Math.round(rows * 10000.0f / ms) / 10; 347 return String.valueOf(f); 348 } 349 350 private int copyClassMainTable(ClassMetaData srcClass, 351 ClassMetaData destClass) throws Exception { 352 out.println(((JdbcClass)srcClass.storeClass).table.name + " - " + srcClass.qname); 353 354 JdbcKeyGenerator keygen = ((JdbcClass)destClass.storeClass).jdbcKeyGenerator; 355 boolean autoinc = keygen != null && keygen.isPostInsertGenerator(); 356 ((JdbcClass)destClass.storeClass).jdbcKeyGenerator = DUMMY_KEY_GEN; 357 358 JdbcQueryResult rs = null; 359 try { 360 Connection destCon = dest.pool.getConnection(false, false); 361 if (autoinc) { 362 dest.sqlDriver.enableIdentityInsert(destCon, 363 ((JdbcClass)destClass.storeClass).table.name, true); 364 } 365 366 PersistGraph pg = new PersistGraph(dest.getJmd(), 367 rowsPerTransaction); 368 369 QueryDetails qp = new QueryDetails(); 370 qp.setCandidateClass(srcClass.cls); 371 qp.setSubClasses(false); 372 qp.setFetchGroupIndex( 373 srcClass.getFetchGroup(FetchGroup.ALL_COLS_NAME).index); 374 qp.setResultBatchSize(rowsPerTransaction); 375 JdbcCompiledQuery cq = (JdbcCompiledQuery)src.getSm().compileQuery(qp); 376 cq.setCacheable(false); 377 378 int tot = 0; 379 int dots = 0; 380 rs = (JdbcQueryResult)src.getSm().executeQuery( 381 DummyApplicationContext.INSTANCE, null, cq, 382 null).getRunningQuery(); 383 StatesReturned container = new StatesReturned(DummyApplicationContext.INSTANCE); 384 for (; ;) { 385 int c = 0; 386 boolean more = false; 387 for (; c < rowsPerTransaction && (more = rs.next(0)); c++) { 388 JdbcGenericOID oid = (JdbcGenericOID)rs.getResultOID(); 389 JdbcGenericState state = (JdbcGenericState)rs.getResultState(false, container); 390 oid.setCmd(destClass); 391 state.setClassMetaData(destClass); 392 NewObjectOID noid = destClass.createNewObjectOID(); 393 noid.realOID = oid; 394 pg.add(noid, null, state); 395 container.clear(); 396 } 397 if (c > 0) { 398 dest.getSm().begin(false); 399 dest.getSm().persistPass1(pg); 400 dest.getSm().commit(); 401 tot += c; 402 if (++dots == DOTS_PER_LINE) { 403 out.println("." + tot); 404 dots = 0; 405 } else { 406 out.print('.'); 407 } 408 pg.clear(); 409 } 410 if (!more) break; 411 checkStopFlag(); 412 } 413 if (dots > 0) out.println(tot); 414 415 if (autoinc) { 416 dest.sqlDriver.enableIdentityInsert(destCon, 417 ((JdbcClass)destClass.storeClass).table.name, false); 418 } 419 420 return tot; 421 } finally { 422 if (rs != null) { 423 try { 424 rs.close(); 425 } catch (Exception e) { 426 } 428 } 429 if (src.getSm().isActive()) { 430 src.getSm().rollback(); 431 } 432 if (dest.getSm().isActive()) { 433 dest.getSm().rollback(); 434 } 435 } 436 } 437 438 private void close(ResultSet rs) { 439 if (rs == null) return; 440 try { 441 rs.close(); 442 } catch (SQLException e) { 443 } 445 } 446 447 private void close(Statement stat) { 448 if (stat == null) return; 449 try { 450 stat.close(); 451 } catch (SQLException e) { 452 } 454 } 455 456 private int copyLinkTable(JdbcLinkCollectionField srcField, 457 JdbcLinkCollectionField destField) throws Exception { 458 out.println(srcField.linkTable.name + " - " + srcField.fmd.getQName()); 459 460 Connection srcCon = null; 461 Connection destCon = null; 462 ResultSet rs = null; 463 PreparedStatement ps = null; 464 Statement stat = null; 465 try { 466 srcCon = src.getAutoCommitCon(); 467 destCon = dest.getSm().con(); 468 469 String insSql = srcField.getInsertLinkTableRowSql(new CharBuf()); 470 boolean batch = dest.getSm().isUseBatchInsert(); 471 472 stat = srcCon.createStatement(); 473 rs = stat.executeQuery( 474 srcField.getFetchAllRowsSql(src.getSm())); 475 if (src.getSm().getSqlDriver().isFetchSizeSupported()) { 476 rs.setFetchSize(rowsPerTransaction); 477 } 478 479 JdbcLinkCollectionField.LinkRow row = 480 new JdbcLinkCollectionField.LinkRow(); 481 482 int tot = 0; 483 int dots = 0; 484 for (; ;) { 485 ps = destCon.prepareStatement(insSql); 486 int c = 0; 487 boolean more = false; 488 for (; c < rowsPerTransaction && (more = rs.next()); c++) { 489 srcField.readRow(rs, row); 490 destField.writeRow(ps, row); 491 if (batch) { 492 ps.addBatch(); 493 } else { 494 ps.execute(); 495 } 496 } 497 if (c > 0) { 498 if (batch) ps.executeBatch(); 499 destCon.commit(); 500 ps.close(); 501 tot += c; 502 if (++dots == DOTS_PER_LINE) { 503 out.println("." + tot); 504 dots = 0; 505 } else { 506 out.print('.'); 507 } 508 } 509 if (!more) break; 510 checkStopFlag(); 511 } 512 if (dots > 0) out.println(tot); 513 return tot; 514 } finally { 515 close(rs); 516 close(stat); 517 close(ps); 518 src.closeAutoCommitCon(srcCon); 519 close(destCon); 520 } 521 } 522 523 private void close(Connection con) { 524 if (con == null) return; 525 try { 526 con.rollback(); 527 } catch (SQLException e) { 528 } 530 try { 531 con.close(); 532 } catch (SQLException e) { 533 } 535 } 536 537 541 private class MiniServer { 542 543 private final JdbcStorageManagerFactory factory; 544 private final JdbcStorageManager sm; 545 private final JdbcConnectionSource pool; 546 private final ModelMetaData jmd; 547 private final ConfigInfo config; 548 private final SqlDriver sqlDriver; 549 550 public MiniServer(Properties props) throws Exception { 551 552 props.put(ConfigParser.STORE_MAX_ACTIVE, "2"); 554 props.put(ConfigParser.STORE_MAX_IDLE, "2"); 555 props.put(ConfigParser.STORE_TEST_ON_ALLOC, "false"); 556 props.put(ConfigParser.STORE_TEST_ON_RELEASE, "false"); 557 props.put(ConfigParser.STORE_TEST_ON_EXCEPTION, "false"); 558 props.put(ConfigParser.STORE_RETRY_COUNT, "-1"); 559 ConfigParser p = new ConfigParser(); 560 config = p.parse(props); 561 config.validate(); 562 config.hyperdrive = false; 563 564 LogEventStore pes = new LogEventStore(); 566 pes.setLogEvents(logEvents); 567 pes.setLogEventsToSysOut(logEventsToSysOut); 568 569 StorageManagerFactoryBuilder b = new StorageManagerFactoryBuilder(); 570 b.setConfig(config); 571 b.setLoader(loader); 572 b.setFullInit(false); 573 factory = (JdbcStorageManagerFactory)b.createStorageManagerFactory(); 574 pool = factory.getConnectionSource(); 575 jmd = factory.getModelMetaData(); 576 sqlDriver = factory.getSqlDriver(); 577 sm = (JdbcStorageManager)factory.getStorageManager(); 578 } 579 580 public JdbcStorageManager getSm() { 581 return sm; 582 } 583 584 public ModelMetaData getJmd() { 585 return jmd; 586 } 587 588 public void shutdown() { 589 factory.returnStorageManager(sm); 590 factory.destroy(); 591 } 592 593 public Connection getAutoCommitCon() throws Exception { 594 return pool.getConnection(false, true); 595 } 596 597 public void closeAutoCommitCon(Connection con) throws SQLException { 598 if (con == null) return; 599 pool.returnConnection(con); 600 } 601 602 606 public void dropAllTables() throws Exception { 607 out.println("=== Dropping tables in: " + pool.getURL() + " ==="); 608 Connection con = null; 609 try { 610 con = getAutoCommitCon(); 611 HashMap dbTableNames = sm.getDatabaseTableNames(con); 612 checkStopFlag(); 613 ArrayList a = sm.getJdbcMetaData().getTables(); 614 for (int i = 0; i < a.size(); i++) { 615 JdbcTable t = (JdbcTable)a.get(i); 616 String name = (String )dbTableNames.get( 617 t.name.toLowerCase()); 618 if (name != null) { 619 out.println(" Dropping " + name); 620 sqlDriver.dropTable(con, name); 621 checkStopFlag(); 622 } 623 } 624 } finally { 625 closeAutoCommitCon(con); 626 } 627 out.println(); 628 } 629 630 633 public void createAllTables() throws Exception { 634 out.println("=== Creating tables in: " + pool.getURL() + " ==="); 635 Connection con = null; 636 Statement stat = null; 637 try { 638 con = getAutoCommitCon(); 639 stat = con.createStatement(); 640 ArrayList tables = sm.getJdbcMetaData().getTables(); 641 int n = tables.size(); 642 for (int i = 0; i < n; i++) { 643 JdbcTable t = (JdbcTable)tables.get(i); 644 sqlDriver.generateCreateTable(t, stat, outw, false); 645 checkStopFlag(); 646 } 647 } finally { 648 close(stat); 649 closeAutoCommitCon(con); 650 } 651 out.println(); 652 } 653 654 657 public void createAllIndexes() throws Exception { 658 out.println("=== Creating indexes in: " + pool.getURL() + " ==="); 659 Connection con = null; 660 Statement stat = null; 661 try { 662 con = getAutoCommitCon(); 663 stat = con.createStatement(); 664 ArrayList tables = sm.getJdbcMetaData().getTables(); 665 int n = tables.size(); 666 for (int i = 0; i < n; i++) { 667 JdbcTable t = (JdbcTable)tables.get(i); 668 if (t.indexes != null && t.indexes.length == 0) continue; 669 sqlDriver.generateCreateIndexes(t, stat, outw, false); 670 checkStopFlag(); 671 } 672 } finally { 673 close(stat); 674 closeAutoCommitCon(con); 675 } 676 out.println(); 677 } 678 679 682 public void createAllConstraints() throws Exception { 683 out.println( 684 "=== Adding constraints in: " + pool.getURL() + " ==="); 685 Connection con = null; 686 Statement stat = null; 687 try { 688 con = getAutoCommitCon(); 689 stat = con.createStatement(); 690 ArrayList tables = sm.getJdbcMetaData().getTables(); 691 int n = tables.size(); 692 for (int i = 0; i < n; i++) { 693 JdbcTable t = (JdbcTable)tables.get(i); 694 if (t.constraints != null && t.constraints.length == 0) continue; 695 sqlDriver.generateConstraints(t, stat, outw, false); 696 checkStopFlag(); 697 } 698 } finally { 699 close(stat); 700 closeAutoCommitCon(con); 701 } 702 out.println(); 703 } 704 705 private void close(Statement stat) { 706 if (stat == null) return; 707 try { 708 stat.close(); 709 } catch (SQLException e) { 710 } 712 } 713 714 718 public ClassMetaData[] getStoreClasses() { 719 ArrayList a = new ArrayList(); 720 for (int i = 0; i < jmd.classes.length; i++) { 721 ClassMetaData cmd = jmd.classes[i]; 722 if (cmd.storeClass != null) { 723 a.add(cmd); 724 } 725 } 726 Collections.sort(a, new Comparator() { 727 public int compare(Object o1, Object o2) { 728 ClassMetaData a = (ClassMetaData)o1; 729 ClassMetaData b = (ClassMetaData)o2; 730 int diff = b.referenceGraphIndex - a.referenceGraphIndex; 731 if (diff != 0) return diff; 732 return b.index - a.index; 733 } 734 }); 735 ClassMetaData[] x = new ClassMetaData[a.size()]; 736 a.toArray(x); 737 return x; 738 } 739 740 } 741 742 745 private static class StoppedException extends RuntimeException { 746 747 } 748 749 753 private static class DummyKeyGen implements JdbcKeyGenerator { 754 755 public void addKeyGenTables(HashSet set, JdbcMetaDataBuilder mdb) { 756 } 757 758 public boolean isPostInsertGenerator() { 759 return false; 760 } 761 762 public void init(String className, JdbcTable classTable, 763 Connection con) throws SQLException { 764 } 765 766 public boolean isRequiresOwnConnection() { 767 return false; 768 } 769 770 public void generatePrimaryKeyPre(String className, 771 JdbcTable classTable, int newObjectCount, Object [] data, 772 Connection con) throws SQLException { 773 } 774 775 public String getPostInsertSQLSuffix(JdbcTable classTable) { 776 return null; 777 } 778 779 public void generatePrimaryKeyPost(String className, 780 JdbcTable classTable, Object [] data, Connection con, 781 Statement stat) throws SQLException { 782 } 783 } 784 } 785 | Popular Tags |