提交 97ba2179 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 2493777f
...@@ -283,12 +283,45 @@ For a list of applications that work with or use H2, see: ...@@ -283,12 +283,45 @@ For a list of applications that work with or use H2, see:
The following connection modes are supported: The following connection modes are supported:
</p> </p>
<ul> <ul>
<li>Local connections using JDBC (embedded) <li>Embedded mode (local connections using JDBC)
</li><li>Remote connections using JDBC over TCP/IP (client/server) </li><li>Remote mode (remote connections using JDBC or ODBC over TCP/IP)
</li><li>Remote connections using ODBC over TCP/IP (client/server) </li><li>Mixed mode (local and remote connections at the same time)
</li><li>In-Memory databases (private and shared)
</li></ul> </li></ul>
<h3>Embedded Mode</h3>
<p>
In embedded mode, an application opens a database from within the same JVM using JDBC.
This is the fastest and easiest connection mode.
The disadvantage is that a database may only be open in one virtual machine (and class loader) at any time.
As in all modes, both persistent and in-memory databases are supported.
There is no limit on the number of database open concurrently,
or on the number of open connections.
</p>
<img src="images/connection-mode-embedded.png" />
<h3>Remote Mode</h3>
<p>
When using the remote mode (sometimes called client/server mode), an application opens a
database remotely using the JDBC or ODBC API. A server needs to be started within the same
or another virtual machine (or on another computer).
Many applications can connect to the same database at the same time.
The remote mode is slower than the embedded mode, because all data
is transferred over TCP/IP.
As in all modes, both persistent and in-memory databases are supported.
There is no limit on the number of database open concurrently,
or on the number of open connections.
</p>
<img src="images/connection-mode-remote.png" />
<h3>Mixed Mode</h3>
<p>
The mixed mode is a combination of the embedded and the remote mode.
The main application connects to a database in embedded mode, but also starts
a server so that other applications (running in different virtual machines) can
concurrently access the same data.
</p>
<img src="images/connection-mode-mixed.png" />
<br /><a name="database_url"></a> <br /><a name="database_url"></a>
<h2>Database URL Overview</h2> <h2>Database URL Overview</h2>
<p> <p>
......
...@@ -112,6 +112,11 @@ Execute Query</a><br /> ...@@ -112,6 +112,11 @@ Execute Query</a><br />
Database utility written in Java. Database utility written in Java.
</p> </p>
<p><a href="http://www.fluxcorp.com">
Flux</a><br />
Java job scheduler, file transfer, workflow, and BPM.
</p>
<p><a href="http://www.goldenstudios.or.id"> <p><a href="http://www.goldenstudios.or.id">
Golden T Studios</a><br /> Golden T Studios</a><br />
Fun-to-play games with a simple interface. Fun-to-play games with a simple interface.
......
...@@ -61,6 +61,7 @@ Roadmap ...@@ -61,6 +61,7 @@ Roadmap
</li><li>Change LOB mechanism (less files, keep index of lob files, point to files and row, delete unused files earlier, maybe bundle files into a tar file) </li><li>Change LOB mechanism (less files, keep index of lob files, point to files and row, delete unused files earlier, maybe bundle files into a tar file)
</li><li>Clustering: recovery needs to becomes fully automatic. Global write lock feature. </li><li>Clustering: recovery needs to becomes fully automatic. Global write lock feature.
</li><li>Option for Java functions: constant/isDeterministic to allow early evaluation when all parameters are constant </li><li>Option for Java functions: constant/isDeterministic to allow early evaluation when all parameters are constant
</li><li>Support function overloading as in Java (multiple functions with the same name, but different parameter count or data types)
</li><li>Deferred integrity checking (DEFERRABLE INITIALLY DEFERRED) </li><li>Deferred integrity checking (DEFERRABLE INITIALLY DEFERRED)
</li><li>Groovy Stored Procedures (http://groovy.codehaus.org/Groovy+SQL) </li><li>Groovy Stored Procedures (http://groovy.codehaus.org/Groovy+SQL)
</li><li>System table / function: cache usage </li><li>System table / function: cache usage
...@@ -124,7 +125,6 @@ Roadmap ...@@ -124,7 +125,6 @@ Roadmap
</li><li>Close all files when closing the database (including LOB files that are open on the client side) </li><li>Close all files when closing the database (including LOB files that are open on the client side)
</li><li>Test Connection Pool http://jakarta.apache.org/commons/dbcp </li><li>Test Connection Pool http://jakarta.apache.org/commons/dbcp
</li><li>Profiler option or profiling tool to find long running and often repeated queries (using DatabaseEventListener API) </li><li>Profiler option or profiling tool to find long running and often repeated queries (using DatabaseEventListener API)
</li><li>Function to read/write a file from/to LOB
</li><li>Allow custom settings (@PATH for RUNSCRIPT for example) </li><li>Allow custom settings (@PATH for RUNSCRIPT for example)
</li><li>EXE file: maybe use http://jsmooth.sourceforge.net </li><li>EXE file: maybe use http://jsmooth.sourceforge.net
</li><li>SELECT ... FOR READ WAIT [maxMillisToWait] </li><li>SELECT ... FOR READ WAIT [maxMillisToWait]
...@@ -398,13 +398,14 @@ Roadmap ...@@ -398,13 +398,14 @@ Roadmap
</li><li>Fluent API for tools: Server.createTcpServer().setPort(9081).setPassword(password).start(); </li><li>Fluent API for tools: Server.createTcpServer().setPort(9081).setPassword(password).start();
</li><li>MySQL compatibility: SHOW TABLES, DESCRIBE TEST (then remove from Shell) </li><li>MySQL compatibility: SHOW TABLES, DESCRIBE TEST (then remove from Shell)
</li><li>Use a default delay of 1 second before closing a database. </li><li>Use a default delay of 1 second before closing a database.
</li><li>Maven: upload source code and javadocs as well </li><li>Maven: upload source code and javadocs as well.
</li><li>Write (log) to system table before adding to internal data structures </li><li>Write (log) to system table before adding to internal data structures.
</li><li>Support very large deletes and updates </li><li>Support very large deletes and updates.
</li><li>Doclet (javadocs): constructors are not listed </li><li>Doclet (javadocs): constructors are not listed.
</li><li>Support direct lookup for MIN and MAX when using WHERE (see todo.txt / Direct Lookup) </li><li>Support direct lookup for MIN and MAX when using WHERE (see todo.txt / Direct Lookup).
</li><li>Support other array types (String[], double[]) in PreparedStatement.setObject(int, Object); </li><li>Support other array types (String[], double[]) in PreparedStatement.setObject(int, Object);
</li><li>MVCC should not be memory bound (uncommitted data is kept in memory in the delta index; maybe using a regular btree index solves the problem) </li><li>MVCC should not be memory bound (uncommitted data is kept in memory in the delta index; maybe using a regular btree index solves the problem).
</li><li>Support CREATE TEMPORARY LINKED TABLE.
</li></ul> </li></ul>
<h2>Not Planned</h2> <h2>Not Planned</h2>
......
...@@ -62,7 +62,7 @@ Depending on your platform and environment, there are multiple ways to start the ...@@ -62,7 +62,7 @@ Depending on your platform and environment, there are multiple ways to start the
Click [Start], [All Programs], [H2], and [H2 Console (Command Line)]<br /> Click [Start], [All Programs], [H2], and [H2 Console (Command Line)]<br />
When using the Sun JDK 1.4 or 1.5, a window with the title 'H2 Console ' should appear. When using the Sun JDK 1.4 or 1.5, a window with the title 'H2 Console ' should appear.
When using the Sun JDK 1.6, an icon will be added to the system tray: When using the Sun JDK 1.6, an icon will be added to the system tray:
<img src="images/h2.png" alt="[H2 icon]" /><br /> <img src="images/db-16.png" alt="[H2 icon]" /><br />
If you don't get the window and the system tray icon, If you don't get the window and the system tray icon,
then maybe Java is not installed correctly (in this case, try another way to start the application). then maybe Java is not installed correctly (in this case, try another way to start the application).
A browser window should open and point to the Login page http://localhost:8082). A browser window should open and point to the Login page http://localhost:8082).
...@@ -536,16 +536,18 @@ OpenOffice.org Base supports database access over the JDBC API. To connect to a ...@@ -536,16 +536,18 @@ OpenOffice.org Base supports database access over the JDBC API. To connect to a
using OpenOffice Base, you first need to add the JDBC driver to OpenOffice. using OpenOffice Base, you first need to add the JDBC driver to OpenOffice.
The steps to connect to a H2 database are: The steps to connect to a H2 database are:
</p> </p>
<ul> <ul><li>Start OpenOffice Writer, go to [Tools], [Options]
<li>Stop OpenOffice, including the autostart </li><li>Make sure you have selected a Java runtime environment in OpenOffice.org / Java
</li><li>Copy h2.jar into the directory &lt;OpenOffice&gt;\program\classes </li><li>Click [Class Path...], [Add Archive...]
</li><li>Select your h2.jar (location is up to you, could be wherever you choose)
</li><li>Click [OK] (as much as needed), stop OpenOffice (including the Quickstarter)
</li><li>Start OpenOffice Base </li><li>Start OpenOffice Base
</li><li>Connect to an existing database; select JDBC; [Next] </li><li>Connect to an existing database; select JDBC; [Next]
</li><li>Example datasource URL: jdbc:h2:c:/temp/test </li><li>Example datasource URL: jdbc:h2:~/test
</li><li>JDBC driver class: org.h2.Driver </li><li>JDBC driver class: org.h2.Driver
</li></ul> </li></ul>
<p> <p>
Now you can access the database stored in the directory C:/temp. Now you can access the database stored in the current users home directory.
</p> </p>
<p> <p>
To use H2 in NeoOffice (OpenOffice without X11): To use H2 in NeoOffice (OpenOffice without X11):
......
差异被折叠。
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -16,6 +16,13 @@ import org.h2.util.FileUtils; ...@@ -16,6 +16,13 @@ import org.h2.util.FileUtils;
*/ */
public class FileLister { public class FileLister {
/**
* Extract the name of the database from a given file name.
* Only files ending with .data.db are considered, all others return null.
*
* @param fileName the file name (without directory)
* @return the database name or null
*/
public static String getDatabaseNameFromFileName(String fileName) { public static String getDatabaseNameFromFileName(String fileName) {
if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) { if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) {
return fileName.substring(0, fileName.length() - Constants.SUFFIX_DATA_FILE.length()); return fileName.substring(0, fileName.length() - Constants.SUFFIX_DATA_FILE.length());
......
...@@ -153,10 +153,15 @@ public class TableLink extends Table { ...@@ -153,10 +153,15 @@ public class TableLink extends Table {
int id = getId(); int id = getId();
linkedIndex = new LinkedIndex(this, id, IndexColumn.wrap(cols), IndexType.createNonUnique(false)); linkedIndex = new LinkedIndex(this, id, IndexColumn.wrap(cols), IndexType.createNonUnique(false));
indexes.add(linkedIndex); indexes.add(linkedIndex);
try {
rs = meta.getPrimaryKeys(null, null, originalTable); rs = meta.getPrimaryKeys(null, null, originalTable);
} catch (SQLException e) {
// Some ODBC bridge drivers don't support it.
rs = null;
}
String pkName = ""; String pkName = "";
ObjectArray list; ObjectArray list;
if (rs.next()) { if (rs != null && rs.next()) {
// the problem is, the rows are not sorted by KEY_SEQ // the problem is, the rows are not sorted by KEY_SEQ
list = new ObjectArray(); list = new ObjectArray();
do { do {
......
...@@ -100,7 +100,7 @@ public class Backup extends Tool { ...@@ -100,7 +100,7 @@ public class Backup extends Tool {
ArrayList list = FileLister.getDatabaseFiles(directory, db, true); ArrayList list = FileLister.getDatabaseFiles(directory, db, true);
if (list.size() == 0) { if (list.size() == 0) {
if (!quiet) { if (!quiet) {
out.println("No database files found"); printNoDatabaseFilesFound(directory, db);
} }
return; return;
} }
......
...@@ -147,6 +147,9 @@ public class ChangePassword extends Tool { ...@@ -147,6 +147,9 @@ public class ChangePassword extends Tool {
// first, test only if the file can be renamed // first, test only if the file can be renamed
// (to find errors with locked files early) // (to find errors with locked files early)
ArrayList files = FileLister.getDatabaseFiles(dir, db, false); ArrayList files = FileLister.getDatabaseFiles(dir, db, false);
if (files.size() == 0 && !quiet) {
printNoDatabaseFilesFound(dir, db);
}
for (int i = 0; i < files.size(); i++) { for (int i = 0; i < files.size(); i++) {
String fileName = (String) files.get(i); String fileName = (String) files.get(i);
String temp = dir + "/temp.db"; String temp = dir + "/temp.db";
...@@ -161,9 +164,6 @@ public class ChangePassword extends Tool { ...@@ -161,9 +164,6 @@ public class ChangePassword extends Tool {
String fileName = (String) files.get(i); String fileName = (String) files.get(i);
change.process(fileName); change.process(fileName);
} }
if (files.size() == 0 && !quiet) {
out.println("No database files found");
}
} }
private void process(String fileName) throws SQLException { private void process(String fileName) throws SQLException {
......
...@@ -93,6 +93,9 @@ public class DeleteDbFiles extends Tool { ...@@ -93,6 +93,9 @@ public class DeleteDbFiles extends Tool {
private void process(String dir, String db, boolean quiet) throws SQLException { private void process(String dir, String db, boolean quiet) throws SQLException {
DeleteDbFiles delete = new DeleteDbFiles(); DeleteDbFiles delete = new DeleteDbFiles();
ArrayList files = FileLister.getDatabaseFiles(dir, db, true); ArrayList files = FileLister.getDatabaseFiles(dir, db, true);
if (files.size() == 0 && !quiet) {
printNoDatabaseFilesFound(dir, db);
}
for (int i = 0; i < files.size(); i++) { for (int i = 0; i < files.size(); i++) {
String fileName = (String) files.get(i); String fileName = (String) files.get(i);
delete.process(fileName, quiet); delete.process(fileName, quiet);
...@@ -100,9 +103,6 @@ public class DeleteDbFiles extends Tool { ...@@ -100,9 +103,6 @@ public class DeleteDbFiles extends Tool {
out.println("Processed: " + fileName); out.println("Processed: " + fileName);
} }
} }
if (files.size() == 0 && !quiet) {
out.println("No database files found");
}
} }
private void process(String fileName, boolean quiet) throws SQLException { private void process(String fileName, boolean quiet) throws SQLException {
......
...@@ -144,6 +144,9 @@ public class Recover extends Tool implements DataHandler { ...@@ -144,6 +144,9 @@ public class Recover extends Tool implements DataHandler {
private void removePassword(String dir, String db) throws SQLException { private void removePassword(String dir, String db) throws SQLException {
ArrayList list = FileLister.getDatabaseFiles(dir, db, true); ArrayList list = FileLister.getDatabaseFiles(dir, db, true);
if (list.size() == 0) {
printNoDatabaseFilesFound(dir, db);
}
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
String fileName = (String) list.get(i); String fileName = (String) list.get(i);
if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) { if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) {
...@@ -292,6 +295,9 @@ public class Recover extends Tool implements DataHandler { ...@@ -292,6 +295,9 @@ public class Recover extends Tool implements DataHandler {
private void process(String dir, String db) throws SQLException { private void process(String dir, String db) throws SQLException {
ArrayList list = FileLister.getDatabaseFiles(dir, db, true); ArrayList list = FileLister.getDatabaseFiles(dir, db, true);
if (list.size() == 0) {
printNoDatabaseFilesFound(dir, db);
}
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
String fileName = (String) list.get(i); String fileName = (String) list.get(i);
if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) { if (fileName.endsWith(Constants.SUFFIX_DATA_FILE)) {
......
...@@ -33,4 +33,23 @@ public abstract class Tool { ...@@ -33,4 +33,23 @@ public abstract class Tool {
*/ */
public abstract void run(String[] args) throws SQLException; public abstract void run(String[] args) throws SQLException;
/**
* Print to the output stream that no database files have been found.
*
* @param dir the directory or null
* @param db the database name or null
*/
protected void printNoDatabaseFilesFound(String dir, String db) {
StringBuffer buff = new StringBuffer("No database files have been found");
if (dir != null) {
buff.append(" in directory ");
buff.append(dir);
}
if (db != null) {
buff.append(" for the directory ");
buff.append(db);
}
out.println(buff.toString());
}
} }
...@@ -159,17 +159,6 @@ java org.h2.test.TestAll timer ...@@ -159,17 +159,6 @@ java org.h2.test.TestAll timer
/* /*
Flux
Java Job Scheduler. File Transfer. Workflow. BPM.
http://www.fluxcorp.com/
No database files found > in directory " + for a database called .
Has anyone had difficulty with Open Office Base and UUID type fields
in H2? I think that I may not be able to view table data that has
UUID data in it. Any ideas?
test case for out of memory (try to corrupt the database using out of memory) test case for out of memory (try to corrupt the database using out of memory)
analyzer configuration option for the fulltext search analyzer configuration option for the fulltext search
......
...@@ -55,7 +55,7 @@ public class Build extends BuildBase { ...@@ -55,7 +55,7 @@ public class Build extends BuildBase {
files = filterFiles(files, false, "*.java"); files = filterFiles(files, false, "*.java");
files = filterFiles(files, false, "*/package.html"); files = filterFiles(files, false, "*/package.html");
files = filterFiles(files, false, "*/java.sql.Driver"); files = filterFiles(files, false, "*/java.sql.Driver");
zip("target/org/h2/util/data.zip", "src/main", files, true, false); zip("temp/org/h2/util/data.zip", "src/main", files, true, false);
} }
private void manifest(String mainClassName) { private void manifest(String mainClassName) {
...@@ -68,39 +68,39 @@ public class Build extends BuildBase { ...@@ -68,39 +68,39 @@ public class Build extends BuildBase {
manifest = replaceAll(manifest, "${createdBy}", createdBy); manifest = replaceAll(manifest, "${createdBy}", createdBy);
String mainClassTag = manifest == null ? "" : "Main-Class: " + mainClassName; String mainClassTag = manifest == null ? "" : "Main-Class: " + mainClassName;
manifest = replaceAll(manifest, "${mainClassTag}", mainClassTag); manifest = replaceAll(manifest, "${mainClassTag}", mainClassTag);
writeFile(new File("target/META-INF/MANIFEST.MF"), manifest.getBytes()); writeFile(new File("temp/META-INF/MANIFEST.MF"), manifest.getBytes());
} }
public void jar() { public void jar() {
compile(); compile();
manifest("org.h2.tools.Console"); manifest("org.h2.tools.Console");
List files = getFiles("target"); List files = getFiles("temp");
files = filterFiles(files, false, "target/org/h2/dev/*"); files = filterFiles(files, false, "temp/org/h2/dev/*");
files = filterFiles(files, false, "target/org/h2/build/*"); files = filterFiles(files, false, "temp/org/h2/build/*");
files = filterFiles(files, false, "target/org/h2/samples/*"); files = filterFiles(files, false, "temp/org/h2/samples/*");
files = filterFiles(files, false, "target/org/h2/test/*"); files = filterFiles(files, false, "temp/org/h2/test/*");
files = filterFiles(files, false, "*.bat"); files = filterFiles(files, false, "*.bat");
files = filterFiles(files, false, "*.sh"); files = filterFiles(files, false, "*.sh");
files = filterFiles(files, false, "*.txt"); files = filterFiles(files, false, "*.txt");
jar("target/h2.jar", "target", files); jar("bin/h2.jar", "temp", files);
} }
public void jarSmall() { public void jarSmall() {
compile(false); compile(false);
List files = getFiles("target"); List files = getFiles("temp");
files = filterFiles(files, false, "target/org/h2/dev/*"); files = filterFiles(files, false, "temp/org/h2/dev/*");
files = filterFiles(files, false, "target/org/h2/build/*"); files = filterFiles(files, false, "temp/org/h2/build/*");
files = filterFiles(files, false, "target/org/h2/samples/*"); files = filterFiles(files, false, "temp/org/h2/samples/*");
files = filterFiles(files, false, "target/org/h2/test/*"); files = filterFiles(files, false, "temp/org/h2/test/*");
files = filterFiles(files, false, "*.bat"); files = filterFiles(files, false, "*.bat");
files = filterFiles(files, false, "*.sh"); files = filterFiles(files, false, "*.sh");
files = filterFiles(files, false, "*.txt"); files = filterFiles(files, false, "*.txt");
files = filterFiles(files, false, "target/META-INF/*"); files = filterFiles(files, false, "temp/META-INF/*");
zip("target/h2classes.zip", "target", files, true, true); zip("temp/h2classes.zip", "temp", files, true, true);
manifest("org.h2.tools.Console\nClass-Path: h2classes.zip"); manifest("org.h2.tools.Console\nClass-Path: h2classes.zip");
files = getFiles("target/h2classes.zip"); files = getFiles("temp/h2classes.zip");
files.addAll(getFiles("target/META-INF")); files.addAll(getFiles("temp/META-INF"));
jar("target/h2small.jar", "target", files); jar("bin/h2small.jar", "temp", files);
} }
public void download() { public void download() {
...@@ -123,44 +123,45 @@ public class Build extends BuildBase { ...@@ -123,44 +123,45 @@ public class Build extends BuildBase {
throw new Error(e); throw new Error(e);
} }
clean(); clean();
mkdir("temp");
resources(); resources();
download(); download();
String classpath = "target" + File.pathSeparatorChar + "ext/servlet-api-2.4.jar" + File.pathSeparatorChar String classpath = "temp" + File.pathSeparatorChar + "ext/servlet-api-2.4.jar" + File.pathSeparatorChar
+ "ext/lucene-core-2.2.0.jar" + File.pathSeparator + System.getProperty("java.home") + "ext/lucene-core-2.2.0.jar" + File.pathSeparator + System.getProperty("java.home")
+ "/../lib/tools.jar"; + "/../lib/tools.jar";
List files = getFiles("src/main"); List files = getFiles("src/main");
if (debugInfo) { if (debugInfo) {
javac(new String[] { "-d", "target", "-sourcepath", "src/main", "-classpath", classpath }, files); javac(new String[] { "-d", "temp", "-sourcepath", "src/main", "-classpath", classpath }, files);
} else { } else {
javac(new String[] { "-g:none", "-d", "target", "-sourcepath", "src/main", "-classpath", classpath }, files); javac(new String[] { "-g:none", "-d", "temp", "-sourcepath", "src/main", "-classpath", classpath }, files);
} }
files = getFiles("src/test"); files = getFiles("src/test");
files.addAll(getFiles("src/tools")); files.addAll(getFiles("src/tools"));
javac(new String[] { "-d", "target", "-sourcepath", "src/test" + File.pathSeparator + "src/tools", javac(new String[] { "-d", "temp", "-sourcepath", "src/test" + File.pathSeparator + "src/tools",
"-classpath", classpath }, files); "-classpath", classpath }, files);
files = getFiles("src/main/META-INF/services"); files = getFiles("src/main/META-INF/services");
copy("target", files, "src/main"); copy("temp", files, "src/main");
files = getFiles("src/installer"); files = getFiles("src/installer");
files = filterFiles(files, true, "*.bat"); files = filterFiles(files, true, "*.bat");
files = filterFiles(files, true, "*.sh"); files = filterFiles(files, true, "*.sh");
copy("target", files, "src/installer"); copy("temp", files, "src/installer");
files = getFiles("src/test"); files = getFiles("src/test");
files = filterFiles(files, false, "*.java"); files = filterFiles(files, false, "*.java");
files = filterFiles(files, false, "*/package.html"); files = filterFiles(files, false, "*/package.html");
copy("target", files, "src/test"); copy("temp", files, "src/test");
} }
public void clean() { public void clean() {
delete("target"); delete("temp");
delete("docs"); delete("docs");
mkdir("target");
mkdir("docs"); mkdir("docs");
mkdir("bin");
} }
public void test() { public void test() {
......
...@@ -492,4 +492,6 @@ selecting vista everywhere locations zones fragment svg thought constructors ...@@ -492,4 +492,6 @@ selecting vista everywhere locations zones fragment svg thought constructors
doubles validating matched established accu accum stats resetting parallel doubles validating matched established accu accum stats resetting parallel
delays guess downloaded jars advantages interrupt javen sourcepath unneeded delays guess downloaded jars advantages interrupt javen sourcepath unneeded
compressibility ext crc enumerate components mkdir jant downloading mismatch compressibility ext crc enumerate components mkdir jant downloading mismatch
timebomb thinks timebomb thinks technotes chmod overloading javase flux solves fastest
\ No newline at end of file quickstarter bridge bpm trust guides improvements customizing easiest
workflow
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论