diff options
author | Mark Spruiell <mes@zeroc.com> | 2009-05-18 14:03:42 -0700 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2009-05-18 14:03:42 -0700 |
commit | b30ccc77d3a9822c6ffcebf9b45945822df200bc (patch) | |
tree | 94105ea42fa81ad0b8731b05a46c7f64304dec55 /java | |
parent | Removed Freeze.UseNonmutating (diff) | |
download | ice-b30ccc77d3a9822c6ffcebf9b45945822df200bc.tar.bz2 ice-b30ccc77d3a9822c6ffcebf9b45945822df200bc.tar.xz ice-b30ccc77d3a9822c6ffcebf9b45945822df200bc.zip |
bug 252 - Freeze finalizers
bug 2552 - Update Freeze for Java5
Diffstat (limited to 'java')
57 files changed, 7665 insertions, 4715 deletions
diff --git a/java/build.xml b/java/build.xml index d6f73fca9b6..798ef767aba 100644 --- a/java/build.xml +++ b/java/build.xml @@ -169,10 +169,9 @@ <depend srcdir="${generated.dir}:${src.dir}" destdir="${lib.dir}" cache="${cache.dir}"/> <javac srcdir="${generated.dir}:${src.dir}" destdir="${lib.dir}" source="1.5" debug="${debug}" - excludes="IceGridGUI/**" + excludes="IceGridGUI/**,Freeze/**,ant/**" includes="**" - deprecation="on" - classpathref="db.classpath"> + deprecation="on"> <compilerarg value="${javac.lint}"/> </javac> </target> @@ -187,7 +186,27 @@ <exclude name="*.jar"/> <manifest> <attribute name="Built-By" value="ZeroC, Inc."/> - <attribute name="Class-Path" value="Freeze.jar"/> + </manifest> + </jar> + </target> + + <target name="freeze-compile" depends="ice-compile"> + <mkdir dir="${lib.dir}"/> + <javac srcdir="${generated.dir}:${src.dir}" destdir="${lib.dir}" + source="1.5" debug="${debug}" + includes="Freeze/**" + deprecation="on" + classpathref="db.classpath"> + <compilerarg value="${javac.lint}"/> + </javac> + </target> + + <target name="freeze-jar" depends="freeze-compile"> + <jar jarfile="${lib.dir}/Freeze.jar" basedir="${lib.dir}"> + <include name="Freeze/**"/> + <manifest> + <attribute name="Built-By" value="ZeroC, Inc."/> + <attribute name="Class-Path" value="db.jar db-${db.version}.jar /usr/share/java/db-${db.version}.jar ../db.jar"/> </manifest> </jar> </target> @@ -196,7 +215,6 @@ <mkdir dir="${generated.test.dir}"/> <!-- Create the output directory for generated code --> <slice2java outputdir="${generated.test.dir}" dependencyfile="${generated.test.dir}/.depend.Test"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> </includepath> @@ -302,7 +320,6 @@ <includepath> <pathelement path="${slice.dir}" /> </includepath> - <meta value="${java2metadata}"/> <fileset dir="test/Freeze/evictor"> <include name="Test.ice" /> </fileset> @@ -310,7 +327,6 @@ <!-- test/Freeze/complex --> <slice2freezej outputdir="${generated.test.dir}" dependencyfile="${generated.test.dir}/.depend.Test"> - <meta value="${java2metadata}"/> <dict name="test.Freeze.complex.Complex.ComplexDict" key="Complex::Key" value="Complex::Node"/> <fileset dir="test/Freeze/complex"> <include name="Complex.ice" /> @@ -319,12 +335,10 @@ <!-- test/Freeze/dbmap --> <slice2freezej outputdir="${generated.test.dir}" dependencyfile="${generated.test.dir}/.depend.Test"> - <meta value="${java2metadata}"/> <dict name="test.Freeze.dbmap.ByteIntMap" key="byte" value="int"/> <dictindex name="test.Freeze.dbmap.ByteIntMap"/> </slice2freezej> <slice2freezej ice="on" outputdir="${generated.test.dir}"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> </includepath> @@ -332,7 +346,6 @@ <dict name="test.Freeze.dbmap.IntIdentityMap" key="int" value="Ice::Identity"/> </slice2freezej> <slice2freezej ice="on" outputdir="${generated.test.dir}"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> </includepath> @@ -341,7 +354,6 @@ <dictindex name="test.Freeze.dbmap.IntIdentityMapWithIndex" member="category"/> </slice2freezej> <slice2freezej ice="on" outputdir="${generated.test.dir}"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> </includepath> @@ -351,7 +363,6 @@ </slice2freezej> <slice2java stream="on" outputdir="${generated.test.dir}" dependencyfile="${generated.test.dir}/.depend.Test"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> </includepath> @@ -364,7 +375,6 @@ </slice2java> <slice2java checksum="test.Ice.checksum.Test.SliceChecksums" outputdir="${generated.test.dir}" dependencyfile="${generated.test.dir}/.depend.Test"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> </includepath> @@ -375,7 +385,6 @@ </slice2java> <slice2java outputdir="${generated.test.dir}" dependencyfile="${generated.test.dir}/.depend.Test"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> <pathelement path="test/Ice/packagemd" /> @@ -388,7 +397,6 @@ </slice2java> <slice2java checksum="test.Ice.checksum.server.Test.SliceChecksums" outputdir="${generated.test.dir}" dependencyfile="${generated.test.dir}/.depend.Test"> - <meta value="${java2metadata}"/> <includepath> <pathelement path="${slice.dir}" /> </includepath> @@ -399,12 +407,12 @@ </slice2java> </target> - <target name="test-compile" depends="ice-compile,test-generate"> + <target name="test-compile" depends="freeze-compile,test-generate"> <mkdir dir="${lib.dir}"/> <mkdir dir="${cache.dir}"/> <depend srcdir="." destdir="${lib.dir}" cache="${cache.dir}"/> <javac srcdir=".:${generated.test.dir}" destdir="${lib.dir}" source="1.5" debug="${debug}" deprecation="on" - classpathref="db.classpath"> + classpathref="freeze.classpath"> <exclude name="${generated.test.dir}/**"/> <include name="test/**"/> <exclude name="test/Ice/translator/"/> @@ -415,7 +423,6 @@ <target name="test-jar" depends="test-compile"> <jar jarfile="${lib.dir}/IceTest.jar" basedir="${lib.dir}"> <include name="test/**"/> - <exclude name="test/Freeze/**"/> <manifest> <attribute name="Built-By" value="ZeroC, Inc."/> <attribute name="Class-Path" value="Ice.jar"/> @@ -423,16 +430,6 @@ </jar> </target> - <target name="freeze-jar" depends="ice-compile"> - <jar jarfile="${lib.dir}/Freeze.jar" basedir="${lib.dir}"> - <include name="Freeze/**"/> - <manifest> - <attribute name="Built-By" value="ZeroC, Inc."/> - <attribute name="Class-Path" value="db.jar db-${db.version}.jar /usr/share/java/db-${db.version}.jar ../db.jar"/> - </manifest> - </jar> - </target> - <target name="icegridadmin-compile" depends="ice-compile"> <javac srcdir="${src.dir}" destdir="${lib.dir}" source="1.5" debug="${debug}" diff --git a/java/config/common.xml b/java/config/common.xml index 0dd06f436e9..223d7007ef7 100644 --- a/java/config/common.xml +++ b/java/config/common.xml @@ -192,7 +192,7 @@ </condition> <path id="db.classpath"> - <pathelement path="${db.jar.file}"/> + <pathelement location="${db.jar.file}"/> </path> <target name="config-init-warn" if="ice.warn.duplicate.translator"> @@ -238,7 +238,27 @@ </condition> <path id="ice.classpath"> - <fileset file="${dist.jar.file}"/> + <pathelement location="${dist.jar.file}"/> + </path> + + <!-- Set freeze.classpath with the distribution Freeze.jar file --> + <condition property="freeze.jar.file" value="${dist.lib.dir}/Freeze-${ice.version}.jar"> + <and> + <not><isset property="freeze.jar.file"/></not> + <available file="${dist.lib.dir}/Freeze-${ice.version}.jar"/> + </and> + </condition> + + <condition property="freeze.jar.file" value="${dist.lib.dir}/Freeze.jar"> + <and> + <not><isset property="freeze.jar.file"/></not> + <available file="${dist.lib.dir}/Freeze.jar"/> + </and> + </condition> + + <path id="freeze.classpath"> + <pathelement location="${freeze.jar.file}"/> + <path refid="db.classpath"/> </path> <condition property="certs.dir" value="${ice.top.dir}/certs" else="${ice.top.dir}/../certs"> diff --git a/java/demo/Freeze/bench/Client.java b/java/demo/Freeze/bench/Client.java index 946dae1c76d..8a795cb63ee 100644 --- a/java/demo/Freeze/bench/Client.java +++ b/java/demo/Freeze/bench/Client.java @@ -12,7 +12,7 @@ import Demo.*; class Client extends Ice.Application { void - IntIntMapTest(Freeze.Map m, boolean fast) + IntIntMapTest(Freeze.Map<Integer, Integer> m, boolean fast) { // // Populate the database. @@ -23,14 +23,14 @@ class Client extends Ice.Application { for(int i = 0; i < _repetitions; ++i) { - m.fastPut(new Integer(i), new Integer(i)); + m.fastPut(i, i); } } else { for(int i = 0; i < _repetitions; ++i) { - m.put(new Integer(i), new Integer(i)); + m.put(i, i); } } tx.commit(); @@ -47,7 +47,7 @@ class Client extends Ice.Application _watch.start(); for(int i = 0; i < _repetitions; ++i) { - Integer n = (Integer)m.get(new Integer(i)); + Integer n = m.get(i); test(n.intValue() == i); } total = _watch.stop(); @@ -65,20 +65,19 @@ class Client extends Ice.Application _watch.start(); for(int i = 0; i < _repetitions; ++i) { - java.util.Iterator p = indexedM.findByValue(i); + java.util.Iterator<java.util.Map.Entry<Integer, Integer>> p = indexedM.findByValue(i); test(p.hasNext()); - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - test(((Integer)e.getKey()).intValue() == i); + java.util.Map.Entry<Integer, Integer> e = p.next(); + test(e.getKey().intValue() == i); m.closeAllIterators(); } total = _watch.stop(); perRecord = total / _repetitions; - + System.out.println("\ttime for " + _repetitions + " indexed reads: " + total + "ms"); System.out.println("\ttime per indexed read: " + perRecord + "ms"); } - // // Remove each record. // @@ -88,14 +87,14 @@ class Client extends Ice.Application { for(int i = 0; i < _repetitions; ++i) { - test(m.fastRemove(new Integer(i))); + test(m.fastRemove(i)); } } else { for(int i = 0; i < _repetitions; ++i) { - Integer n = (Integer)m.remove(new Integer(i)); + Integer n = m.remove(i); test(n.intValue() == i); } } @@ -163,7 +162,7 @@ class Client extends Ice.Application public String toString() { - return new Integer((_max - _min)+1).toString(); + return new Integer((_max - _min) + 1).toString(); } private int _min; @@ -172,20 +171,19 @@ class Client extends Ice.Application } void - generatedRead(Freeze.Map m, int reads, Generator gen) + generatedRead(Freeze.Map<Integer, Integer> m, int reads, Generator gen) { _watch.start(); for(int i = 0; i < reads; ++i) { int key = gen.next(); - Integer n = (Integer)m.get(new Integer(key)); + Integer n = m.get(key); test(n.intValue() == key); } double total = _watch.stop(); double perRecord = total / reads; - System.out.println("\ttime for " + reads + " reads of " + gen + " records: " + - total + "ms"); + System.out.println("\ttime for " + reads + " reads of " + gen + " records: " + total + "ms"); System.out.println("\ttime per read: " + perRecord + "ms"); if(m instanceof IndexedIntIntMap) @@ -195,23 +193,23 @@ class Client extends Ice.Application for(int i = 0; i < reads; ++i) { int val = gen.next(); - java.util.Iterator p = indexedM.findByValue(val); + java.util.Iterator<java.util.Map.Entry<Integer, Integer>> p = indexedM.findByValue(val); test(p.hasNext()); - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - test(((Integer)e.getKey()).intValue() == val); + java.util.Map.Entry<Integer, Integer> e = p.next(); + test(e.getKey().intValue() == val); m.closeAllIterators(); } total = _watch.stop(); perRecord = total / reads; - - System.out.println("\ttime for " + reads + " reverse (indexed) reads of " + gen + " records: " + - total + "ms"); + + System.out.println("\ttime for " + reads + " reverse (indexed) reads of " + gen + " records: " + total + + "ms"); System.out.println("\ttime per reverse (indexed) read: " + perRecord + "ms"); } } void - IntIntMapReadTest(Freeze.Map m) + IntIntMapReadTest(Freeze.Map<Integer, Integer> m) { // // Populate the database. @@ -220,7 +218,7 @@ class Client extends Ice.Application Freeze.Transaction tx = _connection.beginTransaction(); for(int i = 0; i < _repetitions; ++i) { - m.fastPut(new Integer(i), new Integer(i)); + m.fastPut(i, i); } tx.commit(); double total = _watch.stop(); @@ -252,7 +250,7 @@ class Client extends Ice.Application _watch.start(); for(int i = 0; i < _repetitions; ++i) { - test(m.fastRemove(new Integer(i))); + test(m.fastRemove(i)); } total = _watch.stop(); perRecord = total / _repetitions; @@ -265,7 +263,7 @@ class Client extends Ice.Application } void - Struct1Struct2MapTest(Freeze.Map m) + Struct1Struct2MapTest(Freeze.Map<Struct1, Struct2> m) { // // Populate the database. @@ -295,7 +293,7 @@ class Client extends Ice.Application for(int i = 0; i < _repetitions; ++i) { s1.l = i; - Struct2 ns2 = (Struct2)m.get(s1); + Struct2 ns2 = m.get(s1); test(ns2.s.equals(new Integer(i).toString())); } total = _watch.stop(); @@ -304,7 +302,6 @@ class Client extends Ice.Application System.out.println("\ttime for " + _repetitions + " reads: " + total + "ms"); System.out.println("\ttime per read: " + perRecord + "ms"); - // // Optional index test // @@ -316,20 +313,20 @@ class Client extends Ice.Application for(int i = 0; i < _repetitions; ++i) { String s = (new Integer(i)).toString(); - java.util.Iterator p = indexedM.findByS(s); + java.util.Iterator<java.util.Map.Entry<Struct1, Struct2>> p = indexedM.findByS(s); test(p.hasNext()); - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - test(((Struct1)e.getKey()).l == i); + java.util.Map.Entry<Struct1, Struct2> e = p.next(); + test(e.getKey().l == i); m.closeAllIterators(); } for(int i = 0; i < _repetitions; ++i) { s1.l = i; - java.util.Iterator p = indexedM.findByS1(s1); + java.util.Iterator<java.util.Map.Entry<Struct1, Struct2>> p = indexedM.findByS1(s1); test(p.hasNext()); - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - test(((Struct1)e.getKey()).l == i); + java.util.Map.Entry<Struct1, Struct2> e = p.next(); + test(e.getKey().l == i); m.closeAllIterators(); } total = _watch.stop(); @@ -360,7 +357,7 @@ class Client extends Ice.Application } void - Struct1Class1MapTest(Freeze.Map m) + Struct1Class1MapTest(Freeze.Map<Struct1, Class1> m) { // // Populate the database. @@ -389,7 +386,7 @@ class Client extends Ice.Application for(int i = 0; i < _repetitions; ++i) { s1.l = i; - Class1 nc1 = (Class1)m.get(s1); + Class1 nc1 = m.get(s1); test(nc1.s.equals(new Integer(i).toString())); } total = _watch.stop(); @@ -398,7 +395,6 @@ class Client extends Ice.Application System.out.println("\ttime for " + _repetitions + " reads: " + total + "ms"); System.out.println("\ttime per read: " + perRecord + "ms"); - // // Optional index test // @@ -410,10 +406,10 @@ class Client extends Ice.Application for(int i = 0; i < _repetitions; ++i) { String s = (new Integer(i)).toString(); - java.util.Iterator p = indexedM.findByS(s); + java.util.Iterator<java.util.Map.Entry<Struct1, Class1>> p = indexedM.findByS(s); test(p.hasNext()); - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - test(((Struct1)e.getKey()).l == i); + java.util.Map.Entry<Struct1, Class1> e = p.next(); + test(e.getKey().l == i); m.closeAllIterators(); } @@ -445,7 +441,7 @@ class Client extends Ice.Application } void - Struct1ObjectMapTest(Freeze.Map m) + Struct1ObjectMapTest(Freeze.Map<Struct1, Ice.Object> m) { // // Populate the database. @@ -460,7 +456,7 @@ class Client extends Ice.Application for(int i = 0; i < _repetitions; ++i) { s1.l = i; - Object o; + Ice.Object o; if((i % 2) == 0) { o = c2; @@ -489,7 +485,7 @@ class Client extends Ice.Application { s1.l = i; - Object o = m.get(s1); + Ice.Object o = m.get(s1); Class1 nc1; if((i % 2) == 0) @@ -530,7 +526,7 @@ class Client extends Ice.Application m.close(); } - + public int run(String[] args) { @@ -559,7 +555,7 @@ class Client extends Ice.Application System.out.println("Struct1Struct2Map with index"); Struct1Struct2MapTest(new IndexedStruct1Struct2Map(_connection, "IndexedStruct1Struct2", true)); - + System.out.println("Struct1Class1Map"); Struct1Class1MapTest(new Struct1Class1Map(_connection, "Struct1Class1", true)); diff --git a/java/demo/Freeze/bench/build.xml b/java/demo/Freeze/bench/build.xml index 3b81ad1637b..1bbdc29419a 100644 --- a/java/demo/Freeze/bench/build.xml +++ b/java/demo/Freeze/bench/build.xml @@ -56,7 +56,7 @@ <exclude name="${generated.dir}/**"/> <classpath> <path refid="ice.classpath"/> - <path refid="db.classpath"/> + <path refid="freeze.classpath"/> </classpath> <compilerarg value="${javac.lint}"/> </javac> diff --git a/java/demo/Freeze/casino/build.xml b/java/demo/Freeze/casino/build.xml index 99e67437810..72f8f9dc214 100644 --- a/java/demo/Freeze/casino/build.xml +++ b/java/demo/Freeze/casino/build.xml @@ -35,7 +35,7 @@ <exclude name="${generated.dir}/**"/> <classpath> <path refid="ice.classpath"/> - <path refid="db.classpath"/> + <path refid="freeze.classpath"/> </classpath> <compilerarg value="${javac.lint}"/> </javac> diff --git a/java/demo/Freeze/library/Grammar.java b/java/demo/Freeze/library/Grammar.java index c261cc0921e..1541c3b3b36 100644 --- a/java/demo/Freeze/library/Grammar.java +++ b/java/demo/Freeze/library/Grammar.java @@ -53,7 +53,7 @@ class Grammar } else if(_token.type == Token.TOK_ADD_BOOK) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -62,7 +62,7 @@ class Grammar } else if(_token.type == Token.TOK_FIND_ISBN) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -71,7 +71,7 @@ class Grammar } else if(_token.type == Token.TOK_FIND_AUTHORS) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -100,7 +100,7 @@ class Grammar } else if(_token.type == Token.TOK_RENT_BOOK) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -128,7 +128,7 @@ class Grammar } else if(_token.type == Token.TOK_SET_EVICTOR_SIZE) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -157,10 +157,10 @@ class Grammar } } - private java.util.List + private java.util.List<String> strings() { - java.util.List l = new java.util.ArrayList(); + java.util.List<String> l = new java.util.ArrayList<String>(); while(true) { _token = _scanner.nextToken(); diff --git a/java/demo/Freeze/library/LibraryI.java b/java/demo/Freeze/library/LibraryI.java index ca09c0fb908..9035731ac7f 100644 --- a/java/demo/Freeze/library/LibraryI.java +++ b/java/demo/Freeze/library/LibraryI.java @@ -55,7 +55,7 @@ class LibraryI extends _LibraryDisp // // Add the isbn number to the authors map. // - String[] isbnSeq = (String[])_authors.get(description.authors); + String[] isbnSeq = _authors.get(description.authors); int length = (isbnSeq == null) ? 0 : isbnSeq.length; String[] newIsbnSeq = new String[length+1]; @@ -111,7 +111,7 @@ class LibraryI extends _LibraryDisp // Lookup all books that match the given authors, and // return them to the caller. // - String[] isbnSeq = (String[])_authors.get(authors); + String[] isbnSeq = _authors.get(authors); int length = (isbnSeq == null) ? 0 : isbnSeq.length; BookPrx[] books = new BookPrx[length]; @@ -156,7 +156,7 @@ class LibraryI extends _LibraryDisp { try { - String[] isbnSeq = (String[])_authors.get(description.authors); + String[] isbnSeq = _authors.get(description.authors); assert isbnSeq != null; diff --git a/java/demo/Freeze/library/Parser.java b/java/demo/Freeze/library/Parser.java index 8d2c5256f70..8d11881eb71 100644 --- a/java/demo/Freeze/library/Parser.java +++ b/java/demo/Freeze/library/Parser.java @@ -35,21 +35,21 @@ class Parser } void - addBook(java.util.List args) + addBook(java.util.List<String> args) { if(args.size() != 3) { error("`add' requires at exactly three arguments (type `help' for more info)"); return; } - + try { BookDescription desc = new BookDescription(); - desc.isbn = (String)args.get(0); - desc.title = (String)args.get(1); - desc.authors = (String)args.get(2); - + desc.isbn = args.get(0); + desc.title = args.get(1); + desc.authors = args.get(2); + BookPrx book = _library.createBook(desc); System.out.println("added new book with isbn " + desc.isbn); } @@ -68,20 +68,20 @@ class Parser } void - findIsbn(java.util.List args) + findIsbn(java.util.List<String> args) { if(args.size() != 1) { error("`isbn' requires exactly one argument (type `help' for more info)"); return; } - + try { _foundBooks = null; _current = 0; - BookPrx book = _library.findByIsbn((String)args.get(0)); + BookPrx book = _library.findByIsbn(args.get(0)); if(book == null) { System.out.println("no book with that ISBN number exists."); @@ -104,17 +104,17 @@ class Parser } void - findAuthors(java.util.List args) + findAuthors(java.util.List<String> args) { if(args.size() != 1) { error("`authors' requires exactly one argument (type `help' for more info)"); return; } - + try { - _foundBooks = _library.findByAuthors((String)args.get(0)); + _foundBooks = _library.findByAuthors(args.get(0)); _current = 0; System.out.println("number of books found: " + _foundBooks.length); printCurrent(); @@ -138,7 +138,7 @@ class Parser } printCurrent(); } - + void printCurrent() { @@ -181,7 +181,7 @@ class Parser } void - rentCurrent(java.util.List args) + rentCurrent(java.util.List<String> args) { if(args.size() != 1) { @@ -193,8 +193,8 @@ class Parser { if(_foundBooks != null && _current != _foundBooks.length) { - _foundBooks[_current].rentBook((String)args.get(0)); - System.out.println("the book is now rented by `" + (String)args.get(0) + "'"); + _foundBooks[_current].rentBook(args.get(0)); + System.out.println("the book is now rented by `" + args.get(0) + "'"); } else { @@ -274,7 +274,7 @@ class Parser } void - setEvictorSize(java.util.List args) + setEvictorSize(java.util.List<String> args) { if(args.size() != 1) { @@ -282,7 +282,7 @@ class Parser return; } - String s = (String)args.get(0); + String s = args.get(0); try { _library.setEvictorSize(Integer.parseInt(s)); diff --git a/java/demo/Freeze/library/build.xml b/java/demo/Freeze/library/build.xml index dc8d213a27f..7e67186a72d 100644 --- a/java/demo/Freeze/library/build.xml +++ b/java/demo/Freeze/library/build.xml @@ -44,7 +44,7 @@ <exclude name="${generated.dir}/**"/> <classpath> <path refid="ice.classpath"/> - <path refid="db.classpath"/> + <path refid="freeze.classpath"/> </classpath> <compilerarg value="${javac.lint}"/> </javac> diff --git a/java/demo/Freeze/phonebook/Grammar.java b/java/demo/Freeze/phonebook/Grammar.java index 803966e4977..26ba2198ad2 100644 --- a/java/demo/Freeze/phonebook/Grammar.java +++ b/java/demo/Freeze/phonebook/Grammar.java @@ -53,7 +53,7 @@ class Grammar } else if(_token.type == Token.TOK_ADD_CONTACTS) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -62,7 +62,7 @@ class Grammar } else if(_token.type == Token.TOK_FIND_CONTACTS) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -91,7 +91,7 @@ class Grammar } else if(_token.type == Token.TOK_SET_CURRENT_NAME) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -100,7 +100,7 @@ class Grammar } else if(_token.type == Token.TOK_SET_CURRENT_ADDRESS) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -109,7 +109,7 @@ class Grammar } else if(_token.type == Token.TOK_SET_CURRENT_PHONE) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -128,7 +128,7 @@ class Grammar } else if(_token.type == Token.TOK_SET_EVICTOR_SIZE) { - java.util.List s = strings(); + java.util.List<String> s = strings(); if(_token.type != Token.TOK_SEMI) { throw new ParseError("Expected ';'"); @@ -157,10 +157,10 @@ class Grammar } } - private java.util.List + private java.util.List<String> strings() { - java.util.List l = new java.util.ArrayList(); + java.util.List<String> l = new java.util.ArrayList<String>(); while(true) { _token = _scanner.nextToken(); diff --git a/java/demo/Freeze/phonebook/build.xml b/java/demo/Freeze/phonebook/build.xml index 6af5e9f1b60..88b7a9ef591 100644 --- a/java/demo/Freeze/phonebook/build.xml +++ b/java/demo/Freeze/phonebook/build.xml @@ -41,7 +41,7 @@ <exclude name="${generated.dir}/**"/> <classpath> <path refid="ice.classpath"/> - <path refid="db.classpath"/> + <path refid="freeze.classpath"/> </classpath> <compilerarg value="${javac.lint}"/> </javac> diff --git a/java/demo/Freeze/transform/Create.java b/java/demo/Freeze/transform/Create.java index 231730c52b4..d55f9301c4e 100644 --- a/java/demo/Freeze/transform/Create.java +++ b/java/demo/Freeze/transform/Create.java @@ -22,35 +22,32 @@ class Create extends Ice.Application } final String[] names = { "don", "ed", "frank", "gary", "arnold", "bob", "carlos" }; - final String[] phoneNumbers = { "(777)777-7777", "(666)666-6666", "(555)555-5555 x123", + final String[] phoneNumbers = { "(777)777-7777", "(666)666-6666", "(555)555-5555 x123", "(444)444-4444", "(333)333-3333 x1234", "(222)222-2222", "(111)111-1111" }; Connection connection = Util.createConnection(communicator(), "db"); - final java.util.Comparator less = - new java.util.Comparator() + final java.util.Comparator<String> less = new java.util.Comparator<String>() { - public int compare(Object o1, Object o2) + public int compare(String s1, String s2) { - if(o1 == o2) + if(s1 == s2) { return 0; } - else if(o1 == null) + else if(s1 == null) { - return -((Comparable)o2).compareTo(o1); + return -s2.compareTo(s1); } else { - return ((Comparable)o1).compareTo(o2); + return s1.compareTo(s2); } } }; - java.util.Map indexComparators = new java.util.HashMap(); - indexComparators.put("phoneNumber", less); + Contacts.IndexComparators indexComparators = new Contacts.IndexComparators(less); Contacts contacts = new Contacts(connection, "contacts", true, less, indexComparators); - // // Create a bunch of contacts within one transaction, and commit it @@ -73,7 +70,7 @@ class Create extends Ice.Application } System.out.println(names.length + " contacts were successfully created or updated"); - + return 0; } diff --git a/java/demo/Freeze/transform/Read.java b/java/demo/Freeze/transform/Read.java index 995cf531409..efab503377d 100644 --- a/java/demo/Freeze/transform/Read.java +++ b/java/demo/Freeze/transform/Read.java @@ -23,54 +23,44 @@ class Read extends Ice.Application Connection connection = Util.createConnection(communicator(), "db"); - final java.util.Comparator less = - new java.util.Comparator() + final java.util.Comparator<String> less = new java.util.Comparator<String>() { - public int compare(Object o1, Object o2) + public int compare(String s1, String s2) { - if(o1 == o2) + if(s1 == s2) { return 0; } - else if(o1 == null) + else if(s1 == null) { - return -((Comparable)o2).compareTo(o1); + return -s2.compareTo(s1); } else { - return ((Comparable)o1).compareTo(o2); + return s1.compareTo(s2); } } }; - java.util.Map indexComparators = new java.util.HashMap(); - indexComparators.put("phoneNumber", less); - try { + Contacts.IndexComparators indexComparators = new Contacts.IndexComparators(less); Contacts contacts = new Contacts(connection, "contacts", false, less, indexComparators); - + System.out.println("All contacts (default order)"); - java.util.Iterator p = contacts.entrySet().iterator(); - while(p.hasNext()) + for(java.util.Map.Entry<String, ContactData> entry : contacts.entrySet()) { - java.util.Map.Entry entry = (java.util.Map.Entry)p.next(); - System.out.println((String)entry.getKey() + ":\t\t" - + ((ContactData)entry.getValue()).phoneNumber); + System.out.println(entry.getKey() + ":\t\t" + entry.getValue().phoneNumber); } - + System.out.println("\nAll contacts (ordered by phone number)"); - java.util.SortedMap phoneNumberMap = contacts.mapForIndex("phoneNumber"); - p = phoneNumberMap.values().iterator(); - while(p.hasNext()) + java.util.SortedMap<String, java.util.Set<java.util.Map.Entry<String, ContactData>>> phoneNumberMap = + contacts.mapForPhoneNumber(); + for(java.util.Set<java.util.Map.Entry<String, ContactData>> entries : phoneNumberMap.values()) { - java.util.Set entries = (java.util.Set)p.next(); - java.util.Iterator q = entries.iterator(); - while(q.hasNext()) + for(java.util.Map.Entry<String, ContactData> entry : entries) { - java.util.Map.Entry entry = (java.util.Map.Entry)q.next(); - System.out.println((String)entry.getKey() + ":\t\t" - + ((ContactData)entry.getValue()).phoneNumber); + System.out.println(entry.getKey() + ":\t\t" + entry.getValue().phoneNumber); } } } @@ -78,7 +68,7 @@ class Read extends Ice.Application { connection.close(); } - + return 0; } diff --git a/java/demo/Freeze/transform/ReadNew.java b/java/demo/Freeze/transform/ReadNew.java index 96ba48150a5..30add0aa939 100644 --- a/java/demo/Freeze/transform/ReadNew.java +++ b/java/demo/Freeze/transform/ReadNew.java @@ -23,60 +23,47 @@ class ReadNew extends Ice.Application Connection connection = Util.createConnection(communicator(), "dbnew"); - final java.util.Comparator less = - new java.util.Comparator() + final java.util.Comparator<String> less = new java.util.Comparator<String>() { - public int compare(Object o1, Object o2) + public int compare(String s1, String s2) { - if(o1 == o2) + if(s1 == s2) { return 0; } - else if(o1 == null) + else if(s1 == null) { - return -((Comparable)o2).compareTo(o1); + return -s2.compareTo(s1); } else { - return ((Comparable)o1).compareTo(o2); + return s1.compareTo(s2); } } }; - java.util.Map indexComparators = new java.util.HashMap(); - indexComparators.put("phoneNumber", less); - try { + NewContacts.IndexComparators indexComparators = new NewContacts.IndexComparators(less); boolean createDb = true; NewContacts contacts = new NewContacts(connection, "contacts", createDb, less, indexComparators); - + System.out.println("All contacts (default order)"); - java.util.Iterator p = contacts.entrySet().iterator(); - while(p.hasNext()) + for(java.util.Map.Entry<String, NewContactData> entry : contacts.entrySet()) { - java.util.Map.Entry entry = (java.util.Map.Entry)p.next(); - NewContactData data = (NewContactData)entry.getValue(); - - System.out.println((String)entry.getKey() + ":\t\t" - + data.phoneNumber + " " + data.emailAddress); + NewContactData data = entry.getValue(); + System.out.println(entry.getKey() + ":\t\t" + data.phoneNumber + " " + data.emailAddress); } - + System.out.println("\nAll contacts (ordered by phone number)"); - java.util.SortedMap phoneNumberMap = contacts.mapForIndex("phoneNumber"); - p = phoneNumberMap.values().iterator(); - while(p.hasNext()) + java.util.SortedMap<String, java.util.Set<java.util.Map.Entry<String, NewContactData>>> phoneNumberMap = + contacts.mapForPhoneNumber(); + for(java.util.Set<java.util.Map.Entry<String, NewContactData>> entries : phoneNumberMap.values()) { - java.util.Set entries = (java.util.Set)p.next(); - java.util.Iterator q = entries.iterator(); - while(q.hasNext()) + for(java.util.Map.Entry<String, NewContactData> entry : entries) { - java.util.Map.Entry entry = (java.util.Map.Entry)q.next(); - NewContactData data = (NewContactData)entry.getValue(); - - System.out.println((String)entry.getKey() + ":\t\t" - + data.phoneNumber + " " + data.emailAddress); - + NewContactData data = entry.getValue(); + System.out.println(entry.getKey() + ":\t\t" + data.phoneNumber + " " + data.emailAddress); } } } @@ -84,7 +71,7 @@ class ReadNew extends Ice.Application { connection.close(); } - + return 0; } diff --git a/java/demo/Freeze/transform/Recreate.java b/java/demo/Freeze/transform/Recreate.java index fe0bece7663..33a0298d8df 100644 --- a/java/demo/Freeze/transform/Recreate.java +++ b/java/demo/Freeze/transform/Recreate.java @@ -23,40 +23,37 @@ class Recreate extends Ice.Application Connection connection = Util.createConnection(communicator(), "dbnew"); - final java.util.Comparator less = - new java.util.Comparator() + final java.util.Comparator<String> less = new java.util.Comparator<String>() { - public int compare(Object o1, Object o2) + public int compare(String s1, String s2) { - if(o1 == o2) + if(s1 == s2) { return 0; } - else if(o1 == null) + else if(s1 == null) { - return -((Comparable)o2).compareTo(o1); + return -s2.compareTo(s1); } else { - return ((Comparable)o1).compareTo(o2); + return s1.compareTo(s2); } } }; - java.util.Map indexComparators = new java.util.HashMap(); - indexComparators.put("phoneNumber", less); - try { + NewContacts.IndexComparators indexComparators = new NewContacts.IndexComparators(less); NewContacts.recreate(connection, "contacts", less, indexComparators); } finally { connection.close(); } - + System.out.println("Recreated contacts database successfully!"); - + return 0; } diff --git a/java/demo/Freeze/transform/build.xml b/java/demo/Freeze/transform/build.xml index b7a3a940420..786ed1ca1ce 100644 --- a/java/demo/Freeze/transform/build.xml +++ b/java/demo/Freeze/transform/build.xml @@ -43,7 +43,7 @@ <exclude name="${generated.dir}/**"/> <classpath> <path refid="ice.classpath"/> - <path refid="db.classpath"/> + <path refid="freeze.classpath"/> </classpath> <compilerarg value="${javac.lint}"/> </javac> diff --git a/java/demo/book/freeze_filesystem/build.xml b/java/demo/book/freeze_filesystem/build.xml index 96671a6a95c..8010bd22527 100644 --- a/java/demo/book/freeze_filesystem/build.xml +++ b/java/demo/book/freeze_filesystem/build.xml @@ -35,7 +35,7 @@ <exclude name="${generated.dir}/**"/> <classpath> <path refid="ice.classpath"/> - <path refid="db.classpath"/> + <path refid="freeze.classpath"/> </classpath> <compilerarg value="${javac.lint}"/> </javac> diff --git a/java/src/Freeze/BackgroundSaveEvictorI.java b/java/src/Freeze/BackgroundSaveEvictorI.java index 11bdbe289e3..d7649788530 100644 --- a/java/src/Freeze/BackgroundSaveEvictorI.java +++ b/java/src/Freeze/BackgroundSaveEvictorI.java @@ -20,22 +20,22 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, // Clean object; can become modified or destroyed // static final byte clean = 0; - + // // New object; can become clean, dead or destroyed // static final byte created = 1; - + // // Modified object; can become clean or destroyed // static final byte modified = 2; - + // // Being saved. Can become dead or created // static final byte destroyed = 3; - + // // Exists only in the SaveAsyncEvictor; for example the object was created // and later destroyed (without a save in between), or it was @@ -58,7 +58,8 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, assert timeout > 0; } - public synchronized void run() + public synchronized void + run() { while(!_done) { @@ -91,7 +92,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, if(IceInternal.Time.currentMonotonicTimeMillis() - startTime >= _timeout) { _communicator.getLogger().error(_errorPrefix + - "Fatal error: streaming watch dog thread timed out."); + "Fatal error: streaming watch dog thread timed out"); Util.handleFatalError(BackgroundSaveEvictorI.this, _communicator, null); } @@ -99,19 +100,22 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } - synchronized void activate() + synchronized void + activate() { _active = true; notify(); } - - synchronized void deactivate() + + synchronized void + deactivate() { _active = false; notify(); } - synchronized void terminate() + synchronized void + terminate() { _done = true; notify(); @@ -122,23 +126,21 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, private boolean _active = false; } - - BackgroundSaveEvictorI(Ice.ObjectAdapter adapter, String envName, String filename, + BackgroundSaveEvictorI(Ice.ObjectAdapter adapter, String envName, String filename, ServantInitializer initializer, Index[] indices, boolean createDb) { this(adapter, envName, null, filename, initializer, indices, createDb); } - - BackgroundSaveEvictorI(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, + BackgroundSaveEvictorI(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, String filename, ServantInitializer initializer, Index[] indices, boolean createDb) { super(adapter, envName, dbEnv, filename, null, initializer, indices, createDb); - String propertyPrefix = "Freeze.Evictor." + envName + '.' + filename; - - // - // By default, we save every minute or when the size of the modified + String propertyPrefix = "Freeze.Evictor." + envName + '.' + filename; + + // + // By default, we save every minute or when the size of the modified // queue reaches 10. // @@ -158,12 +160,12 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { _maxTxSize = 100; } - + // // Start threads // String savingThreadName; - + String programName = _communicator.getProperties().getProperty("Ice.ProgramName"); if(programName.length() > 0) { @@ -191,13 +193,12 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, _thread = new Thread(this, savingThreadName); _thread.start(); } - - + public Ice.ObjectPrx addFacet(Ice.Object servant, Ice.Identity ident, String facet) { checkIdentity(ident); - + if(facet == null) { facet = ""; @@ -211,42 +212,41 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, if(store == null) { NotFoundException ex = new NotFoundException(); - ex.message = _errorPrefix + "addFacet: could not open database for facet '" - + facet + "'"; + ex.message = _errorPrefix + "addFacet: could not open database for facet '" + facet + "'"; throw ex; } boolean alreadyThere = false; - + for(;;) { // // Create a new entry // - + EvictorElement element = new EvictorElement(ident, store); element.status = dead; element.rec = new ObjectRecord(); element.rec.stats = new Statistics(); - + Object o = store.cache().putIfAbsent(ident, element); - + if(o != null) { element = (EvictorElement)o; } - + synchronized(this) - { + { if(element.stale) { // // Try again - // + // continue; } fixEvictPosition(element); - + synchronized(element) { switch(element.status) @@ -257,12 +257,12 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { alreadyThere = true; break; - } + } case destroyed: { element.status = modified; element.rec.servant = servant; - + // // No need to push it on the modified queue, as a destroyed object // is either already on the queue or about to be saved. When saved, @@ -274,12 +274,12 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { element.status = created; ObjectRecord rec = element.rec; - + rec.servant = servant; rec.stats.creationTime = IceInternal.Time.currentMonotonicTimeMillis(); rec.stats.lastSaveTime = 0; rec.stats.avgSaveTime = 0; - + addToModifiedQueue(element); break; } @@ -293,7 +293,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } break; // for(;;) } - + if(alreadyThere) { Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); @@ -305,7 +305,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } throw ex; } - + if(_trace >= 1) { String objString = "object \"" + _communicator.identityToString(ident) + "\""; @@ -313,11 +313,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { objString += " with facet \"" + facet + "\""; } - + _communicator.getLogger().trace("Freeze.Evictor", "added " + objString + " to Db \"" + _filename + "\""); } - + Ice.ObjectPrx obj = _adapter.createProxy(ident); if(facet.length() > 0) { @@ -346,10 +346,10 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { ObjectStore store = findStore(facet, false); Ice.Object servant = null; - + if(store != null) { - for(;;) + for(;;) { // // Retrieve object @@ -363,10 +363,10 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { // // Try again - // + // continue; } - + fixEvictPosition(element); synchronized(element) { @@ -398,7 +398,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, // (at which point it becomes clean) // break; - } + } case destroyed: case dead: { @@ -411,11 +411,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } } - + if(element.keepCount > 0) { assert servant != null; - + element.keepCount = 0; // // Add to front of evictor queue @@ -432,10 +432,10 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } } - break; // for(;;) + break; // for(;;) } } - + if(servant == null) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); @@ -447,7 +447,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } throw ex; } - + if(_trace >= 1) { String objString = "object \"" + _communicator.identityToString(ident) + "\""; @@ -455,7 +455,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { objString += " with facet \"" + facet + "\""; } - + _communicator.getLogger().trace("Freeze.Evictor", "removed " + objString + " from Db \"" + _filename + "\""); } @@ -466,7 +466,6 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, _deactivateController.unlock(); } } - public void keep(Ice.Identity ident) @@ -487,7 +486,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, try { boolean notThere = false; - + ObjectStore store = findStore(facet, false); if(store == null) { @@ -503,7 +502,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, notThere = true; break; } - + synchronized(this) { if(element.stale) @@ -513,7 +512,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, // continue; } - + synchronized(element) { if(element.status == destroyed || element.status == dead) @@ -522,11 +521,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, break; } } - + // // Found! // - + if(element.keepCount == 0) { if(element.usageCount < 0) @@ -553,7 +552,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } } - + if(notThere) { Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); @@ -597,11 +596,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { synchronized(this) { - EvictorElement element = (EvictorElement) store.cache().getIfPinned(ident); + EvictorElement element = (EvictorElement)store.cache().getIfPinned(ident); if(element != null) { assert !element.stale; - if(element.keepCount > 0) + if(element.keepCount > 0) { if(--element.keepCount == 0) { @@ -628,7 +627,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } } - + Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); ex.kindOfObject = "servant"; ex.id = _communicator.identityToString(ident); @@ -636,7 +635,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); } - + throw ex; } finally @@ -644,7 +643,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, _deactivateController.unlock(); } } - + public boolean hasFacet(Ice.Identity ident, String facet) { @@ -659,19 +658,19 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { ObjectStore store = findStore(facet, false); - + if(store == null) { return false; } synchronized(this) - { + { EvictorElement element = (EvictorElement)store.cache().getIfPinned(ident); if(element != null) { - assert !element.stale; - + assert !element.stale; + synchronized(element) { return element.status != dead && element.status != destroyed; @@ -686,7 +685,6 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } - protected boolean hasAnotherFacet(Ice.Identity ident, String facet) { @@ -694,36 +692,33 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, try { // - // If the object exists in another store, throw FacetNotExistException + // If the object exists in another store, throw FacetNotExistException // instead of returning null (== ObjectNotExistException) - // - java.util.Map storeMapCopy; + // + java.util.Map<String, ObjectStore> storeMapCopy; synchronized(this) { - storeMapCopy = new java.util.HashMap(_storeMap); - } - - java.util.Iterator p = storeMapCopy.entrySet().iterator(); - while(p.hasNext()) + storeMapCopy = new java.util.HashMap<String, ObjectStore>(_storeMap); + } + + for(java.util.Map.Entry<String, ObjectStore> entry : storeMapCopy.entrySet()) { - java.util.Map.Entry entry = (java.util.Map.Entry) p.next(); - // // Do not check facet // if(!facet.equals(entry.getKey())) { - ObjectStore store = (ObjectStore)entry.getValue(); + ObjectStore store = entry.getValue(); boolean inCache = false; - + synchronized(this) { EvictorElement element = (EvictorElement)store.cache().getIfPinned(ident); if(element != null) { inCache = true; - assert !element.stale; - + assert !element.stale; + synchronized(element) { if(element.status != dead && element.status != destroyed) @@ -740,7 +735,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, return true; } } - } + } } return false; } @@ -750,22 +745,20 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } - - protected Object + protected Object createEvictorElement(Ice.Identity ident, ObjectRecord rec, ObjectStore store) { EvictorElement elt = new EvictorElement(ident, store); elt.rec = rec; return elt; } - + protected Ice.Object locateImpl(Ice.Current current, Ice.LocalObjectHolder cookie) { _deactivateController.lock(); try { - cookie.value = null; ObjectStore store = findStore(current.facet, false); @@ -794,7 +787,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } synchronized(this) - { + { if(element.stale) { // @@ -805,8 +798,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, synchronized(element) { - if(element.status == destroyed || - element.status == dead) + if(element.status == destroyed || element.status == dead) { if(_trace >= 2) { @@ -836,7 +828,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, return element.rec.servant; } } - } + } } finally { @@ -853,9 +845,9 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, if(cookie != null) { EvictorElement element = (EvictorElement)cookie; - + boolean enqueue = false; - + if((servant.ice_operationAttributes(current.operation) & 0x1) != 0) { synchronized(element) @@ -864,27 +856,27 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { // // Assume this operation updated the object - // + // element.status = modified; enqueue = true; } } } - + synchronized(this) { // - // Only elements with a usageCount == 0 can become stale and we own + // Only elements with a usageCount == 0 can become stale and we own // one count! - // + // assert !element.stale; assert element.usageCount >= 1; - + // // Decrease the usage count of the evictor queue element. // element.usageCount--; - + if(enqueue) { addToModifiedQueue(element); @@ -904,7 +896,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, _deactivateController.unlock(); } } - + public void deactivate(String category) { @@ -922,11 +914,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, // _evictorSize = 0; evict(); - + _savingThreadDone = true; notifyAll(); } - + try { _thread.join(); @@ -934,20 +926,20 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, catch(InterruptedException ex) { } - + if(_watchDogThread != null) { _watchDogThread.terminate(); - + try { _watchDogThread.join(); } catch(InterruptedException ex) { - } + } } - + closeDbEnv(); } finally @@ -956,7 +948,6 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } } - public void run() @@ -965,11 +956,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { for(;;) { - java.util.List allObjects; - java.util.List deadObjects = new java.util.LinkedList(); + java.util.List<EvictorElement> allObjects; + java.util.List<EvictorElement> deadObjects = new java.util.LinkedList<EvictorElement>(); int saveNowThreadsSize = 0; - + synchronized(this) { while(!_savingThreadDone && @@ -996,16 +987,16 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { } } - + saveNowThreadsSize = _saveNowThreads.size(); - + if(_savingThreadDone) { assert(_modifiedQueue.size() == 0); assert(saveNowThreadsSize == 0); break; // for(;;) } - + // // Check first if there is something to do! // @@ -1018,35 +1009,35 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } continue; // for(;;) } - + allObjects = _modifiedQueue; - _modifiedQueue = new java.util.ArrayList(); + _modifiedQueue = new java.util.ArrayList<EvictorElement>(); } - + int size = allObjects.size(); - - java.util.List streamedObjectQueue = new java.util.ArrayList(); - + + java.util.List<StreamedObject> streamedObjectQueue = new java.util.ArrayList<StreamedObject>(); + long streamStart = IceInternal.Time.currentMonotonicTimeMillis(); - + // // Stream each element // for(int i = 0; i < size; i++) { - EvictorElement element = (EvictorElement)allObjects.get(i); - + EvictorElement element = allObjects.get(i); + boolean tryAgain; - + do { tryAgain = false; Ice.Object servant = null; - + synchronized(element) { byte status = element.status; - + switch(status) { case created: @@ -1054,7 +1045,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { servant = element.rec.servant; break; - } + } case destroyed: { streamedObjectQueue.add(stream(element, streamStart)); @@ -1062,7 +1053,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, element.status = dead; deadObjects.add(element); break; - } + } case dead: { deadObjects.add(element); @@ -1077,7 +1068,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } } - + if(servant != null) { // @@ -1098,7 +1089,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, synchronized(element) { byte status = element.status; - + switch(status) { case created: @@ -1119,11 +1110,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, case destroyed: { streamedObjectQueue.add(stream(element, streamStart)); - + element.status = dead; deadObjects.add(element); break; - } + } case dead: { deadObjects.add(element); @@ -1142,18 +1133,18 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } while(tryAgain); } - + if(_trace >= 1) { long now = IceInternal.Time.currentMonotonicTimeMillis(); _communicator.getLogger().trace("Freeze.Evictor", "streamed " + streamedObjectQueue.size() + " objects in " + (now - streamStart) + " ms"); } - + // // Now let's save all these streamed objects to disk using a transaction // - + // // Each time we get a deadlock, we reduce the number of objects to save // per transaction @@ -1163,20 +1154,20 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { txSize = _maxTxSize; } - + boolean tryAgain; - + do { tryAgain = false; - + while(streamedObjectQueue.size() > 0) { if(txSize > streamedObjectQueue.size()) { txSize = streamedObjectQueue.size(); } - + long saveStart = IceInternal.Time.currentMonotonicTimeMillis(); String txnId = null; @@ -1186,20 +1177,20 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, if(_txTrace >= 1) { - txnId = Long.toHexString((tx.getId() & 0x7FFFFFFF) + 0x80000000L); + txnId = Long.toHexString((tx.getId() & 0x7FFFFFFF) + 0x80000000L); _communicator.getLogger().trace("Freeze.Evictor", _errorPrefix + "started transaction " + txnId + " in saving thread"); } try - { + { for(int i = 0; i < txSize; i++) { - StreamedObject obj = (StreamedObject) streamedObjectQueue.get(i); + StreamedObject obj = streamedObjectQueue.get(i); obj.store.save(obj.key, obj.value, obj.status, tx); } - + com.sleepycat.db.Transaction toCommit = tx; tx = null; toCommit.commit(); @@ -1222,12 +1213,12 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } } } - + for(int i = 0; i < txSize; i++) { streamedObjectQueue.remove(0); } - + if(_trace >= 1) { long now = IceInternal.Time.currentMonotonicTimeMillis(); @@ -1239,10 +1230,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { if(_deadlockWarning) { - _communicator.getLogger().warning("Deadlock in Freeze.BackgroundSaveEvictorI.run while writing " + - "into Db \"" + _filename + "\"; retrying..."); + _communicator.getLogger().warning( + "Deadlock in Freeze.BackgroundSaveEvictorI.run while writing " + + "into Db \"" + _filename + "\"; retrying..."); } - + tryAgain = true; txSize = (txSize + 1)/2; } @@ -1253,27 +1245,24 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, ex.message = _errorPrefix + "saving: " + dx.getMessage(); throw ex; } - } + } } while(tryAgain); - + synchronized(this) - { + { // // Release usage count // for(int i = 0; i < allObjects.size(); i++) - { - EvictorElement element = (EvictorElement) allObjects.get(i); + { + EvictorElement element = allObjects.get(i); assert element.usageCount > 0; element.usageCount--; } allObjects.clear(); - java.util.Iterator p = deadObjects.iterator(); - while(p.hasNext()) + for(EvictorElement element : deadObjects) { - EvictorElement element = (EvictorElement) p.next(); - // // Can be stale when there are duplicates on the deadObjects list // @@ -1323,19 +1312,19 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, { assert Thread.holdsLock(this); - java.util.Iterator p = _evictorList.riterator(); + java.util.Iterator<EvictorElement> p = _evictorList.riterator(); while(p.hasNext() && _currentEvictorSize > _evictorSize) { // // Get the last unused element from the evictor queue. // - EvictorElement element = (EvictorElement)p.next(); + EvictorElement element = p.next(); if(element.usageCount == 0) { // // Fine, servant is not in use (and not in the modifiedQueue) // - + assert !element.stale; assert element.keepCount == 0; assert element.evictPosition != null; @@ -1351,8 +1340,8 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, _communicator.getLogger().trace("Freeze.Evictor", "evicting " + objString + " from the queue; " + "number of elements in the queue: " + _currentEvictorSize); - } - + } + // // Remove last unused element from the evictor queue. // @@ -1360,7 +1349,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, element.store.cache().unpin(element.identity); p.remove(); element.evictPosition = null; - _currentEvictorSize--; + _currentEvictorSize--; } } } @@ -1374,7 +1363,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, synchronized private void saveNow() - { + { Thread myself = Thread.currentThread(); _saveNowThreads.add(myself); @@ -1392,7 +1381,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, while(_saveNowThreads.contains(myself)); } - private void + private void fixEvictPosition(EvictorElement element) { assert Thread.holdsLock(this); @@ -1404,7 +1393,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, if(element.usageCount < 0) { assert element.evictPosition == null; - + // // New object // @@ -1432,7 +1421,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, assert !element.stale; assert element.keepCount == 0; - + element.evictPosition.remove(); _currentEvictorSize--; element.stale = true; @@ -1446,7 +1435,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, element.usageCount++; _modifiedQueue.add(element); - + if(_saveSizeTrigger >= 0 && _modifiedQueue.size() >= _saveSizeTrigger) { notifyAll(); @@ -1459,13 +1448,13 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, assert Thread.holdsLock(element); assert element.status != dead; - + StreamedObject obj = new StreamedObject(); obj.status = element.status; obj.store = element.store; obj.key = ObjectStore.marshalKey(element.identity, _communicator); - + if(element.status != destroyed) { updateStats(element.rec.stats, streamStart); @@ -1473,7 +1462,7 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, } return obj; } - + static private class EvictorElement { EvictorElement(Ice.Identity identity, ObjectStore store) @@ -1481,18 +1470,18 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, this.identity = identity; this.store = store; } - + final ObjectStore store; final Ice.Identity identity; - + // // Protected by SaveAsyncEvictor // - java.util.Iterator evictPosition = null; + java.util.Iterator<EvictorElement> evictPosition = null; int usageCount = -1; int keepCount = 0; boolean stale = false; - + // // Protected by this // @@ -1500,7 +1489,6 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, byte status = clean; } - static private class StreamedObject { byte[] key = null; @@ -1508,11 +1496,11 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, byte status = dead; ObjectStore store = null; } - + // // List of EvictorElement with stable iterators // - private final Freeze.LinkedList _evictorList = new Freeze.LinkedList(); + private final Freeze.LinkedList<EvictorElement> _evictorList = new Freeze.LinkedList<EvictorElement>(); private int _currentEvictorSize = 0; // @@ -1520,16 +1508,16 @@ class BackgroundSaveEvictorI extends EvictorI implements BackgroundSaveEvictor, // Each element in the queue "owns" a usage count, to ensure the // elements containing them remain in the map. // - private java.util.List _modifiedQueue = new java.util.ArrayList(); - - private boolean _savingThreadDone = false; - private WatchDogThread _watchDogThread = null; + private java.util.List<EvictorElement> _modifiedQueue = new java.util.ArrayList<EvictorElement>(); + + private boolean _savingThreadDone = false; + private WatchDogThread _watchDogThread = null; // // Threads that have requested a "saveNow" and are waiting for // its completion // - private final java.util.List _saveNowThreads = new java.util.ArrayList(); + private final java.util.List<Thread> _saveNowThreads = new java.util.ArrayList<Thread>(); private int _saveSizeTrigger; private int _maxTxSize; diff --git a/java/src/Freeze/ConnectionI.java b/java/src/Freeze/ConnectionI.java index 9b403b345bb..94fd8cfb656 100644 --- a/java/src/Freeze/ConnectionI.java +++ b/java/src/Freeze/ConnectionI.java @@ -9,9 +9,8 @@ package Freeze; -class ConnectionI implements Connection +public class ConnectionI implements Connection { - public Transaction beginTransaction() { @@ -37,7 +36,7 @@ class ConnectionI implements Connection { throw new DatabaseException("Closed connection"); } - + try { _dbEnv.getEnv().removeDatabase(dbTxn(), mapName + "." + indexName, null); @@ -60,42 +59,11 @@ class ConnectionI implements Connection } } - public void close() { - close(false); - } - - public Ice.Communicator - getCommunicator() - { - return _communicator; - } - - public String - getName() - { - return _envName; - } - - protected void - finalize() - { - close(true); - } - - void - close(boolean finalizing) - { if(_transaction != null) { - if(finalizing) - { - _communicator.getLogger().warning - ("Finalizing Connection on DbEnv \"" + _envName + "\" with active transaction"); - } - try { _transaction.rollback(); @@ -108,16 +76,11 @@ class ConnectionI implements Connection } } - - synchronized(this) + java.util.Iterator<Map> p = _mapList.iterator(); + while(p.hasNext()) { - java.util.Iterator p = _mapList.iterator(); - while(p.hasNext()) - { - ((Map) p.next()).close(finalizing); - } + p.next().close(); } - if(_dbEnv != null) { @@ -132,17 +95,40 @@ class ConnectionI implements Connection } } + public Ice.Communicator + getCommunicator() + { + return _communicator; + } + + public String + getName() + { + return _envName; + } + + protected void + finalize() + throws Throwable + { + if(_dbEnv != null) + { + _logger.warning("leaked Connection for DbEnv \"" + _envName + "\""); + } + super.finalize(); + } + ConnectionI(SharedDbEnv dbEnv) { _dbEnv = dbEnv; _communicator = dbEnv.getCommunicator(); + _logger = _communicator.getLogger(); _envName = dbEnv.getEnvName(); _trace = _communicator.getProperties().getPropertyAsInt("Freeze.Trace.Map"); _txTrace = _communicator.getProperties().getPropertyAsInt("Freeze.Trace.Transaction"); - + Ice.Properties properties = _communicator.getProperties(); _deadlockWarning = properties.getPropertyAsInt("Freeze.Warn.Deadlocks") > 0; - _closeInFinalizeWarning = properties.getPropertyAsIntWithDefault("Freeze.Warn.CloseInFinalize", 1) > 0; } ConnectionI(Ice.Communicator communicator, String envName, com.sleepycat.db.Environment dbEnv) @@ -150,31 +136,26 @@ class ConnectionI implements Connection this(SharedDbEnv.get(communicator, envName, dbEnv)); } - - // - // The synchronization is only needed only during finalization - // - - synchronized void + public void closeAllIterators() { - java.util.Iterator p = _mapList.iterator(); + java.util.Iterator<Map> p = _mapList.iterator(); while(p.hasNext()) { - ((Map) p.next()).closeAllIterators(); + p.next().closeAllIterators(); } } - synchronized java.util.Iterator + public java.util.Iterator registerMap(Map map) { _mapList.addFirst(map); - java.util.Iterator p = _mapList.iterator(); + java.util.Iterator<Map> p = _mapList.iterator(); p.next(); return p; } - synchronized void + public void unregisterMap(java.util.Iterator p) { p.remove(); @@ -186,7 +167,7 @@ class ConnectionI implements Connection _transaction = null; } - com.sleepycat.db.Transaction + public com.sleepycat.db.Transaction dbTxn() { if(_transaction == null) @@ -199,61 +180,55 @@ class ConnectionI implements Connection } } - SharedDbEnv + public SharedDbEnv dbEnv() { return _dbEnv; } - String + public String envName() { return _envName; } - Ice.Communicator + public Ice.Communicator communicator() { return _communicator; } - final int + public final int trace() { return _trace; } - final int + public final int txTrace() { return _txTrace; } - final boolean + public final boolean deadlockWarning() { return _deadlockWarning; } - final boolean - closeInFinalizeWarning() - { - return _closeInFinalizeWarning; - } - - private String errorPrefix() + private String + errorPrefix() { return "DbEnv(\"" + _envName + "\"): "; } - private Ice.Communicator _communicator; + private Ice.Logger _logger; private SharedDbEnv _dbEnv; private String _envName; private TransactionI _transaction; - private LinkedList _mapList = new Freeze.LinkedList(); + private LinkedList<Map> _mapList = new LinkedList<Map>(); private int _trace; private int _txTrace; private boolean _deadlockWarning; - private boolean _closeInFinalizeWarning; } diff --git a/java/src/Freeze/EvictorElement.java b/java/src/Freeze/EvictorElement.java index 67e28c49135..e0c366f78d1 100644 --- a/java/src/Freeze/EvictorElement.java +++ b/java/src/Freeze/EvictorElement.java @@ -50,7 +50,7 @@ class EvictorElement // // Protected by EvictorI // - java.util.Iterator evictPosition = null; + java.util.Iterator<EvictorElement> evictPosition = null; int usageCount = -1; int keepCount = 0; boolean stale = false; diff --git a/java/src/Freeze/EvictorI.java b/java/src/Freeze/EvictorI.java index c032894a4d0..6be4de9e7db 100644 --- a/java/src/Freeze/EvictorI.java +++ b/java/src/Freeze/EvictorI.java @@ -20,13 +20,15 @@ abstract class EvictorI implements Evictor // class DeactivateController { - synchronized void activate() + synchronized void + activate() { assert !_activated; _activated = true; } - synchronized void lock() + synchronized void + lock() { assert _activated; @@ -37,7 +39,8 @@ abstract class EvictorI implements Evictor _guardCount++; } - synchronized void unlock() + synchronized void + unlock() { assert _activated; @@ -51,13 +54,15 @@ abstract class EvictorI implements Evictor notifyAll(); } } - - synchronized boolean deactivated() + + synchronized boolean + deactivated() { return !_activated || _deactivated; } - - synchronized boolean deactivate() + + synchronized boolean + deactivate() { assert _activated; @@ -65,7 +70,7 @@ abstract class EvictorI implements Evictor { return false; } - + if(_deactivating) { // @@ -91,9 +96,8 @@ abstract class EvictorI implements Evictor { if(_trace >= 1) { - _communicator.getLogger().trace( - "Freeze.Evictor", "Waiting for " + _guardCount + - " threads to complete before starting deactivation."); + _communicator.getLogger().trace("Freeze.Evictor", "Waiting for " + _guardCount + + " threads to complete before starting deactivation."); } try @@ -114,7 +118,8 @@ abstract class EvictorI implements Evictor } } - synchronized void deactivationComplete() + synchronized void + deactivationComplete() { if(_trace >= 1) { @@ -135,7 +140,6 @@ abstract class EvictorI implements Evictor static final String defaultDb = "$default"; static final String indexPrefix = "$index:"; - public Ice.ObjectPrx add(Ice.Object servant, Ice.Identity ident) { @@ -161,7 +165,7 @@ abstract class EvictorI implements Evictor // Special ice_ping() handling // if(current.operation != null && current.operation.equals("ice_ping")) - { + { if(hasFacet(current.id, current.facet)) { if(_trace >= 3) @@ -170,6 +174,7 @@ abstract class EvictorI implements Evictor "Freeze.Evictor", "ice_ping found \"" + _communicator.identityToString(current.id) + "\" with facet \"" + current.facet + "\""); } + cookie.value = null; return _pingObject; } @@ -181,7 +186,7 @@ abstract class EvictorI implements Evictor "Freeze.Evictor", "ice_ping raises FacetNotExistException for \"" + _communicator.identityToString(current.id) + "\" with facet \"" + current.facet + "\""); } - + throw new Ice.FacetNotExistException(); } else @@ -192,13 +197,13 @@ abstract class EvictorI implements Evictor "Freeze.Evictor", "ice_ping will raise ObjectNotExistException for \"" + _communicator.identityToString(current.id) + "\" with facet \"" + current.facet + "\""); } - + return null; } } - + Ice.Object result = locateImpl(current, cookie); - + if(result == null) { if(hasAnotherFacet(current.id, current.facet)) @@ -222,12 +227,12 @@ abstract class EvictorI implements Evictor { return; } - + // // Update the evictor size. // _evictorSize = evictorSize; - + // // Evict as many elements as necessary. // @@ -238,14 +243,13 @@ abstract class EvictorI implements Evictor _deactivateController.unlock(); } } - + synchronized public int getSize() - { + { return _evictorSize; } - public EvictorIterator getIterator(String facet, int batchSize) { @@ -268,53 +272,38 @@ abstract class EvictorI implements Evictor abstract protected boolean hasAnotherFacet(Ice.Identity ident, String facet); abstract protected Object createEvictorElement(Ice.Identity ident, ObjectRecord rec, ObjectStore store); - - abstract protected Ice.Object locateImpl(Ice.Current current, Ice.LocalObjectHolder cookie); - - abstract protected void evict(); + abstract protected Ice.Object locateImpl(Ice.Current current, Ice.LocalObjectHolder cookie); - synchronized protected void - finalize() - { - if(!_deactivateController.deactivated()) - { - _communicator.getLogger().warning("Freeze evictor " + toString() + " has not been deactivated"); - deactivate(""); - } - } + abstract protected void evict(); protected void closeDbEnv() { assert _dbEnv != null; - java.util.Iterator p = _storeMap.values().iterator(); - while(p.hasNext()) + for(ObjectStore store : _storeMap.values()) { - ObjectStore store = (ObjectStore)p.next(); store.close(); } _dbEnv.close(); _dbEnv = null; } - protected synchronized ObjectStore findStore(String facet, boolean createIt) { - ObjectStore os = (ObjectStore)_storeMap.get(facet); + ObjectStore os = _storeMap.get(facet); if(os == null && createIt) { - String facetType = (String)_facetTypes.get(facet); - os = new ObjectStore(facet, facetType, true, this, new java.util.LinkedList(), false); - + String facetType = _facetTypes.get(facet); + os = new ObjectStore(facet, facetType, true, this, new java.util.LinkedList<Index>(), false); _storeMap.put(facet, os); } return os; } - protected void + protected void initialize(Ice.Identity ident, String facet, Ice.Object servant) { if(_initializer != null) @@ -323,37 +312,39 @@ abstract class EvictorI implements Evictor } } - protected EvictorI(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, String filename, - java.util.Map facetTypes, ServantInitializer initializer, Index[] indices, boolean createDb) + protected + EvictorI(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, String filename, + java.util.Map<String, String> facetTypes, ServantInitializer initializer, Index[] indices, + boolean createDb) { _adapter = adapter; _communicator = adapter.getCommunicator(); _initializer = initializer; _filename = filename; _createDb = createDb; - _facetTypes = facetTypes == null ? new java.util.HashMap() : new java.util.HashMap(facetTypes); - + _facetTypes = facetTypes == null ? new java.util.HashMap<String, String>() : + new java.util.HashMap<String, String>(facetTypes); + _dbEnv = SharedDbEnv.get(_communicator, envName, dbEnv); _trace = _communicator.getProperties().getPropertyAsInt("Freeze.Trace.Evictor"); _txTrace = _communicator.getProperties().getPropertyAsInt("Freeze.Trace.Transaction"); _deadlockWarning = _communicator.getProperties().getPropertyAsInt("Freeze.Warn.Deadlocks") != 0; - + _errorPrefix = "Freeze Evictor DbEnv(\"" + envName + "\") Db(\"" + _filename + "\"): "; String propertyPrefix = "Freeze.Evictor." + envName + '.' + _filename; - + boolean populateEmptyIndices = - _communicator.getProperties().getPropertyAsIntWithDefault(propertyPrefix + - ".PopulateEmptyIndices", 0) != 0; - + _communicator.getProperties().getPropertyAsIntWithDefault(propertyPrefix + ".PopulateEmptyIndices", 0) != 0; + // // Instantiate all Dbs in 2 steps: // (1) iterate over the indices and create ObjectStore with indices // (2) open ObjectStores without indices // - java.util.List dbs = allDbs(); + java.util.List<String> dbs = allDbs(); // // Add default db in case it's not there // @@ -364,10 +355,10 @@ abstract class EvictorI implements Evictor for(int i = 0; i < indices.length; ++i) { String facet = indices[i].facet(); - + if(_storeMap.get(facet) == null) { - java.util.List storeIndices = new java.util.LinkedList(); + java.util.List<Index> storeIndices = new java.util.LinkedList<Index>(); for(int j = i; j < indices.length; ++j) { if(indices[j].facet().equals(facet)) @@ -375,40 +366,38 @@ abstract class EvictorI implements Evictor storeIndices.add(indices[j]); } } - - String facetType = (String)_facetTypes.get(facet); - ObjectStore store = new ObjectStore(facet, facetType,_createDb, this, storeIndices, + + String facetType = _facetTypes.get(facet); + ObjectStore store = new ObjectStore(facet, facetType,_createDb, this, storeIndices, populateEmptyIndices); _storeMap.put(facet, store); } } } - - java.util.Iterator p = dbs.iterator(); - while(p.hasNext()) + + for(String facet : dbs) { - String facet = (String) p.next(); if(facet.equals(defaultDb)) { facet = ""; } - + if(_storeMap.get(facet) == null) { - String facetType = (String)_facetTypes.get(facet); + String facetType = _facetTypes.get(facet); + + ObjectStore store = new ObjectStore(facet, facetType, _createDb, this, + new java.util.LinkedList<Index>(), populateEmptyIndices); - ObjectStore store = new ObjectStore(facet, facetType, _createDb, this, new java.util.LinkedList(), - populateEmptyIndices); - _storeMap.put(facet, store); } } _deactivateController.activate(); } - - protected EvictorI(Ice.ObjectAdapter adapter, String envName, String filename, java.util.Map facetTypes, - ServantInitializer initializer, Index[] indices, boolean createDb) + protected + EvictorI(Ice.ObjectAdapter adapter, String envName, String filename, java.util.Map<String, String> facetTypes, + ServantInitializer initializer, Index[] indices, boolean createDb) { this(adapter, envName, null, filename, facetTypes, initializer, indices, createDb); } @@ -465,7 +454,7 @@ abstract class EvictorI implements Evictor deadlockWarning() { return _deadlockWarning; - } + } final int trace() @@ -473,11 +462,11 @@ abstract class EvictorI implements Evictor return _trace; } - private java.util.List + private java.util.List<String> allDbs() { - java.util.List result = new java.util.LinkedList(); - + java.util.List<String> result = new java.util.LinkedList<String>(); + com.sleepycat.db.Database db = null; com.sleepycat.db.Cursor dbc = null; @@ -503,7 +492,7 @@ abstract class EvictorI implements Evictor // Assumes Berkeley-DB encodes the db names in UTF-8! // String dbName = new String(key.getData(), 0, key.getSize(), "UTF8"); - + if(!dbName.startsWith(indexPrefix)) { result.add(dbName); @@ -576,17 +565,12 @@ abstract class EvictorI implements Evictor throw e; } } - - protected int _evictorSize = 10; - // - // Map of string (facet) to ObjectStore - // - protected final java.util.Map _storeMap = new java.util.HashMap(); - private final java.util.Map _facetTypes; - + protected final java.util.Map<String, ObjectStore> _storeMap = new java.util.HashMap<String, ObjectStore>(); + private final java.util.Map<String, String> _facetTypes; + protected final Ice.ObjectAdapter _adapter; protected final Ice.Communicator _communicator; @@ -601,11 +585,10 @@ abstract class EvictorI implements Evictor protected int _txTrace = 0; protected String _errorPrefix; - - protected boolean _deadlockWarning; - + + protected boolean _deadlockWarning; + protected DeactivateController _deactivateController = new DeactivateController(); private Ice.Object _pingObject = new PingObject(); - } diff --git a/java/src/Freeze/EvictorIteratorI.java b/java/src/Freeze/EvictorIteratorI.java index 98bacdde010..be011a906c7 100644 --- a/java/src/Freeze/EvictorIteratorI.java +++ b/java/src/Freeze/EvictorIteratorI.java @@ -14,7 +14,7 @@ class EvictorIteratorI implements EvictorIterator public boolean hasNext() { - if(_batchIterator != null && _batchIterator.hasNext()) + if(_batchIterator != null && _batchIterator.hasNext()) { return true; } @@ -30,69 +30,66 @@ class EvictorIteratorI implements EvictorIterator { if(hasNext()) { - return (Ice.Identity)_batchIterator.next(); + return _batchIterator.next(); } else { throw new NoSuchElementException(); } } - + EvictorIteratorI(ObjectStore store, TransactionI tx, int batchSize) { _store = store; _more = (store != null); _batchSize = batchSize; _tx = tx; - + assert batchSize > 0; _key.setReuseBuffer(true); // - // dlen is 0, so we should not retrieve any value - // + // dlen is 0, so we should not retrieve any value + // _value.setPartial(true); } - private java.util.Iterator + private java.util.Iterator<Ice.Identity> nextBatch() { EvictorI.DeactivateController deactivateController = _store.evictor().deactivateController(); deactivateController.lock(); - + com.sleepycat.db.Transaction txn = _tx == null ? null : _tx.dbTxn(); - + try { - if(!_more) { return null; } - - java.util.List evictorElements = null; - + Ice.Communicator communicator = _store.communicator(); - + byte[] firstKey = null; if(_key.getSize() > 0) { firstKey = new byte[_key.getSize()]; System.arraycopy(_key.getData(), 0, firstKey, 0, firstKey.length); } - + for(;;) { com.sleepycat.db.Cursor dbc = null; - - _batch = new java.util.ArrayList(); - + + _batch = new java.util.ArrayList<Ice.Identity>(); + try { // // Move to the first record - // + // boolean range = false; if(firstKey != null) { @@ -102,9 +99,9 @@ class EvictorIteratorI implements EvictorIterator // range = true; } - + dbc = _store.db().openCursor(txn, null); - + boolean done = false; do { @@ -118,11 +115,11 @@ class EvictorIteratorI implements EvictorIterator status = dbc.getNext(_key, _value, null); } _more = (status == com.sleepycat.db.OperationStatus.SUCCESS); - + if(_more) { range = false; - + if(_batch.size() < _batchSize) { Ice.Identity ident = ObjectStore.unmarshalKey(_key.getData(), communicator); @@ -138,7 +135,7 @@ class EvictorIteratorI implements EvictorIterator } } while(!done && _more); - + break; // for (;;) } catch(com.sleepycat.db.DeadlockException dx) @@ -146,10 +143,10 @@ class EvictorIteratorI implements EvictorIterator if(_store.evictor().deadlockWarning()) { communicator.getLogger().warning("Deadlock in Freeze.EvictorIteratorI.load while " + - "iterating over Db \"" + _store.evictor().filename() + "/" + _store.dbName() + - "\""); + "iterating over Db \"" + _store.evictor().filename() + "/" + + _store.dbName() + "\""); } - + if(_tx == null) { if(firstKey != null) @@ -162,7 +159,7 @@ class EvictorIteratorI implements EvictorIterator { _key.setSize(0); } - + // // Retry // @@ -209,7 +206,7 @@ class EvictorIteratorI implements EvictorIterator } } } - + if(_batch.size() == 0) { return null; @@ -228,10 +225,10 @@ class EvictorIteratorI implements EvictorIterator private final ObjectStore _store; private final TransactionI _tx; private final int _batchSize; - private java.util.Iterator _batchIterator; + private java.util.Iterator<Ice.Identity> _batchIterator; private final com.sleepycat.db.DatabaseEntry _key = new com.sleepycat.db.DatabaseEntry(); private final com.sleepycat.db.DatabaseEntry _value = new com.sleepycat.db.DatabaseEntry(); - private java.util.List _batch = null; + private java.util.List<Ice.Identity> _batch = null; private boolean _more = true; } diff --git a/java/src/Freeze/Index.java b/java/src/Freeze/Index.java index 86fb253f3bc..8a98ca8e9d3 100644 --- a/java/src/Freeze/Index.java +++ b/java/src/Freeze/Index.java @@ -14,7 +14,7 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator // // Implementation details // - + public boolean createSecondaryKey(com.sleepycat.db.SecondaryDatabase secondary, com.sleepycat.db.DatabaseEntry key, @@ -53,15 +53,15 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator return _facet; } - protected Index(String name, String facet) + protected + Index(String name, String facet) { _name = name; _facet = facet; } - protected abstract byte[] - marshalKey(Ice.Object servant); - + protected abstract byte[] marshalKey(Ice.Object servant); + protected Ice.Identity[] untypedFindFirst(byte[] k, int firstN) { @@ -70,42 +70,43 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator try { com.sleepycat.db.DatabaseEntry key = new com.sleepycat.db.DatabaseEntry(k); - + + // // When we have a custom-comparison function, Berkeley DB returns // the key on-disk (when it finds one). We disable this behavior: // (ref Oracle SR 5925672.992) // key.setPartial(true); - + com.sleepycat.db.DatabaseEntry pkey = new com.sleepycat.db.DatabaseEntry(); com.sleepycat.db.DatabaseEntry value = new com.sleepycat.db.DatabaseEntry(); // - // dlen is 0, so we should not retrieve any value - // + // dlen is 0, so we should not retrieve any value + // value.setPartial(true); - + Ice.Communicator communicator = _store.communicator(); TransactionI transaction = _store.evictor().beforeQuery(); com.sleepycat.db.Transaction tx = transaction == null ? null : transaction.dbTxn(); - java.util.List identities; - + java.util.List<Ice.Identity> identities; + for(;;) { com.sleepycat.db.SecondaryCursor dbc = null; - identities = new java.util.ArrayList(); - + identities = new java.util.ArrayList<Ice.Identity>(); + try { // // Move to the first record - // + // dbc = _db.openSecondaryCursor(tx, null); boolean first = true; - + boolean found; - + do { com.sleepycat.db.OperationStatus status; @@ -117,9 +118,9 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator { status = dbc.getNextDup(key, pkey, value, null); } - + found = status == com.sleepycat.db.OperationStatus.SUCCESS; - + if(found) { Ice.Identity ident = ObjectStore.unmarshalKey(pkey.getData(), communicator); @@ -128,7 +129,7 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator } } while((firstN <= 0 || identities.size() < firstN) && found); - + break; // for(;;) } catch(com.sleepycat.db.DeadlockException dx) @@ -139,7 +140,7 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator "iterating over Db \"" + _store.evictor().filename() + "/" + _dbName + "\""); } - + if(tx != null) { DeadlockException ex = new DeadlockException( @@ -147,7 +148,7 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator ex.initCause(dx); throw ex; } - + // // Otherwise retry // @@ -186,11 +187,11 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator } } } - + if(identities.size() != 0) { Ice.Identity[] result = new Ice.Identity[identities.size()]; - return (Ice.Identity[])identities.toArray(result); + return identities.toArray(result); } else { @@ -202,7 +203,7 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator deactivateController.unlock(); } } - + protected Ice.Identity[] untypedFind(byte[] key) { @@ -216,29 +217,29 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator deactivateController.lock(); try { - com.sleepycat.db.DatabaseEntry key = new com.sleepycat.db.DatabaseEntry(k); - + + // // When we have a custom-comparison function, Berkeley DB returns // the key on-disk (when it finds one). We disable this behavior: // (ref Oracle SR 5925672.992) // key.setPartial(true); - + com.sleepycat.db.DatabaseEntry value = new com.sleepycat.db.DatabaseEntry(); // - // dlen is 0, so we should not retrieve any value - // + // dlen is 0, so we should not retrieve any value + // value.setPartial(true); TransactionI transaction = _store.evictor().beforeQuery(); com.sleepycat.db.Transaction tx = transaction == null ? null : transaction.dbTxn(); - + for(;;) { com.sleepycat.db.Cursor dbc = null; try { - dbc = _db.openCursor(tx, null); + dbc = _db.openCursor(tx, null); if(dbc.getSearchKey(key, value, null) == com.sleepycat.db.OperationStatus.SUCCESS) { return dbc.count(); @@ -254,8 +255,7 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator { _store.communicator().getLogger().warning("Deadlock in Freeze.Index.untypedCount while " + "iterating over Db \"" + - _store.evictor().filename() + "/" + _dbName + - "\""); + _store.evictor().filename() + "/" + _dbName + "\""); } if(tx != null) @@ -309,20 +309,20 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator deactivateController.unlock(); } } - + protected final Ice.Communicator communicator() { return _store.communicator(); } - + void associate(ObjectStore store, com.sleepycat.db.Transaction txn, boolean createDb, boolean populateIndex) throws com.sleepycat.db.DatabaseException, java.io.FileNotFoundException { assert(txn != null); _store = store; - + _dbName = EvictorI.indexPrefix + store.dbName() + "." + _name; com.sleepycat.db.SecondaryConfig config = new com.sleepycat.db.SecondaryConfig(); @@ -334,18 +334,19 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator Ice.Properties properties = store.evictor().communicator().getProperties(); String propPrefix = "Freeze.Evictor." + store.evictor().filename() + "."; - + int btreeMinKey = properties.getPropertyAsInt(propPrefix + _dbName + ".BtreeMinKey"); if(btreeMinKey > 2) { if(store.evictor().trace() >= 1) { store.evictor().communicator().getLogger().trace( - "Freeze.Evictor", "Setting \"" + store.evictor().filename() + "." + _dbName + "\"'s btree minkey to " + btreeMinKey); + "Freeze.Evictor", "Setting \"" + store.evictor().filename() + "." + _dbName + + "\"'s btree minkey to " + btreeMinKey); } config.setBtreeMinKey(btreeMinKey); } - + boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0; if(checksum) { @@ -354,7 +355,7 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator // config.setChecksum(true); } - + // // Can't change page size // @@ -379,10 +380,10 @@ public abstract class Index implements com.sleepycat.db.SecondaryKeyCreator ex.message = _store.evictor().errorPrefix() + "Db.close: " + dx.getMessage(); throw ex; } - _db = null; + _db = null; } } - + private final String _name; private final String _facet; private String _dbName; diff --git a/java/src/Freeze/LinkedList.java b/java/src/Freeze/LinkedList.java index c4457255527..36ef4e8cb50 100644 --- a/java/src/Freeze/LinkedList.java +++ b/java/src/Freeze/LinkedList.java @@ -20,7 +20,7 @@ package Freeze; // retained over structural changes to the list itself (similar to an // STL list). // -public class LinkedList +public class LinkedList<T> { public LinkedList() @@ -28,7 +28,7 @@ public class LinkedList _header.next = _header.previous = _header; } - public java.lang.Object + public T getFirst() { if(_size == 0) @@ -39,7 +39,7 @@ public class LinkedList return _header.next.element; } - public java.lang.Object + public T getLast() { if(_size == 0) @@ -51,11 +51,11 @@ public class LinkedList } public void - addFirst(java.lang.Object o) + addFirst(T o) { addBefore(o, _header.next); } - + public boolean isEmpty() { @@ -68,19 +68,19 @@ public class LinkedList return _size; } - public java.util.Iterator + public java.util.Iterator<T> iterator() { return new ForwardIterator(); } - public java.util.Iterator + public java.util.Iterator<T> riterator() { return new ReverseIterator(); } - private class ForwardIterator implements java.util.Iterator + private class ForwardIterator implements java.util.Iterator<T> { public boolean hasNext() @@ -88,7 +88,7 @@ public class LinkedList return _next != null; } - public java.lang.Object + public T next() { if(_next == null) @@ -133,11 +133,11 @@ public class LinkedList _current = null; } - private Entry _current; - private Entry _next; + private Entry<T> _current; + private Entry<T> _next; } - private class ReverseIterator implements java.util.Iterator + private class ReverseIterator implements java.util.Iterator<T> { public boolean hasNext() @@ -145,7 +145,7 @@ public class LinkedList return _next != null; } - public java.lang.Object + public T next() { if(_next == null) @@ -190,17 +190,17 @@ public class LinkedList _current = null; } - private Entry _current; - private Entry _next; + private Entry<T> _current; + private Entry<T> _next; } - private static class Entry + private static class Entry<T> { - java.lang.Object element; - Entry next; - Entry previous; + T element; + Entry<T> next; + Entry<T> previous; - Entry(java.lang.Object element, Entry next, Entry previous) + Entry(T element, Entry<T> next, Entry<T> previous) { this.element = element; this.next = next; @@ -208,10 +208,10 @@ public class LinkedList } } - private Entry - addBefore(java.lang.Object o, Entry e) + private Entry<T> + addBefore(T o, Entry<T> e) { - Entry newEntry = new Entry(o, e, e.previous); + Entry<T> newEntry = new Entry<T>(o, e, e.previous); newEntry.previous.next = newEntry; newEntry.next.previous = newEntry; _size++; @@ -219,7 +219,7 @@ public class LinkedList } private void - remove(Entry e) + remove(Entry<T> e) { if(e == _header) { @@ -231,6 +231,6 @@ public class LinkedList _size--; } - private Entry _header = new Entry(null, null, null); + private Entry<T> _header = new Entry<T>(null, null, null); private int _size = 0; } diff --git a/java/src/Freeze/Map.java b/java/src/Freeze/Map.java index 282a533c6e0..5769b1e2a79 100644 --- a/java/src/Freeze/Map.java +++ b/java/src/Freeze/Map.java @@ -9,2490 +9,39 @@ package Freeze; -public abstract class Map extends java.util.AbstractMap - implements java.util.SortedMap, KeyCodec +public interface Map<K, V> extends NavigableMap<K, V> { - public abstract byte[] encodeValue(Object o, Ice.Communicator communicator); - public abstract Object decodeValue(byte[] b, Ice.Communicator communicator); - - protected - Map(Connection connection, String dbName, String key, String value, - boolean createDb, java.util.Comparator comparator) - { - _connection = (ConnectionI)connection; - _dbName = dbName; - _comparator = (comparator == null) ? null : new Comparator(comparator); - - _errorPrefix = "Freeze DB DbEnv(\"" + _connection.envName() + "\") Db(\"" + dbName + "\"): "; - _trace = _connection.trace(); - - init(null, dbName, key, value, createDb, null); - } - - protected - Map(Connection connection, String dbName, java.util.Comparator comparator) - { - _connection = (ConnectionI)connection; - _dbName = dbName; - _comparator = (comparator == null) ? null : new Comparator(comparator); - - _errorPrefix = "Freeze DB DbEnv(\"" + _connection.envName() + "\") Db(\"" + dbName + "\"): "; - _trace = _connection.trace(); - } - - - protected static void - recreate(Map map, String dbName, String key, String value, - Freeze.Map.Index[] indices, java.util.Map indexComparators) - { - ConnectionI connection = map._connection; - String envName = connection.dbEnv().getEnvName(); - - if(dbName.equals(Util.catalogName()) || dbName.equals(Util.catalogIndexListName())) - { - throw new DatabaseException(errorPrefix(envName, dbName) + "You cannot recreate the \"" - + dbName + "\" database"); - } - - if(connection.trace() >= 1) - { - connection.communicator().getLogger().trace("Freeze.Map", - "Recreating \"" + dbName + "\""); - } - - Transaction tx = connection.currentTransaction(); - boolean ownTx = (tx == null); - - com.sleepycat.db.DatabaseEntry keyEntry = new com.sleepycat.db.DatabaseEntry(); - com.sleepycat.db.DatabaseEntry valueEntry = new com.sleepycat.db.DatabaseEntry(); - - com.sleepycat.db.Database oldDb = null; - MapDb newDb = null; - - for(;;) - { - try - { - if(ownTx) - { - tx = null; - tx = connection.beginTransaction(); - } - - com.sleepycat.db.Transaction txn = connection.dbTxn(); - - if(connection.trace() >= 2) - { - connection.communicator().getLogger().trace( - "Freeze.Map", "Removing all existing indices for \"" + dbName + "\""); - } - CatalogIndexList catalogIndexList = new CatalogIndexList(connection, Util.catalogIndexListName(), true); - String[] oldIndices = (String[])catalogIndexList.remove(dbName); - - - if(oldIndices != null) - { - for(int i = 0; i < oldIndices.length; ++i) - { - try - { - connection.removeMapIndex(dbName, oldIndices[i]); - } - catch(IndexNotFoundException e) - { - // - // Ignored - // - } - } - } - - // - // Rename existing database - // - String oldDbName = dbName + ".old-" + java.util.UUID.randomUUID().toString(); - - if(connection.trace() >= 2) - { - connection.communicator().getLogger().trace( - "Freeze.Map", "Renaming \"" + dbName + "\" to \"" + oldDbName + "\""); - } - - connection.dbEnv().getEnv().renameDatabase(txn, dbName, null, oldDbName); - - com.sleepycat.db.DatabaseConfig oldDbConfig = new com.sleepycat.db.DatabaseConfig(); - oldDbConfig.setType(com.sleepycat.db.DatabaseType.BTREE); - - oldDb = connection.dbEnv().getEnv().openDatabase(txn, oldDbName, null, oldDbConfig); - - newDb = new MapDb(connection, dbName, key, value, map._comparator, indices, indexComparators, true); - map.init(newDb, indices); - - - if(connection.trace() >= 2) - { - connection.communicator().getLogger().trace( - "Freeze.Map", "Writing contents of \"" + oldDbName + "\" to fresh \"" + dbName + "\""); - } - - // - // Now simply write all of oldDb into newDb - // - com.sleepycat.db.Cursor dbc = null; - try - { - dbc = oldDb.openCursor(txn, null); - - while(dbc.getNext(keyEntry, valueEntry, null) == com.sleepycat.db.OperationStatus.SUCCESS) - { - newDb.db().put(txn, keyEntry, valueEntry); - } - } - finally - { - if(dbc != null) - { - dbc.close(); - } - } - - if(connection.trace() >= 2) - { - connection.communicator().getLogger().trace( - "Freeze.Map", "Transfer complete; removing \"" + oldDbName + "\""); - } - connection.dbEnv().getEnv().removeDatabase(txn, oldDbName, null); - - if(ownTx) - { - try - { - tx.commit(); - } - finally - { - tx = null; - } - } - - break; // for (;;) - } - catch(com.sleepycat.db.DeadlockException dx) - { - if(ownTx) - { - if(connection.deadlockWarning()) - { - connection.communicator().getLogger().warning( - "Deadlock in Freeze.Map.recreate on Db \"" - + dbName + "\"; retrying ..."); - } - - // - // Ignored, try again - // - } - else - { - DeadlockException ex = new DeadlockException( - errorPrefix(envName, dbName) + "Map.recreate: " + dx.getMessage(), tx); - ex.initCause(dx); - throw ex; - } - } - catch(com.sleepycat.db.DatabaseException dx) - { - DatabaseException ex = new DatabaseException(errorPrefix(envName, dbName) + "Map.recreate: " + dx.getMessage()); - ex.initCause(dx); - throw ex; - } - catch(java.io.FileNotFoundException fne) - { - DatabaseException ex = new DatabaseException(errorPrefix(envName, dbName) + "Map.recreate: " + fne.getMessage()); - ex.initCause(fne); - throw ex; - } - finally - { - if(ownTx && tx != null) - { - try - { - tx.rollback(); - } - catch(DatabaseException de) - { - } - } - - try - { - if(newDb != null) - { - newDb.close(); - } - - if(oldDb != null) - { - try - { - oldDb.close(); - } - catch(com.sleepycat.db.DatabaseException dx) - { - DatabaseException ex = new DatabaseException( - errorPrefix(envName, dbName) + "Map.recreate: " + dx.getMessage()); - ex.initCause(dx); - throw ex; - } - } - } - finally - { - newDb = null; - oldDb = null; - } - } - } - } - - - protected void - init(Freeze.Map.Index[] indices, String dbName, - String key, String value, boolean createDb, java.util.Map indexComparators) - { - init(_connection.dbEnv().getSharedMapDb(dbName, key, value, _comparator, indices, indexComparators, createDb), - indices); - } - - protected void - init(MapDb db, Freeze.Map.Index[] indices) - { - _db = db; - _token = _connection.registerMap(this); - - if(indices != null) - { - for(int i = 0; i < indices.length; ++i) - { - _indexMap.put(indices[i].name(), indices[i]); - } - } - } - - public void - close() - { - close(false); - } - - public void - closeDb() - { - close(false); - _connection.dbEnv().removeSharedMapDb(_dbName); - } - - public Connection - getConnection() - { - return _connection; - } - // - // SortedMap methods + // Faster alternative to the standard put() method because it + // doesn't read and decode the old value. // + void fastPut(K key, V value); - public java.util.Comparator - comparator() - { - if(_comparator == null) - { - return null; - } - else - { - // - // Return's the user's comparator, not the DB comparator. - // - return _comparator.comparator(); - } - } - - public Object firstKey() - { - return firstKey(null, null); - } - - public Object lastKey() - { - return lastKey(null, null); - } - - Object firstKey(Object fromKey, Object toKey) - { - byte[] fk = fromKey == null ? null : - encodeKey(fromKey, _connection.communicator()); - - byte[] k = getFirstOrLastKey(_db.db(), _db.dbName(), fk, true); - if(k == null) - { - throw new NoSuchElementException(); - } - else - { - Object key = decodeKey(k, _connection.communicator()); - if(toKey != null && comparator().compare(key, toKey) >= 0) - { - throw new NoSuchElementException(); - } - return key; - } - } - - Object lastKey(Object fromKey, Object toKey) - { - byte[] tk = toKey == null ? null : - encodeKey(toKey, _connection.communicator()); - - byte[] k = getFirstOrLastKey(_db.db(), _db.dbName(), tk, false); - if(k == null) - { - throw new NoSuchElementException(); - } - else - { - Object key = decodeKey(k, _connection.communicator()); - if(fromKey != null && comparator().compare(fromKey, key) > 0) - { - throw new NoSuchElementException(); - } - return key; - } - } - - public java.util.SortedMap headMap(Object toKey) - { - if(toKey == null) - { - throw new NullPointerException(); - } - if(_comparator == null) - { - throw new UnsupportedOperationException(); - } - - return new SubMap(this, null, toKey); - } - - public java.util.SortedMap tailMap(Object fromKey) - { - if(fromKey == null) - { - throw new NullPointerException(); - } - if(_comparator == null) - { - throw new UnsupportedOperationException(); - } + void close(); - return new SubMap(this, fromKey, null); - } - - public java.util.SortedMap subMap(Object fromKey, Object toKey) - { - if(fromKey == null || toKey == null ) - { - throw new NullPointerException(); - } - if(_comparator == null) - { - throw new UnsupportedOperationException(); - } - return new SubMap(this, fromKey, toKey); - } - - // - // Additional non-standard xxMapForIndex methods + // Close all iterators for this map. Returns the number of + // iterators that were closed. // - public java.util.SortedMap headMapForIndex(String indexName, Object toKey) - { - if(toKey == null) - { - throw new NullPointerException(); - } - - Map.Index index = _indexMap.get(indexName); - if(index == null) - { - throw new IllegalArgumentException("Can't find index '" + indexName + "'"); - } - else if(index.comparator() == null) - { - throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator"); - } - return new SubMap(index, null, toKey); - } - - public java.util.SortedMap tailMapForIndex(String indexName, Object fromKey) - { - if(fromKey == null) - { - throw new NullPointerException(); - } - Map.Index index = _indexMap.get(indexName); - if(index == null) - { - throw new IllegalArgumentException("Can't find index '" + indexName + "'"); - } - else if(index.comparator() == null) - { - throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator"); - } - return new SubMap(index, fromKey, null); - } - - public java.util.SortedMap subMapForIndex(String indexName, Object fromKey, Object toKey) - { - if(fromKey == null || toKey == null ) - { - throw new NullPointerException(); - } - Map.Index index = _indexMap.get(indexName); - if(index == null) - { - throw new IllegalArgumentException("Can't find index '" + indexName + "'"); - } - else if(index.comparator() == null) - { - throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator"); - } - return new SubMap(index, fromKey, toKey); - } - - public java.util.SortedMap mapForIndex(String indexName) - { - Map.Index index = _indexMap.get(indexName); - if(index == null) - { - throw new IllegalArgumentException("Can't find index '" + indexName + "'"); - } - else if(index.comparator() == null) - { - throw new IllegalArgumentException("Index '" + indexName + "' has no user-defined comparator"); - } - return new SubMap(index, null, null); - } - - // - // Plain Map methods - // - public int - size() - { - if(_db == null) - { - DatabaseException ex = new DatabaseException(); - ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed"; - throw ex; - } - - // - // The number of records cannot be cached and then adjusted by - // the member functions since the map would no longer work in - // the presence of transactions - if a record is added (and - // the size adjusted) and the transaction aborted then the - // cached map size() would be incorrect. - // - - // - // TODO: DB_FAST_STAT doesn't seem to do what the - // documentation says... - // - try - { - com.sleepycat.db.StatsConfig config = new com.sleepycat.db.StatsConfig(); - // - // TODO: DB_FAST_STAT doesn't seem to do what the - // documentation says... - // - //config.setFast(true); - com.sleepycat.db.BtreeStats s = (com.sleepycat.db.BtreeStats)_db.db().getStats(null, config); - return s.getNumData(); - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Db.stat: " + e.getMessage(); - throw ex; - } - } - - public boolean - containsValue(Object value) - { - for(;;) - { - EntryIterator p = null; - try - { - p = (EntryIterator)entrySet().iterator(); - - if(value == null) - { - while(p.hasNext()) - { - Entry e = (Entry)p.next(); - if(e.getValue() == null) - { - return true; - } - } - } - else - { - while(p.hasNext()) - { - Entry e = (Entry)p.next(); - if(value.equals(e.getValue())) - { - return true; - } - } - } - return false; - } - catch(DeadlockException e) - { - if(_connection.dbTxn() != null) - { - throw e; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.containsValue while " + - "iterating over Db \"" + _db.dbName() + - "\"; retrying..."); - } - - // - // Try again - // - } - } - finally - { - if(p != null) - { - p.close(); - } - } - } - } - - public boolean - containsKey(Object key) - { - if(_db == null) - { - DatabaseException ex = new DatabaseException(); - ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed"; - throw ex; - } - - byte[] k = encodeKey(key, _connection.communicator()); - - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); - dbValue.setPartial(true); - - if(_trace >= 2) - { - _connection.communicator().getLogger().trace("Freeze.Map", "checking key in Db \"" + _db.dbName() + "\""); - } - - for(;;) - { - try - { - return _db.db().get(_connection.dbTxn(), dbKey, dbValue, null) - == com.sleepycat.db.OperationStatus.SUCCESS; - } - catch(com.sleepycat.db.DeadlockException e) - { - if(_connection.dbTxn() != null) - { - DeadlockException ex = new DeadlockException( - _errorPrefix + "Db.get: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning( - "Deadlock in Freeze.Map.containsKey while " + - "reading Db \"" + _db.dbName() + - "\"; retrying..."); - } - // - // Try again - // - } - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Db.get: " + e.getMessage(); - throw ex; - } - } - } - - public Object - get(Object key) - { - byte[] k = encodeKey(key, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - byte[] v = getImpl(dbKey); - if(v == null) - { - return null; - } - else - { - return decodeValue(v, _connection.communicator()); - } - } - - public Object - put(Object key, Object value) - { - byte[] k = encodeKey(key, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - byte[] v = getImpl(dbKey); - Object o = null; - if(v != null) - { - o = decodeValue(v, _connection.communicator()); - } - putImpl(dbKey, value); - return o; - } - - public Object - remove(Object key) - { - byte[] k = encodeKey(key, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - byte[] v = getImpl(dbKey); - - if(v != null && removeImpl(dbKey)) - { - return decodeValue(v, _connection.communicator()); - } - else - { - return null; - } - } - - // - // Proprietary API calls. These are much faster than the - // corresponding Java collections API methods since the unwanted - // reads are avoided. - // - public void - fastPut(Object key, Object value) - { - byte[] k = encodeKey(key, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - putImpl(dbKey, value); - } + int closeAllIterators(); // - // Returns true if the record was removed, false otherwise. + // Close this map and destroy the underlying Berkeley DB database. // - public boolean - fastRemove(Object key) - { - byte[] k = encodeKey(key, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - return removeImpl(dbKey); - } - - public void - clear() - { - if(_db == null) - { - DatabaseException ex = new DatabaseException(); - ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed"; - throw ex; - } - - com.sleepycat.db.Transaction txn = _connection.dbTxn(); - - for(;;) - { - try - { - _db.db().truncate(txn, false); - break; - } - catch(com.sleepycat.db.DeadlockException e) - { - if(txn != null) - { - DeadlockException ex = new DeadlockException( - _errorPrefix + "Db.truncate: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.clear on Db \"" + - _db.dbName() + "\"; retrying..."); - } - - // - // Try again - // - } - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Db.truncate: " + e.getMessage(); - throw ex; - } - } - } - - public java.util.Set - entrySet() - { - if(_entrySet == null) - { - _entrySet = new java.util.AbstractSet() - { - public java.util.Iterator - iterator() - { - return new EntryIteratorImpl(null, null, null, false, false); - } - - public boolean - contains(Object o) - { - if(!(o instanceof Map.Entry)) - { - return false; - } - Map.Entry entry = (Map.Entry)o; - Object value = entry.getValue(); - - byte[] v = getImpl(entry.getDbKey()); - return v != null && valEquals(decodeValue(v, _connection.communicator()), value); - } - - public boolean - remove(Object o) - { - if(!(o instanceof Map.Entry)) - { - return false; - } - Map.Entry entry = (Map.Entry)o; - Object value = entry.getValue(); - - byte[] v = getImpl(entry.getDbKey()); - if(v != null && valEquals(decodeValue(v, _connection.communicator()), value)) - { - return removeImpl(entry.getDbKey()); - } - return false; - } - - public int - size() - { - return Map.this.size(); - } - - public void - clear() - { - Map.this.clear(); - } - }; - } - - return _entrySet; - } - - public void - closeAllIterators() - { - closeAllIteratorsExcept(null, false); - } - - - // - // Close this map and destroy the underlying Berkeley DB database - // - public void destroy() - { - if(_db == null) - { - throw new DatabaseException(_errorPrefix + "This map is closed"); - } - - String dbName = _db.dbName(); - - if(dbName.equals(Util.catalogName()) || dbName.equals(Util.catalogIndexListName())) - { - throw new DatabaseException(_errorPrefix + "You cannot destroy the \"" + dbName + "\" database"); - } - - if(_connection.currentTransaction() != null) - { - throw new DatabaseException(_errorPrefix + "You cannot destroy a database within an active transaction"); - } - - if(_trace >= 1) - { - _connection.communicator().getLogger().trace("Freeze.Map", "destroying \"" + dbName + "\""); - } - - closeDb(); - - for(;;) - { - Transaction tx = null; - try - { - tx = _connection.beginTransaction(); - com.sleepycat.db.Transaction txn = _connection.dbTxn(); - - - Catalog catalog = new Catalog(_connection, Util.catalogName(), true); - catalog.remove(dbName); - - CatalogIndexList catalogIndexList = new CatalogIndexList(_connection, Util.catalogIndexListName(), true); - catalogIndexList.remove(dbName); - - _connection.dbEnv().getEnv().removeDatabase(txn, dbName, null); - - // - // Remove all indices - // - for(String index : _indexMap.keySet()) - { - _connection.removeMapIndex(dbName, index); - - } - - tx.commit(); - - break; // for(;;) - } - catch(java.io.FileNotFoundException dx) - { - try - { - tx.rollback(); - } - catch(DatabaseException e) - { - } - - DatabaseException e = new DatabaseException(_errorPrefix + "file not found"); - e.initCause(dx); - throw e; - } - catch(com.sleepycat.db.DeadlockException dx) - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.destroy on Db \"" + - dbName + "\"; retrying..."); - } - - // - // Ignored, try again - // - } - catch(com.sleepycat.db.DatabaseException dx) - { - try - { - tx.rollback(); - } - catch(DatabaseException e) - { - } - - DatabaseException e = new DatabaseException(_errorPrefix + dx.getMessage()); - e.initCause(dx); - throw e; - } - catch(RuntimeException rx) - { - try - { - tx.rollback(); - } - catch(DatabaseException e) - { - } - - throw rx; - } - } - } - - - void - closeAllIteratorsExcept(Object except, boolean finalizing) - { - synchronized(_iteratorList) - { - java.util.Iterator p = _iteratorList.iterator(); - - while(p.hasNext()) - { - Object obj = p.next(); - if(obj != except) - { - ((EntryIteratorImpl)obj).close(finalizing); - } - } - } - } - - protected void - finalize() - { - close(true); - } - - // - // The synchronization is only needed when finalizing is true - // - void - close(boolean finalizing) - { - synchronized(_connection) - { - if(_db != null) - { - try - { - closeAllIteratorsExcept(null, finalizing); - } - finally - { - _db = null; - _connection.unregisterMap(_token); - _token = null; - } - } - } - } - - EntryIterator - createIterator(Index index, Object fromKey, Object toKey) - { - KeyCodec codec = index == null ? (KeyCodec)this : (KeyCodec)index; - - Ice.Communicator communicator = _connection.getCommunicator(); - - return new EntryIteratorImpl(index, - fromKey == null ? null : codec.encodeKey(fromKey, communicator), - toKey == null ? null : codec.encodeKey(toKey, communicator), - false, true); - } - - ConnectionI connection() - { - return _connection; - } - - private static String - errorPrefix(String envName, String dbName) - { - return "Freeze DB DbEnv(\"" + envName + "\") Db(\"" + dbName + "\"): "; - } - - private static boolean - valEquals(Object o1, Object o2) - { - return (o1 == null ? o2 == null : o1.equals(o2)); - } - - private byte[] - getFirstOrLastKey(com.sleepycat.db.Database db, String dbName, byte[] key, boolean first) - { - if(db == null) - { - DatabaseException ex = new DatabaseException(); - ex.message = _errorPrefix + "\"" + dbName + "\" has been closed"; - throw ex; - } - - if(_trace >= 2) - { - _connection.communicator().getLogger().trace("Freeze.Map", "searching Db \"" + dbName + "\""); - } - - com.sleepycat.db.DatabaseEntry dbKey = key == null ? - new com.sleepycat.db.DatabaseEntry(): - new com.sleepycat.db.DatabaseEntry(key); - - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); - dbValue.setPartial(true); // not interested in value - - try - { - for(;;) - { - com.sleepycat.db.Cursor dbc = null; - try - { - dbc = db.openCursor(_connection.dbTxn(), null); - com.sleepycat.db.OperationStatus status; - - if(key == null) - { - status = first ? - dbc.getFirst(dbKey, dbValue, null) : dbc.getLast(dbKey, dbValue, null); - } - else if(first) - { - status = dbc.getSearchKeyRange(dbKey, dbValue, null); - } - else - { - status = dbc.getSearchKeyRange(dbKey, dbValue, null); - - if(status == com.sleepycat.db.OperationStatus.SUCCESS) - { - // - // goto the previous pair, which must be < key - // - status = dbc.getPrevNoDup(dbKey, dbValue, null); - } - else if(status == com.sleepycat.db.OperationStatus.NOTFOUND) - { - // - // All keys < desired toKey, so we pick the largest of - // all, the last one - // - status = dbc.getLast(dbKey, dbValue, null); - } - } - - if(status == com.sleepycat.db.OperationStatus.SUCCESS) - { - return dbKey.getData(); - } - else - { - return null; - } - } - catch(com.sleepycat.db.DeadlockException dx) - { - if(_connection.dbTxn() != null) - { - DeadlockException ex = new DeadlockException( - _errorPrefix + "Dbc.getXXX: " + dx.getMessage(), _connection.currentTransaction()); - ex.initCause(dx); - throw ex; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning( - "Deadlock in Freeze.Map while searching \"" + db.getDatabaseName() + - "\"; retrying..."); - } - - // - // Retry - // - } - } - finally - { - if(dbc != null) - { - try - { - dbc.close(); - } - catch(com.sleepycat.db.DeadlockException dx) - { - // - // Ignored - // - } - } - } - } - } - catch(com.sleepycat.db.DatabaseException dx) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(dx); - ex.message = _errorPrefix + "Db.openCursor/Dbc.getXXX: " + dx.getMessage(); - throw ex; - } - } - - private byte[] - getImpl(com.sleepycat.db.DatabaseEntry dbKey) - { - if(_db == null) - { - DatabaseException ex = new DatabaseException(); - ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed"; - throw ex; - } - - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); - - if(_trace >= 2) - { - _connection.communicator().getLogger().trace("Freeze.Map", "reading value from Db \"" + _db.dbName() + - "\""); - } - - for(;;) - { - try - { - com.sleepycat.db.OperationStatus rc = _db.db().get(_connection.dbTxn(), dbKey, dbValue, null); - if(rc == com.sleepycat.db.OperationStatus.SUCCESS) - { - return dbValue.getData(); - } - else - { - return null; - } - } - catch(com.sleepycat.db.DeadlockException e) - { - if(_connection.dbTxn() != null) - { - DeadlockException ex = new DeadlockException( - _errorPrefix + "Db.get: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.getImpl while " + - "reading Db \"" + _db.dbName() + - "\"; retrying..."); - } - - // - // Try again - // - } - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Db.get: " + e.getMessage(); - throw ex; - } - } - } - - private void - putImpl(com.sleepycat.db.DatabaseEntry dbKey, Object value) - { - if(_db == null) - { - DatabaseException ex = new DatabaseException(); - ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed"; - throw ex; - } - - byte[] v = encodeValue(value, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v); - - if(_trace >= 2) - { - _connection.communicator().getLogger().trace("Freeze.Map", "writing value in Db \"" + _db.dbName() + "\""); - } - - com.sleepycat.db.Transaction txn = _connection.dbTxn(); - if(txn == null) - { - closeAllIterators(); - } - - for(;;) - { - try - { - _db.db().put(txn, dbKey, dbValue); - break; - } - catch(com.sleepycat.db.DeadlockException e) - { - if(txn != null) - { - DeadlockException ex = new DeadlockException( - _errorPrefix + "Db.put: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.putImpl while " + - "writing into Db \"" + _db.dbName() + - "\"; retrying..."); - } - - // - // Try again - // - } - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Db.put: " + e.getMessage(); - throw ex; - } - } - } - - private boolean - removeImpl(com.sleepycat.db.DatabaseEntry dbKey) - { - if(_db == null) - { - DatabaseException ex = new DatabaseException(); - ex.message = _errorPrefix + "\"" + _db.dbName() + "\" has been closed"; - throw ex; - } - - if(_trace >= 2) - { - _connection.communicator().getLogger().trace("Freeze.Map", "deleting value from Db \"" + _db.dbName() + - "\""); - } - - com.sleepycat.db.Transaction txn = _connection.dbTxn(); - if(txn == null) - { - closeAllIterators(); - } - - for(;;) - { - try - { - com.sleepycat.db.OperationStatus rc = _db.db().delete(txn, dbKey); - return (rc == com.sleepycat.db.OperationStatus.SUCCESS); - } - catch(com.sleepycat.db.DeadlockException e) - { - if(txn != null) - { - DeadlockException ex = new DeadlockException( - _errorPrefix + "Db.del: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning("Deadlock in Freeze.Map.removeImpl while " + - "writing into Db \"" + _db.dbName() + - "\"; retrying..."); - } - - // - // Try again - // - } - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Db.del: " + e.getMessage(); - throw ex; - } - } - } - - private class Comparator implements java.util.Comparator - { - Comparator(java.util.Comparator comparator) - { - _comparator = comparator; - } - - public java.util.Comparator comparator() - { - return _comparator; - } - - public int compare(Object o1, Object o2) - { - byte[] d1 = (byte[])o1; - byte[] d2 = (byte[])o2; - - Ice.Communicator communicator = _connection.communicator(); - - return _comparator.compare(decodeKey(d1, communicator), - decodeKey(d2, communicator)); - } - - // - // The user-supplied comparator - // - private final java.util.Comparator _comparator; - } - - public abstract class Index - implements com.sleepycat.db.SecondaryKeyCreator, java.util.Comparator, KeyCodec - { - // - // Implementation details - // - public boolean - createSecondaryKey(com.sleepycat.db.SecondaryDatabase secondary, - com.sleepycat.db.DatabaseEntry key, - com.sleepycat.db.DatabaseEntry value, - com.sleepycat.db.DatabaseEntry result) - throws com.sleepycat.db.DatabaseException - { - Ice.Communicator communicator = _connection.getCommunicator(); - byte[] secondaryKey = marshalKey(value.getData()); - assert(secondaryKey != null); - - result.setData(secondaryKey); - result.setSize(secondaryKey.length); - return true; - } - - com.sleepycat.db.SecondaryDatabase - db() - { - return _db; - } - - String name() - { - return _name; - } - - protected Index(String name) - { - _name = name; - } - - void - associate(String dbName, com.sleepycat.db.Database db, - com.sleepycat.db.Transaction txn, boolean createDb, - java.util.Comparator comparator) - throws com.sleepycat.db.DatabaseException, java.io.FileNotFoundException - { - _dbName = dbName + "." + _name; - _comparator = comparator; - - assert(txn != null); - assert(_db == null); - - com.sleepycat.db.SecondaryConfig config = new com.sleepycat.db.SecondaryConfig(); - config.setAllowCreate(createDb); - config.setAllowPopulate(true); // We always populate empty indices - config.setSortedDuplicates(true); - config.setType(com.sleepycat.db.DatabaseType.BTREE); - if(_comparator != null) - { - config.setBtreeComparator(this); - } - config.setKeyCreator(this); - - Ice.Properties properties = _connection.communicator().getProperties(); - String propPrefix = "Freeze.Map." + _dbName + "."; - - int btreeMinKey = properties.getPropertyAsInt(propPrefix + "BtreeMinKey"); - if(btreeMinKey > 2) - { - if(_trace >= 1) - { - _connection.communicator().getLogger().trace( - "Freeze.Map", "Setting \"" + _dbName + "\"'s btree minkey to " + btreeMinKey); - } - config.setBtreeMinKey(btreeMinKey); - } - - boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0; - if(checksum) - { - if(_trace >= 1) - { - _connection.communicator().getLogger().trace( - "Freeze.Map", "Turning checksum on for \"" + _dbName + "\""); - } - - config.setChecksum(true); - } - - int pageSize = properties.getPropertyAsInt(propPrefix + "PageSize"); - if(pageSize > 0) - { - if(_trace >= 1) - { - _connection.communicator().getLogger().trace( - "Freeze.Map", "Setting \"" + _dbName + "\"'s pagesize to " + pageSize); - } - config.setPageSize(pageSize); - } - - _db = _connection.dbEnv().getEnv().openSecondaryDatabase(txn, _dbName, null, db, config); - } - - void init(Index from) - { - assert(_name.equals(from._name)); - assert(_db == null); - - _dbName = from._dbName; - _db = from._db; - _comparator = from._comparator; - } - - java.util.Comparator comparator() - { - return _comparator; - } - - Map parent() - { - return Map.this; - } - - Object firstKey(Object fromKey, Object toKey) - { - byte[] fk = fromKey == null ? null : - encodeKey(fromKey, _connection.communicator()); - - byte[] k = getFirstOrLastKey(_db, _dbName, fk, true); - if(k == null) - { - throw new NoSuchElementException(); - } - else - { - Object key = decodeKey(k, _connection.communicator()); - if(toKey != null && _comparator.compare(key, toKey) >= 0) - { - throw new NoSuchElementException(); - } - return key; - } - } - - Object lastKey(Object fromKey, Object toKey) - { - byte[] tk = toKey == null ? null : - encodeKey(toKey, _connection.communicator()); - - byte[] k = getFirstOrLastKey(_db, _dbName, tk, false); - if(k == null) - { - throw new NoSuchElementException(); - } - else - { - Object key = decodeKey(k, _connection.communicator()); - if(fromKey != null && _comparator.compare(fromKey, key) > 0) - { - throw new NoSuchElementException(); - } - return key; - } - } - - void close() - { - // - // close() is called by MapDb only on the "main" index - // (the one that was associated) - // - - if(_db != null) - { - try - { - _db.close(); - } - catch(com.sleepycat.db.DatabaseException dx) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(dx); - ex.message = _errorPrefix + "Db.close for index \"" + _dbName + "\": " + dx.getMessage(); - throw ex; - } - _db = null; - } - } - - public EntryIterator - untypedFind(Object key, boolean onlyDups) - { - byte[] k = encodeKey(key, _connection.communicator()); - return new EntryIteratorImpl(this, k, null, onlyDups, false); - } - - public int - untypedCount(Object key) - { - byte[] k = encodeKey(key, _connection.communicator()); - - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); - - // - // When we have a custom-comparison function, Berkeley DB returns - // the key on-disk (when it finds one). We disable this behavior: - // (ref Oracle SR 5925672.992) - // - dbKey.setPartial(true); - - // - // dlen is 0, so we should not retrieve any value - // - dbValue.setPartial(true); - - try - { - for(;;) - { - com.sleepycat.db.Cursor dbc = null; - try - { - dbc = _db.openCursor(null, null); - if(dbc.getSearchKey(dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS) - { - return dbc.count(); - } - else - { - return 0; - } - } - catch(com.sleepycat.db.DeadlockException dx) - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning( - "Deadlock in Freeze.Map.Index.untypedCount while iterating over index \"" + _dbName + - "\"; retrying..."); - } - - // - // Retry - // - } - finally - { - if(dbc != null) - { - try - { - dbc.close(); - } - catch(com.sleepycat.db.DeadlockException dx) - { - // - // Ignored - // - } - } - } - } - } - catch(com.sleepycat.db.DatabaseException dx) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(dx); - ex.message = _errorPrefix + "Db.cursor for index \"" + _dbName + "\": " + dx.getMessage(); - throw ex; - } - } - - boolean containsKey(Object key) - { - byte[] k = encodeKey(key, _connection.communicator()); - - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); - dbValue.setPartial(true); - - if(_trace >= 2) - { - _connection.communicator().getLogger().trace("Freeze.Map.Index", "checking key in Db \"" + _dbName + - "\""); - } - - for(;;) - { - try - { - return _db.get(_connection.dbTxn(), dbKey, dbValue, null) - == com.sleepycat.db.OperationStatus.SUCCESS; - } - catch(com.sleepycat.db.DeadlockException e) - { - if(_connection.dbTxn() != null) - { - DeadlockException ex = new DeadlockException( - _errorPrefix + "Db.get: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - else - { - if(_connection.deadlockWarning()) - { - _connection.communicator().getLogger().warning( - "Deadlock in Freeze.Map.Index.containsKey while " + - "reading Db \"" + _dbName + "\"; retrying..."); - } - // - // Try again - // - } - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Db.get: " + e.getMessage(); - throw ex; - } - } - } - - // - // Extracts the index key from this value - // - public abstract Object extractKey(Object value); - - protected byte[] marshalKey(byte[] value) - { - Object decodedValue = decodeValue(value, _connection.communicator()); - return encodeKey(extractKey(decodedValue), _connection.communicator()); - } - - // - // The user-supplied comparator - // - protected java.util.Comparator _comparator; - - private String _name; - private String _dbName; - private com.sleepycat.db.SecondaryDatabase _db; - } + void destroy(); /** * - * The entry iterator allows clients to explicitly close the iterator + * The entry iterator allows clients to explicitly close the iterator * and free resources allocated for the iterator as soon as possible. * **/ - public interface EntryIterator extends java.util.Iterator + public interface EntryIterator<T> extends java.util.Iterator<T> { void close(); void destroy(); // an alias for close } - class EntryIteratorImpl implements EntryIterator - { - EntryIteratorImpl(Index index, byte[] fromKey, byte[] toKey, - boolean onlyFromKeyDups, boolean skipDups) - { - _index = index; - _fromKey = fromKey; - _toKey = toKey; - _onlyFromKeyDups = onlyFromKeyDups; - _skipDups = skipDups; - - try - { - com.sleepycat.db.Transaction txn = _connection.dbTxn(); - if(txn == null) - { - // - // Start transaction - // - txn = _connection.dbEnv().getEnv().beginTransaction(null, null); - _txn = txn; - - if(_connection.txTrace() >= 1) - { - String txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); - - _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix + - "started transaction " + txnId + " for cursor"); - } - } - - // - // Open cursor with this transaction - // - if(index == null) - { - _cursor = _db.db().openCursor(txn, null); - } - else - { - _cursor = index.db().openSecondaryCursor(txn, null); - } - } - catch(com.sleepycat.db.DeadlockException dx) - { - dead(); - DeadlockException ex = new DeadlockException( - _errorPrefix + "EntryIterator constructor: " + dx.getMessage(), _connection.currentTransaction()); - ex.initCause(dx); - throw ex; - } - catch(com.sleepycat.db.DatabaseException dx) - { - dead(); - DatabaseException ex = new DatabaseException(); - ex.initCause(dx); - ex.message = _errorPrefix + "EntryIterator constructor: " + dx.getMessage(); - throw ex; - } - - synchronized(_iteratorList) - { - _iteratorList.addFirst(this); - java.util.Iterator p = _iteratorList.iterator(); - p.next(); - _iteratorListToken = p; - } - } - - public boolean - hasNext() - { - if(_current == null || _current == _lastReturned) - { - com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); - com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry(); - com.sleepycat.db.OperationStatus status = null; - - try - { - if(_index != null) - { - com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)_cursor; - if(_current == null) - { - // - // First key - // - if(_fromKey != null) - { - dbIKey.setData(_fromKey); - status = c.getSearchKey(dbIKey, dbKey, dbValue, null); - } - else - { - status = c.getFirst(dbIKey, dbKey, dbValue, null); - } - } - else - { - if(_onlyFromKeyDups) - { - status = c.getNextDup(dbIKey, dbKey, dbValue, null); - } - else if(_skipDups) - { - status = c.getNextNoDup(dbIKey, dbKey, dbValue, null); - } - else - { - status = c.getNext(dbIKey, dbKey, dbValue, null); - } - } - } - else - { - if(_current == null && _fromKey != null) - { - dbKey.setData(_fromKey); - status = _cursor.getSearchKey(dbKey, dbValue, null); - } - else - { - status = _cursor.getNext(dbKey, dbValue, null); - } - } - } - catch(com.sleepycat.db.DeadlockException dx) - { - dead(); - DeadlockException ex = new DeadlockException( - _errorPrefix + "Dbc.get: " + dx.getMessage(), _connection.currentTransaction()); - ex.initCause(dx); - throw ex; - } - catch(com.sleepycat.db.DatabaseException dx) - { - dead(); - DatabaseException ex = new DatabaseException(); - ex.initCause(dx); - ex.message = _errorPrefix + "Dbc.get: " + dx.getMessage(); - throw ex; - } - - if(status == com.sleepycat.db.OperationStatus.SUCCESS) - { - // - // Verify it's < _toKey - // - boolean inRange = true; - if(_toKey != null) - { - if(_index != null) - { - inRange = _index.compare(dbIKey.getData(), _toKey) < 0; - } - else - { - inRange = _comparator.compare(dbKey.getData(), _toKey) < 0; - } - } - - if(inRange) - { - _current = new Entry(this, Map.this, _connection.communicator(), dbKey, - dbValue.getData(), dbIKey.getData()); - return true; - } - } - return false; - } - else - { - return true; - } - } - - public Object - next() - { - if(hasNext()) - { - _lastReturned = _current; - return _lastReturned; - } - else - { - throw new java.util.NoSuchElementException(); - } - } - - public void - remove() - { - if(_txn != null) - { - closeAllIteratorsExcept(this, false); - } - - // - // Removes the last object returned by next() - // - if(_lastReturned == null) - { - throw new IllegalStateException(); - } - - if(_lastReturned == _current) - { - try - { - if(_cursor.delete() == com.sleepycat.db.OperationStatus.KEYEMPTY) - { - throw new IllegalStateException(); - } - } - catch(com.sleepycat.db.DeadlockException e) - { - dead(); - DeadlockException ex = new DeadlockException(_errorPrefix + "Dbc.del: " + e.getMessage(), - _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Dbc.del: " + e.getMessage(); - throw ex; - } - } - else - { - // - // Duplicate the cursor and move the _lastReturned - // element to delete it (using the duplicate) - // - - // - // This works only for non-index iterators - // - if(_index != null) - { - throw new UnsupportedOperationException(); - } - - com.sleepycat.db.Cursor clone = null; - - try - { - clone = _cursor.dup(true); - - // - // Not interested in data - // - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); - dbValue.setPartial(true); - - com.sleepycat.db.OperationStatus rc = clone.getSearchKey(_lastReturned.getDbKey(), dbValue, null); - - if(rc == com.sleepycat.db.OperationStatus.NOTFOUND) - { - throw new IllegalStateException(); - } - if(clone.delete() == com.sleepycat.db.OperationStatus.KEYEMPTY) - { - throw new IllegalStateException(); - } - } - catch(com.sleepycat.db.DeadlockException e) - { - dead(); - DeadlockException ex = new DeadlockException(_errorPrefix + "EntryIterator.remove: " + e.getMessage(), - _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "EntryIterator.remove: " + e.getMessage(); - throw ex; - } - finally - { - if(clone != null) - { - closeCursor(clone); - } - } - } - } - - // - // Extra operations. - // - public void - close() - { - close(false); - } - - // - // The synchronized is needed because this method can be called - // concurrently by Connection, Map and Map.EntryIterator finalizers. - // - synchronized void - close(boolean finalizing) - { - if(finalizing && (_cursor != null || _txn != null) && _connection.closeInFinalizeWarning()) - { - _connection.communicator().getLogger().warning( - "finalize() closing a live iterator on Map \"" + _db.dbName() + "\"; the application " + - "should have closed it earlier by calling Map.EntryIterator.close(), " + - "Map.closeAllIterators(), Map.close(), Connection.close(), or (if also " + - "leaking a transaction) Transaction.commit() or Transaction.rollback()"); - } - - if(_iteratorListToken != null) - { - synchronized(_iteratorList) - { - _iteratorListToken.remove(); - _iteratorListToken = null; - } - } - - if(_cursor != null) - { - com.sleepycat.db.Cursor cursor = _cursor; - _cursor = null; - closeCursor(cursor); - } - - if(_txn != null) - { - String txnId = null; - - try - { - if(_connection.txTrace() >= 1) - { - txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); - } - - _txn.commit(); - - if(_connection.txTrace() >= 1) - { - _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix + - "committed transaction " + txnId); - } - } - catch(com.sleepycat.db.DeadlockException e) - { - if(_connection.txTrace() >= 1) - { - _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix + - "failed to commit transaction " + txnId + ": " + - e.getMessage()); - } - - DeadlockException ex = new DeadlockException( - _errorPrefix + "DbTxn.commit: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - catch(com.sleepycat.db.DatabaseException e) - { - if(_connection.txTrace() >= 1) - { - _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix + - "failed to commit transaction " + txnId + ": " + - e.getMessage()); - } - - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "DbTxn.commit: " + e.getMessage(); - throw ex; - } - finally - { - _txn = null; - } - } - } - - // - // An alias for close() - // - public void - destroy() - { - close(); - } - - protected void - finalize() - { - close(true); - } - - void - setValue(Map.Entry entry, Object value) - { - if(_index != null) - { - throw new UnsupportedOperationException( - _errorPrefix + "Cannot set an iterator retrieved through an index"); - } - - if(_txn != null) - { - closeAllIteratorsExcept(this, false); - } - - // - // Are we trying to update the current value? - // - if(_current == entry) - { - // - // Yes, update it directly - // - byte[] v = encodeValue(value, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v); - - try - { - _cursor.putCurrent(dbValue); - } - catch(com.sleepycat.db.DeadlockException e) - { - dead(); - DeadlockException ex = new DeadlockException(_errorPrefix + "Dbc.put: " + e.getMessage(), - _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Dbc.put: " + e.getMessage(); - throw ex; - } - } - else - { - // - // Duplicate the cursor and move the entry - // element to update it (using the duplicate cursor) - // - - com.sleepycat.db.Cursor clone = null; - - try - { - clone = _cursor.dup(true); - - // - // Not interested in data - // - com.sleepycat.db.DatabaseEntry dummy = new com.sleepycat.db.DatabaseEntry(); - dummy.setPartial(true); - - com.sleepycat.db.OperationStatus rc = clone.getSearchKey(entry.getDbKey(), dummy, null); - - if(rc == com.sleepycat.db.OperationStatus.NOTFOUND) - { - NotFoundException ex = new NotFoundException(); - ex.message = _errorPrefix + "Dbc.get: DB_NOTFOUND"; - throw ex; - } - - byte[] v = encodeValue(value, _connection.communicator()); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v); - clone.putCurrent(dbValue); - } - catch(com.sleepycat.db.DeadlockException e) - { - dead(); - DeadlockException ex = new DeadlockException(_errorPrefix + "EntryIterator.setValue: " + e.getMessage(), - _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "EntryIterator.setValue: " + e.getMessage(); - throw ex; - } - finally - { - if(clone != null) - { - closeCursor(clone); - } - } - } - } - - private void - closeCursor(com.sleepycat.db.Cursor cursor) - { - try - { - cursor.close(); - } - catch(com.sleepycat.db.DeadlockException e) - { - dead(); - DeadlockException ex = new DeadlockException( - _errorPrefix + "Dbc.close: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - catch(com.sleepycat.db.DatabaseException e) - { - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "Dbc.close: " + e.getMessage(); - throw ex; - } - } - - private void - dead() - { - if(_cursor != null) - { - com.sleepycat.db.Cursor cursor = _cursor; - _cursor = null; - closeCursor(cursor); - } - - if(_txn != null) - { - String txnId = null; - - try - { - if(_connection.txTrace() >= 1) - { - txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); - } - - _txn.abort(); - - if(_connection.txTrace() >= 1) - { - _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix + - "rolled back transaction " + txnId); - } - } - catch(com.sleepycat.db.DeadlockException e) - { - if(_connection.txTrace() >= 1) - { - _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix + - "failed to roll back transaction " + txnId + - ": " + e.getMessage()); - } - - DeadlockException ex = new DeadlockException( - _errorPrefix + "DbTxn.abort: " + e.getMessage(), _connection.currentTransaction()); - ex.initCause(e); - throw ex; - } - catch(com.sleepycat.db.DatabaseException e) - { - if(_connection.txTrace() >= 1) - { - _connection.communicator().getLogger().trace("Freeze.Map", _errorPrefix + - "failed to roll back transaction " + - txnId + ": " + e.getMessage()); - } - - DatabaseException ex = new DatabaseException(); - ex.initCause(e); - ex.message = _errorPrefix + "DbTxn.abort: " + e.getMessage(); - throw ex; - } - finally - { - _txn = null; - } - } - } - - private com.sleepycat.db.Transaction _txn; - private com.sleepycat.db.Cursor _cursor; - private Entry _current; - private Entry _lastReturned; - private java.util.Iterator _iteratorListToken; - - private final Index _index; - private final byte[] _fromKey; - private final byte[] _toKey; - private final boolean _onlyFromKeyDups; - private final boolean _skipDups; - } - - static class Entry implements java.util.Map.Entry - { - public - Entry(EntryIteratorImpl iterator, Map map, Ice.Communicator communicator, - com.sleepycat.db.DatabaseEntry dbKey, byte[] valueBytes, byte[] indexBytes) - { - _iterator = iterator; - _map = map; - _communicator = communicator; - _dbKey = dbKey; - _valueBytes = valueBytes; - _indexBytes = indexBytes; - } - - public Object - getKey() - { - if(!_haveKey) - { - assert(_dbKey != null); - _key = _map.decodeKey(_dbKey.getData(), _communicator); - _haveKey = true; - } - return _key; - } - - public Object - getValue() - { - if(!_haveValue) - { - assert(_valueBytes != null); - _value = _map.decodeValue(_valueBytes, _communicator); - _haveValue = true; - // - // Not needed anymore - // - _valueBytes = null; - } - return _value; - } - - public byte[] - getIndexBytes() - { - return _indexBytes; - } - - public Object - setValue(Object value) - { - Object old = getValue(); - _iterator.setValue(this, value); - _value = value; - _haveValue = true; - return old; - } - - public boolean - equals(Object o) - { - if(!(o instanceof Map.Entry)) - { - return false; - } - Map.Entry e = (Map.Entry)o; - return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue()); - } - - public int - hashCode() - { - return ((getKey() == null) ? 0 : getKey().hashCode()) ^ - ((getValue() == null) ? 0 : getValue().hashCode()); - } - - public String - toString() - { - return getKey() + "=" + getValue(); - } - - com.sleepycat.db.DatabaseEntry - getDbKey() - { - return _dbKey; - } - - private /*static*/ boolean - eq(Object o1, Object o2) - { - return (o1 == null ? o2 == null : o1.equals(o2)); - } - - private EntryIteratorImpl _iterator; - private Map _map; - private Ice.Communicator _communicator; - private com.sleepycat.db.DatabaseEntry _dbKey; - private byte[] _valueBytes; - private byte[] _indexBytes; - private Object _key; - private boolean _haveKey = false; - private Object _value; - private boolean _haveValue = false; - } - - public static class Patcher implements IceInternal.Patcher - { - public - Patcher(String type) - { - this.type = type; - } - - public void - patch(Ice.Object v) - { - value = v; - } - - public String - type() - { - return this.type; - } - - public Ice.Object - value() - { - return this.value; - } - - public String type; - public Ice.Object value; - } - - protected ConnectionI _connection; - private final Comparator _comparator; - private final String _dbName; - - protected java.util.Iterator _token; - protected MapDb _db; - protected String _errorPrefix; - protected int _trace; - - private java.util.Set _entrySet; - private LinkedList _iteratorList = new LinkedList(); - private java.util.Map<String, Map.Index> _indexMap = new java.util.HashMap(); + Connection getConnection(); + void closeDb(); } diff --git a/java/src/Freeze/MapDb.java b/java/src/Freeze/MapDb.java index 1089d32c027..0d90b85bfb1 100644 --- a/java/src/Freeze/MapDb.java +++ b/java/src/Freeze/MapDb.java @@ -14,19 +14,18 @@ package Freeze; // share the very same MapDb object; SharedDbEnv manages these shared MapDb objects. // -class MapDb -{ - - MapDb(ConnectionI connection, String dbName, String key, String value, - java.util.Comparator comparator, Map.Index[] indices, java.util.Map indexComparators, - boolean createDb) - { +public class MapDb +{ + public + MapDb(ConnectionI connection, String dbName, String key, String value, java.util.Comparator comparator, + MapIndex[] indices, boolean createDb) + { _communicator = connection.communicator(); _dbName = dbName; _errorPrefix = "Freeze DB DbEnv(\"" + connection.dbEnv().getEnvName() + "\") Db(\"" + dbName + "\"): "; _indices = indices; _trace = connection.trace(); - + Catalog catalog = new Catalog(connection, Util.catalogName(), true); CatalogData catalogData = (CatalogData)catalog.get(_dbName); if(catalogData != null) @@ -44,10 +43,9 @@ class MapDb _key = key; _value = value; } - + com.sleepycat.db.DatabaseConfig config = new com.sleepycat.db.DatabaseConfig(); - - + config.setAllowCreate(createDb); config.setType(com.sleepycat.db.DatabaseType.BTREE); @@ -57,7 +55,7 @@ class MapDb } Ice.Properties properties = _communicator.getProperties(); String propPrefix = "Freeze.Map." + _dbName + "."; - + int btreeMinKey = properties.getPropertyAsInt(propPrefix + "BtreeMinKey"); if(btreeMinKey > 2) { @@ -68,26 +66,24 @@ class MapDb } config.setBtreeMinKey(btreeMinKey); } - + boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0; if(checksum) { if(_trace >= 1) { - _communicator.getLogger().trace( - "Freeze.Map", "Turning checksum on for \"" + _dbName + "\""); + _communicator.getLogger().trace("Freeze.Map", "Turning checksum on for \"" + _dbName + "\""); } - + config.setChecksum(true); } - + int pageSize = properties.getPropertyAsInt(propPrefix + "PageSize"); if(pageSize > 0) { if(_trace >= 1) { - _communicator.getLogger().trace( - "Freeze.Map", "Setting \"" + _dbName + "\"'s pagesize to " + pageSize); + _communicator.getLogger().trace("Freeze.Map", "Setting \"" + _dbName + "\"'s pagesize to " + pageSize); } config.setPageSize(pageSize); } @@ -109,36 +105,29 @@ class MapDb tx = null; tx = connection.beginTransaction(); } - + com.sleepycat.db.Transaction txn = Util.getTxn(tx); - + _db = connection.dbEnv().getEnv().openDatabase(txn, _dbName, null, config); - + String[] oldIndices = null; java.util.List<String> newIndices = new java.util.LinkedList<String>(); - + CatalogIndexList catalogIndexList = new CatalogIndexList(connection, Util.catalogIndexListName(), true); - + if(createDb) { - oldIndices = (String[])catalogIndexList.get(_dbName); + oldIndices = catalogIndexList.get(_dbName); } - - + if(_indices != null) { - for(int i = 0; i < _indices.length; ++i) + for(MapIndex i : _indices) { - String indexName = _indices[i].name(); - - java.util.Comparator indexComparator = null; - if(indexComparators != null) - { - indexComparator = (java.util.Comparator)indexComparators.get(indexName); - } - - _indices[i].associate(_dbName, _db, txn, createDb, indexComparator); - + String indexName = i.name(); + + i.associate(_dbName, _db, txn, createDb); + if(createDb) { if(oldIndices != null) @@ -153,7 +142,7 @@ class MapDb } } } - + if(catalogData == null) { catalogData = new CatalogData(); @@ -162,29 +151,28 @@ class MapDb catalogData.value = value; catalog.put(_dbName, catalogData); } - + if(createDb) { boolean indexRemoved = false; - + if(oldIndices != null) { // // Remove old indices and write the new ones // - for(int i = 0; i < oldIndices.length; ++i) + for(String index : oldIndices) { - String index = oldIndices[i]; if(index != null) { if(_trace >= 1) { - _communicator.getLogger().trace( - "Freeze.Map", "removing old index \"" + index + "\" on Db \"" + _dbName + "\""); + _communicator.getLogger().trace("Freeze.Map", "removing old index \"" + index + + "\" on Db \"" + _dbName + "\""); } - + indexRemoved = true; - + try { connection.removeMapIndex(_dbName, index); @@ -192,21 +180,21 @@ class MapDb catch(IndexNotFoundException ife) { // Ignored - + if(_trace >= 1) { - _communicator.getLogger().trace( - "Freeze.Map", "index \"" + index + "\" on Db \"" + _dbName + "\" does not exist"); + _communicator.getLogger().trace("Freeze.Map", "index \"" + index + + "\" on Db \"" + _dbName + "\" does not exist"); } } } } } - + int oldSize = oldIndices == null ? 0 : oldIndices.length; - + if(indexRemoved || newIndices.size() != oldSize) - { + { if(newIndices.size() == 0) { catalogIndexList.remove(_dbName); @@ -215,7 +203,6 @@ class MapDb _communicator.getLogger().trace( "Freeze.Map", "Removed catalogIndexList entry for Db \"" + _dbName + "\""); } - } else { @@ -253,12 +240,11 @@ class MapDb catch(com.sleepycat.db.DeadlockException dx) { if(ownTx) - { + { if(connection.deadlockWarning()) { - connection.communicator().getLogger().warning( - "Deadlock in Freeze.Shared.Shared on Db \"" - + _dbName + "\"; retrying ..."); + connection.communicator().getLogger().warning("Deadlock in Freeze.Shared.Shared on Db \"" + + _dbName + "\"; retrying ..."); } tx = null; } @@ -293,23 +279,22 @@ class MapDb } } } - // // The constructor for catalogs // - MapDb(Ice.Communicator communicator, String envName, String dbName, String key, String value, + MapDb(Ice.Communicator communicator, String envName, String dbName, String key, String value, com.sleepycat.db.Environment dbEnv) throws com.sleepycat.db.DatabaseException - { + { _communicator = communicator; _dbName = dbName; _errorPrefix = "Freeze DB DbEnv(\"" + envName + "\") Db(\"" + dbName + "\"): "; _key = key; _value = value; _trace = _communicator.getProperties().getPropertyAsInt("Freeze.Trace.Map"); - + if(_trace >= 1) { _communicator.getLogger().trace("Freeze.Map", "opening Db \"" + _dbName + "\""); @@ -336,7 +321,8 @@ class MapDb } } - void close() + public void + close() { if(_trace >= 1) { @@ -365,9 +351,8 @@ class MapDb } } - void - connectIndices(Map.Index[] indices) + connectIndices(MapIndex[] indices) { if(indices != null) { @@ -385,22 +370,21 @@ class MapDb { if(_indices != null) { - for(int i = 0; i < _indices.length; ++i) + for(MapIndex i : _indices) { - _indices[i].close(); + i.close(); } _indices = null; } } - - com.sleepycat.db.Database + public com.sleepycat.db.Database db() { return _db; } - String + public String dbName() { return _dbName; @@ -411,14 +395,12 @@ class MapDb { if(!key.equals(_key)) { - throw new DatabaseException(_errorPrefix + _dbName + "'s key type is " + _key + - ", not " + key); + throw new DatabaseException(_errorPrefix + _dbName + "'s key type is " + _key + ", not " + key); } - + if(!value.equals(_value)) { - throw new DatabaseException(_errorPrefix + _dbName + "'s value type is " + _value + - ", not " + value); + throw new DatabaseException(_errorPrefix + _dbName + "'s value type is " + _value + ", not " + value); } } @@ -429,5 +411,5 @@ class MapDb private String _key; private String _value; private final int _trace; - private Map.Index[] _indices; + private MapIndex[] _indices; } diff --git a/java/src/Freeze/MapIndex.java b/java/src/Freeze/MapIndex.java new file mode 100644 index 00000000000..9bab3d4e5bf --- /dev/null +++ b/java/src/Freeze/MapIndex.java @@ -0,0 +1,22 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze; + +public interface MapIndex +{ + String name(); + + void associate(String dbName, com.sleepycat.db.Database db, com.sleepycat.db.Transaction txn, boolean createDb) + throws com.sleepycat.db.DatabaseException, java.io.FileNotFoundException; + + void init(MapIndex i); + + void close(); +} diff --git a/java/src/Freeze/MapInternal/EntryI.java b/java/src/Freeze/MapInternal/EntryI.java new file mode 100644 index 00000000000..29fa155e83d --- /dev/null +++ b/java/src/Freeze/MapInternal/EntryI.java @@ -0,0 +1,131 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +class EntryI<K, V> implements java.util.Map.Entry<K, V> +{ + public + EntryI(MapI<K, V> map, K key, com.sleepycat.db.DatabaseEntry dbKey, byte[] valueBytes, byte[] indexBytes) + { + _map = map; + _dbKey = dbKey; + _valueBytes = valueBytes; + _indexBytes = indexBytes; + _communicator = map.connection().getCommunicator(); + _key = key; + _haveKey = key != null; + } + + public K + getKey() + { + if(!_haveKey) + { + assert(_dbKey != null); + _key = _map.decodeKey(_dbKey.getData(), _communicator); + _haveKey = true; + } + return _key; + } + + public V + getValue() + { + if(!_haveValue) + { + assert(_valueBytes != null); + _value = _map.decodeValue(_valueBytes, _communicator); + _haveValue = true; + // + // Not needed anymore + // + _valueBytes = null; + } + return _value; + } + + public byte[] + getIndexBytes() + { + return _indexBytes; + } + + public V + setValue(V value) + { + V old = getValue(); + if(_iterator != null) + { + _iterator.setValue(this, value); + } + else + { + _map.putImpl(_dbKey, value); + } + _value = value; + _haveValue = true; + return old; + } + + public boolean + equals(Object o) + { + if(!(o instanceof EntryI)) + { + return false; + } + @SuppressWarnings("unchecked") + EntryI<K, V> e = (EntryI<K, V>)o; + return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue()); + } + + public int + hashCode() + { + return ((getKey() == null) ? 0 : getKey().hashCode()) ^ + ((getValue() == null) ? 0 : getValue().hashCode()); + } + + public String + toString() + { + return getKey() + "=" + getValue(); + } + + void + iterator(IteratorI<K, V> iterator) + { + _iterator = iterator; + } + + com.sleepycat.db.DatabaseEntry + getDbKey() + { + return _dbKey; + } + + private static boolean + eq(Object o1, Object o2) + { + return (o1 == null ? o2 == null : o1.equals(o2)); + } + + private MapI<K, V> _map; + private com.sleepycat.db.DatabaseEntry _dbKey; + private byte[] _valueBytes; + private byte[] _indexBytes; + + private Ice.Communicator _communicator; + private K _key; + private boolean _haveKey = false; + private V _value; + private boolean _haveValue = false; + private IteratorI<K, V> _iterator; +} diff --git a/java/src/Freeze/MapInternal/Index.java b/java/src/Freeze/MapInternal/Index.java new file mode 100644 index 00000000000..d95813a7058 --- /dev/null +++ b/java/src/Freeze/MapInternal/Index.java @@ -0,0 +1,708 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +import Freeze.DatabaseException; +import Freeze.DeadlockException; +import Freeze.ConnectionI; +import Freeze.Map; +import Freeze.MapIndex; +import Freeze.NavigableMap; + +public abstract class Index<K, V, I> + implements MapIndex, com.sleepycat.db.SecondaryKeyCreator, java.util.Comparator<byte[]>, KeyCodec<I> +{ + protected + Index(MapI<K, V> map, String name, java.util.Comparator<I> comparator) + { + _map = map; + _name = name; + _comparator = comparator; + } + + // + // Subclasses define this so that we can extract the index key from a value. + // + protected abstract I extractKey(V value); + + // + // MapIndex methods + // + + public String + name() + { + return _name; + } + + public void + associate(String dbName, com.sleepycat.db.Database db, com.sleepycat.db.Transaction txn, boolean createDb) + throws com.sleepycat.db.DatabaseException, java.io.FileNotFoundException + { + _dbName = dbName + "." + _name; + _trace = new TraceLevels(_map.connection(), _dbName); + + assert(txn != null); + assert(_db == null); + + com.sleepycat.db.SecondaryConfig config = new com.sleepycat.db.SecondaryConfig(); + config.setAllowCreate(createDb); + config.setAllowPopulate(true); // We always populate empty indices + config.setSortedDuplicates(true); + config.setType(com.sleepycat.db.DatabaseType.BTREE); + if(_comparator != null) + { + config.setBtreeComparator(this); + } + config.setKeyCreator(this); + + Ice.Properties properties = _map.connection().getCommunicator().getProperties(); + String propPrefix = "Freeze.Map." + _dbName + "."; + + int btreeMinKey = properties.getPropertyAsInt(propPrefix + "BtreeMinKey"); + if(btreeMinKey > 2) + { + if(_trace.level >= 1) + { + _trace.logger.trace("Freeze.Map", "Setting \"" + _dbName + "\"'s btree minkey to " + btreeMinKey); + } + config.setBtreeMinKey(btreeMinKey); + } + + boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0; + if(checksum) + { + if(_trace.level >= 1) + { + _trace.logger.trace("Freeze.Map", "Turning checksum on for \"" + _dbName + "\""); + } + config.setChecksum(true); + } + + int pageSize = properties.getPropertyAsInt(propPrefix + "PageSize"); + if(pageSize > 0) + { + if(_trace.level >= 1) + { + _trace.logger.trace("Freeze.Map", "Setting \"" + _dbName + "\"'s pagesize to " + pageSize); + } + config.setPageSize(pageSize); + } + + _db = _map.connection().dbEnv().getEnv().openSecondaryDatabase(txn, _dbName, null, db, config); + } + + public void + init(MapIndex f) + { + @SuppressWarnings("unchecked") + Index<K, V, I> from = (Index<K, V, I>)f; + + assert(_name.equals(from._name)); + assert(_db == null); + + _dbName = from._dbName; + _db = from._db; + _comparator = from._comparator; + _trace = _map.traceLevels(); + } + + public void + close() + { + // + // close() is called by MapDb only on the "main" index + // (the one that was associated) + // + + if(_db != null) + { + try + { + _db.close(); + } + catch(com.sleepycat.db.DatabaseException dx) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(dx); + ex.message = _trace.errorPrefix + "Db.close for index \"" + _dbName + "\": " + dx.getMessage(); + throw ex; + } + _db = null; + } + } + + // + // SecondaryKeyCreator methods + // + + public boolean + createSecondaryKey(com.sleepycat.db.SecondaryDatabase secondary, + com.sleepycat.db.DatabaseEntry key, + com.sleepycat.db.DatabaseEntry value, + com.sleepycat.db.DatabaseEntry result) + throws com.sleepycat.db.DatabaseException + { + Ice.Communicator communicator = _map.connection().getCommunicator(); + byte[] secondaryKey = marshalKey(value.getData()); + assert(secondaryKey != null); + + result.setData(secondaryKey); + result.setSize(secondaryKey.length); + return true; + } + + // + // java.util.Comparator<byte[]> methods + // + + public int + compare(byte[] k1, byte[] k2) + { + assert(_comparator != null); + Ice.Communicator communicator = _map.connection().getCommunicator(); + return _comparator.compare(decodeKey(k1, communicator), decodeKey(k2, communicator)); + } + + private class FindModel implements IteratorModel<K, V> + { + FindModel(I key, boolean onlyDups) + { + _fromKey = key; + _onlyDups = onlyDups; + } + + public String + dbName() + { + return Index.this.dbName(); + } + + public TraceLevels + traceLevels() + { + return _trace; + } + + public com.sleepycat.db.Cursor + openCursor() + throws com.sleepycat.db.DatabaseException + { + return _db.openSecondaryCursor(_map.connection().dbTxn(), null); + } + + public EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return Index.this.findFirstEntry(cursor, _fromKey); + } + + public EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return Index.this.findNextEntry(cursor, _onlyDups); + } + + private final I _fromKey; + private final boolean _onlyDups; + } + + public IteratorI<K, V> + find(I key, boolean onlyDups) + { + return new IteratorI<K, V>(_map, new FindModel(key, onlyDups)); + } + + public IteratorI<K, V> + find(I key) + { + return find(key, true); + } + + public int + count(I key) + { + byte[] k = encodeKey(key, _map.connection().getCommunicator()); + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + + // + // When we have a custom-comparison function, Berkeley DB returns + // the key on-disk (when it finds one). We disable this behavior: + // (ref Oracle SR 5925672.992) + // + dbKey.setPartial(true); + + // + // dlen is 0, so we should not retrieve any value + // + dbValue.setPartial(true); + + try + { + for(;;) + { + com.sleepycat.db.Cursor dbc = null; + try + { + dbc = _db.openCursor(null, null); + if(dbc.getSearchKey(dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + return dbc.count(); + } + else + { + return 0; + } + } + catch(com.sleepycat.db.DeadlockException dx) + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.MapIndex.count while iterating over index \"" + + _dbName + "\"; retrying..."); + } + + // + // Retry + // + } + finally + { + if(dbc != null) + { + try + { + dbc.close(); + } + catch(com.sleepycat.db.DeadlockException dx) + { + // + // Ignored + // + } + } + } + } + } + catch(com.sleepycat.db.DatabaseException dx) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(dx); + ex.message = _trace.errorPrefix + "Db.cursor for index \"" + _dbName + "\": " + dx.getMessage(); + throw ex; + } + } + + // + // Used by subclasses to implement headMapForXXX. + // + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + createHeadMap(I toKey, boolean inclusive) + { + if(toKey == null) + { + throw new NullPointerException(); + } + + if(_comparator == null) + { + throw new UnsupportedOperationException("Index '" + _name + "' has no user-defined comparator"); + } + + return new IndexedSubMap<K, V, I>(this, null, false, toKey, inclusive); + } + + // + // Used by subclasses to implement tailMapForXXX. + // + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + createTailMap(I fromKey, boolean inclusive) + { + if(fromKey == null) + { + throw new NullPointerException(); + } + + if(_comparator == null) + { + throw new UnsupportedOperationException("Index '" + _name + "' has no user-defined comparator"); + } + + return new IndexedSubMap<K, V, I>(this, fromKey, inclusive, null, false); + } + + // + // Used by subclasses to implement subMapForXXX. + // + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + createSubMap(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + if(fromKey == null || toKey == null ) + { + throw new NullPointerException(); + } + + if(_comparator == null) + { + throw new UnsupportedOperationException("Index '" + _name + "' has no user-defined comparator"); + } + + return new IndexedSubMap<K, V, I>(this, fromKey, fromInclusive, toKey, toInclusive); + } + + // + // Used by subclasses to implement mapForXXX. + // + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + createMap() + { + if(_comparator == null) + { + throw new UnsupportedOperationException("Index '" + _name + "' has no user-defined comparator"); + } + + return new IndexedSubMap<K, V, I>(this, null, false, null, false); + } + + com.sleepycat.db.SecondaryDatabase + db() + { + return _db; + } + + String + dbName() + { + return _dbName; + } + + TraceLevels + traceLevels() + { + return _trace; + } + + java.util.Comparator<I> + comparator() + { + return _comparator; + } + + MapI<K, V> + parent() + { + return _map; + } + + boolean + containsKey(Object o) + { + @SuppressWarnings("unchecked") + I key = (I)o; + + byte[] k = encodeKey(key, _map.connection().getCommunicator()); + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + dbValue.setPartial(true); + + if(_trace.level >= 2) + { + _trace.logger.trace("Freeze.MapIndex", "checking key in Db \"" + _dbName + "\""); + } + + for(;;) + { + try + { + return _db.get(_map.connection().dbTxn(), dbKey, dbValue, null) == + com.sleepycat.db.OperationStatus.SUCCESS; + } + catch(com.sleepycat.db.DeadlockException e) + { + if(_map.connection().dbTxn() != null) + { + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Db.get: " + e.getMessage(), _map.connection().currentTransaction()); + ex.initCause(e); + throw ex; + } + else + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.MapIndex.containsKey while " + "reading Db \"" + + _dbName + "\"; retrying..."); + } + // + // Try again + // + } + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Db.get: " + e.getMessage(); + throw ex; + } + } + } + + // + // Used by the iterator created by the findByXXX methods. + // + EntryI<K, V> + findFirstEntry(com.sleepycat.db.Cursor cursor, I fromKey) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)cursor; + + assert(fromKey != null); + byte[] k = encodeKey(fromKey, _map.connection().getCommunicator()); + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry(k); + + if(c.getSearchKey(dbIKey, dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + return new EntryI<K, V>(_map, null, dbKey, dbValue.getData(), dbIKey.getData()); + } + + return null; + } + + // + // Used by the iterator created by the findByXXX methods. + // + EntryI<K, V> + findNextEntry(com.sleepycat.db.Cursor cursor, boolean onlyDups) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)cursor; + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry(); + + com.sleepycat.db.OperationStatus status; + + if(onlyDups) + { + status = c.getNextDup(dbIKey, dbKey, dbValue, null); + } + else + { + status = c.getNext(dbIKey, dbKey, dbValue, null); + } + + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + return new EntryI<K, V>(_map, null, dbKey, dbValue.getData(), dbIKey.getData()); + } + + return null; + } + + // + // Used by IndexedSubMap for ascending maps. + // + EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)cursor; + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry(); + + com.sleepycat.db.OperationStatus status; + + if(fromKey != null) + { + byte[] k = encodeKey(fromKey, _map.connection().getCommunicator()); + dbIKey.setData(k); + dbIKey.setReuseBuffer(false); + + status = c.getSearchKeyRange(dbIKey, dbKey, dbValue, null); + + if(status == com.sleepycat.db.OperationStatus.SUCCESS && !fromInclusive) + { + int cmp = compare(dbIKey.getData(), k); + assert(cmp >= 0); + if(cmp == 0) + { + status = c.getNextNoDup(dbIKey, dbKey, dbValue, null); + } + } + } + else + { + status = c.getFirst(dbIKey, dbKey, dbValue, null); + } + + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbIKey, dbKey, dbValue, fromKey, fromInclusive, toKey, toInclusive); + } + + return null; + } + + // + // Used by IndexedSubMap for ascending maps. + // + EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor, I toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)cursor; + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry(); + + if(c.getNextNoDup(dbIKey, dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbIKey, dbKey, dbValue, null, false, toKey, toInclusive); + } + + return null; + } + + // + // Used by IndexedSubMap for descending maps. + // + EntryI<K, V> + lastEntry(com.sleepycat.db.Cursor cursor, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)cursor; + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry(); + + com.sleepycat.db.OperationStatus status; + + if(fromKey != null) + { + byte[] k = encodeKey(fromKey, _map.connection().getCommunicator()); + dbIKey.setData(k); + dbIKey.setReuseBuffer(false); + + status = c.getSearchKeyRange(dbIKey, dbKey, dbValue, null); + + if(status == com.sleepycat.db.OperationStatus.SUCCESS && !fromInclusive) + { + int cmp = compare(dbIKey.getData(), k); + assert(cmp >= 0); + if(cmp == 0) + { + status = c.getPrevNoDup(dbIKey, dbKey, dbValue, null); + } + } + } + else + { + status = c.getLast(dbIKey, dbKey, dbValue, null); + } + + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbIKey, dbKey, dbValue, toKey, toInclusive, fromKey, fromInclusive); + } + + return null; + } + + // + // Used by IndexedSubMap for descending maps. + // + EntryI<K, V> + previousEntry(com.sleepycat.db.Cursor cursor, I toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.SecondaryCursor c = (com.sleepycat.db.SecondaryCursor)cursor; + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbIKey = new com.sleepycat.db.DatabaseEntry(); + + if(c.getPrevNoDup(dbIKey, dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbIKey, dbKey, dbValue, toKey, toInclusive, null, false); + } + + return null; + } + + // + // marshalKey may be overridden by subclasses as an optimization. + // + protected byte[] + marshalKey(byte[] value) + { + V decodedValue = _map.decodeValue(value, _map.connection().getCommunicator()); + return encodeKey(extractKey(decodedValue), _map.connection().getCommunicator()); + } + + private EntryI<K, V> + newEntry(com.sleepycat.db.DatabaseEntry dbIKey, com.sleepycat.db.DatabaseEntry dbKey, + com.sleepycat.db.DatabaseEntry dbValue, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + I key = null; + if(fromKey != null || toKey != null) + { + key = decodeKey(dbIKey.getData(), _map.connection().getCommunicator()); + if(!checkRange(key, fromKey, fromInclusive, toKey, toInclusive)) + { + return null; + } + } + + return new EntryI<K, V>(_map, null, dbKey, dbValue.getData(), dbIKey.getData()); + } + + private boolean + checkRange(I key, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + if(fromKey != null) + { + int cmp = _comparator.compare(key, fromKey); + if((fromInclusive && cmp < 0) || (!fromInclusive && cmp <= 0)) + { + return false; + } + } + if(toKey != null) + { + int cmp = _comparator.compare(key, toKey); + if((toInclusive && cmp > 0) || (!toInclusive && cmp >= 0)) + { + return false; + } + } + return true; + } + + private MapI<K, V> _map; + private String _name; + private java.util.Comparator<I> _comparator; + private TraceLevels _trace; + private String _dbName; + private com.sleepycat.db.SecondaryDatabase _db; +} diff --git a/java/src/Freeze/MapInternal/IndexedSubMap.java b/java/src/Freeze/MapInternal/IndexedSubMap.java new file mode 100644 index 00000000000..313308b80dd --- /dev/null +++ b/java/src/Freeze/MapInternal/IndexedSubMap.java @@ -0,0 +1,869 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +import Freeze.ConnectionI; +import Freeze.DatabaseException; +import Freeze.Map; +import Freeze.NavigableMap; + +// +// Indexed submap of a Freeze Map or of another submap +// +class IndexedSubMap<K, V, I> + extends java.util.AbstractMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + implements NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> +{ + private class Value extends java.util.AbstractSet<java.util.Map.Entry<K, V>> + { + public java.util.Iterator<java.util.Map.Entry<K, V>> + iterator() + { + return _index.find(_myKey, true); + } + + public int + size() + { + return _index.count(_myKey); + } + + public boolean + equals(Object o) + { + if(o instanceof IndexedSubMap.Value) + { + IndexedSubMap.Value v = (IndexedSubMap.Value)o; + return v._myKey.equals(_myKey); + } + else + { + return false; + } + } + + public int + hashCode() + { + return _myKey.hashCode(); + } + + private + Value(I key) + { + _myKey = key; + } + + private I + getKey() + { + return _myKey; + } + + private I _myKey; + } + + private class Entry implements java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + { + public I + getKey() + { + return _value.getKey(); + } + + public java.util.Set<java.util.Map.Entry<K, V>> + getValue() + { + return _value; + } + + public java.util.Set<java.util.Map.Entry<K, V>> + setValue(java.util.Set<java.util.Map.Entry<K, V>> value) + { + throw new UnsupportedOperationException(); + } + + public boolean + equals(Object o) + { + if(o instanceof IndexedSubMap.Entry) + { + IndexedSubMap.Entry e = (IndexedSubMap.Entry)o; + return e._value.equals(_value); + } + else + { + return false; + } + } + + public int + hashCode() + { + return _value.hashCode(); + } + + IndexedSubMap<K, V, I> + parent() + { + return IndexedSubMap.this; + } + + private + Entry(I key) + { + _value = new Value(key); + } + + private Value _value; + } + + private class Iterator + implements Map.EntryIterator<java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>>> + { + public boolean + hasNext() + { + return _iterator.hasNext(); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + next() + { + EntryI<K, V> entry = (EntryI<K, V>)_iterator.next(); + return new Entry(_index.decodeKey(entry.getIndexBytes(), _map.connection().getCommunicator())); + } + + public void + remove() + { + _iterator.remove(); + } + + public void + close() + { + _iterator.close(); + } + + public void + destroy() + { + close(); + } + + private + Iterator() + { + assert(_index != null); + _iterator = new IteratorI<K, V>(_map, _view); + } + + Map.EntryIterator<java.util.Map.Entry<K, V>> _iterator; + } + + IndexedSubMap(Index<K, V, I> index, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + _map = index.parent(); + _index = index; + _view = new AscendingView(fromKey, fromInclusive, toKey, toInclusive); + } + + private + IndexedSubMap(Index<K, V, I> index, View v) + { + _map = index.parent(); + _index = index; + _view = v; + } + + // + // NavigableMap methods + // + + public boolean + fastRemove(I key) + { + if(!_view.inRange(key, true)) + { + return false; + } + + // + // Not yet implemented + // + throw new UnsupportedOperationException(); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + firstEntry() + { + return _view.first(); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + lastEntry() + { + return _view.last(); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + ceilingEntry(I key) + { + return _view.ceiling(key); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + floorEntry(I key) + { + return _view.floor(key); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + higherEntry(I key) + { + return _view.higher(key); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + lowerEntry(I key) + { + return _view.lower(key); + } + + public I + ceilingKey(I key) + { + Entry e = _view.ceiling(key); + return e != null ? e.getKey() : null; + } + + public I + floorKey(I key) + { + Entry e = _view.floor(key); + return e != null ? e.getKey() : null; + } + + public I + higherKey(I key) + { + Entry e = _view.higher(key); + return e != null ? e.getKey() : null; + } + + public I + lowerKey(I key) + { + Entry e = _view.lower(key); + return e != null ? e.getKey() : null; + } + + public java.util.Set<I> + descendingKeySet() + { + return descendingMap().keySet(); + } + + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + descendingMap() + { + if(_descendingMap == null) + { + View v = _view.descendingView(); + _descendingMap = new IndexedSubMap<K, V, I>(_index, v); + } + return _descendingMap; + } + + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + headMap(I toKey, boolean inclusive) + { + if(toKey == null) + { + throw new NullPointerException(); + } + View v = _view.subView(null, false, toKey, inclusive); + return new IndexedSubMap<K, V, I>(_index, v); + } + + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + subMap(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + if(fromKey == null || toKey == null) + { + throw new NullPointerException(); + } + View v = _view.subView(fromKey, fromInclusive, toKey, toInclusive); + return new IndexedSubMap<K, V, I>(_index, v); + } + + public NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + tailMap(I fromKey, boolean inclusive) + { + if(fromKey == null) + { + throw new NullPointerException(); + } + View v = _view.subView(fromKey, inclusive, null, false); + return new IndexedSubMap<K, V, I>(_index, v); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + pollFirstEntry() + { + // + // Not yet implemented + // + throw new UnsupportedOperationException(); + } + + public java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>> + pollLastEntry() + { + // + // Not yet implemented + // + throw new UnsupportedOperationException(); + } + + // + // SortedMap methods + // + + public java.util.Comparator<? super I> + comparator() + { + return _view.comparator(); + } + + public I + firstKey() + { + Entry e = _view.first(); + if(e == null) + { + throw new java.util.NoSuchElementException(); + } + return e.getKey(); + } + + public I + lastKey() + { + Entry e = _view.last(); + if(e == null) + { + throw new java.util.NoSuchElementException(); + } + return e.getKey(); + } + + public java.util.SortedMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + headMap(I toKey) + { + return headMap(toKey, false); + } + + public java.util.SortedMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + tailMap(I fromKey) + { + return tailMap(fromKey, true); + } + + public java.util.SortedMap<I, java.util.Set<java.util.Map.Entry<K, V>>> + subMap(I fromKey, I toKey) + { + return subMap(fromKey, true, toKey, false); + } + + // + // Map methods + // + + public java.util.Set<java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>>> + entrySet() + { + if(_entrySet == null) + { + _entrySet = new java.util.AbstractSet<java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>>>() + { + public java.util.Iterator<java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>>> + iterator() + { + return new Iterator(); + } + + public boolean + contains(Object o) + { + if(o instanceof IndexedSubMap.Entry) + { + IndexedSubMap.Entry e = (IndexedSubMap.Entry)o; + return e.parent() == IndexedSubMap.this && _index.containsKey(e.getKey()); + } + else + { + return false; + } + } + + public boolean + remove(Object o) + { + // + // Not yet implemented, should remove all objects that + // match this index-key + // + throw new UnsupportedOperationException(); + } + + public int + size() + { + throw new UnsupportedOperationException(); + } + + public boolean + isEmpty() + { + try + { + firstKey(); + return false; + } + catch(java.util.NoSuchElementException e) + { + return true; + } + } + }; + } + return _entrySet; + } + + // + // Put is not implemented (you have to put in the main map view) + // + + public boolean + constainsKey(Object key) + { + @SuppressWarnings("unchecked") + I k = (I)key; + if(!_view.inRange(k, true)) + { + return false; + } + + return _index.containsKey(key); + } + + public java.util.Set<java.util.Map.Entry<K, V>> + get(Object key) + { + @SuppressWarnings("unchecked") + I k = (I)key; + if(!_view.inRange(k, true)) + { + return null; + } + + if(_index.containsKey(k)) + { + return new Value(k); + } + else + { + return null; + } + } + + public java.util.Set<java.util.Map.Entry<K, V>> + remove(Object key) + { + @SuppressWarnings("unchecked") + I k = (I)key; + if(!_view.inRange(k, true)) + { + return null; + } + + // + // Not yet implemented + // + throw new UnsupportedOperationException(); + } + + private Entry + entrySearch(Search.Type type, byte[] key) + { + if(type != Search.Type.FIRST && type != Search.Type.LAST && key == null) + { + throw new NullPointerException(); + } + + if(_index.db() == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _index.traceLevels().errorPrefix + "\"" + _index.dbName() + "\" has been closed"; + throw ex; + } + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(key); + + if(Search.search(type, _map.connection(), _index.dbName(), _index.db(), dbKey, null, _index, _view, + _index.traceLevels())) + { + I k = _index.decodeKey(dbKey.getData(), _map.connection().getCommunicator()); + return new Entry(k); + } + + return null; + } + + private abstract class View implements IteratorModel<K, V>, Search.KeyValidator + { + protected + View(java.util.Comparator<? super I> comparator, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + _comparator = comparator; + _fromKey = fromKey; + _fromInclusive = fromInclusive; + _toKey = toKey; + _toInclusive = toInclusive; + + // + // Validate the key range. + // + if(_fromKey != null && _toKey != null) + { + int cmp = comparator.compare(_fromKey, _toKey); + if(cmp > 0 || (cmp == 0 && !(_fromInclusive && _toInclusive))) + { + throw new IllegalArgumentException(); + } + } + } + + protected + View(View v, java.util.Comparator<? super I> comparator, I fromKey, boolean fromInclusive, I toKey, + boolean toInclusive) + { + this(comparator, fromKey, fromInclusive, toKey, toInclusive); + + // + // Verify that the key range is correct with respect to the original view. + // + if(!v.inRange(_fromKey, _fromInclusive) || !v.inRange(_toKey, _toInclusive)) + { + throw new IllegalArgumentException(); + } + } + + abstract Search.Type mapSearchType(Search.Type type); + abstract View copy(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive); + abstract View descendingView(); + + final Entry + first() + { + Search.Type type; + byte[] key = null; + if(_fromKey != null) + { + type = _fromInclusive ? mapSearchType(Search.Type.CEILING) : mapSearchType(Search.Type.HIGHER); + key = fromKeyBytes(); + } + else + { + type = mapSearchType(Search.Type.FIRST); + } + return entrySearch(type, key); + } + + final Entry + last() + { + Search.Type type; + byte[] key = null; + if(_toKey != null) + { + type = _toInclusive ? mapSearchType(Search.Type.FLOOR) : mapSearchType(Search.Type.LOWER); + key = toKeyBytes(); + } + else + { + type = mapSearchType(Search.Type.LAST); + } + return entrySearch(type, key); + } + + final Entry + ceiling(I key) + { + byte[] k = _index.encodeKey(key, _map.connection().getCommunicator()); + return entrySearch(mapSearchType(Search.Type.CEILING), k); + } + + final Entry + floor(I key) + { + byte[] k = _index.encodeKey(key, _map.connection().getCommunicator()); + return entrySearch(mapSearchType(Search.Type.FLOOR), k); + } + + final Entry + higher(I key) + { + byte[] k = _index.encodeKey(key, _map.connection().getCommunicator()); + return entrySearch(mapSearchType(Search.Type.HIGHER), k); + } + + final Entry + lower(I key) + { + byte[] k = _index.encodeKey(key, _map.connection().getCommunicator()); + return entrySearch(mapSearchType(Search.Type.LOWER), k); + } + + final View + subView(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + if(fromKey == null) + { + fromKey = _fromKey; + fromInclusive = _fromInclusive; + } + if(toKey == null) + { + toKey = _toKey; + toInclusive = _toInclusive; + } + return copy(fromKey, fromInclusive, toKey, toInclusive); + } + + // + // IteratorModel methods (partial) + // + + final public String + dbName() + { + return _index.dbName(); + } + + final public TraceLevels + traceLevels() + { + return _index.traceLevels(); + } + + final public com.sleepycat.db.Cursor + openCursor() + throws com.sleepycat.db.DatabaseException + { + return _index.db().openSecondaryCursor(_map.connection().dbTxn(), null); + } + + // + // Search.KeyValidator methods + // + + final public boolean + keyInRange(byte[] key) + { + I k = _index.decodeKey(key, _map.connection().getCommunicator()); + return inRange(k, true); + } + + final boolean + inRange(I key, boolean inclusive) + { + return !tooLow(key, inclusive, _fromKey, _fromInclusive) && + !tooHigh(key, inclusive, _toKey, _toInclusive); + } + + final java.util.Comparator<? super I> + comparator() + { + return _comparator; + } + + final protected byte[] + fromKeyBytes() + { + if(_fromKey != null && _fromKeyBytes == null) + { + _fromKeyBytes = _index.encodeKey(_fromKey, _map.connection().getCommunicator()); + } + return _fromKeyBytes; + } + + final protected byte[] + toKeyBytes() + { + if(_toKey != null && _toKeyBytes == null) + { + _toKeyBytes = _index.encodeKey(_toKey, _map.connection().getCommunicator()); + } + return _toKeyBytes; + } + + final protected boolean + tooLow(I key, boolean inclusive, I targetKey, boolean targetInclusive) + { + if(key != null && targetKey != null) + { + int cmp = comparator().compare(key, targetKey); + if(cmp < 0 || (cmp == 0 && inclusive && !targetInclusive)) + { + return true; + } + } + return false; + } + + final protected boolean + tooHigh(I key, boolean inclusive, I targetKey, boolean targetInclusive) + { + if(key != null && targetKey != null) + { + int cmp = comparator().compare(key, targetKey); + if(cmp > 0 || (cmp == 0 && inclusive && !targetInclusive)) + { + return true; + } + } + return false; + } + + final java.util.Comparator<? super I> _comparator; + final I _fromKey; + final boolean _fromInclusive; + final I _toKey; + final boolean _toInclusive; + private byte[] _fromKeyBytes; + private byte[] _toKeyBytes; + } + + private class AscendingView extends View + { + AscendingView(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + super(_index.comparator(), fromKey, fromInclusive, toKey, toInclusive); + } + + AscendingView(View v, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + super(v, _index.comparator(), fromKey, fromInclusive, toKey, toInclusive); + } + + // + // View methods + // + + Search.Type + mapSearchType(Search.Type type) + { + return type; + } + + View + copy(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + return new AscendingView(this, fromKey, fromInclusive, toKey, toInclusive); + } + + View + descendingView() + { + return new DescendingView(this, _toKey, _toInclusive, _fromKey, _fromInclusive); + } + + // + // IteratorModel methods + // + + public EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _index.firstEntry(cursor, _fromKey, _fromInclusive, _toKey, _toInclusive); + } + + public EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _index.nextEntry(cursor, _toKey, _toInclusive); + } + } + + private class DescendingView extends View + { + DescendingView(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + super(java.util.Collections.reverseOrder(_index.comparator()), fromKey, fromInclusive, toKey, toInclusive); + } + + DescendingView(View v, I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + super(v, java.util.Collections.reverseOrder(_index.comparator()), fromKey, fromInclusive, toKey, + toInclusive); + } + + // + // View methods + // + + Search.Type + mapSearchType(Search.Type type) + { + return type.descending(); + } + + View + copy(I fromKey, boolean fromInclusive, I toKey, boolean toInclusive) + { + return new DescendingView(this, fromKey, fromInclusive, toKey, toInclusive); + } + + View + descendingView() + { + return new AscendingView(this, _toKey, _toInclusive, _fromKey, _fromInclusive); + } + + // + // IteratorModel methods + // + + public EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _index.lastEntry(cursor, _fromKey, _fromInclusive, _toKey, _toInclusive); + } + + public EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _index.previousEntry(cursor, _toKey, _toInclusive); + } + } + + private final MapI<K, V> _map; + private final Index<K, V, I> _index; + private final View _view; + private java.util.Set<java.util.Map.Entry<I, java.util.Set<java.util.Map.Entry<K, V>>>> _entrySet; + private NavigableMap<I, java.util.Set<java.util.Map.Entry<K, V>>> _descendingMap; +} diff --git a/java/src/Freeze/MapInternal/IteratorI.java b/java/src/Freeze/MapInternal/IteratorI.java new file mode 100644 index 00000000000..4af39cf7498 --- /dev/null +++ b/java/src/Freeze/MapInternal/IteratorI.java @@ -0,0 +1,422 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +import Freeze.Connection; +import Freeze.ConnectionI; +import Freeze.DatabaseException; +import Freeze.DeadlockException; +import Freeze.NotFoundException; +import Freeze.Map; + +class IteratorI<K, V> implements Freeze.Map.EntryIterator<java.util.Map.Entry<K, V>> +{ + IteratorI(MapI<K, V> map, IteratorModel<K, V> model) + { + _map = map; + _model = model; + _trace = model.traceLevels(); + _dbName = model.dbName(); + + try + { + _txn = _map.connection().dbTxn(); + _cursor = _model.openCursor(); + } + catch(com.sleepycat.db.DeadlockException dx) + { + dead(); + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "EntryIterator constructor: " + dx.getMessage(), + _map.connection().currentTransaction()); + ex.initCause(dx); + throw ex; + } + catch(com.sleepycat.db.DatabaseException dx) + { + dead(); + DatabaseException ex = new DatabaseException(); + ex.initCause(dx); + ex.message = _trace.errorPrefix + "EntryIterator constructor: " + dx.getMessage(); + throw ex; + } + + _iteratorListToken = _map.addIterator(this); + } + + public boolean + hasNext() + { + if(_current == null || _current == _lastReturned) + { + try + { + if(_current == null) + { + _current = _model.firstEntry(_cursor); + } + else + { + _current = _model.nextEntry(_cursor); + } + } + catch(com.sleepycat.db.DeadlockException dx) + { + dead(); + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Dbc.get: " + dx.getMessage(), _map.connection().currentTransaction()); + ex.initCause(dx); + throw ex; + } + catch(com.sleepycat.db.DatabaseException dx) + { + dead(); + DatabaseException ex = new DatabaseException(); + ex.initCause(dx); + ex.message = _trace.errorPrefix + "Dbc.get: " + dx.getMessage(); + throw ex; + } + + // + // For a read-only iterator, we can close the cursor automatically when there + // are no more entries. + // + if(_current == null && _txn == null) + { + close(); + } + + if(_current != null) + { + _current.iterator(this); + } + + return _current != null; + } + else + { + return true; + } + } + + public java.util.Map.Entry<K, V> + next() + { + if(hasNext()) + { + _lastReturned = _current; + return _lastReturned; + } + else + { + throw new java.util.NoSuchElementException(); + } + } + + public void + remove() + { + if(_txn == null) + { + throw new UnsupportedOperationException( + _trace.errorPrefix + "Cannot remove using an iterator without a transaction"); + } + + // + // Remove the last object returned by next() + // + if(_lastReturned == null) + { + throw new IllegalStateException(); + } + + if(_lastReturned == _current) + { + try + { + if(_cursor.delete() == com.sleepycat.db.OperationStatus.KEYEMPTY) + { + throw new IllegalStateException(); + } + } + catch(com.sleepycat.db.DeadlockException e) + { + dead(); + DeadlockException ex = new DeadlockException(_trace.errorPrefix + "Dbc.del: " + e.getMessage(), + _map.connection().currentTransaction()); + ex.initCause(e); + throw ex; + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Dbc.del: " + e.getMessage(); + throw ex; + } + } + else + { + // + // Duplicate the cursor and move the _lastReturned element to delete it (using the duplicate). + // + + // + // This works only for non-index iterators. + // + if(_cursor instanceof com.sleepycat.db.SecondaryCursor) + { + throw new UnsupportedOperationException( + _trace.errorPrefix + "Cannot remove using an iterator retrieved through an index"); + } + + com.sleepycat.db.Cursor clone = null; + + try + { + clone = _cursor.dup(true); + + // + // Not interested in data. + // + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + dbValue.setPartial(true); + + com.sleepycat.db.OperationStatus rc = clone.getSearchKey(_lastReturned.getDbKey(), dbValue, null); + + if(rc == com.sleepycat.db.OperationStatus.NOTFOUND) + { + throw new IllegalStateException(); + } + if(clone.delete() == com.sleepycat.db.OperationStatus.KEYEMPTY) + { + throw new IllegalStateException(); + } + } + catch(com.sleepycat.db.DeadlockException e) + { + dead(); + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "EntryIterator.remove: " + e.getMessage(), + _map.connection().currentTransaction()); + ex.initCause(e); + throw ex; + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "EntryIterator.remove: " + e.getMessage(); + throw ex; + } + finally + { + if(clone != null) + { + closeCursor(clone); + } + } + } + } + + // + // Extra operations. + // + public void + close() + { + if(_iteratorListToken != null) + { + _map.removeIterator(_iteratorListToken); + _iteratorListToken = null; + } + + if(_cursor != null) + { + com.sleepycat.db.Cursor cursor = _cursor; + _cursor = null; + closeCursor(cursor); + } + } + + // + // An alias for close() + // + public void + destroy() + { + close(); + } + + protected void + finalize() + throws Throwable + { + if(_cursor != null) + { + _trace.logger.warning( + "iterator leaked for Map \"" + _dbName + "\"; the application " + + "should have closed it earlier by calling Map.EntryIterator.close(), " + + "Map.closeAllIterators(), Map.close(), Connection.close(), or (if also " + + "leaking a transaction) Transaction.commit() or Transaction.rollback()"); + } + super.finalize(); + } + + void + setValue(EntryI<K, V> entry, V value) + { + if(_cursor instanceof com.sleepycat.db.SecondaryCursor) + { + throw new UnsupportedOperationException( + _trace.errorPrefix + "Cannot set an iterator retrieved through an index"); + } + + if(_txn == null) + { + throw new UnsupportedOperationException( + _trace.errorPrefix + "Cannot set a value without a transaction"); + } + + // + // Are we trying to update the current value? + // + if(_current == entry) + { + // + // Yes, update it directly + // + byte[] v = _map.encodeValue(value, _map.connection().getCommunicator()); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v); + + try + { + _cursor.putCurrent(dbValue); + } + catch(com.sleepycat.db.DeadlockException e) + { + dead(); + DeadlockException ex = new DeadlockException(_trace.errorPrefix + "Dbc.put: " + e.getMessage(), + _map.connection().currentTransaction()); + ex.initCause(e); + throw ex; + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Dbc.put: " + e.getMessage(); + throw ex; + } + } + else + { + // + // Duplicate the cursor and move the entry + // element to update it (using the duplicate cursor) + // + + com.sleepycat.db.Cursor clone = null; + + try + { + clone = _cursor.dup(true); + + // + // Not interested in data + // + com.sleepycat.db.DatabaseEntry dummy = new com.sleepycat.db.DatabaseEntry(); + dummy.setPartial(true); + + com.sleepycat.db.OperationStatus rc = clone.getSearchKey(entry.getDbKey(), dummy, null); + + if(rc == com.sleepycat.db.OperationStatus.NOTFOUND) + { + NotFoundException ex = new NotFoundException(); + ex.message = _trace.errorPrefix + "Dbc.get: DB_NOTFOUND"; + throw ex; + } + + byte[] v = _map.encodeValue(value, _map.connection().getCommunicator()); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v); + clone.putCurrent(dbValue); + } + catch(com.sleepycat.db.DeadlockException e) + { + dead(); + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "EntryIterator.setValue: " + e.getMessage(), + _map.connection().currentTransaction()); + ex.initCause(e); + throw ex; + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "EntryIterator.setValue: " + e.getMessage(); + throw ex; + } + finally + { + if(clone != null) + { + closeCursor(clone); + } + } + } + } + + private void + closeCursor(com.sleepycat.db.Cursor cursor) + { + try + { + cursor.close(); + } + catch(com.sleepycat.db.DeadlockException e) + { + dead(); + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Dbc.close: " + e.getMessage(), _map.connection().currentTransaction()); + ex.initCause(e); + throw ex; + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Dbc.close: " + e.getMessage(); + throw ex; + } + } + + private void + dead() + { + if(_cursor != null) + { + com.sleepycat.db.Cursor cursor = _cursor; + _cursor = null; + closeCursor(cursor); + } + } + + private final MapI<K, V> _map; + private final IteratorModel<K, V> _model; + + private final TraceLevels _trace; + private final String _dbName; // For use in finalizer. + private final com.sleepycat.db.Transaction _txn; + private com.sleepycat.db.Cursor _cursor; + private EntryI<K, V> _current; + private EntryI<K, V> _lastReturned; + private Object _iteratorListToken; +} diff --git a/java/src/Freeze/MapInternal/IteratorModel.java b/java/src/Freeze/MapInternal/IteratorModel.java new file mode 100644 index 00000000000..8adeea782ac --- /dev/null +++ b/java/src/Freeze/MapInternal/IteratorModel.java @@ -0,0 +1,25 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +interface IteratorModel<K, V> +{ + String dbName(); + TraceLevels traceLevels(); + + com.sleepycat.db.Cursor openCursor() + throws com.sleepycat.db.DatabaseException; + + EntryI<K, V> firstEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException; + + EntryI<K, V> nextEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException; +} diff --git a/java/src/Freeze/KeyCodec.java b/java/src/Freeze/MapInternal/KeyCodec.java index 3f4697c658f..3239d203797 100644 --- a/java/src/Freeze/KeyCodec.java +++ b/java/src/Freeze/MapInternal/KeyCodec.java @@ -7,10 +7,10 @@ // // ********************************************************************** -package Freeze; +package Freeze.MapInternal; -public interface KeyCodec +interface KeyCodec<K> { - public abstract byte[] encodeKey(Object o, Ice.Communicator communicator); - public abstract Object decodeKey(byte[] b, Ice.Communicator communicator); + public abstract byte[] encodeKey(K k, Ice.Communicator communicator); + public abstract K decodeKey(byte[] b, Ice.Communicator communicator); } diff --git a/java/src/Freeze/MapInternal/MapI.java b/java/src/Freeze/MapInternal/MapI.java new file mode 100644 index 00000000000..3d523f617ad --- /dev/null +++ b/java/src/Freeze/MapInternal/MapI.java @@ -0,0 +1,1571 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +import Freeze.Catalog; +import Freeze.CatalogIndexList; +import Freeze.Connection; +import Freeze.ConnectionI; +import Freeze.DatabaseException; +import Freeze.DeadlockException; +import Freeze.IndexNotFoundException; +import Freeze.LinkedList; +import Freeze.Map; +import Freeze.MapDb; +import Freeze.MapIndex; +import Freeze.NavigableMap; +import Freeze.Transaction; +import Freeze.Util; + +public abstract class MapI<K, V> extends java.util.AbstractMap<K, V> + implements Map<K, V>, KeyCodec<K>, IteratorModel<K, V> +{ + public abstract byte[] encodeValue(V o, Ice.Communicator communicator); + public abstract V decodeValue(byte[] b, Ice.Communicator communicator); + + protected + MapI(Connection connection, String dbName, String key, String value, boolean createDb, + java.util.Comparator<K> comparator) + { + _connection = (ConnectionI)connection; + _dbName = dbName; + _comparator = (comparator == null) ? null : new Comparator(comparator); + + _trace = new TraceLevels(_connection, dbName); + + init(null, dbName, key, value, createDb); + } + + protected + MapI(Connection connection, String dbName, java.util.Comparator<K> comparator) + { + _connection = (ConnectionI)connection; + _dbName = dbName; + _comparator = (comparator == null) ? null : new Comparator(comparator); + + _trace = new TraceLevels(_connection, dbName); + } + + protected static <K, V> void + recreate(MapI<K, V> map, String dbName, String key, String value, MapIndex[] indices) + { + ConnectionI connection = map._connection; + TraceLevels trace = map._trace; + + if(dbName.equals(Util.catalogName()) || dbName.equals(Util.catalogIndexListName())) + { + throw new DatabaseException(trace.errorPrefix + "You cannot recreate the \"" + dbName + "\" database"); + } + + if(trace.level >= 1) + { + trace.logger.trace("Freeze.Map", "Recreating \"" + dbName + "\""); + } + + Transaction tx = connection.currentTransaction(); + boolean ownTx = (tx == null); + + com.sleepycat.db.DatabaseEntry keyEntry = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry valueEntry = new com.sleepycat.db.DatabaseEntry(); + + com.sleepycat.db.Database oldDb = null; + MapDb newDb = null; + + for(;;) + { + try + { + if(ownTx) + { + tx = null; + tx = connection.beginTransaction(); + } + + com.sleepycat.db.Transaction txn = connection.dbTxn(); + + if(trace.level >= 2) + { + trace.logger.trace("Freeze.Map", "Removing all existing indices for \"" + dbName + "\""); + } + + CatalogIndexList catalogIndexList = new CatalogIndexList(connection, Util.catalogIndexListName(), true); + String[] oldIndices = catalogIndexList.remove(dbName); + + if(oldIndices != null) + { + for(String oldIndex : oldIndices) + { + try + { + connection.removeMapIndex(dbName, oldIndex); + } + catch(IndexNotFoundException e) + { + // + // Ignored + // + } + } + } + + // + // Rename existing database + // + String oldDbName = dbName + ".old-" + java.util.UUID.randomUUID().toString(); + + if(trace.level >= 2) + { + trace.logger.trace("Freeze.Map", "Renaming \"" + dbName + "\" to \"" + oldDbName + "\""); + } + + connection.dbEnv().getEnv().renameDatabase(txn, dbName, null, oldDbName); + + com.sleepycat.db.DatabaseConfig oldDbConfig = new com.sleepycat.db.DatabaseConfig(); + oldDbConfig.setType(com.sleepycat.db.DatabaseType.BTREE); + + oldDb = connection.dbEnv().getEnv().openDatabase(txn, oldDbName, null, oldDbConfig); + + newDb = new MapDb(connection, dbName, key, value, map._comparator, indices, true); + map.init(newDb, indices); + + if(trace.level >= 2) + { + trace.logger.trace("Freeze.Map", "Writing contents of \"" + oldDbName + "\" to fresh \"" + + dbName + "\""); + } + + // + // Now simply write all of oldDb into newDb + // + com.sleepycat.db.Cursor dbc = null; + try + { + dbc = oldDb.openCursor(txn, null); + + while(dbc.getNext(keyEntry, valueEntry, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + newDb.db().put(txn, keyEntry, valueEntry); + } + } + finally + { + if(dbc != null) + { + dbc.close(); + } + } + + if(trace.level >= 2) + { + trace.logger.trace("Freeze.Map", "Transfer complete; removing \"" + oldDbName + "\""); + } + connection.dbEnv().getEnv().removeDatabase(txn, oldDbName, null); + + if(ownTx) + { + try + { + tx.commit(); + } + finally + { + tx = null; + } + } + + break; // for (;;) + } + catch(com.sleepycat.db.DeadlockException dx) + { + if(ownTx) + { + if(trace.deadlockWarning) + { + trace.logger.warning("Deadlock in Freeze.Map.recreate on Db \"" + dbName + "\"; retrying ..."); + } + + // + // Ignored, try again + // + } + else + { + DeadlockException ex = new DeadlockException( + trace.errorPrefix + "Map.recreate: " + dx.getMessage(), tx); + ex.initCause(dx); + throw ex; + } + } + catch(com.sleepycat.db.DatabaseException dx) + { + DatabaseException ex = new DatabaseException(trace.errorPrefix + "Map.recreate: " + dx.getMessage()); + ex.initCause(dx); + throw ex; + } + catch(java.io.FileNotFoundException fne) + { + DatabaseException ex = new DatabaseException(trace.errorPrefix + "Map.recreate: " + fne.getMessage()); + ex.initCause(fne); + throw ex; + } + finally + { + if(ownTx && tx != null) + { + try + { + tx.rollback(); + } + catch(DatabaseException de) + { + } + } + + try + { + if(newDb != null) + { + newDb.close(); + } + + if(oldDb != null) + { + try + { + oldDb.close(); + } + catch(com.sleepycat.db.DatabaseException dx) + { + DatabaseException ex = new DatabaseException( + trace.errorPrefix + "Map.recreate: " + dx.getMessage()); + ex.initCause(dx); + throw ex; + } + } + } + finally + { + newDb = null; + oldDb = null; + } + } + } + } + + protected void + init(MapIndex[] indices, String dbName, String key, String value, boolean createDb) + { + init(_connection.dbEnv().getSharedMapDb(dbName, key, value, _comparator, indices, createDb), indices); + } + + protected void + init(MapDb db, MapIndex[] indices) + { + _db = db; + _token = _connection.registerMap(this); + + if(indices != null) + { + for(MapIndex index : indices) + { + _indexMap.put(index.name(), index); + } + } + } + + // + // Freeze.Map methods + // + + public void + fastPut(K key, V value) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + putImpl(dbKey, value); + } + + public boolean + fastRemove(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + return removeImpl(dbKey); + } + + public void + close() + { + if(_db != null) + { + try + { + closeAllIterators(); + } + finally + { + _db = null; + _connection.unregisterMap(_token); + _token = null; + } + } + } + + public int + closeAllIterators() + { + return closeAllIteratorsExcept(null); + } + + // + // Close this map and destroy the underlying Berkeley DB database + // + public void + destroy() + { + if(_db == null) + { + throw new DatabaseException(_trace.errorPrefix + "This map is closed"); + } + + if(_dbName.equals(Util.catalogName()) || _dbName.equals(Util.catalogIndexListName())) + { + throw new DatabaseException(_trace.errorPrefix + "You cannot destroy the \"" + _dbName + "\" database"); + } + + if(_connection.currentTransaction() != null) + { + throw new DatabaseException( + _trace.errorPrefix + "You cannot destroy a database within an active transaction"); + } + + if(_trace.level >= 1) + { + _trace.logger.trace("Freeze.Map", "destroying \"" + _dbName + "\""); + } + + closeDb(); + + for(;;) + { + Transaction tx = null; + try + { + tx = _connection.beginTransaction(); + com.sleepycat.db.Transaction txn = _connection.dbTxn(); + + Catalog catalog = new Catalog(_connection, Util.catalogName(), true); + catalog.remove(_dbName); + + CatalogIndexList catalogIndexList = + new CatalogIndexList(_connection, Util.catalogIndexListName(), true); + catalogIndexList.remove(_dbName); + + _connection.dbEnv().getEnv().removeDatabase(txn, _dbName, null); + + // + // Remove all indices + // + for(String index : _indexMap.keySet()) + { + _connection.removeMapIndex(_dbName, index); + } + + tx.commit(); + + break; // for(;;) + } + catch(java.io.FileNotFoundException dx) + { + try + { + tx.rollback(); + } + catch(DatabaseException e) + { + } + + DatabaseException e = new DatabaseException(_trace.errorPrefix + "file not found"); + e.initCause(dx); + throw e; + } + catch(com.sleepycat.db.DeadlockException dx) + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.Map.destroy on Db \"" + _dbName + "\"; retrying..."); + } + + // + // Ignored, try again + // + } + catch(com.sleepycat.db.DatabaseException dx) + { + try + { + tx.rollback(); + } + catch(DatabaseException e) + { + } + + DatabaseException e = new DatabaseException(_trace.errorPrefix + dx.getMessage()); + e.initCause(dx); + throw e; + } + catch(RuntimeException rx) + { + try + { + tx.rollback(); + } + catch(DatabaseException e) + { + } + + throw rx; + } + } + } + + public Connection + getConnection() + { + return _connection; + } + + public void + closeDb() + { + close(); + _connection.dbEnv().removeSharedMapDb(_dbName); + } + + // + // NavigableMap methods + // + + public java.util.Map.Entry<K, V> + firstEntry() + { + return entrySearch(Search.Type.FIRST, null, true); + } + + public java.util.Map.Entry<K, V> + lastEntry() + { + return entrySearch(Search.Type.LAST, null, true); + } + + public java.util.Map.Entry<K, V> + ceilingEntry(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + return entrySearch(Search.Type.CEILING, k, true); + } + + public java.util.Map.Entry<K, V> + floorEntry(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + return entrySearch(Search.Type.FLOOR, k, true); + } + + public java.util.Map.Entry<K, V> + higherEntry(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + return entrySearch(Search.Type.HIGHER, k, true); + } + + public java.util.Map.Entry<K, V> + lowerEntry(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + return entrySearch(Search.Type.LOWER, k, true); + } + + public K + ceilingKey(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + java.util.Map.Entry<K, V> e = entrySearch(Search.Type.CEILING, k, false); + return e != null ? e.getKey() : null; + } + + public K + floorKey(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + java.util.Map.Entry<K, V> e = entrySearch(Search.Type.FLOOR, k, false); + return e != null ? e.getKey() : null; + } + + public K + higherKey(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + java.util.Map.Entry<K, V> e = entrySearch(Search.Type.HIGHER, k, false); + return e != null ? e.getKey() : null; + } + + public K + lowerKey(K key) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + java.util.Map.Entry<K, V> e = entrySearch(Search.Type.LOWER, k, false); + return e != null ? e.getKey() : null; + } + + public java.util.Set<K> + descendingKeySet() + { + return descendingMap().keySet(); + } + + public NavigableMap<K, V> + descendingMap() + { + if(_comparator == null) + { + throw new UnsupportedOperationException("A comparator is required"); + } + + if(_descendingMap == null) + { + _descendingMap = new SubMap<K, V>(this, null, false, null, false, false); + } + + return _descendingMap; + } + + public NavigableMap<K, V> + headMap(K toKey, boolean inclusive) + { + if(toKey == null) + { + throw new NullPointerException(); + } + + if(_comparator == null) + { + throw new UnsupportedOperationException("A comparator is required"); + } + + return new SubMap<K, V>(this, null, false, toKey, inclusive, true); + } + + public NavigableMap<K, V> + subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + if(fromKey == null || toKey == null) + { + throw new NullPointerException(); + } + + if(_comparator == null) + { + throw new UnsupportedOperationException("A comparator is required"); + } + + return new SubMap<K, V>(this, fromKey, fromInclusive, toKey, toInclusive, true); + } + + public NavigableMap<K, V> + tailMap(K fromKey, boolean inclusive) + { + if(fromKey == null) + { + throw new NullPointerException(); + } + + if(_comparator == null) + { + throw new UnsupportedOperationException("A comparator is required"); + } + + return new SubMap<K, V>(this, fromKey, inclusive, null, false, true); + } + + public java.util.Map.Entry<K, V> + pollFirstEntry() + { + EntryI<K, V> e = entrySearch(Search.Type.FIRST, null, true); + if(e != null) + { + removeImpl(e.getDbKey()); + } + return e; + } + + public java.util.Map.Entry<K, V> + pollLastEntry() + { + EntryI<K, V> e = entrySearch(Search.Type.LAST, null, true); + if(e != null) + { + removeImpl(e.getDbKey()); + } + return e; + } + + // + // SortedMap methods + // + + public java.util.Comparator<? super K> + comparator() + { + if(_comparator == null) + { + return null; + } + else + { + // + // Return's the user's comparator, not the DB comparator. + // + return _comparator.comparator(); + } + } + + public K + firstKey() + { + EntryI<K, V> e = entrySearch(Search.Type.FIRST, null, false); + if(e == null) + { + throw new java.util.NoSuchElementException(); + } + return e.getKey(); + } + + public K + lastKey() + { + EntryI<K, V> e = entrySearch(Search.Type.LAST, null, false); + if(e == null) + { + throw new java.util.NoSuchElementException(); + } + return e.getKey(); + } + + public java.util.SortedMap<K, V> + headMap(K toKey) + { + return headMap(toKey, false); + } + + public java.util.SortedMap<K, V> + tailMap(K fromKey) + { + return tailMap(fromKey, true); + } + + public java.util.SortedMap<K, V> + subMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + // + // Map methods + // + + public int + size() + { + if(_db == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _trace.errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + // + // The number of records cannot be cached and then adjusted by + // the member functions since the map would no longer work in + // the presence of transactions - if a record is added (and + // the size adjusted) and the transaction aborted then the + // cached map size() would be incorrect. + // + + // + // TODO: DB_FAST_STAT doesn't seem to do what the + // documentation says... + // + try + { + com.sleepycat.db.StatsConfig config = new com.sleepycat.db.StatsConfig(); + // + // TODO: DB_FAST_STAT doesn't seem to do what the + // documentation says... + // + //config.setFast(true); + com.sleepycat.db.BtreeStats s = (com.sleepycat.db.BtreeStats)_db.db().getStats(null, config); + return s.getNumData(); + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Db.stat: " + e.getMessage(); + throw ex; + } + } + + public boolean + containsValue(Object value) + { + for(;;) + { + Map.EntryIterator<java.util.Map.Entry<K, V>> p = null; + try + { + p = (Map.EntryIterator<java.util.Map.Entry<K, V>>)entrySet().iterator(); + + if(value == null) + { + while(p.hasNext()) + { + Entry e = (Entry)p.next(); + if(e.getValue() == null) + { + return true; + } + } + } + else + { + while(p.hasNext()) + { + Entry e = (Entry)p.next(); + if(value.equals(e.getValue())) + { + return true; + } + } + } + return false; + } + catch(DeadlockException e) + { + if(_connection.dbTxn() != null) + { + throw e; + } + else + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.Map.containsValue while " + "iterating over Db \"" + + _dbName + "\"; retrying..."); + } + + // + // Try again + // + } + } + finally + { + if(p != null) + { + p.close(); + } + } + } + } + + public boolean + containsKey(Object o) + { + @SuppressWarnings("unchecked") + K key = (K)o; + + if(_db == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _trace.errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + byte[] k = encodeKey(key, _connection.getCommunicator()); + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + dbValue.setPartial(true); + + if(_trace.level >= 2) + { + _trace.logger.trace("Freeze.Map", "checking key in Db \"" + _dbName + "\""); + } + + for(;;) + { + try + { + return _db.db().get(_connection.dbTxn(), dbKey, dbValue, null) == + com.sleepycat.db.OperationStatus.SUCCESS; + } + catch(com.sleepycat.db.DeadlockException e) + { + if(_connection.dbTxn() != null) + { + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Db.get: " + e.getMessage(), _connection.currentTransaction()); + ex.initCause(e); + throw ex; + } + else + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.Map.containsKey while " + "reading Db \"" + _dbName + + "\"; retrying..."); + } + // + // Try again + // + } + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Db.get: " + e.getMessage(); + throw ex; + } + } + } + + public V + get(Object o) + { + @SuppressWarnings("unchecked") + K key = (K)o; + + byte[] k = encodeKey(key, _connection.getCommunicator()); + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + byte[] v = getImpl(dbKey); + if(v == null) + { + return null; + } + else + { + return decodeValue(v, _connection.getCommunicator()); + } + } + + public V + put(K key, V value) + { + byte[] k = encodeKey(key, _connection.getCommunicator()); + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + byte[] v = getImpl(dbKey); + V old = null; + if(v != null) + { + old = decodeValue(v, _connection.getCommunicator()); + } + putImpl(dbKey, value); + return old; + } + + public V + remove(Object o) + { + @SuppressWarnings("unchecked") + K key = (K)o; + + byte[] k = encodeKey(key, _connection.getCommunicator()); + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(k); + byte[] v = getImpl(dbKey); + + if(v != null && removeImpl(dbKey)) + { + return decodeValue(v, _connection.getCommunicator()); + } + else + { + return null; + } + } + + public void + clear() + { + if(_db == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _trace.errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + com.sleepycat.db.Transaction txn = _connection.dbTxn(); + + for(;;) + { + try + { + _db.db().truncate(txn, false); + break; + } + catch(com.sleepycat.db.DeadlockException e) + { + if(txn != null) + { + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Db.truncate: " + e.getMessage(), _connection.currentTransaction()); + ex.initCause(e); + throw ex; + } + else + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.Map.clear on Db \"" + _dbName + "\"; retrying..."); + } + + // + // Try again + // + } + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Db.truncate: " + e.getMessage(); + throw ex; + } + } + } + + public java.util.Set<java.util.Map.Entry<K, V>> + entrySet() + { + if(_entrySet == null) + { + _entrySet = new java.util.AbstractSet<java.util.Map.Entry<K, V>>() + { + public java.util.Iterator<java.util.Map.Entry<K, V>> + iterator() + { + return new IteratorI<K, V>(MapI.this, MapI.this); + } + + public boolean + contains(Object o) + { + if(!(o instanceof Entry)) + { + return false; + } + @SuppressWarnings("unchecked") + EntryI<K, V> entry = (EntryI<K, V>)o; + V value = entry.getValue(); + + byte[] v = getImpl(entry.getDbKey()); + return v != null && valEquals(decodeValue(v, _connection.getCommunicator()), value); + } + + public boolean + remove(Object o) + { + if(!(o instanceof Entry)) + { + return false; + } + @SuppressWarnings("unchecked") + EntryI<K, V> entry = (EntryI<K, V>)o; + V value = entry.getValue(); + + byte[] v = getImpl(entry.getDbKey()); + if(v != null && valEquals(decodeValue(v, _connection.getCommunicator()), value)) + { + return removeImpl(entry.getDbKey()); + } + return false; + } + + public int + size() + { + return MapI.this.size(); + } + + public void + clear() + { + MapI.this.clear(); + } + }; + } + + return _entrySet; + } + + // + // IteratorModel methods + // + + public String + dbName() + { + return _dbName; + } + + public TraceLevels + traceLevels() + { + return _trace; + } + + public com.sleepycat.db.Cursor + openCursor() + throws com.sleepycat.db.DatabaseException + { + return _db.db().openCursor(_connection.dbTxn(), null); + } + + public EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return firstEntry(cursor, null, false, null, false); + } + + public EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return nextEntry(cursor, null, false); + } + + com.sleepycat.db.Database + db() + { + return _db.db(); + } + + ConnectionI + connection() + { + return _connection; + } + + int + closeAllIteratorsExcept(Map.EntryIterator<java.util.Map.Entry<K, V>> except) + { + int count = 0; + + synchronized(_iteratorList) + { + java.util.Iterator<IteratorI> p = _iteratorList.iterator(); + + while(p.hasNext()) + { + IteratorI i = p.next(); + if(i != except) + { + i.close(); + ++count; + } + } + } + + return count; + } + + Object + addIterator(IteratorI i) + { + synchronized(_iteratorList) + { + _iteratorList.addFirst(i); + java.util.Iterator<IteratorI> p = _iteratorList.iterator(); + p.next(); + return p; + } + } + + void + removeIterator(Object token) + { + @SuppressWarnings("unchecked") + java.util.Iterator<IteratorI> i = (java.util.Iterator<IteratorI>)token; + + synchronized(_iteratorList) + { + i.remove(); + } + } + + // + // Convenience method for use in this class. + // + private EntryI<K, V> + entrySearch(Search.Type type, byte[] key, boolean includeValue) + { + return entrySearch(type, key, includeValue, null); + } + + // + // Also used by SubMap. + // + EntryI<K, V> + entrySearch(Search.Type type, byte[] key, boolean includeValue, Search.KeyValidator validator) + { + if(type != Search.Type.FIRST && type != Search.Type.LAST && key == null) + { + throw new NullPointerException(); + } + + if(_db.db() == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _trace.errorPrefix + "\"" + dbName() + "\" has been closed"; + throw ex; + } + + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(key); + com.sleepycat.db.DatabaseEntry dbValue = includeValue ? new com.sleepycat.db.DatabaseEntry() : null; + + if(Search.search(type, _connection, _dbName, _db.db(), dbKey, dbValue, _comparator, validator, _trace)) + { + return new EntryI<K, V>(this, null, dbKey, dbValue != null ? dbValue.getData() : null, null); + } + + return null; + } + + // + // For ascending maps. + // + EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + if(fromKey != null) + { + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + + byte[] k = encodeKey(fromKey, _connection.getCommunicator()); + dbKey.setData(k); + dbKey.setReuseBuffer(false); + + com.sleepycat.db.OperationStatus status = cursor.getSearchKeyRange(dbKey, dbValue, null); + + if(status == com.sleepycat.db.OperationStatus.SUCCESS && !fromInclusive) + { + int cmp = _comparator.compare(dbKey.getData(), k); + assert(cmp >= 0); + if(cmp == 0) + { + status = cursor.getNextNoDup(dbKey, dbValue, null); + } + } + + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbKey, dbValue, fromKey, fromInclusive, toKey, toInclusive); + } + + return null; + } + else + { + return nextEntry(cursor, toKey, toInclusive); + } + } + + // + // For ascending maps. + // + EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor, K toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + + if(cursor.getNext(dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbKey, dbValue, null, false, toKey, toInclusive); + } + + return null; + } + + // + // For descending maps. + // + EntryI<K, V> + lastEntry(com.sleepycat.db.Cursor cursor, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.OperationStatus status = null; + + if(fromKey != null) + { + byte[] k = encodeKey(fromKey, _connection.getCommunicator()); + dbKey.setData(k); + dbKey.setReuseBuffer(false); + + status = cursor.getSearchKeyRange(dbKey, dbValue, null); + + if(status == com.sleepycat.db.OperationStatus.SUCCESS && !fromInclusive) + { + int cmp = _comparator.compare(dbKey.getData(), k); + assert(cmp >= 0); + if(cmp == 0) + { + status = cursor.getPrevNoDup(dbKey, dbValue, null); + } + } + } + else + { + status = cursor.getLast(dbKey, dbValue, null); + } + + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbKey, dbValue, toKey, toInclusive, fromKey, fromInclusive); + } + + return null; + } + + // + // For descending maps. + // + EntryI<K, V> + previousEntry(com.sleepycat.db.Cursor cursor, K toKey, boolean toInclusive) + throws com.sleepycat.db.DatabaseException + { + com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + + if(cursor.getPrev(dbKey, dbValue, null) == com.sleepycat.db.OperationStatus.SUCCESS) + { + return newEntry(dbKey, dbValue, toKey, toInclusive, null, false); + } + + return null; + } + + void + putImpl(com.sleepycat.db.DatabaseEntry dbKey, V value) + { + if(_db == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _trace.errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + byte[] v = encodeValue(value, _connection.getCommunicator()); + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(v); + + if(_trace.level >= 2) + { + _trace.logger.trace("Freeze.Map", "writing value in Db \"" + _dbName + "\""); + } + + com.sleepycat.db.Transaction txn = _connection.dbTxn(); + if(txn == null) + { + closeAllIterators(); + } + + for(;;) + { + try + { + _db.db().put(txn, dbKey, dbValue); + break; + } + catch(com.sleepycat.db.DeadlockException e) + { + if(txn != null) + { + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Db.put: " + e.getMessage(), _connection.currentTransaction()); + ex.initCause(e); + throw ex; + } + else + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.Map.putImpl while " + "writing into Db \"" + + _dbName + "\"; retrying..."); + } + + // + // Try again + // + } + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Db.put: " + e.getMessage(); + throw ex; + } + } + } + + boolean + removeImpl(com.sleepycat.db.DatabaseEntry dbKey) + { + if(_db == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _trace.errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + if(_trace.level >= 2) + { + _trace.logger.trace("Freeze.Map", "deleting value from Db \"" + _dbName + "\""); + } + + com.sleepycat.db.Transaction txn = _connection.dbTxn(); + if(txn == null) + { + closeAllIterators(); + } + + for(;;) + { + try + { + com.sleepycat.db.OperationStatus rc = _db.db().delete(txn, dbKey); + return (rc == com.sleepycat.db.OperationStatus.SUCCESS); + } + catch(com.sleepycat.db.DeadlockException e) + { + if(txn != null) + { + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Db.del: " + e.getMessage(), _connection.currentTransaction()); + ex.initCause(e); + throw ex; + } + else + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.Map.removeImpl while " + "writing into Db \"" + + _dbName + "\"; retrying..."); + } + + // + // Try again + // + } + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Db.del: " + e.getMessage(); + throw ex; + } + } + } + + private byte[] + getImpl(com.sleepycat.db.DatabaseEntry dbKey) + { + if(_db == null) + { + DatabaseException ex = new DatabaseException(); + ex.message = _trace.errorPrefix + "\"" + _dbName + "\" has been closed"; + throw ex; + } + + com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); + + if(_trace.level >= 2) + { + _trace.logger.trace("Freeze.Map", "reading value from Db \"" + _dbName + "\""); + } + + for(;;) + { + try + { + com.sleepycat.db.OperationStatus rc = _db.db().get(_connection.dbTxn(), dbKey, dbValue, null); + if(rc == com.sleepycat.db.OperationStatus.SUCCESS) + { + return dbValue.getData(); + } + else + { + return null; + } + } + catch(com.sleepycat.db.DeadlockException e) + { + if(_connection.dbTxn() != null) + { + DeadlockException ex = new DeadlockException( + _trace.errorPrefix + "Db.get: " + e.getMessage(), _connection.currentTransaction()); + ex.initCause(e); + throw ex; + } + else + { + if(_trace.deadlockWarning) + { + _trace.logger.warning("Deadlock in Freeze.Map.getImpl while " + "reading Db \"" + _dbName + + "\"; retrying..."); + } + + // + // Try again + // + } + } + catch(com.sleepycat.db.DatabaseException e) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(e); + ex.message = _trace.errorPrefix + "Db.get: " + e.getMessage(); + throw ex; + } + } + } + + private EntryI<K, V> + newEntry(com.sleepycat.db.DatabaseEntry dbKey, com.sleepycat.db.DatabaseEntry dbValue, K fromKey, + boolean fromInclusive, K toKey, boolean toInclusive) + { + K key = null; + if(fromKey != null || toKey != null) + { + key = decodeKey(dbKey.getData(), _connection.getCommunicator()); + if(!checkRange(key, fromKey, fromInclusive, toKey, toInclusive)) + { + return null; + } + } + + return new EntryI<K, V>(this, key, dbKey, dbValue.getData(), null); + } + + private boolean + checkRange(K key, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + if(fromKey != null) + { + int cmp = _comparator.comparator().compare(key, fromKey); + if((fromInclusive && cmp < 0) || (!fromInclusive && cmp <= 0)) + { + return false; + } + } + if(toKey != null) + { + int cmp = _comparator.comparator().compare(key, toKey); + if((toInclusive && cmp > 0) || (!toInclusive && cmp >= 0)) + { + return false; + } + } + return true; + } + + private static boolean + valEquals(Object v1, Object v2) + { + return (v1 == null ? v2 == null : v1.equals(v2)); + } + + private class Comparator implements java.util.Comparator<byte[]> + { + Comparator(java.util.Comparator<K> comparator) + { + _comparator = comparator; + } + + public java.util.Comparator<K> + comparator() + { + return _comparator; + } + + public int + compare(byte[] d1, byte[] d2) + { + Ice.Communicator communicator = _connection.getCommunicator(); + return _comparator.compare(decodeKey(d1, communicator), decodeKey(d2, communicator)); + } + + // + // The user-supplied comparator + // + private final java.util.Comparator<K> _comparator; + } + + public static class Patcher implements IceInternal.Patcher + { + public + Patcher(String type) + { + this.type = type; + } + + public void + patch(Ice.Object v) + { + value = v; + } + + public String + type() + { + return this.type; + } + + public Ice.Object + value() + { + return this.value; + } + + public String type; + public Ice.Object value; + } + + private final ConnectionI _connection; + private final Comparator _comparator; + private final String _dbName; + + private final TraceLevels _trace; + private java.util.Iterator _token; + private MapDb _db; + + private java.util.Set<java.util.Map.Entry<K, V>> _entrySet; + private NavigableMap<K, V> _descendingMap; + private LinkedList<IteratorI> _iteratorList = new LinkedList<IteratorI>(); + private java.util.Map<String, MapIndex> _indexMap = new java.util.HashMap<String, MapIndex>(); +} diff --git a/java/src/Freeze/MapInternal/Search.java b/java/src/Freeze/MapInternal/Search.java new file mode 100644 index 00000000000..195430c631e --- /dev/null +++ b/java/src/Freeze/MapInternal/Search.java @@ -0,0 +1,238 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +import Freeze.ConnectionI; +import Freeze.DatabaseException; +import Freeze.DeadlockException; + +class Search +{ + enum Type + { + FIRST // The first entry + { + Type descending() { return LAST; }; + }, + LAST // The last entry + { + Type descending() { return FIRST; }; + }, + CEILING // The entry with the smallest key greater than or equal to the target key + { + Type descending() { return FLOOR; }; + }, + FLOOR // The entry with the greatest key less than or equal to the target key + { + Type descending() { return CEILING; }; + }, + HIGHER // The entry with the smallest key greater than the target key + { + Type descending() { return LOWER; }; + }, + LOWER // The entry with the greatest key less than the target key + { + Type descending() { return HIGHER; }; + }; + + abstract Type descending(); // Returns the descending (opposite) value. + } + + interface KeyValidator + { + boolean keyInRange(byte[] key); + } + + static boolean + search(Type type, ConnectionI connection, String dbName, com.sleepycat.db.Database db, + com.sleepycat.db.DatabaseEntry key, com.sleepycat.db.DatabaseEntry value, + java.util.Comparator<byte[]> comparator, KeyValidator validator, TraceLevels trace) + { + if(type != Type.FIRST && type != Type.LAST && comparator == null) + { + throw new UnsupportedOperationException("A comparator is required"); + } + + if(trace.level >= 2) + { + trace.logger.trace("Freeze.Map", "searching Db \"" + dbName + "\""); + } + + if(value == null) + { + value = new com.sleepycat.db.DatabaseEntry(); + value.setPartial(true); // Not interested in the value. + } + + try + { + for(;;) + { + com.sleepycat.db.Cursor dbc = null; + try + { + com.sleepycat.db.DatabaseEntry dbcKey = + new com.sleepycat.db.DatabaseEntry(key != null ? key.getData() : null); + dbcKey.setReuseBuffer(false); + + dbc = db.openCursor(connection.dbTxn(), null); + + com.sleepycat.db.OperationStatus status = null; + + switch(type) + { + case FIRST: + { + status = dbc.getFirst(dbcKey, value, null); + break; + } + case LAST: + { + status = dbc.getLast(dbcKey, value, null); + break; + } + case CEILING: + { + // + // The semantics of getSearchKeyRange match CEILING. + // + status = dbc.getSearchKeyRange(dbcKey, value, null); + break; + } + case FLOOR: + { + status = dbc.getSearchKeyRange(dbcKey, value, null); + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + // + // getSearchKeyRange returns the smallest key greater than or equal to + // the target key. If the matching key is greater than the target key + // then we need to get the previous entry. + // + int cmp = comparator.compare(dbcKey.getData(), key.getData()); + assert(cmp >= 0); + if(cmp > 0) + { + status = dbc.getPrevNoDup(dbcKey, value, null); + } + } + else if(status == com.sleepycat.db.OperationStatus.NOTFOUND) + { + // + // All keys must be less than the target key so we pick the largest of + // all (the last one). + // + status = dbc.getLast(dbcKey, value, null); + } + break; + } + case HIGHER: + { + status = dbc.getSearchKeyRange(dbcKey, value, null); + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + // + // getSearchKeyRange returns the smallest key greater than or equal to + // the target key. If the matching key is equal to the target key + // then we need to get the next entry. + // + int cmp = comparator.compare(dbcKey.getData(), key.getData()); + assert(cmp >= 0); + if(cmp == 0) + { + status = dbc.getNextNoDup(dbcKey, value, null); + } + } + break; + } + case LOWER: + { + status = dbc.getSearchKeyRange(dbcKey, value, null); + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + // + // getSearchKeyRange returns the smallest key greater than or equal to + // the target key. We move to the previous entry, whose key must be less + // than the target key. + // + status = dbc.getPrevNoDup(dbcKey, value, null); + } + else if(status == com.sleepycat.db.OperationStatus.NOTFOUND) + { + // + // All keys must be less than the target key so we pick the largest of + // all (the last one). + // + status = dbc.getLast(dbcKey, value, null); + } + break; + } + } + + if(status == com.sleepycat.db.OperationStatus.SUCCESS) + { + if(validator == null || validator.keyInRange(dbcKey.getData())) + { + key.setData(dbcKey.getData()); + return true; + } + } + + return false; + } + catch(com.sleepycat.db.DeadlockException dx) + { + if(connection.dbTxn() != null) + { + DeadlockException ex = new DeadlockException( + trace.errorPrefix + dx.getMessage(), connection.currentTransaction()); + ex.initCause(dx); + throw ex; + } + else + { + if(trace.deadlockWarning) + { + trace.logger.warning("Deadlock in Freeze.Map while searching \"" + dbName + + "\"; retrying..."); + } + + // + // Retry + // + } + } + finally + { + if(dbc != null) + { + try + { + dbc.close(); + } + catch(com.sleepycat.db.DeadlockException dx) + { + // + // Ignored + // + } + } + } + } + } + catch(com.sleepycat.db.DatabaseException dx) + { + DatabaseException ex = new DatabaseException(); + ex.initCause(dx); + ex.message = trace.errorPrefix + dx.getMessage(); + throw ex; + } + } +} diff --git a/java/src/Freeze/MapInternal/SubMap.java b/java/src/Freeze/MapInternal/SubMap.java new file mode 100644 index 00000000000..c503fae0abf --- /dev/null +++ b/java/src/Freeze/MapInternal/SubMap.java @@ -0,0 +1,695 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +import Freeze.ConnectionI; +import Freeze.Map; +import Freeze.NavigableMap; + +// +// Submap of a Freeze Map or of another submap +// + +class SubMap<K, V> extends java.util.AbstractMap<K, V> implements NavigableMap<K, V> +{ + SubMap(MapI<K, V> map, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive, boolean ascending) + { + _map = map; + if(ascending) + { + _view = new AscendingView(fromKey, fromInclusive, toKey, toInclusive); + } + else + { + _view = new DescendingView(fromKey, fromInclusive, toKey, toInclusive); + } + } + + private + SubMap(MapI<K, V> map, View v) + { + _map = map; + _view = v; + } + + // + // NavigableMap methods + // + + public boolean + fastRemove(K key) + { + if(!_view.inRange(key, true)) + { + return false; + } + + return _map.fastRemove(key); + } + + public java.util.Map.Entry<K, V> + firstEntry() + { + return _view.first(); + } + + public java.util.Map.Entry<K, V> + lastEntry() + { + return _view.last(); + } + + public java.util.Map.Entry<K, V> + ceilingEntry(K key) + { + return _view.ceiling(key); + } + + public java.util.Map.Entry<K, V> + floorEntry(K key) + { + return _view.floor(key); + } + + public java.util.Map.Entry<K, V> + higherEntry(K key) + { + return _view.higher(key); + } + + public java.util.Map.Entry<K, V> + lowerEntry(K key) + { + return _view.lower(key); + } + + public K + ceilingKey(K key) + { + EntryI<K, V> e = _view.ceiling(key); + return e != null ? e.getKey() : null; + } + + public K + floorKey(K key) + { + EntryI<K, V> e = _view.floor(key); + return e != null ? e.getKey() : null; + } + + public K + higherKey(K key) + { + EntryI<K, V> e = _view.higher(key); + return e != null ? e.getKey() : null; + } + + public K + lowerKey(K key) + { + EntryI<K, V> e = _view.lower(key); + return e != null ? e.getKey() : null; + } + + public java.util.Set<K> + descendingKeySet() + { + return descendingMap().keySet(); + } + + public NavigableMap<K, V> + descendingMap() + { + if(_descendingMap == null) + { + View v = _view.descendingView(); + _descendingMap = new SubMap<K, V>(_map, v); + } + return _descendingMap; + } + + public NavigableMap<K, V> + headMap(K toKey, boolean inclusive) + { + if(toKey == null) + { + throw new NullPointerException(); + } + View v = _view.subView(null, false, toKey, inclusive); + return new SubMap<K, V>(_map, v); + } + + public NavigableMap<K, V> + subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + if(fromKey == null || toKey == null) + { + throw new NullPointerException(); + } + View v = _view.subView(fromKey, fromInclusive, toKey, toInclusive); + return new SubMap<K, V>(_map, v); + } + + public NavigableMap<K, V> + tailMap(K fromKey, boolean inclusive) + { + if(fromKey == null) + { + throw new NullPointerException(); + } + View v = _view.subView(fromKey, inclusive, null, false); + return new SubMap<K, V>(_map, v); + } + + public java.util.Map.Entry<K, V> + pollFirstEntry() + { + EntryI<K, V> e = _view.first(); + if(e != null) + { + _map.removeImpl(e.getDbKey()); + } + return e; + } + + public java.util.Map.Entry<K, V> + pollLastEntry() + { + EntryI<K, V> e = _view.last(); + if(e != null) + { + _map.removeImpl(e.getDbKey()); + } + return e; + } + + // + // SortedMap methods + // + + public java.util.Comparator<? super K> + comparator() + { + return _view.comparator(); + } + + public K + firstKey() + { + EntryI<K, V> e = _view.first(); + if(e == null) + { + throw new java.util.NoSuchElementException(); + } + return e.getKey(); + } + + public K + lastKey() + { + EntryI<K, V> e = _view.last(); + if(e == null) + { + throw new java.util.NoSuchElementException(); + } + return e.getKey(); + } + + public java.util.SortedMap<K, V> + headMap(K toKey) + { + return headMap(toKey, false); + } + + public java.util.SortedMap<K, V> + tailMap(K fromKey) + { + return tailMap(fromKey, true); + } + + public java.util.SortedMap<K, V> + subMap(K fromKey, K toKey) + { + return subMap(fromKey, true, toKey, false); + } + + // + // Map methods + // + + public java.util.Set<java.util.Map.Entry<K, V>> + entrySet() + { + if(_entrySet == null) + { + _entrySet = new java.util.AbstractSet<java.util.Map.Entry<K, V>>() + { + public java.util.Iterator<java.util.Map.Entry<K, V>> + iterator() + { + return new IteratorI<K, V>(_map, _view); + } + + public boolean + contains(Object o) + { + // + // If the main map contains this object, verify it's within the range of this submap. + // + if(_map.entrySet().contains(o)) + { + @SuppressWarnings("unchecked") + EntryI<K, V> entry = (EntryI<K, V>)o; + return _view.inRange(entry.getKey(), true); + } + else + { + return false; + } + } + + public boolean + remove(Object o) + { + if(o instanceof EntryI) + { + @SuppressWarnings("unchecked") + EntryI<K, V> entry = (EntryI<K, V>)o; + return _view.inRange(entry.getKey(), true) && _map.entrySet().remove(o); + } + else + { + return false; + } + } + + public int + size() + { + throw new UnsupportedOperationException(); + } + + public boolean + isEmpty() + { + try + { + firstKey(); + return false; + } + catch(java.util.NoSuchElementException e) + { + return true; + } + } + }; + } + return _entrySet; + } + + // + // Put is not implemented (you have to put in the main map view) + // + + public boolean + constainsKey(Object key) + { + @SuppressWarnings("unchecked") + K k = (K)key; + if(!_view.inRange(k, true)) + { + return false; + } + + return _map.containsKey(k); + } + + public V + get(Object key) + { + @SuppressWarnings("unchecked") + K k = (K)key; + if(!_view.inRange(k, true)) + { + return null; + } + + return _map.get(k); + } + + public V + remove(Object key) + { + @SuppressWarnings("unchecked") + K k = (K)key; + if(!_view.inRange(k, true)) + { + return null; + } + + return _map.remove(k); + } + + private abstract class View implements IteratorModel<K, V>, Search.KeyValidator + { + protected + View(java.util.Comparator<? super K> comparator, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + _comparator = comparator; + _fromKey = fromKey; + _fromInclusive = fromInclusive; + _toKey = toKey; + _toInclusive = toInclusive; + + // + // Validate the key range. + // + if(_fromKey != null && _toKey != null) + { + int cmp = comparator.compare(_fromKey, _toKey); + if(cmp > 0 || (cmp == 0 && !(_fromInclusive && _toInclusive))) + { + throw new IllegalArgumentException(); + } + } + } + + protected + View(View v, java.util.Comparator<? super K> comparator, K fromKey, boolean fromInclusive, K toKey, + boolean toInclusive) + { + this(comparator, fromKey, fromInclusive, toKey, toInclusive); + + // + // Verify that the key range is correct with respect to the original view. + // + if(!v.inRange(_fromKey, _fromInclusive) || !v.inRange(_toKey, _toInclusive)) + { + throw new IllegalArgumentException(); + } + } + + abstract Search.Type mapSearchType(Search.Type type); + abstract View copy(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive); + abstract View descendingView(); + + final EntryI<K, V> + first() + { + Search.Type type; + byte[] key = null; + if(_fromKey != null) + { + type = _fromInclusive ? mapSearchType(Search.Type.CEILING) : mapSearchType(Search.Type.HIGHER); + key = fromKeyBytes(); + } + else + { + type = mapSearchType(Search.Type.FIRST); + } + return _map.entrySearch(type, key, true, this); + } + + final EntryI<K, V> + last() + { + Search.Type type; + byte[] key = null; + if(_toKey != null) + { + type = _toInclusive ? mapSearchType(Search.Type.FLOOR) : mapSearchType(Search.Type.LOWER); + key = toKeyBytes(); + } + else + { + type = mapSearchType(Search.Type.LAST); + } + return _map.entrySearch(type, key, true, this); + } + + final EntryI<K, V> + ceiling(K key) + { + byte[] k = _map.encodeKey(key, _map.connection().getCommunicator()); + return _map.entrySearch(mapSearchType(Search.Type.CEILING), k, true, this); + } + + final EntryI<K, V> + floor(K key) + { + byte[] k = _map.encodeKey(key, _map.connection().getCommunicator()); + return _map.entrySearch(mapSearchType(Search.Type.FLOOR), k, true, this); + } + + final EntryI<K, V> + higher(K key) + { + byte[] k = _map.encodeKey(key, _map.connection().getCommunicator()); + return _map.entrySearch(mapSearchType(Search.Type.HIGHER), k, true, this); + } + + final EntryI<K, V> + lower(K key) + { + byte[] k = _map.encodeKey(key, _map.connection().getCommunicator()); + return _map.entrySearch(mapSearchType(Search.Type.LOWER), k, true, this); + } + + final View + subView(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + if(fromKey == null) + { + fromKey = _fromKey; + fromInclusive = _fromInclusive; + } + if(toKey == null) + { + toKey = _toKey; + toInclusive = _toInclusive; + } + return copy(fromKey, fromInclusive, toKey, toInclusive); + } + + // + // IteratorModel methods (partial) + // + + final public String + dbName() + { + return _map.dbName(); + } + + final public TraceLevels + traceLevels() + { + return _map.traceLevels(); + } + + final public com.sleepycat.db.Cursor + openCursor() + throws com.sleepycat.db.DatabaseException + { + return _map.openCursor(); + } + + // + // Search.KeyValidator methods + // + + final public boolean + keyInRange(byte[] key) + { + K k = _map.decodeKey(key, _map.connection().getCommunicator()); + return inRange(k, true); + } + + final boolean + inRange(K key, boolean inclusive) + { + return !tooLow(key, inclusive, _fromKey, _fromInclusive) && + !tooHigh(key, inclusive, _toKey, _toInclusive); + } + + final java.util.Comparator<? super K> + comparator() + { + return _comparator; + } + + final protected byte[] + fromKeyBytes() + { + if(_fromKey != null && _fromKeyBytes == null) + { + _fromKeyBytes = _map.encodeKey(_fromKey, _map.connection().getCommunicator()); + } + return _fromKeyBytes; + } + + final protected byte[] + toKeyBytes() + { + if(_toKey != null && _toKeyBytes == null) + { + _toKeyBytes = _map.encodeKey(_toKey, _map.connection().getCommunicator()); + } + return _toKeyBytes; + } + + final protected boolean + tooLow(K key, boolean inclusive, K targetKey, boolean targetInclusive) + { + if(key != null && targetKey != null) + { + int cmp = comparator().compare(key, targetKey); + if(cmp < 0 || (cmp == 0 && inclusive && !targetInclusive)) + { + return true; + } + } + return false; + } + + final protected boolean + tooHigh(K key, boolean inclusive, K targetKey, boolean targetInclusive) + { + if(key != null && targetKey != null) + { + int cmp = comparator().compare(key, targetKey); + if(cmp > 0 || (cmp == 0 && inclusive && !targetInclusive)) + { + return true; + } + } + return false; + } + + final java.util.Comparator<? super K> _comparator; + final K _fromKey; + final boolean _fromInclusive; + final K _toKey; + final boolean _toInclusive; + private byte[] _fromKeyBytes; + private byte[] _toKeyBytes; + } + + private class AscendingView extends View + { + AscendingView(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + super(_map.comparator(), fromKey, fromInclusive, toKey, toInclusive); + } + + AscendingView(View v, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + super(v, _map.comparator(), fromKey, fromInclusive, toKey, toInclusive); + } + + // + // View methods + // + + Search.Type + mapSearchType(Search.Type type) + { + return type; + } + + View + copy(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return new AscendingView(this, fromKey, fromInclusive, toKey, toInclusive); + } + + View + descendingView() + { + return new DescendingView(this, _toKey, _toInclusive, _fromKey, _fromInclusive); + } + + // + // IteratorModel methods + // + + public EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _map.firstEntry(cursor, _fromKey, _fromInclusive, _toKey, _toInclusive); + } + + public EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _map.nextEntry(cursor, _toKey, _toInclusive); + } + } + + private class DescendingView extends View + { + DescendingView(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + super(java.util.Collections.reverseOrder(_map.comparator()), fromKey, fromInclusive, toKey, toInclusive); + } + + DescendingView(View v, K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + super(v, java.util.Collections.reverseOrder(_map.comparator()), fromKey, fromInclusive, toKey, toInclusive); + } + + // + // View methods + // + + Search.Type + mapSearchType(Search.Type type) + { + return type.descending(); + } + + View + copy(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) + { + return new DescendingView(this, fromKey, fromInclusive, toKey, toInclusive); + } + + View + descendingView() + { + return new AscendingView(this, _toKey, _toInclusive, _fromKey, _fromInclusive); + } + + // + // IteratorModel methods + // + + public EntryI<K, V> + firstEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _map.lastEntry(cursor, _fromKey, _fromInclusive, _toKey, _toInclusive); + } + + public EntryI<K, V> + nextEntry(com.sleepycat.db.Cursor cursor) + throws com.sleepycat.db.DatabaseException + { + return _map.previousEntry(cursor, _toKey, _toInclusive); + } + } + + private final MapI<K, V> _map; + private final View _view; + private java.util.Set<java.util.Map.Entry<K, V>> _entrySet; + private NavigableMap<K, V> _descendingMap; +} diff --git a/java/src/Freeze/MapInternal/TraceLevels.java b/java/src/Freeze/MapInternal/TraceLevels.java new file mode 100644 index 00000000000..a6058f14f39 --- /dev/null +++ b/java/src/Freeze/MapInternal/TraceLevels.java @@ -0,0 +1,28 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze.MapInternal; + +import Freeze.ConnectionI; + +class TraceLevels +{ + TraceLevels(ConnectionI connection, String dbName) + { + errorPrefix = "Freeze DB DbEnv(\"" + connection.envName() + "\") Db(\"" + dbName + "\"): "; + level = connection.trace(); + deadlockWarning = connection.deadlockWarning(); + logger = connection.getCommunicator().getLogger(); + } + + final String errorPrefix; + final int level; + final boolean deadlockWarning; + final Ice.Logger logger; +} diff --git a/java/src/Freeze/NavigableMap.java b/java/src/Freeze/NavigableMap.java new file mode 100644 index 00000000000..7d9e3ecfbc8 --- /dev/null +++ b/java/src/Freeze/NavigableMap.java @@ -0,0 +1,42 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +package Freeze; + +public interface NavigableMap<K, V> extends java.util.SortedMap<K, V> +{ + // + // Faster alternative to the standard remove() method because it + // doesn't read and decode the old value. + // + boolean fastRemove(K key); + + java.util.Map.Entry<K, V> firstEntry(); + java.util.Map.Entry<K, V> lastEntry(); + + java.util.Map.Entry<K, V> ceilingEntry(K key); + java.util.Map.Entry<K, V> floorEntry(K key); + java.util.Map.Entry<K, V> higherEntry(K key); + java.util.Map.Entry<K, V> lowerEntry(K key); + + K ceilingKey(K key); + K floorKey(K key); + K higherKey(K key); + K lowerKey(K key); + + java.util.Set<K> descendingKeySet(); + NavigableMap<K, V> descendingMap(); + + NavigableMap<K, V> headMap(K toKey, boolean inclusive); + NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive); + NavigableMap<K, V> tailMap(K fromKey, boolean inclusive); + + java.util.Map.Entry<K, V> pollFirstEntry(); + java.util.Map.Entry<K, V> pollLastEntry(); +} diff --git a/java/src/Freeze/ObjectStore.java b/java/src/Freeze/ObjectStore.java index 1bf9f3ee1db..6bbdfa5024a 100644 --- a/java/src/Freeze/ObjectStore.java +++ b/java/src/Freeze/ObjectStore.java @@ -11,17 +11,17 @@ package Freeze; class ObjectStore implements IceUtil.Store { - ObjectStore(String facet, String facetType, boolean createDb, EvictorI evictor, - java.util.List indices, boolean populateEmptyIndices) + ObjectStore(String facet, String facetType, boolean createDb, EvictorI evictor, java.util.List<Index> indices, + boolean populateEmptyIndices) { _cache = new IceUtil.Cache(this); - + _facet = facet; - + _evictor = evictor; _indices = indices; _communicator = evictor.communicator(); - + if(facet.equals("")) { _dbName = EvictorI.defaultDb; @@ -39,30 +39,29 @@ class ObjectStore implements IceUtil.Store Ice.ObjectFactory factory = _communicator.findObjectFactory(facetType); if(factory == null) { - throw new DatabaseException(_evictor.errorPrefix() + "No object factory registered for type-id '" - + facetType + "'"); + throw new DatabaseException(_evictor.errorPrefix() + "No object factory registered for type-id '" + + facetType + "'"); } - + _sampleServant = factory.create(facetType); } - Connection connection = Util.createConnection(_communicator, evictor.dbEnv().getEnvName()); try { - Catalog catalog = new Catalog(connection, Util.catalogName(), true); - CatalogData catalogData = (CatalogData)catalog.get(evictor.filename()); - + Catalog catalog = new Catalog(connection, Util.catalogName(), true); + CatalogData catalogData = catalog.get(evictor.filename()); + if(catalogData != null && catalogData.evictor == false) { DatabaseException ex = new DatabaseException(); ex.message = _evictor.errorPrefix() + evictor.filename() + " is not an evictor database"; throw ex; } - + com.sleepycat.db.Environment dbEnv = evictor.dbEnv().getEnv(); - + // // TODO: FREEZE_DB_MODE // @@ -72,18 +71,19 @@ class ObjectStore implements IceUtil.Store Ice.Properties properties = _evictor.communicator().getProperties(); String propPrefix = "Freeze.Evictor." + _evictor.filename() + "."; - + int btreeMinKey = properties.getPropertyAsInt(propPrefix + _dbName + ".BtreeMinKey"); if(btreeMinKey > 2) { if(_evictor.trace() >= 1) { _evictor.communicator().getLogger().trace( - "Freeze.Evictor", "Setting \"" + _evictor.filename() + "." + _dbName + "\"'s btree minkey to " + btreeMinKey); + "Freeze.Evictor", "Setting \"" + _evictor.filename() + "." + _dbName + + "\"'s btree minkey to " + btreeMinKey); } config.setBtreeMinKey(btreeMinKey); } - + boolean checksum = properties.getPropertyAsInt(propPrefix + "Checksum") > 0; if(checksum) { @@ -92,10 +92,10 @@ class ObjectStore implements IceUtil.Store _evictor.communicator().getLogger().trace( "Freeze.Evictor", "Turning checksum on for \"" + _evictor.filename() + "\""); } - + config.setChecksum(true); } - + int pageSize = properties.getPropertyAsInt(propPrefix + "PageSize"); if(pageSize > 0) { @@ -107,21 +107,18 @@ class ObjectStore implements IceUtil.Store config.setPageSize(pageSize); } - try - { + { Transaction tx = connection.beginTransaction(); com.sleepycat.db.Transaction txn = Util.getTxn(tx); _db = dbEnv.openDatabase(txn, evictor.filename(), _dbName, config); - java.util.Iterator p = _indices.iterator(); - while(p.hasNext()) + for(Index index : _indices) { - Index index = (Index) p.next(); index.associate(this, txn, createDb, populateEmptyIndices); } - + if(catalogData == null) { catalogData = new CatalogData(); @@ -172,11 +169,9 @@ class ObjectStore implements IceUtil.Store try { _db.close(); - - java.util.Iterator p = _indices.iterator(); - while(p.hasNext()) + + for(Index index : _indices) { - Index index = (Index)p.next(); index.close(); } _indices.clear(); @@ -190,7 +185,7 @@ class ObjectStore implements IceUtil.Store } _db = null; } - + boolean dbHasObject(Ice.Identity ident, TransactionI transaction) { @@ -205,22 +200,21 @@ class ObjectStore implements IceUtil.Store } } - byte[] key = marshalKey(ident, _communicator); com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(key); - + // // Keep 0 length since we're not interested in the data // com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); dbValue.setPartial(true); - + for(;;) { try - { + { com.sleepycat.db.OperationStatus err = _db.get(tx, dbKey, dbValue, null); - + if(err == com.sleepycat.db.OperationStatus.SUCCESS) { return true; @@ -239,8 +233,7 @@ class ObjectStore implements IceUtil.Store if(_evictor.deadlockWarning()) { _communicator.getLogger().warning("Deadlock in Freeze.ObjectStore.dhHasObject while reading " + - "Db \"" + _evictor.filename() + "/" + _dbName + - "\""); + "Db \"" + _evictor.filename() + "/" + _dbName + "\""); } if(tx != null) @@ -376,19 +369,19 @@ class ObjectStore implements IceUtil.Store { return _db; } - + final Ice.Communicator communicator() { return _communicator; } - + final EvictorI evictor() { return _evictor; } - + final String facet() { @@ -424,9 +417,9 @@ class ObjectStore implements IceUtil.Store for(;;) { try - { + { com.sleepycat.db.OperationStatus rs = _db.get(null, dbKey, dbValue, null); - + if(rs == com.sleepycat.db.OperationStatus.NOTFOUND) { return null; @@ -461,7 +454,7 @@ class ObjectStore implements IceUtil.Store ObjectRecord rec = unmarshalValue(dbValue.getData(), _communicator); _evictor.initialize(ident, _facet, rec.servant); - + Object result = _evictor.createEvictorElement(ident, rec, this); return result; } @@ -489,9 +482,9 @@ class ObjectStore implements IceUtil.Store com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(); try - { + { com.sleepycat.db.OperationStatus rs = _db.get(tx, dbKey, dbValue, null); - + if(rs == com.sleepycat.db.OperationStatus.NOTFOUND) { return null; @@ -509,9 +502,9 @@ class ObjectStore implements IceUtil.Store _communicator.getLogger().warning("Deadlock in Freeze.ObjectStore.load while reading Db \"" + _evictor.filename() + "/" + _dbName + "\""); } - - DeadlockException ex = new DeadlockException(_evictor.errorPrefix() + "Db.get: " + dx.getMessage(), - transaction); + + DeadlockException ex = new DeadlockException( + _evictor.errorPrefix() + "Db.get: " + dx.getMessage(), transaction); ex.initCause(dx); throw ex; } @@ -528,7 +521,6 @@ class ObjectStore implements IceUtil.Store return rec; } - void update(Ice.Identity ident, ObjectRecord objectRecord, TransactionI transaction) { @@ -546,12 +538,13 @@ class ObjectStore implements IceUtil.Store { String msg = _evictor.errorPrefix() + "Attempting to save a '" + objectRecord.servant.ice_id() + "' servant in a database of '" + _sampleServant.ice_id() + "' servants"; - + throw new DatabaseException(msg); } com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(marshalKey(ident, _communicator)); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(marshalValue(objectRecord, _communicator)); + com.sleepycat.db.DatabaseEntry dbValue = + new com.sleepycat.db.DatabaseEntry(marshalValue(objectRecord, _communicator)); try { @@ -568,7 +561,7 @@ class ObjectStore implements IceUtil.Store _communicator.getLogger().warning("Deadlock in Freeze.ObjectStore.update while updating Db \"" + _evictor.filename() + "/" + _dbName + "\""); } - + DeadlockException ex = new DeadlockException( _evictor.errorPrefix() + "Db.put: " + dx.getMessage(), transaction); ex.initCause(dx); @@ -598,13 +591,14 @@ class ObjectStore implements IceUtil.Store } com.sleepycat.db.DatabaseEntry dbKey = new com.sleepycat.db.DatabaseEntry(marshalKey(ident, _communicator)); - com.sleepycat.db.DatabaseEntry dbValue = new com.sleepycat.db.DatabaseEntry(marshalValue(objectRecord, _communicator)); + com.sleepycat.db.DatabaseEntry dbValue = + new com.sleepycat.db.DatabaseEntry(marshalValue(objectRecord, _communicator)); if(_sampleServant != null && !objectRecord.servant.ice_id().equals(_sampleServant.ice_id())) { - String msg = _evictor.errorPrefix() + "Attempting to save a '" + objectRecord.servant.ice_id() - + "' servant in a database of '" + _sampleServant.ice_id() + "' servants"; - + String msg = _evictor.errorPrefix() + "Attempting to save a '" + objectRecord.servant.ice_id() + + "' servant in a database of '" + _sampleServant.ice_id() + "' servants"; + throw new DatabaseException(msg); } @@ -621,7 +615,7 @@ class ObjectStore implements IceUtil.Store _communicator.getLogger().warning("Deadlock in Freeze.ObjectStore.update while updating Db \"" + _evictor.filename() + "/" + _dbName + "\""); } - + if(tx != null) { DeadlockException ex = new DeadlockException( @@ -645,7 +639,7 @@ class ObjectStore implements IceUtil.Store boolean remove(Ice.Identity ident, TransactionI transaction) - { + { com.sleepycat.db.Transaction tx = null; if(transaction != null) @@ -675,8 +669,8 @@ class ObjectStore implements IceUtil.Store if(tx != null) { - DeadlockException ex = new DeadlockException(_evictor.errorPrefix() + "Db.delete: " + dx.getMessage(), - transaction); + DeadlockException ex = new DeadlockException( + _evictor.errorPrefix() + "Db.delete: " + dx.getMessage(), transaction); ex.initCause(dx); throw ex; } @@ -700,7 +694,7 @@ class ObjectStore implements IceUtil.Store private final String _facet; private final String _dbName; private final EvictorI _evictor; - private final java.util.List _indices; + private final java.util.List<Index> _indices; private final Ice.Communicator _communicator; private com.sleepycat.db.Database _db; diff --git a/java/src/Freeze/SharedDbEnv.java b/java/src/Freeze/SharedDbEnv.java index 983740d0f06..b39088ec48f 100644 --- a/java/src/Freeze/SharedDbEnv.java +++ b/java/src/Freeze/SharedDbEnv.java @@ -9,7 +9,7 @@ package Freeze; -class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable +public class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable { public static SharedDbEnv get(Ice.Communicator communicator, String envName, com.sleepycat.db.Environment dbEnv) @@ -20,12 +20,12 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable synchronized(_map) { - result = (SharedDbEnv)_map.get(key); + result = _map.get(key); if(result == null) { result = new SharedDbEnv(key, dbEnv); - Object previousValue = _map.put(key, result); + SharedDbEnv previousValue = _map.put(key, result); assert(previousValue == null); } else @@ -40,9 +40,9 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable // // Returns a shared map Db; the caller should NOT close this Db. // - MapDb getSharedMapDb(String dbName, String key, String value, - java.util.Comparator comparator, Map.Index[] indices, java.util.Map indexComparators, - boolean createDb) + public MapDb + getSharedMapDb(String dbName, String key, String value, java.util.Comparator comparator, MapIndex[] indices, + boolean createDb) { if(dbName.equals(_catalog.dbName())) { @@ -64,14 +64,14 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable try { - db = new MapDb(insertConnection, dbName, key, value, comparator, indices, indexComparators, createDb); + db = new MapDb(insertConnection, dbName, key, value, comparator, indices, createDb); } finally { insertConnection.close(); } - Object previousValue = _sharedDbMap.put(dbName, db); + MapDb previousValue = _sharedDbMap.put(dbName, db); assert(previousValue == null); } else @@ -86,7 +86,8 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable // // Tell SharedDbEnv to close and remove this Shared Db from the map // - void removeSharedMapDb(String dbName) + public void + removeSharedMapDb(String dbName) { synchronized(_sharedDbMap) { @@ -126,7 +127,7 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable // // Remove from map // - Object value = _map.remove(_key); + SharedDbEnv value = _map.remove(_key); assert(value == this); // @@ -188,11 +189,9 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable _key.communicator.getLogger().error("Freeze database error in DbEnv \"" + _key.envName + "\": " + message); } - // // EvictorContext factory/manager // - // // Create an evictor context associated with the calling thread @@ -200,9 +199,9 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable synchronized TransactionalEvictorContext createCurrent() { - Object k = Thread.currentThread(); + Thread t = Thread.currentThread(); - TransactionalEvictorContext ctx = (TransactionalEvictorContext)_ctxMap.get(k); + TransactionalEvictorContext ctx = _ctxMap.get(t); assert ctx == null; ctx = new TransactionalEvictorContext(this); @@ -210,7 +209,7 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable { _refCount++; // owned by the underlying ConnectionI } - _ctxMap.put(k, ctx); + _ctxMap.put(t, ctx); return ctx; } @@ -218,8 +217,8 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable synchronized TransactionalEvictorContext getCurrent() { - Object k = Thread.currentThread(); - return (TransactionalEvictorContext)_ctxMap.get(k); + Thread t = Thread.currentThread(); + return _ctxMap.get(t); } synchronized void @@ -245,20 +244,20 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable } } - Object k = Thread.currentThread(); + Thread t = Thread.currentThread(); if(txi != null) { - TransactionalEvictorContext ctx = (TransactionalEvictorContext)_ctxMap.get(k); + TransactionalEvictorContext ctx = _ctxMap.get(t); if(ctx == null || !tx.equals(ctx.transaction())) { ctx = new TransactionalEvictorContext(txi, getCommunicator()); - _ctxMap.put(k, ctx); + _ctxMap.put(t, ctx); } } else { - _ctxMap.put(k, null); + _ctxMap.put(t, null); } } @@ -357,7 +356,8 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable } } - _catalog = new MapDb(_key.communicator, _key.envName, Util.catalogName(), "string", "::Freeze::CatalogData", _dbEnv); + _catalog = new MapDb(_key.communicator, _key.envName, Util.catalogName(), "string", + "::Freeze::CatalogData", _dbEnv); _catalogIndexList = new MapDb(_key.communicator, _key.envName, Util.catalogIndexListName(), "string", "::Ice::StringSeq", _dbEnv); } @@ -499,7 +499,8 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable } } - public int hashCode() + public int + hashCode() { return envName.hashCode() ^ communicator.hashCode(); } @@ -517,12 +518,10 @@ class SharedDbEnv implements com.sleepycat.db.ErrorHandler, Runnable private int _kbyte = 0; private Thread _thread; - private java.util.Map _ctxMap = new java.util.HashMap(); + private java.util.Map<Thread, TransactionalEvictorContext> _ctxMap = + new java.util.HashMap<Thread, TransactionalEvictorContext>(); private java.util.Map<String, MapDb> _sharedDbMap = new java.util.HashMap<String, MapDb>(); - // - // Hash map of (MapKey, SharedDbEnv) - // - private static java.util.Map _map = new java.util.HashMap(); + private static java.util.Map<MapKey, SharedDbEnv> _map = new java.util.HashMap<MapKey, SharedDbEnv>(); } diff --git a/java/src/Freeze/SubMap.java b/java/src/Freeze/SubMap.java deleted file mode 100644 index f7b9f94ea6c..00000000000 --- a/java/src/Freeze/SubMap.java +++ /dev/null @@ -1,476 +0,0 @@ -// ********************************************************************** -// -// Copyright (c) 2003-2009 ZeroC, Inc. All rights reserved. -// -// This copy of Ice is licensed to you under the terms described in the -// ICE_LICENSE file included in this distribution. -// -// ********************************************************************** - -package Freeze; - -// -// Sub-map of a Freeze Map or of another submap -// -// -// When it's based of an index, the key is the index key and the value -// is a Set of Map.Entry. -// - -class SubMap extends java.util.AbstractMap implements java.util.SortedMap -{ - private class IndexValue extends java.util.AbstractSet - { - public java.util.Iterator - iterator() - { - return _index.untypedFind(_myKey, true); - } - - public int - size() - { - return _index.untypedCount(_myKey); - } - - public boolean equals(Object o) - { - if(o instanceof IndexValue) - { - IndexValue indexValue = (IndexValue)o; - return indexValue._myKey.equals(_myKey); - } - else - { - return false; - } - } - - public int hashCode() - { - return _myKey.hashCode(); - } - - private IndexValue(Object key) - { - _myKey = key; - } - - private Object - getKey() - { - return _myKey; - } - - private Object _myKey; - } - - private class IndexEntry implements java.util.Map.Entry - { - public Object getKey() - { - return _value.getKey(); - } - - public Object getValue() - { - return _value; - } - - public Object setValue(Object value) - { - throw new UnsupportedOperationException(); - } - - public boolean equals(Object o) - { - if(o instanceof IndexEntry) - { - IndexEntry indexEntry = (IndexEntry)o; - return indexEntry._value.equals(_value); - } - else - { - return false; - } - } - - public int hashCode() - { - return _value.hashCode(); - } - - SubMap parent() - { - return SubMap.this; - } - - private IndexEntry(Object key) - { - _value = new IndexValue(key); - } - - private IndexValue _value; - } - - private class IndexIterator implements Map.EntryIterator - { - public boolean hasNext() - { - return _iterator.hasNext(); - } - - public Object next() - { - Map.Entry entry = (Map.Entry)_iterator.next(); - return new IndexEntry(_index.decodeKey(entry.getIndexBytes(), - _map.connection().communicator())); - } - - public void remove() - { - _iterator.remove(); - } - - public void close() - { - _iterator.close(); - } - - public void destroy() - { - close(); - } - - private IndexIterator() - { - assert _index != null; - _iterator = _map.createIterator(_index, _fromKey, _toKey); - } - - Map.EntryIterator _iterator; - } - - SubMap(Map map, Object fromKey, Object toKey) - { - _fromKey = fromKey; - _toKey = toKey; - _map = map; - _index = null; - - if(fromKey != null && toKey != null) - { - if(map.comparator().compare(fromKey, toKey) >= 0) - { - throw new IllegalArgumentException(); - } - } - } - - SubMap(Map.Index index, Object fromKey, Object toKey) - { - _fromKey = fromKey; - _toKey = toKey; - _map = index.parent(); - _index = index; - - if(fromKey != null && toKey != null) - { - if(index.comparator().compare(fromKey, toKey) >= 0) - { - throw new IllegalArgumentException(); - } - } - } - - private SubMap(SubMap subMap, Object fromKey, Object toKey) - { - _fromKey = fromKey; - _toKey = toKey; - _map = subMap._map; - _index = subMap._index; - - if(fromKey != null && toKey != null) - { - if(comparator().compare(fromKey, toKey) >= 0) - { - throw new IllegalArgumentException(); - } - } - } - - // - // SortedMap methods - // - public java.util.Comparator comparator() - { - if(_index != null) - { - return _index.comparator(); - } - else - { - return _map.comparator(); - } - } - - public Object firstKey() - { - return _index != null ? - _index.firstKey(_fromKey, _toKey) : - _map.firstKey(_fromKey, _toKey); - } - - public Object lastKey() - { - return _index != null ? - _index.lastKey(_fromKey, _toKey) : - _map.lastKey(_fromKey, _toKey); - } - - public java.util.SortedMap headMap(Object toKey) - { - if(toKey == null) - { - throw new NullPointerException(); - } - return new SubMap(this, _fromKey, toKey); - - } - - public java.util.SortedMap tailMap(Object fromKey) - { - if(fromKey == null) - { - throw new NullPointerException(); - } - return new SubMap(this, fromKey, _toKey); - } - - public java.util.SortedMap subMap(Object fromKey, Object toKey) - { - if(fromKey == null || toKey == null ) - { - throw new NullPointerException(); - } - return new SubMap(this, fromKey, toKey); - } - - // - // java.util.Map methods - // - public java.util.Set - entrySet() - { - if(_entrySet == null) - { - _entrySet = new java.util.AbstractSet() - { - public java.util.Iterator - iterator() - { - if(_index == null) - { - return _map.createIterator(_index, _fromKey, _toKey); - } - else - { - return new IndexIterator(); - } - } - - public boolean - contains(Object o) - { - if(_index == null) - { - // - // If the main map contains this object, check it's within [fromKey, toKey[ - // - if(_map.entrySet().contains(o)) - { - Map.Entry entry = (Map.Entry)o; - return inRange(entry.getKey()); - } - else - { - return false; - } - } - else - { - if(o instanceof IndexEntry) - { - IndexEntry indexEntry = (IndexEntry)o; - return indexEntry.parent() == SubMap.this && - _index.containsKey(indexEntry.getKey()); - } - else - { - return false; - } - } - } - - public boolean - remove(Object o) - { - if(_index == null) - { - if(o instanceof Map.Entry) - { - Map.Entry entry = (Map.Entry)o; - return inRange(entry.getKey()) && _map.entrySet().remove(o); - } - else - { - return false; - } - } - else - { - // - // Not yet implemented, should remove all objects that - // match this index-key - // - throw new UnsupportedOperationException(); - } - } - - public int - size() - { - throw new UnsupportedOperationException(); - } - - public boolean - isEmpty() - { - try - { - firstKey(); - return false; - } - catch(NoSuchElementException e) - { - return true; - } - } - }; - } - return _entrySet; - } - - // - // Put is not implemented (you have to put in the main map view) - // - - - public boolean constainsKey(Object key) - { - if(!inRange(key)) - { - return false; - } - - // - // Then check if it's in the map - // - if(_index == null) - { - return _map.containsKey(key); - } - else - { - return _index.containsKey(key); - } - } - - - public Object - get(Object key) - { - if(!inRange(key)) - { - return null; - } - - if(_index == null) - { - return _map.get(key); - } - else - { - if(_index.containsKey(key)) - { - return new IndexValue(key); - } - else - { - return null; - } - } - } - - public Object - remove(Object key) - { - if(!inRange(key)) - { - return null; - } - - if(_index == null) - { - return _map.remove(key); - } - else - { - // - // Not yet implemented - // - throw new UnsupportedOperationException(); - } - } - - public boolean - fastRemove(Object key) - { - if(!inRange(key)) - { - return false; - } - - if(_index == null) - { - return _map.fastRemove(key); - } - else - { - // - // Not yet implemented - // - throw new UnsupportedOperationException(); - } - } - - - private boolean inRange(Object key) - { - if(_fromKey != null && comparator().compare(_fromKey, key) > 0) - { - return false; - } - if(_toKey != null && comparator().compare(key, _toKey) >= 0) - { - return false; - } - return true; - } - - private final Object _fromKey; - private final Object _toKey; - private final Map _map; - private final Map.Index _index; - private java.util.Set _entrySet; -} diff --git a/java/src/Freeze/TransactionI.java b/java/src/Freeze/TransactionI.java index 2644f9c0fee..7d311acb2b9 100644 --- a/java/src/Freeze/TransactionI.java +++ b/java/src/Freeze/TransactionI.java @@ -29,7 +29,7 @@ class TransactionI implements Transaction if(_txTrace >= 1) { - txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); + txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); } _txn.commit(); @@ -37,8 +37,8 @@ class TransactionI implements Transaction if(_txTrace >= 1) { - _connection.communicator().getLogger().trace("Freeze.Transaction", _errorPrefix + "committed transaction " + - txnId); + _connection.communicator().getLogger().trace("Freeze.Transaction", _errorPrefix + + "committed transaction " + txnId); } } catch(com.sleepycat.db.DeadlockException e) @@ -97,18 +97,18 @@ class TransactionI implements Transaction try { _connection.closeAllIterators(); - + if(_txTrace >= 1) { - txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); + txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); } _txn.abort(); if(_txTrace >= 1) { - _connection.communicator().getLogger().trace("Freeze.Transaction", _errorPrefix + "rolled back transaction " + - txnId); + _connection.communicator().getLogger().trace("Freeze.Transaction", _errorPrefix + + "rolled back transaction " + txnId); } } catch(com.sleepycat.db.DeadlockException e) @@ -152,7 +152,7 @@ class TransactionI implements Transaction postCompletion(false, deadlock); } } - + public Connection getConnection() { @@ -168,13 +168,13 @@ class TransactionI implements Transaction try { _txn = _connection.dbEnv().getEnv().beginTransaction(null, null); - + if(_txTrace >= 1) { - String txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); + String txnId = Long.toHexString((_txn.getId() & 0x7FFFFFFF) + 0x80000000L); - _connection.communicator().getLogger().trace("Freeze.Transaction", _errorPrefix + "started transaction " + - txnId); + _connection.communicator().getLogger().trace("Freeze.Transaction", _errorPrefix + + "started transaction " + txnId); } } catch(com.sleepycat.db.DatabaseException e) @@ -192,13 +192,13 @@ class TransactionI implements Transaction } } - void + void setPostCompletionCallback(PostCompletionCallback cb) { _postCompletionCallback = cb; } - void + void adoptConnection() { _ownConnection = true; @@ -209,14 +209,13 @@ class TransactionI implements Transaction { return _connection; } - + com.sleepycat.db.Transaction dbTxn() { return _txn; } - private void postCompletion(boolean committed, boolean deadlock) { diff --git a/java/src/Freeze/TransactionalEvictorContext.java b/java/src/Freeze/TransactionalEvictorContext.java index 094b310b590..d934eb56e29 100644 --- a/java/src/Freeze/TransactionalEvictorContext.java +++ b/java/src/Freeze/TransactionalEvictorContext.java @@ -16,9 +16,9 @@ package Freeze; class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallback, PostCompletionCallback { - public void + public void postCompletion(boolean committed, boolean deadlock) - { + { try { if(committed) @@ -26,10 +26,8 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac // // Remove updated & removed objects from cache // - java.util.Iterator p = _invalidateList.iterator(); - while(p.hasNext()) + for(ToInvalidate ti : _invalidateList) { - ToInvalidate ti = (ToInvalidate)p.next(); ti.invalidate(); } _invalidateList.clear(); @@ -106,14 +104,13 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac return true; } - class ServantHolder { ServantHolder(Ice.Current current, ObjectStore store) { _current = current; _store = store; - + ServantHolder sh = findServantHolder(_current.id, _store); if(sh != null) { @@ -124,9 +121,9 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac if(_trace >= 3) { - _communicator.getLogger().trace("Freeze.Evictor", "found \"" - + _communicator.identityToString(_current.id) +"\" with facet \"" + _store.facet() - + "\" in current context"); + _communicator.getLogger().trace("Freeze.Evictor", "found \"" + + _communicator.identityToString(_current.id) + + "\" with facet \"" + _store.facet() + "\" in current context"); } } } @@ -140,9 +137,10 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac { if(_trace >= 3) { - _communicator.getLogger().trace("Freeze.Evictor", "loaded \"" - + _communicator.identityToString(_current.id) +"\" with facet \"" + _store.facet() - + "\" into current context"); + _communicator.getLogger().trace("Freeze.Evictor", "loaded \"" + + _communicator.identityToString(_current.id) + + "\" with facet \"" + _store.facet() + + "\" into current context"); } _stack.push(this); @@ -151,7 +149,7 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac } } - void + void markReadWrite() { if(_ownServant) @@ -167,7 +165,7 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac } } - void + void release() { if(_ownServant) @@ -181,12 +179,13 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac if(_trace >= 3) { - _communicator.getLogger().trace("Freeze.Evictor", "updated \"" - + _communicator.identityToString(_current.id) +"\" with facet \"" + _store.facet() - + "\" within transaction"); + _communicator.getLogger().trace("Freeze.Evictor", "updated \"" + + _communicator.identityToString(_current.id) + + "\" with facet \"" + _store.facet() + + "\" within transaction"); } } - + if(!_readOnly || _removed) { _invalidateList.add(new ToInvalidate(_current.id, _store)); @@ -195,15 +194,15 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac _stack.pop(); } } - + boolean matches(Ice.Identity ident, ObjectStore store) { return ident.equals(_current.id) && store == _store; } - Ice.Object - servant() + Ice.Object + servant() { if(_rec == null) { @@ -215,12 +214,12 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac } } - void + void removed() { _removed = true; } - + private boolean _ownServant = false; private boolean _removed = false; private boolean _readOnly = true; @@ -228,8 +227,7 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac private final Ice.Current _current; private final ObjectStore _store; private ObjectRecord _rec; - }; - + } TransactionalEvictorContext(SharedDbEnv dbEnv) { @@ -277,7 +275,6 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac } } - void checkDeadlockException() { @@ -296,16 +293,15 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac clearUserException() { // - // No need to synchronize; _userExceptionDetected is only read/written by the + // No need to synchronize; _userExceptionDetected is only read/written by the // dispatch thread // boolean result = _userExceptionDetected; _userExceptionDetected = false; return result; } - - - TransactionI + + TransactionI transaction() { return _tx; @@ -316,7 +312,7 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac { return new ServantHolder(current, store); } - + void deadlockException() { @@ -328,7 +324,7 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac rollback(); } - + Ice.Object servantRemoved(Ice.Identity ident, ObjectStore store) { @@ -351,25 +347,12 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac } return null; } - - - protected void - finalize() - { - if(_tx != null) - { - _tx.getConnectionI().communicator().getLogger().warning - ("Finalizing incomplete TransactionalEvictorContext on DbEnv '" + _tx.getConnectionI().dbEnv().getEnvName() + "'"); - } - } private ServantHolder findServantHolder(Ice.Identity ident, ObjectStore store) { - java.util.Iterator p = _stack.iterator(); - while(p.hasNext()) + for(ServantHolder sh : _stack) { - ServantHolder sh = (ServantHolder)p.next(); if(sh.matches(ident, store)) { return sh; @@ -377,7 +360,7 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac } return null; } - + private static class ToInvalidate { ToInvalidate(Ice.Identity ident, ObjectStore store) @@ -386,7 +369,7 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac _store = store; } - void + void invalidate() { ((TransactionalEvictorI)_store.evictor()).evict(_ident, _store); @@ -396,16 +379,12 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac private final ObjectStore _store; } + private final java.util.Stack<ServantHolder> _stack = new java.util.Stack<ServantHolder>(); // - // Stack of ServantHolder - // - private final java.util.Stack _stack = new java.util.Stack(); - - // // List of objects to invalidate from the caches upon commit // - private final java.util.List _invalidateList = new java.util.LinkedList(); + private final java.util.List<ToInvalidate> _invalidateList = new java.util.LinkedList<ToInvalidate>(); private TransactionI _tx; private final Thread _owner; @@ -418,7 +397,6 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac // private boolean _deadlockExceptionDetected = false; - // // Only updated by the dispatch thread // diff --git a/java/src/Freeze/TransactionalEvictorI.java b/java/src/Freeze/TransactionalEvictorI.java index 3eb79a879c9..5851a184bb8 100644 --- a/java/src/Freeze/TransactionalEvictorI.java +++ b/java/src/Freeze/TransactionalEvictorI.java @@ -22,73 +22,72 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor public Transaction getCurrentTransaction() { - _deactivateController.lock(); - try - { - TransactionalEvictorContext ctx = _dbEnv.getCurrent(); - return ctx == null ? null : ctx.transaction(); - } - finally - { - _deactivateController.unlock(); - } + _deactivateController.lock(); + try + { + TransactionalEvictorContext ctx = _dbEnv.getCurrent(); + return ctx == null ? null : ctx.transaction(); + } + finally + { + _deactivateController.unlock(); + } } - + public void setCurrentTransaction(Transaction tx) { - _deactivateController.lock(); - try - { - _dbEnv.setCurrentTransaction(tx); - } - finally - { - _deactivateController.unlock(); - } + _deactivateController.lock(); + try + { + _dbEnv.setCurrentTransaction(tx); + } + finally + { + _deactivateController.unlock(); + } } public Ice.ObjectPrx addFacet(Ice.Object servant, Ice.Identity ident, String facet) { - checkIdentity(ident); - - if(facet == null) - { - facet = ""; - } - - _deactivateController.lock(); - try - { - long currentTime = IceInternal.Time.currentMonotonicTimeMillis(); - - ObjectRecord rec = new ObjectRecord(servant, new Statistics(currentTime, 0, 0)); - - ObjectStore store = findStore(facet, _createDb); - if(store == null) - { - NotFoundException ex = new NotFoundException(); - ex.message = _errorPrefix + "addFacet: could not open database for facet '" - + facet + "'"; - throw ex; - } - - TransactionI tx = beforeQuery(); - - updateStats(rec.stats, currentTime); - - if(!store.insert(ident, rec, tx)) - { - Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); - ex.kindOfObject = "servant"; - ex.id = _communicator.identityToString(ident); - if(facet.length() > 0) - { - ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); - } - throw ex; - } + checkIdentity(ident); + + if(facet == null) + { + facet = ""; + } + + _deactivateController.lock(); + try + { + long currentTime = IceInternal.Time.currentMonotonicTimeMillis(); + + ObjectRecord rec = new ObjectRecord(servant, new Statistics(currentTime, 0, 0)); + + ObjectStore store = findStore(facet, _createDb); + if(store == null) + { + NotFoundException ex = new NotFoundException(); + ex.message = _errorPrefix + "addFacet: could not open database for facet '" + facet + "'"; + throw ex; + } + + TransactionI tx = beforeQuery(); + + updateStats(rec.stats, currentTime); + + if(!store.insert(ident, rec, tx)) + { + Ice.AlreadyRegisteredException ex = new Ice.AlreadyRegisteredException(); + ex.kindOfObject = "servant"; + ex.id = _communicator.identityToString(ident); + if(facet.length() > 0) + { + ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); + } + throw ex; + } if(_trace >= 1) { @@ -97,161 +96,160 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor { objString += " with facet \"" + facet + "\""; } - + _communicator.getLogger().trace("Freeze.Evictor", "added " + objString + " to Db \"" + _filename + "\""); } - Ice.ObjectPrx obj = _adapter.createProxy(ident); - if(facet.length() > 0) - { - obj = obj.ice_facet(facet); - } - return obj; - } - finally - { - _deactivateController.unlock(); - } + Ice.ObjectPrx obj = _adapter.createProxy(ident); + if(facet.length() > 0) + { + obj = obj.ice_facet(facet); + } + return obj; + } + finally + { + _deactivateController.unlock(); + } } public Ice.Object removeFacet(Ice.Identity ident, String facet) { - checkIdentity(ident); - if(facet == null) - { - facet = ""; - } - - _deactivateController.lock(); - try - { - Ice.Object servant = null; - boolean removed = false; - - ObjectStore store = findStore(facet, false); - if(store != null) - { - TransactionalEvictorContext ctx = _dbEnv.getCurrent(); - TransactionI tx = null; - if(ctx != null) - { - tx = ctx.transaction(); - if(tx == null) - { - throw new DatabaseException(_errorPrefix + "inactive transaction"); - } - } - - removed = store.remove(ident, tx); - - if(removed) - { - if(ctx != null) - { - // - // Remove from cache when transaction commits - // - servant = ctx.servantRemoved(ident, store); - } - else - { - // - // Remove from cache immediately - // - servant = evict(ident, store); - } - } - } - - if(!removed) - { - Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); - ex.kindOfObject = "servant"; - ex.id = _communicator.identityToString(ident); - if(facet.length() > 0) - { - ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); - } - throw ex; - } - - if(_trace >= 1) - { - String objString = "object \"" + _communicator.identityToString(ident) + "\""; - if(!facet.equals("")) - { - objString += " with facet \"" + facet + "\""; - } - - _communicator.getLogger().trace("Freeze.Evictor", "removed " + objString + " from Db \"" + _filename + - "\""); - } - return servant; - } - finally - { - _deactivateController.unlock(); - } + checkIdentity(ident); + if(facet == null) + { + facet = ""; + } + + _deactivateController.lock(); + try + { + Ice.Object servant = null; + boolean removed = false; + + ObjectStore store = findStore(facet, false); + if(store != null) + { + TransactionalEvictorContext ctx = _dbEnv.getCurrent(); + TransactionI tx = null; + if(ctx != null) + { + tx = ctx.transaction(); + if(tx == null) + { + throw new DatabaseException(_errorPrefix + "inactive transaction"); + } + } + + removed = store.remove(ident, tx); + + if(removed) + { + if(ctx != null) + { + // + // Remove from cache when transaction commits + // + servant = ctx.servantRemoved(ident, store); + } + else + { + // + // Remove from cache immediately + // + servant = evict(ident, store); + } + } + } + + if(!removed) + { + Ice.NotRegisteredException ex = new Ice.NotRegisteredException(); + ex.kindOfObject = "servant"; + ex.id = _communicator.identityToString(ident); + if(facet.length() > 0) + { + ex.id += " -f " + IceUtilInternal.StringUtil.escapeString(facet, ""); + } + throw ex; + } + + if(_trace >= 1) + { + String objString = "object \"" + _communicator.identityToString(ident) + "\""; + if(!facet.equals("")) + { + objString += " with facet \"" + facet + "\""; + } + + _communicator.getLogger().trace("Freeze.Evictor", "removed " + objString + " from Db \"" + _filename + + "\""); + } + return servant; + } + finally + { + _deactivateController.unlock(); + } } public boolean hasFacet(Ice.Identity ident, String facet) { - checkIdentity(ident); - if(facet == null) - { - facet = ""; - } - - _deactivateController.lock(); - try - { - ObjectStore store = findStore(facet, false); - - if(store == null) - { - return false; - } - - TransactionI tx = beforeQuery(); - - if(tx == null) - { - EvictorElement element = (EvictorElement)store.cache().getIfPinned(ident); - if(element != null) - { - return true; - } - - return store.dbHasObject(ident, null); - } - else - { - return store.dbHasObject(ident, tx); - } - } - finally - { - _deactivateController.unlock(); - } + checkIdentity(ident); + if(facet == null) + { + facet = ""; + } + + _deactivateController.lock(); + try + { + ObjectStore store = findStore(facet, false); + + if(store == null) + { + return false; + } + + TransactionI tx = beforeQuery(); + + if(tx == null) + { + EvictorElement element = (EvictorElement)store.cache().getIfPinned(ident); + if(element != null) + { + return true; + } + + return store.dbHasObject(ident, null); + } + else + { + return store.dbHasObject(ident, tx); + } + } + finally + { + _deactivateController.unlock(); + } } - - + public void finished(Ice.Current current, Ice.Object servant, java.lang.Object cookieObj) - { - // - // Nothing to do - // + { + // + // Nothing to do + // } public void deactivate(String category) { - if(_deactivateController.deactivate()) - { + if(_deactivateController.deactivate()) + { synchronized(this) { // @@ -262,54 +260,56 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor evict(); } - try - { - closeDbEnv(); - } - finally - { - _deactivateController.deactivationComplete(); - } - } + try + { + closeDbEnv(); + } + finally + { + _deactivateController.deactivationComplete(); + } + } } - TransactionalEvictorI(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, String filename, - java.util.Map facetTypes, ServantInitializer initializer, Index[] indices, boolean createDb) + TransactionalEvictorI(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, + String filename, java.util.Map<String, String> facetTypes, ServantInitializer initializer, + Index[] indices, boolean createDb) { - super(adapter, envName, dbEnv, filename, facetTypes, initializer, indices, createDb); - - String propertyPrefix = "Freeze.Evictor." + envName + '.' + filename; - _rollbackOnUserException = _communicator.getProperties(). - getPropertyAsIntWithDefault(propertyPrefix + ".RollbackOnUserException", 0) != 0; + super(adapter, envName, dbEnv, filename, facetTypes, initializer, indices, createDb); + + String propertyPrefix = "Freeze.Evictor." + envName + '.' + filename; + _rollbackOnUserException = _communicator.getProperties(). + getPropertyAsIntWithDefault(propertyPrefix + ".RollbackOnUserException", 0) != 0; } - TransactionalEvictorI(Ice.ObjectAdapter adapter, String envName, String filename, - java.util.Map facetTypes, ServantInitializer initializer, Index[] indices, boolean createDb) + TransactionalEvictorI(Ice.ObjectAdapter adapter, String envName, String filename, + java.util.Map<String, String> facetTypes, ServantInitializer initializer, Index[] indices, + boolean createDb) { - this(adapter, envName, null, filename, facetTypes, initializer, indices, createDb); + this(adapter, envName, null, filename, facetTypes, initializer, indices, createDb); } // // The interceptor dispatch call // - Ice.DispatchStatus + Ice.DispatchStatus dispatch(Ice.Request request) { - _deactivateController.lock(); - try - { - Ice.Current current = request.getCurrent(); - - ObjectStore store = findStore(current.facet, false); - if(store == null) - { - servantNotFound(current); - } - - TransactionalEvictorContext ctx = _dbEnv.getCurrent(); - - Ice.Object sample = store.sampleServant(); - Ice.Object cachedServant = null; + _deactivateController.lock(); + try + { + Ice.Current current = request.getCurrent(); + + ObjectStore store = findStore(current.facet, false); + if(store == null) + { + servantNotFound(current); + } + + TransactionalEvictorContext ctx = _dbEnv.getCurrent(); + + Ice.Object sample = store.sampleServant(); + Ice.Object cachedServant = null; TransactionalEvictorContext.ServantHolder servantHolder = null; try @@ -317,11 +317,11 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor if(sample == null) { if(ctx != null) - { + { try { servantHolder = ctx.createServantHolder(current, store); - } + } catch(DeadlockException dx) { assert dx.tx == ctx.transaction(); @@ -335,9 +335,9 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor // // find / load read-only servant // - + cachedServant = loadCachedServant(current.id, store); - + if(cachedServant == null) { servantNotFound(current); @@ -345,17 +345,17 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor sample = cachedServant; } } - + assert sample != null; int operationAttributes = sample.ice_operationAttributes(current.operation); - + boolean readOnly = (operationAttributes & 0x1) == 0; - + int txMode = (operationAttributes & 0x6) >> 1; - + boolean ownCtx = false; - + // // Establish the proper context // @@ -396,7 +396,7 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor assert false; } } - + if(ctx == null && !ownCtx) { // @@ -406,7 +406,7 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor if(cachedServant == null) { cachedServant = loadCachedServant(current.id, store); - + if(cachedServant == null) { servantNotFound(current); @@ -425,13 +425,13 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor { ctx = _dbEnv.createCurrent(); } - + tx = ctx.transaction(); try { try - { + { TransactionalEvictorContext.ServantHolder sh; if(servantHolder != null) { @@ -446,7 +446,7 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor { sh = ctx.createServantHolder(current, store); } - + if(sh.servant() == null) { servantNotFound(current); @@ -456,11 +456,12 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor { sh.markReadWrite(); } - + try { Ice.DispatchStatus dispatchStatus = sh.servant().ice_dispatch(request, ctx); - if(dispatchStatus == Ice.DispatchStatus.DispatchUserException && _rollbackOnUserException) + if(dispatchStatus == Ice.DispatchStatus.DispatchUserException && + _rollbackOnUserException) { ctx.rollback(); } @@ -550,7 +551,7 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor servantHolder.release(); } } - + // // Javac does not detect this can't be reached // @@ -563,260 +564,256 @@ class TransactionalEvictorI extends EvictorI implements TransactionalEvictor } } - synchronized Ice.Object + synchronized Ice.Object evict(Ice.Identity ident, ObjectStore store) { - EvictorElement element = (EvictorElement)store.cache().unpin(ident); - - if(element != null) - { - element.evict(false); - return element.servant; - } - return null; + EvictorElement element = (EvictorElement)store.cache().unpin(ident); + + if(element != null) + { + element.evict(false); + return element.servant; + } + return null; } - protected Object + protected Object createEvictorElement(Ice.Identity ident, ObjectRecord rec, ObjectStore store) { - return new EvictorElement(rec.servant, ident, store); + return new EvictorElement(rec.servant, ident, store); } protected Ice.Object locateImpl(Ice.Current current, Ice.LocalObjectHolder cookie) { - return _interceptor; + return _interceptor; } protected boolean hasAnotherFacet(Ice.Identity ident, String facet) { - _deactivateController.lock(); - try - { - java.util.Map storeMapCopy; - synchronized(this) - { - storeMapCopy = new java.util.HashMap(_storeMap); - } - - TransactionI tx = beforeQuery(); - - java.util.Iterator p = storeMapCopy.entrySet().iterator(); - while(p.hasNext()) - { - java.util.Map.Entry entry = (java.util.Map.Entry)p.next(); - - // - // Do not check this facet again - // - if(!facet.equals(entry.getKey())) - { - ObjectStore store = (ObjectStore)entry.getValue(); - - if(tx == null && store.cache().getIfPinned(ident) != null) - { - return true; - } - - if(store.dbHasObject(ident, tx)) - { - return true; - } - } - } - - return false; - } - finally - { - _deactivateController.unlock(); - } + _deactivateController.lock(); + try + { + java.util.Map<String, ObjectStore> storeMapCopy; + synchronized(this) + { + storeMapCopy = new java.util.HashMap<String, ObjectStore>(_storeMap); + } + + TransactionI tx = beforeQuery(); + + for(java.util.Map.Entry<String, ObjectStore> entry : storeMapCopy.entrySet()) + { + // + // Do not check this facet again + // + if(!facet.equals(entry.getKey())) + { + ObjectStore store = (ObjectStore)entry.getValue(); + + if(tx == null && store.cache().getIfPinned(ident) != null) + { + return true; + } + + if(store.dbHasObject(ident, tx)) + { + return true; + } + } + } + + return false; + } + finally + { + _deactivateController.unlock(); + } } protected void evict() - { - assert Thread.holdsLock(this); - - while(_currentEvictorSize > _evictorSize) - { - // - // Evict, no matter what! - // - EvictorElement element = (EvictorElement)_evictorList.getLast(); - element.evict(true); - } - } + { + assert Thread.holdsLock(this); + + while(_currentEvictorSize > _evictorSize) + { + // + // Evict, no matter what! + // + EvictorElement element = _evictorList.getLast(); + element.evict(true); + } + } protected TransactionI beforeQuery() { - TransactionalEvictorContext ctx = _dbEnv.getCurrent(); - TransactionI tx = null; - if(ctx != null) - { - tx = ctx.transaction(); - if(tx == null) - { - throw new DatabaseException(_errorPrefix + "inactive transaction"); - } - } - - return tx; + TransactionalEvictorContext ctx = _dbEnv.getCurrent(); + TransactionI tx = null; + if(ctx != null) + { + tx = ctx.transaction(); + if(tx == null) + { + throw new DatabaseException(_errorPrefix + "inactive transaction"); + } + } + + return tx; } - private void + private void servantNotFound(Ice.Current current) - { - if(_trace >= 2) - { - _communicator.getLogger().trace("Freeze.Evictor", "could not find \"" - + _communicator.identityToString(current.id) +"\" with facet \"" + current.facet + "\""); - } - - if(hasAnotherFacet(current.id, current.facet)) - { - throw new Ice.FacetNotExistException(current.id, current.facet, current.operation); - } - else - { - throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation); - } + { + if(_trace >= 2) + { + _communicator.getLogger().trace("Freeze.Evictor", "could not find \"" + + _communicator.identityToString(current.id) + "\" with facet \"" + + current.facet + "\""); + } + + if(hasAnotherFacet(current.id, current.facet)) + { + throw new Ice.FacetNotExistException(current.id, current.facet, current.operation); + } + else + { + throw new Ice.ObjectNotExistException(current.id, current.facet, current.operation); + } } private Ice.Object loadCachedServant(Ice.Identity ident, ObjectStore store) { - for(;;) - { - EvictorElement element = (EvictorElement)store.cache().pin(ident); - - if(element == null) - { - return null; - } - - synchronized(this) - { - if(element.stale) - { - // - // try again - // - continue; - } - - element.fixEvictPosition(); - - // - // if _evictorSize is 0, I may evict myself ... no big deal - // - evict(); + for(;;) + { + EvictorElement element = (EvictorElement)store.cache().pin(ident); + + if(element == null) + { + return null; + } + + synchronized(this) + { + if(element.stale) + { + // + // try again + // + continue; + } + + element.fixEvictPosition(); + + // + // if _evictorSize is 0, I may evict myself ... no big deal + // + evict(); if(_trace >= 3) { - _communicator.getLogger().trace("Freeze.Evictor", "loaded \"" - + _communicator.identityToString(ident) +"\" with facet \"" + store.facet() - + "\" into the cache"); + _communicator.getLogger().trace("Freeze.Evictor", "loaded \"" + + _communicator.identityToString(ident) + "\" with facet \"" + + store.facet() + "\" into the cache"); } - return element.servant; - } - } + return element.servant; + } + } } - + private class EvictorElement { - EvictorElement(Ice.Object servant, Ice.Identity identity, ObjectStore store) - { - this.servant = servant; - _identity = identity; - _store = store; - } - - void - evict(boolean unpin) - { - assert Thread.holdsLock(TransactionalEvictorI.this); - assert stale == false; - stale = true; - - if(unpin) - { - _store.cache().unpin(_identity); - } - - if(_evictPosition != null) - { - _evictPosition.remove(); - _evictPosition = null; - _currentEvictorSize--; - } - else - { - assert(!unpin); - } - } - - void - fixEvictPosition() - { - assert Thread.holdsLock(TransactionalEvictorI.this); - assert stale == false; - - if(_evictPosition == null) - { - // - // New element - // - _currentEvictorSize++; - } - else - { - _evictPosition.remove(); - } - _evictorList.addFirst(this); - _evictPosition = _evictorList.iterator(); - // - // Position the iterator "on" the element. - // - _evictPosition.next(); - } - - - final Ice.Object servant; - - // - // Protected by the TransactionEvictorI mutex - // - boolean stale = false; // stale = true means no longer in the cache - private java.util.Iterator _evictPosition; - - // - // These two fields are only needed for eviction - // - final private ObjectStore _store; - final private Ice.Identity _identity; - } + EvictorElement(Ice.Object servant, Ice.Identity identity, ObjectStore store) + { + this.servant = servant; + _identity = identity; + _store = store; + } + void + evict(boolean unpin) + { + assert Thread.holdsLock(TransactionalEvictorI.this); + assert stale == false; + stale = true; + + if(unpin) + { + _store.cache().unpin(_identity); + } + + if(_evictPosition != null) + { + _evictPosition.remove(); + _evictPosition = null; + _currentEvictorSize--; + } + else + { + assert(!unpin); + } + } + + void + fixEvictPosition() + { + assert Thread.holdsLock(TransactionalEvictorI.this); + assert stale == false; + + if(_evictPosition == null) + { + // + // New element + // + _currentEvictorSize++; + } + else + { + _evictPosition.remove(); + } + _evictorList.addFirst(this); + _evictPosition = _evictorList.iterator(); + // + // Position the iterator "on" the element. + // + _evictPosition.next(); + } + + final Ice.Object servant; + + // + // Protected by the TransactionEvictorI mutex + // + boolean stale = false; // stale = true means no longer in the cache + private java.util.Iterator<EvictorElement> _evictPosition; + + // + // These two fields are only needed for eviction + // + final private ObjectStore _store; + final private Ice.Identity _identity; + } // // List of EvictorElement with stable iterators // - private final Freeze.LinkedList _evictorList = new Freeze.LinkedList(); + private final Freeze.LinkedList<EvictorElement> _evictorList = new Freeze.LinkedList<EvictorElement>(); private int _currentEvictorSize = 0; // // A simple adapter // private Ice.DispatchInterceptor _interceptor = new Ice.DispatchInterceptor() - { - public Ice.DispatchStatus - dispatch(Ice.Request request) - { - return TransactionalEvictorI.this.dispatch(request); - } - }; + { + public Ice.DispatchStatus + dispatch(Ice.Request request) + { + return TransactionalEvictorI.this.dispatch(request); + } + }; private boolean _rollbackOnUserException; } diff --git a/java/src/Freeze/Util.java b/java/src/Freeze/Util.java index 10497faf7a4..c045e9b0797 100644 --- a/java/src/Freeze/Util.java +++ b/java/src/Freeze/Util.java @@ -12,40 +12,40 @@ package Freeze; public class Util { public static BackgroundSaveEvictor - createBackgroundSaveEvictor(Ice.ObjectAdapter adapter, String envName, String filename, ServantInitializer initializer, - Index[] indices, boolean createDb) + createBackgroundSaveEvictor(Ice.ObjectAdapter adapter, String envName, String filename, + ServantInitializer initializer, Index[] indices, boolean createDb) { return new BackgroundSaveEvictorI(adapter, envName, filename, initializer, indices, createDb); - } + } public static BackgroundSaveEvictor - createBackgroundSaveEvictor(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, String filename, - ServantInitializer initializer, Index[] indices, boolean createDb) + createBackgroundSaveEvictor(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, + String filename, ServantInitializer initializer, Index[] indices, boolean createDb) { return new BackgroundSaveEvictorI(adapter, envName, dbEnv, filename, initializer, indices, createDb); - } - + } public static TransactionalEvictor - createTransactionalEvictor(Ice.ObjectAdapter adapter, String envName, String filename, java.util.Map facetTypes, - ServantInitializer initializer, Index[] indices, boolean createDb) + createTransactionalEvictor(Ice.ObjectAdapter adapter, String envName, String filename, + java.util.Map<String, String> facetTypes, ServantInitializer initializer, + Index[] indices, boolean createDb) { return new TransactionalEvictorI(adapter, envName, filename, facetTypes, initializer, indices, createDb); - } + } public static TransactionalEvictor - createTransactionalEvictor(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, String filename, - java.util.Map facetTypes, ServantInitializer initializer, Index[] indices, boolean createDb) + createTransactionalEvictor(Ice.ObjectAdapter adapter, String envName, com.sleepycat.db.Environment dbEnv, + String filename, java.util.Map<String, String> facetTypes, + ServantInitializer initializer, Index[] indices, boolean createDb) { return new TransactionalEvictorI(adapter, envName, dbEnv, filename, facetTypes, initializer, indices, createDb); } - public static Connection createConnection(Ice.Communicator communicator, String envName) { return new ConnectionI(communicator, envName, null); - } + } public static Connection createConnection(Ice.Communicator communicator, String envName, com.sleepycat.db.Environment dbEnv) @@ -53,17 +53,18 @@ public class Util return new ConnectionI(communicator, envName, dbEnv); } - public static String catalogName() + public static String + catalogName() { return _catalogName; } - - public static String catalogIndexListName() + + public static String + catalogIndexListName() { return _catalogIndexListName; } - public static com.sleepycat.db.Transaction getTxn(Transaction tx) { @@ -84,8 +85,9 @@ public class Util _fatalErrorCallback = cb; return result; } - - static synchronized void handleFatalError(BackgroundSaveEvictor evictor, Ice.Communicator communicator, RuntimeException ex) + + static synchronized void + handleFatalError(BackgroundSaveEvictor evictor, Ice.Communicator communicator, RuntimeException ex) { if(_fatalErrorCallback != null) { diff --git a/java/src/IceGridGUI/BareBonesBrowserLaunch.java b/java/src/IceGridGUI/BareBonesBrowserLaunch.java index 6cfe3732c72..6900313af0c 100644 --- a/java/src/IceGridGUI/BareBonesBrowserLaunch.java +++ b/java/src/IceGridGUI/BareBonesBrowserLaunch.java @@ -26,10 +26,9 @@ public class BareBonesBrowserLaunch { String osName = System.getProperty("os.name"); try { if (osName.startsWith("Mac OS")) { - Class macUtils = Class.forName("com.apple.mrj.MRJFileUtils"); - Method openURL = macUtils.getDeclaredMethod("openURL", - new Class[] {String.class}); - openURL.invoke(null, new Object[] {url}); + Class<?> macUtils = Class.forName("com.apple.mrj.MRJFileUtils"); + Method openURL = macUtils.getDeclaredMethod("openURL", String.class); + openURL.invoke(null, url); } else if (osName.startsWith("Windows")) Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); diff --git a/java/src/IceInternal/PropertyNames.java b/java/src/IceInternal/PropertyNames.java index 8812b8a54db..ab58a9d6731 100644 --- a/java/src/IceInternal/PropertyNames.java +++ b/java/src/IceInternal/PropertyNames.java @@ -8,7 +8,7 @@ // ********************************************************************** // -// Generated by makeprops.py from file ../config/PropertyNames.xml, Fri May 15 13:11:40 2009 +// Generated by makeprops.py from file ../config/PropertyNames.xml, Mon May 18 11:29:29 2009 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -556,7 +556,6 @@ public final class PropertyNames new Property("Freeze\\.Trace\\.Evictor", false, null), new Property("Freeze\\.Trace\\.Map", false, null), new Property("Freeze\\.Trace\\.Transaction", false, null), - new Property("Freeze\\.Warn\\.CloseInFinalize", false, null), new Property("Freeze\\.Warn\\.Deadlocks", false, null), new Property("Freeze\\.Warn\\.Rollback", false, null), null diff --git a/java/test/Freeze/complex/Client.java b/java/test/Freeze/complex/Client.java index e3065200b46..4f6cd92f983 100644 --- a/java/test/Freeze/complex/Client.java +++ b/java/test/Freeze/complex/Client.java @@ -34,20 +34,20 @@ public class Client try { Parser parser = new Parser(); - + System.out.print("testing database expressions... "); - java.util.Iterator p = m.entrySet().iterator(); + java.util.Iterator<java.util.Map.Entry<Key, Node>> p = m.entrySet().iterator(); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); + java.util.Map.Entry<Key, Node> e = p.next(); - Key key = (Key)e.getKey(); + Key key = e.getKey(); // // Verify the stored record is correct. // - test(key.result == ((Node)e.getValue()).calc()); - + test(key.result == e.getValue().calc()); + // // Verify that the expression & result again. // @@ -61,17 +61,17 @@ public class Client e.printStackTrace(); test(false); } - + m.close(); return 0; } - + private int populate(String dbName) throws DatabaseException { - String[] expressions = + String[] expressions = { "2", "10", @@ -79,13 +79,13 @@ public class Client "5*(2+3)", "10+(10+(20+(8*(2*(3*2+4+5+6)))))" }; - + ComplexDict m = new ComplexDict(_connection, dbName, true); try { Parser parser = new Parser(); - + System.out.print("populating the database... "); for(String expr : expressions) { @@ -103,11 +103,11 @@ public class Client e.printStackTrace(); test(false); } - + m.close(); return 0; } - + static void usage(String name) { @@ -127,7 +127,7 @@ public class Client _communicator.addObjectFactory(factory, "::Complex::NumberNode"); _communicator.addObjectFactory(factory, "::Complex::AddNode"); _communicator.addObjectFactory(factory, "::Complex::MultiplyNode"); - + if(args.length != 0 && args[0].equals("populate")) { return populate(dbName); @@ -137,17 +137,16 @@ public class Client return validate(dbName); } usage(progName); - + return 0; } - + private void close() { _connection.close(); } - private Client(Ice.Communicator communicator, String envName) { @@ -155,7 +154,6 @@ public class Client _connection = Freeze.Util.createConnection(communicator, envName); } - static public void main(String[] args) { @@ -178,7 +176,7 @@ public class Client usage(progName); System.exit(1); } - + envName = args[i+1]; envName += "/"; envName += "db"; @@ -240,5 +238,4 @@ public class Client private Ice.Communicator _communicator; private Freeze.Connection _connection; - } diff --git a/java/test/Freeze/complex/Parser.java b/java/test/Freeze/complex/Parser.java index d2aa4b1c93f..61f7d8be4c5 100644 --- a/java/test/Freeze/complex/Parser.java +++ b/java/test/Freeze/complex/Parser.java @@ -71,10 +71,10 @@ public class Parser { throw new ParseError("Expected number"); } - + NumberNode number = new NumberNodeI(Integer.parseInt(_token)); Node result = number; - + // // expr? // @@ -90,7 +90,7 @@ public class Parser Node right = expr(); result = new AddNodeI(number, right); } - + // // expr '*' expr // @@ -132,12 +132,12 @@ public class Parser } StringBuilder buf = new StringBuilder(128); - + // // Get the next character // char c = _buf.charAt(_pos); - + // // '(', ')', '+' and '*' are tokens. // @@ -156,7 +156,7 @@ public class Parser buf.append(_buf.charAt(_pos++)); } } - + _token = buf.toString(); } diff --git a/java/test/Freeze/dbmap/Client.java b/java/test/Freeze/dbmap/Client.java index ba99c46a2d2..84f264f18a4 100644 --- a/java/test/Freeze/dbmap/Client.java +++ b/java/test/Freeze/dbmap/Client.java @@ -17,26 +17,25 @@ public class Client { public void run() - { + { try { for(int i = 0; i < 10; ++i) { for(;;) { - java.util.Iterator p = null; + Transaction tx = _connection.beginTransaction(); try { - java.util.Set entrySet = _map.entrySet(); - p = entrySet.iterator(); - + java.util.Iterator<java.util.Map.Entry<Byte, Integer>> p = _map.entrySet().iterator(); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - byte v = ((Byte)e.getKey()).byteValue(); + java.util.Map.Entry<Byte, Integer> e = p.next(); + byte v = e.getKey().byteValue(); test(e.getValue().equals(new Integer(v - (byte)'a'))); } + break; } catch(DeadlockException ex) @@ -48,10 +47,7 @@ public class Client } finally { - if(p != null) - { - ((Freeze.Map.EntryIterator)p).close(); - } + tx.rollback(); } } } @@ -63,11 +59,11 @@ public class Client } finally { - ((Freeze.Map) _map).close(); + ((Freeze.Map)_map).close(); _connection.close(); } } - + ReadThread(Ice.Communicator communicator, String envName, String dbName) { _connection = Freeze.Util.createConnection(communicator, envName); @@ -75,10 +71,9 @@ public class Client } private Freeze.Connection _connection; - private java.util.Map _map; + private java.util.Map<Byte, Integer> _map; } - static class WriteThread extends Thread { public void @@ -90,21 +85,22 @@ public class Client { for(;;) { - java.util.Iterator p = null; + Transaction tx = _connection.beginTransaction(); try { - java.util.Set entrySet = _map.entrySet(); - p = entrySet.iterator(); - + java.util.Iterator<java.util.Map.Entry<Byte, Integer>> p = _map.entrySet().iterator(); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - int v = ((Integer)e.getValue()).intValue() + 1; - e.setValue(new Integer(v)); + java.util.Map.Entry<Byte, Integer> e = p.next(); + int v = e.getValue().intValue() + 1; + e.setValue(v); p.remove(); } - + + tx.commit(); + tx = null; + break; } catch(DeadlockException ex) @@ -116,9 +112,9 @@ public class Client } finally { - if(p != null) + if(tx != null) { - ((Freeze.Map.EntryIterator)p).close(); + tx.rollback(); } } } @@ -136,7 +132,7 @@ public class Client _connection.close(); } } - + WriteThread(Ice.Communicator communicator, String envName, String dbName) { _connection = Freeze.Util.createConnection(communicator, envName); @@ -144,10 +140,9 @@ public class Client } private Freeze.Connection _connection; - private java.util.Map _map; + private java.util.Map<Byte, Integer> _map; } - static String alphabet = "abcdefghijklmnopqrstuvwxyz"; private static void @@ -160,20 +155,20 @@ public class Client } private static void - populateDB(Freeze.Connection connection, java.util.Map m) + populateDB(Freeze.Connection connection, java.util.Map<Byte, Integer> m) throws DatabaseException { int length = alphabet.length(); for(;;) { - + try { Transaction tx = connection.beginTransaction(); for(int j = 0; j < length; ++j) { - m.put(new Byte((byte)alphabet.charAt(j)), new Integer(j)); + m.put((byte)alphabet.charAt(j), j); } tx.commit(); break; // for(;;) @@ -208,13 +203,13 @@ public class Client { Transaction tx = connection.beginTransaction(); ByteIntMap m = new ByteIntMap(connection, dbName, true); - - m.put(new Byte((byte)'a'), new Integer(1)); + + m.put((byte)'a', 1); m.close(); tx.rollback(); } - java.util.Map m = new ByteIntMap(connection, dbName, true); + java.util.Map<Byte, Integer> m = new ByteIntMap(connection, dbName, true); // // Populate the database with the alphabet. @@ -227,39 +222,41 @@ public class Client System.out.flush(); for(j = 0; j < alphabet.length(); ++j) { - Object value = m.get(new Byte((byte)alphabet.charAt(j))); + Integer value = m.get((byte)alphabet.charAt(j)); test(value != null); } - test(m.get(new Byte((byte)'0')) == null); + test(m.get((byte)'0') == null); for(j = 0; j < alphabet.length(); ++j) { - test(m.containsKey(new Byte((byte)alphabet.charAt(j)))); + test(m.containsKey((byte)alphabet.charAt(j))); } - test(!m.containsKey(new Byte((byte)'0'))); + test(!m.containsKey((byte)'0')); for(j = 0; j < alphabet.length(); ++j) { - test(m.containsValue(new Integer(j))); + test(m.containsValue(j)); } - test(!m.containsValue(new Integer(-1))); + test(!m.containsValue(-1)); test(m.size() == alphabet.length()); test(!m.isEmpty()); System.out.println("ok"); System.out.print("testing erase... "); System.out.flush(); - m.remove(new Byte((byte)'a')); - m.remove(new Byte((byte)'b')); - m.remove(new Byte((byte)'c')); + m.remove((byte)'a'); + m.remove((byte)'b'); + m.remove((byte)'c'); for(j = 3; j < alphabet.length(); ++j) { - Object value = m.get(new Byte((byte)alphabet.charAt(j))); + Integer value = m.get((byte)alphabet.charAt(j)); test(value != null); } - test(m.get(new Byte((byte)'a')) == null); - test(m.get(new Byte((byte)'b')) == null); - test(m.get(new Byte((byte)'c')) == null); + test(m.get((byte)'a') == null); + test(m.get((byte)'b') == null); + test(m.get((byte)'c') == null); + test(((ByteIntMap)m).fastRemove((byte)'d') == true); + test(((ByteIntMap)m).fastRemove((byte)'d') == false); System.out.println("ok"); - + // // Re-populate. // @@ -268,55 +265,338 @@ public class Client { System.out.print("testing keySet... "); System.out.flush(); - java.util.Set keys = m.keySet(); + java.util.Set<Byte> keys = m.keySet(); test(keys.size() == alphabet.length()); test(!keys.isEmpty()); - java.util.Iterator p = keys.iterator(); + java.util.Iterator<Byte> p = keys.iterator(); while(p.hasNext()) { - Object o = p.next(); - test(keys.contains(o)); - - Byte b = (Byte)o; + Byte b = p.next(); + test(keys.contains(b)); test(m.containsKey(b)); } + + // + // The iterator should have already been closed when we reached the last entry. + // + int count = ((Freeze.Map)m).closeAllIterators(); + test(count == 0); + + try + { + keys.remove((byte)'a'); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - no transaction. + } + + count = ((Freeze.Map)m).closeAllIterators(); + test(count == 1); // Opened by keys.remove() + + Transaction tx = connection.beginTransaction(); + test(keys.remove((byte)'a') == true); + test(keys.remove((byte)'a') == false); + tx.commit(); + test(m.containsKey((byte)'a') == false); + System.out.println("ok"); } + // + // Re-populate. + // + populateDB(connection, m); + { System.out.print("testing values... "); System.out.flush(); - java.util.Collection values = m.values(); + java.util.Collection<Integer> values = m.values(); test(values.size() == alphabet.length()); test(!values.isEmpty()); - java.util.Iterator p = values.iterator(); + java.util.Iterator<Integer> p = values.iterator(); while(p.hasNext()) { - Object o = p.next(); - test(values.contains(o)); - - Integer i = (Integer)o; + Integer i = p.next(); + test(values.contains(i)); test(m.containsValue(i)); } + + // + // The iterator should have already been closed when we reached the last entry. + // + int count = ((Freeze.Map)m).closeAllIterators(); + test(count == 0); + + try + { + values.remove(0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - no transaction. + } + + count = ((Freeze.Map)m).closeAllIterators(); + test(count == 1); // Opened by keys.remove() + + Transaction tx = connection.beginTransaction(); + test(values.remove(0) == true); + test(values.remove(0) == false); + tx.commit(); + test(m.containsKey((byte)'a') == false); + System.out.println("ok"); } + // + // Re-populate. + // + populateDB(connection, m); + { System.out.print("testing entrySet... "); System.out.flush(); - java.util.Set entrySet = m.entrySet(); + java.util.Set<java.util.Map.Entry<Byte, Integer>> entrySet = m.entrySet(); test(entrySet.size() == alphabet.length()); test(!entrySet.isEmpty()); - java.util.Iterator p = entrySet.iterator(); + java.util.Iterator<java.util.Map.Entry<Byte, Integer>> p = entrySet.iterator(); while(p.hasNext()) { - Object o = p.next(); - test(entrySet.contains(o)); + java.util.Map.Entry<Byte, Integer> e = p.next(); + test(entrySet.contains(e)); + test(m.containsKey(e.getKey())); + test(m.containsValue(e.getValue())); + } + + // + // The iterator should have already been closed when we reached the last entry. + // + int count = ((Freeze.Map)m).closeAllIterators(); + test(count == 0); + System.out.println("ok"); + } + + { + System.out.print("testing unsorted map... "); + System.out.flush(); + + NavigableMap<Byte, Integer> nm = (NavigableMap<Byte, Integer>)m; + final byte firstByte = (byte)alphabet.charAt(0); + final byte lastByte = (byte)alphabet.charAt(alphabet.length() - 1); + final int length = alphabet.length(); + + // + // Keys + // + + Byte key; + + key = nm.firstKey(); + test(key != null); + test(key.byteValue() == firstByte); + + key = nm.lastKey(); + test(key != null); + test(key.byteValue() == lastByte); + + try + { + nm.ceilingKey((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + nm.floorKey((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + nm.higherKey((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + nm.lowerKey((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + m.clear(); + try + { + nm.firstKey(); + test(false); + } + catch(java.util.NoSuchElementException ex) + { + // Expected. + } + try + { + nm.lastKey(); + test(false); + } + catch(java.util.NoSuchElementException ex) + { + // Expected. + } + + populateDB(connection, m); + + // + // Entries + // + + java.util.Map.Entry<Byte, Integer> e; + + e = nm.firstEntry(); + test(e != null); + test(e.getKey().byteValue() == (byte)firstByte); + test(e.getValue().intValue() == 0); + + e = nm.lastEntry(); + test(e != null); + test(e.getKey().byteValue() == (byte)lastByte); + test(e.getValue().intValue() == length - 1); + + try + { + nm.ceilingEntry((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + nm.floorEntry((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + nm.higherEntry((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + nm.lowerEntry((byte)0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + e = nm.pollFirstEntry(); + test(e != null); + test(e.getKey().byteValue() == (byte)firstByte); + test(e.getValue().intValue() == 0); + test(!nm.containsKey(firstByte)); + + e = nm.pollLastEntry(); + test(e != null); + test(e.getKey().byteValue() == (byte)lastByte); + test(e.getValue().intValue() == length - 1); + test(!nm.containsKey(lastByte)); + + ByteIntMap typedM = (ByteIntMap)m; + + try + { + typedM.headMapForValue(0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + typedM.tailMapForValue(0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + typedM.subMapForValue(0, 0); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + try + { + typedM.mapForValue(); + test(false); + } + catch(UnsupportedOperationException ex) + { + // Expected - a comparator is required. + } + + m.clear(); + test(nm.firstEntry() == null); + test(nm.lastEntry() == null); + populateDB(connection, m); - java.util.Map.Entry e = (java.util.Map.Entry)o; + System.out.println("ok"); + } + + { + System.out.print("testing for loop... "); + System.out.flush(); + for(java.util.Map.Entry<Byte, Integer> e : m.entrySet()) + { test(m.containsKey(e.getKey())); test(m.containsValue(e.getValue())); } + + // + // The iterator should have already been closed when we reached the last entry. + // + int count = ((Freeze.Map)m).closeAllIterators(); + test(count == 0); + System.out.println("ok"); } @@ -324,20 +604,40 @@ public class Client System.out.print("testing iterator.remove... "); System.out.flush(); + Freeze.Map<Byte, Integer> fm = (Freeze.Map<Byte, Integer>)m; + java.util.Iterator<java.util.Map.Entry<Byte, Integer>> p; + Transaction tx; + int count; + test(m.size() == 26); - test(m.get(new Byte((byte)'b')) != null); - test(m.get(new Byte((byte)'n')) != null); - test(m.get(new Byte((byte)'z')) != null); + test(m.get((byte)'b') != null); + test(m.get((byte)'n') != null); + test(m.get((byte)'z') != null); + + // + // Verify that remove fails without a transaction. + // + p = m.entrySet().iterator(); + test(p.hasNext()); + p.next(); + try + { + p.remove(); + } + catch(UnsupportedOperationException ex) + { + // Expected. + } - ((Freeze.Map) m).closeAllIterators(); + count = fm.closeAllIterators(); + test(count == 1); - java.util.Set entrySet = m.entrySet(); - java.util.Iterator p = entrySet.iterator(); - + tx = connection.beginTransaction(); + p = m.entrySet().iterator(); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - Byte b = (Byte)e.getKey(); + java.util.Map.Entry<Byte, Integer> e = p.next(); + Byte b = e.getKey(); byte v = b.byteValue(); if(v == (byte)'b' || v == (byte)'n' || v == (byte)'z') { @@ -352,37 +652,41 @@ public class Client } } } - ((Freeze.Map) m).closeAllIterators(); + tx.commit(); + count = fm.closeAllIterators(); // Committing the transaction should close the iterator. + test(count == 0); test(m.size() == 23); - test(m.get(new Byte((byte)'b')) == null); - test(m.get(new Byte((byte)'n')) == null); - test(m.get(new Byte((byte)'z')) == null); + test(m.get((byte)'b') == null); + test(m.get((byte)'n') == null); + test(m.get((byte)'z') == null); // // Re-populate. // populateDB(connection, m); - + test(m.size() == 26); - entrySet = m.entrySet(); - p = entrySet.iterator(); + tx = connection.beginTransaction(); + p = m.entrySet().iterator(); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - byte v = ((Byte)e.getKey()).byteValue(); + java.util.Map.Entry<Byte, Integer> e = p.next(); + byte v = e.getKey().byteValue(); if(v == (byte)'a' || v == (byte)'b' || v == (byte)'c') { p.remove(); } } - ((Freeze.Map) m).closeAllIterators(); + tx.commit(); + count = fm.closeAllIterators(); // Committing the transaction should close the iterator. + test(count == 0); test(m.size() == 23); - test(m.get(new Byte((byte)'a')) == null); - test(m.get(new Byte((byte)'b')) == null); - test(m.get(new Byte((byte)'c')) == null); + test(m.get((byte)'a') == null); + test(m.get((byte)'b') == null); + test(m.get((byte)'c') == null); System.out.println("ok"); } @@ -395,28 +699,48 @@ public class Client // populateDB(connection, m); - java.util.Set entrySet = m.entrySet(); - java.util.Iterator p = entrySet.iterator(); + Freeze.Map<Byte, Integer> fm = (Freeze.Map<Byte, Integer>)m; + java.util.Iterator<java.util.Map.Entry<Byte, Integer>> p; + Transaction tx; + java.util.Map.Entry<Byte, Integer> e; + + // + // Verify that setValue on an iterator fails without a transaction. + // + p = m.entrySet().iterator(); + test(p.hasNext()); + try + { + e = p.next(); + e.setValue(0); + } + catch(UnsupportedOperationException ex) + { + // Expected. + } + + tx = connection.beginTransaction(); + p = m.entrySet().iterator(); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - byte v = ((Byte)e.getKey()).byteValue(); + e = p.next(); + byte v = e.getKey().byteValue(); if(v == (byte)'b' || v == (byte)'n' || v == (byte)'z') { - e.setValue(new Integer(v + 100)); + e.setValue(v + 100); } } - ((Freeze.Map) m).closeAllIterators(); + tx.commit(); test(m.size() == 26); - test(m.get(new Byte((byte)'b')) != null); - test(m.get(new Byte((byte)'n')) != null); - test(m.get(new Byte((byte)'z')) != null); + test(m.get((byte)'b') != null); + test(m.get((byte)'n') != null); + test(m.get((byte)'z') != null); - p = entrySet.iterator(); + p = m.entrySet().iterator(); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - byte v = ((Byte)e.getKey()).byteValue(); + e = p.next(); + byte v = e.getKey().byteValue(); if(v == (byte)'b' || v == (byte)'n' || v == (byte)'z') { test(e.getValue().equals(new Integer(v + 100))); @@ -426,6 +750,18 @@ public class Client test(e.getValue().equals(new Integer(v - (byte)'a'))); } } + + // + // No transaction is necessary for entries obtained without an iterator. + // + e = fm.firstEntry(); + test(e != null); + e.setValue(-1); + test(e.getValue().intValue() == -1); + e = fm.firstEntry(); + test(e != null); + test(e.getValue().intValue() == -1); + System.out.println("ok"); } @@ -440,8 +776,9 @@ public class Client ByteIntMap typedM = (ByteIntMap)m; - java.util.Map.Entry e; - java.util.Iterator p; + java.util.Map.Entry<Byte, Integer> e; + java.util.Iterator<java.util.Map.Entry<Byte, Integer>> p; + Transaction tx; int length = alphabet.length(); @@ -449,76 +786,95 @@ public class Client { p = typedM.findByValue(k); test(p.hasNext()); - e = (java.util.Map.Entry)p.next(); - test(((Byte)e.getKey()).byteValue() == (byte)alphabet.charAt(k)); + e = p.next(); + test(e.getKey().byteValue() == (byte)alphabet.charAt(k)); test(!p.hasNext()); } // - // 2 items at 17 - // - m.put(new Byte((byte)alphabet.charAt(21)), new Integer(17)); + // Change the value associated with key 21 to 17. + // + m.put((byte)alphabet.charAt(21), 17); // - // Non-existent index value + // Verify that the index no longer has an entry for value 21. // p = typedM.findByValue(21); test(!p.hasNext()); - + // + // Verify that the iterator returns two entries for value 17. + // p = typedM.findByValue(17); - test(p.hasNext()); - e = (java.util.Map.Entry)p.next(); - byte v = ((Byte)e.getKey()).byteValue(); + e = p.next(); + byte v = e.getKey().byteValue(); test(v == (byte)alphabet.charAt(17) || v == (byte)alphabet.charAt(21)); - + test(p.hasNext()); - e = (java.util.Map.Entry)p.next(); - v = ((Byte)e.getKey()).byteValue(); + e = p.next(); + v = e.getKey().byteValue(); test(v == (byte)alphabet.charAt(17) || v == (byte)alphabet.charAt(21)); - - test(!p.hasNext()); + + test(!p.hasNext()); // Iterator defaults to returning only exact matches. test(typedM.valueCount(17) == 2); + // + // Cannot remove without a transaction. + // + p = typedM.findByValue(17); + test(p.hasNext()); + p.next(); + try + { + p.remove(); + } + catch(UnsupportedOperationException ex) + { + // Expected. + } + + tx = connection.beginTransaction(); p = typedM.findByValue(17); test(p.hasNext()); p.next(); p.remove(); test(p.hasNext()); - e = (java.util.Map.Entry)p.next(); - v = ((Byte)e.getKey()).byteValue(); + e = p.next(); + v = e.getKey().byteValue(); test(v == (byte)alphabet.charAt(17) || v == (byte)alphabet.charAt(21)); test(!p.hasNext()); + tx.commit(); - // - // We need to close this write iterator before further reads - // - typedM.closeAllIterators(); + int count = typedM.closeAllIterators(); + test(count == 0); // Committing the transaction also closes the iterators. test(typedM.valueCount(17) == 1); p = typedM.findByValue(17); test(p.hasNext()); - e = (java.util.Map.Entry)p.next(); + e = p.next(); + // + // Cannot set a value on an index iterator. + // try { - e.setValue(new Integer(18)); + e.setValue(18); test(false); } catch(UnsupportedOperationException ex) { - // Expected + // Expected. } - v = ((Byte)e.getKey()).byteValue(); + v = e.getKey().byteValue(); test(v == (byte)alphabet.charAt(17) || v == (byte)alphabet.charAt(21)); test(typedM.valueCount(17) == 1); - m.put(new Byte((byte)alphabet.charAt(21)), new Integer(17)); - - // + m.put((byte)alphabet.charAt(21), 17); + + // // Non-exact match // p = typedM.findByValue(21); @@ -531,35 +887,33 @@ public class Client p = typedM.findByValue(22, false); int previous = 21; - int count = 0; + count = 0; while(p.hasNext()) { - e = (java.util.Map.Entry)p.next(); + e = p.next(); + + int val = e.getValue().intValue(); - int val = ((Integer)e.getValue()).intValue(); - test(val > previous); previous = val; count++; } test(count == 4); - + System.out.println("ok"); } - - ((Freeze.Map) m).closeAllIterators(); + ((Freeze.Map)m).closeAllIterators(); { System.out.print("testing concurrent access... "); System.out.flush(); - + m.clear(); populateDB(connection, m); - - java.util.List l = new java.util.ArrayList(); - + java.util.List<Thread> l = new java.util.ArrayList<Thread>(); + // // Create each thread. // @@ -572,25 +926,21 @@ public class Client // // Start each thread. // - java.util.Iterator p = l.iterator(); - while(p.hasNext()) + for(Thread t : l) { - Thread thr = (Thread)p.next(); - thr.start(); + t.start(); } - + // // Wait for each thread to terminate. // - p = l.iterator(); - while(p.hasNext()) + for(Thread t : l) { - Thread thr = (Thread)p.next(); - while(thr.isAlive()) + while(t.isAlive()) { try { - thr.join(); + t.join(); } catch(InterruptedException e) { @@ -610,42 +960,42 @@ public class Client Ice.Identity odd = new Ice.Identity(); odd.name = "foo"; odd.category = "odd"; - + Ice.Identity even = new Ice.Identity(); even.name = "bar"; even.category = "even"; - + Transaction tx = connection.beginTransaction(); for(int i = 0; i < 1000; i++) { if(i % 2 == 0) { - iim.fastPut(new Integer(i), even); + iim.fastPut(i, even); } else { - iim.fastPut(new Integer(i), odd); + iim.fastPut(i, odd); } } tx.commit(); iim.closeDb(); } - + { // // Need true to create the index // IntIdentityMapWithIndex iim = new IntIdentityMapWithIndex(connection, "intIdentity", true); - + test(iim.categoryCount("even") == 500); test(iim.categoryCount("odd") == 500); - + int count = 0; - java.util.Iterator p = iim.findByCategory("even"); + java.util.Iterator<java.util.Map.Entry<Integer, Ice.Identity>> p = iim.findByCategory("even"); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - int k = ((Integer)e.getKey()).intValue(); + java.util.Map.Entry<Integer, Ice.Identity> e = p.next(); + int k = e.getKey().intValue(); test(k % 2 == 0); ++count; } @@ -655,52 +1005,61 @@ public class Client p = iim.findByCategory("odd"); while(p.hasNext()) { - java.util.Map.Entry e = (java.util.Map.Entry)p.next(); - int k = ((Integer)e.getKey()).intValue(); + java.util.Map.Entry<Integer, Ice.Identity> e = p.next(); + int k = e.getKey().intValue(); test(k % 2 == 1); ++count; } test(count == 500); - + iim.destroy(); } System.out.println("ok"); - - System.out.print("testing sorting... "); - System.out.flush(); + // + // Sorting + // - final java.util.Comparator less = - new java.util.Comparator() + final java.util.Comparator<Integer> less = new java.util.Comparator<Integer>() + { + public int compare(Integer i1, Integer i2) { - public int compare(Object o1, Object o2) + if(i1 == i2) { - if(o1 == o2) - { - return 0; - } - else if(o1 == null) - { - return -((Comparable)o2).compareTo(o1); - } - else - { - return ((Comparable)o1).compareTo(o2); - } + return 0; + } + else if(i1 == null) + { + return -i2.compareTo(i1); } - }; - - java.util.Comparator greater = - new java.util.Comparator() + else + { + return i1.compareTo(i2); + } + } + }; + + java.util.Comparator<String> greater = new java.util.Comparator<String>() + { + public int compare(String s1, String s2) { - public int compare(Object o1, Object o2) + if(s1 == s2) { - return -less.compare(o1, o2); + return 0; } - }; - - java.util.Map indexComparators = new java.util.HashMap(); - indexComparators.put("category", greater); + else if(s1 == null) + { + return s2.compareTo(s1); + } + else + { + return -s1.compareTo(s2); + } + } + }; + + SortedMap.IndexComparators indexComparators = new SortedMap.IndexComparators(); + indexComparators.categoryComparator = greater; java.util.Random rand = new java.util.Random(); { @@ -709,13 +1068,9 @@ public class Client Transaction tx = connection.beginTransaction(); for(int i = 0; i < 500; i++) { - int k = rand.nextInt(1000); - - Ice.Identity id = new Ice.Identity("foo", - String.valueOf(alphabet.charAt(k % 26))); - - - sm.fastPut(new Integer(k), id); + int k = rand.nextInt(1000); + Ice.Identity id = new Ice.Identity("foo", String.valueOf(alphabet.charAt(k % 26))); + sm.fastPut(k, id); } tx.commit(); sm.close(); @@ -723,137 +1078,1032 @@ public class Client { SortedMap sm = new SortedMap(connection, "sortedMap", true, less, indexComparators); - + NavigableMap<Integer, Ice.Identity> sub = null; + + System.out.print("testing sorting with primary key... "); + System.out.flush(); + + testSortedMap(sm, true); + + { + final Integer first = sm.firstKey(); + final Integer last = sm.lastKey(); + + // + // fastRemove + // + sub = sm.headMap(first, true); + Ice.Identity id = sub.get(first); + test(sub.fastRemove(first) == true); + test(sub.fastRemove(first) == false); + test(sm.containsKey(first) == false); + sm.put(first, id); + test(sm.containsKey(first) == true); + } + + System.out.println("ok"); + // - // Primary key + // Category index // - for(int i = 0; i < 100; i++) + { - int k = rand.nextInt(1000); + System.out.print("testing sorting with secondary key... "); + System.out.flush(); + + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> isub = null; - java.util.SortedMap subMap = sm.tailMap(new Integer(k)); + isub = sm.mapForCategory(); + final String first = isub.firstKey(); + final String last = isub.lastKey(); + + // + // Head map + // + isub = sm.headMapForCategory(last); + test(greater.compare(isub.lastKey(), last) < 0); + isub = sm.headMapForCategory(last, true); + test(greater.compare(isub.lastKey(), last) == 0); + isub = sm.headMapForCategory(first); + test(isub.firstEntry() == null); // map is empty + isub = sm.headMapForCategory(first, true); + test(greater.compare(isub.firstKey(), first) == 0); + test(greater.compare(isub.lastKey(), first) == 0); + + sm.headMapForCategory(first, true).headMap(first, true); + sm.headMapForCategory(first, true).headMap(first); + sm.headMapForCategory(first).headMap(first); try { - Integer fk = (Integer)subMap.firstKey(); - test(fk.intValue() >= k); + sm.headMapForCategory(first).headMap(first, true); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. } - catch(NoSuchElementException e) + { - // Expected from time to time + String category = null; + while(true) + { + int k = rand.nextInt(1000); + category = String.valueOf(alphabet.charAt(k % 26)); + isub = sm.headMapForCategory(category); + if(isub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testSecondaryKey(isub, null, false, category, false); + + try + { + isub.tailMap(category); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } } - - subMap = sm.headMap(new Integer(k)); + + { + String category = null; + while(true) + { + int k = rand.nextInt(1000); + category = String.valueOf(alphabet.charAt(k % 26)); + isub = sm.headMapForCategory(category, true); + if(isub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testSecondaryKey(isub, null, false, category, true); + + try + { + String invalid = String.valueOf(category.charAt(0) + 1); + isub.tailMap(invalid); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + } + + // + // Tail map + // + isub = sm.tailMapForCategory(first); + test(greater.compare(isub.firstKey(), first) == 0); + isub = sm.tailMapForCategory(first, false); + test(greater.compare(isub.firstKey(), first) > 0); + isub = sm.tailMapForCategory(last); + test(greater.compare(isub.firstKey(), last) == 0); + test(greater.compare(isub.lastKey(), last) == 0); + isub = sm.tailMapForCategory(last, false); + test(isub.firstEntry() == null); // map is empty + + sm.tailMapForCategory(last).tailMap(last); + sm.tailMapForCategory(last).tailMap(last, false); try { - Integer lk = (Integer)subMap.lastKey(); - test(lk.intValue() < k); + sm.tailMapForCategory(last, false).tailMap(last); + test(false); } - catch(NoSuchElementException e) + catch(IllegalArgumentException ex) { - // Expected from time to time + // Expected. } - + + { + String category = null; + while(true) + { + int k = rand.nextInt(1000); + category = String.valueOf(alphabet.charAt(k % 26)); + isub = sm.tailMapForCategory(category); + if(isub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testSecondaryKey(isub, category, true, null, false); + + try + { + String invalid = String.valueOf((char)(category.charAt(0) + 1)); + isub.headMap(invalid); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + } + + { + String category = null; + while(true) + { + int k = rand.nextInt(1000); + category = String.valueOf(alphabet.charAt(k % 26)); + isub = sm.tailMapForCategory(category, false); + if(isub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testSecondaryKey(isub, category, false, null, false); + + try + { + isub.headMap(category); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + } + // - // Now with an iterator + // Sub map // - java.util.Iterator p = subMap.keySet().iterator(); - while(p.hasNext()) + isub = sm.subMapForCategory(first, last); + test(greater.compare(isub.firstKey(), first) == 0); + test(greater.compare(isub.lastKey(), last) < 0); + isub = sm.subMapForCategory(first, false, last, false); + test(greater.compare(isub.firstKey(), first) > 0); + isub = sm.subMapForCategory(first, true, last, true); + test(greater.compare(isub.firstKey(), first) == 0); + test(greater.compare(isub.lastKey(), last) == 0); + + try { - Integer ck = (Integer)p.next(); - test(ck.intValue() < k); + sm.subMapForCategory(first, false, first, false); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. } - sm.closeAllIterators(); - } - // - // Category index - // - for(int i = 0; i < 100; i++) - { - int k = rand.nextInt(1000); - String category = String.valueOf(alphabet.charAt(k % 26)); - - java.util.SortedMap subMap = sm.tailMapForIndex("category", category); + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> isubsub = null; + + isubsub = isub.subMap(first, true, last, true); + test(greater.compare(isubsub.firstKey(), first) == 0); + test(greater.compare(isubsub.lastKey(), last) == 0); + + isubsub = isub.subMap(first, false, last, false); + test(greater.compare(isubsub.firstKey(), first) > 0); + test(greater.compare(isubsub.lastKey(), last) < 0); + try { - String fk = (String)subMap.firstKey(); - test(greater.compare(fk, category) >= 0); + isubsub.subMap(first, true, last, false); + test(false); } - catch(NoSuchElementException e) + catch(IllegalArgumentException ex) { - // Expected from time to time + // Expected. } - - subMap = sm.headMapForIndex("category", category); + try { - String lk = (String)subMap.lastKey(); - test(greater.compare(lk, category) < 0); + isubsub.subMap(first, false, last, true); + test(false); } - catch(NoSuchElementException e) + catch(IllegalArgumentException ex) + { + // Expected. + } + { - // Expected from time to time + final boolean fromInclusive[] = { false, false, true, true }; + final boolean toInclusive[] = { false, true, false, true }; + for(int i = 0; i < 4; ++i) + { + String from = null, to = null; + while(true) + { + int f = rand.nextInt(1000) % 26; + int t = rand.nextInt(1000) % 26; + int f1 = Math.max(f, t); + int t1 = Math.min(f, t); + if(f1 - t1 < 10) + { + continue; + } + from = String.valueOf(alphabet.charAt(f1 % 26)); + to = String.valueOf(alphabet.charAt(t1 % 26)); + isub = sm.subMapForCategory(from, fromInclusive[i], to, toInclusive[i]); + if(isub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testSecondaryKey(isub, from, fromInclusive[i], to, toInclusive[i]); + } } // - // Now with an iterator + // fastRemove // - java.util.Iterator p = subMap.keySet().iterator(); - while(p.hasNext()) + isub = sm.headMapForCategory(first, true); + try + { + isub.fastRemove(first); + test(false); + } + catch(UnsupportedOperationException ex) { - String ck = (String)p.next(); - test(greater.compare(ck, category) < 0); + // Expected. } - sm.closeAllIterators(); + + System.out.println("ok"); } - - java.util.SortedMap subMap = sm.mapForIndex("category"); - java.util.Iterator p = subMap.entrySet().iterator(); - String category = null; - while(p.hasNext()) + sm.close(); + } + + { + SortedMap sm = new SortedMap(connection, "sortedMap", true, less, indexComparators); + + System.out.print("testing descending map... "); + System.out.flush(); + + { + NavigableMap<Integer, Ice.Identity> dmap = sm.descendingMap(); + testSortedMap(dmap, false); + testSortedMap(dmap.descendingMap(), true); // Ascending submap. + } + + int finc, tinc; // Inclusive flags + + for(tinc = 0; tinc < 2; ++tinc) { - java.util.Map.Entry entry = (java.util.Map.Entry)p.next(); - - if(category != null) + while(true) { - test(greater.compare(category, entry.getKey()) < 0); + NavigableMap<Integer, Ice.Identity> sub = sm.headMap(rand.nextInt(1000), tinc == 0); + if(sub.firstEntry() == null) + { + continue; + } + NavigableMap<Integer, Ice.Identity> dmap = sub.descendingMap(); + test(dmap.firstKey().equals(sub.lastKey())); + test(dmap.lastKey().equals(sub.firstKey())); + break; } - category = (String)entry.getKey(); - // System.out.println("*******Category == " + category); + } - - java.util.Iterator q = ((java.util.Set)entry.getValue()).iterator(); - while(q.hasNext()) + for(finc = 0; finc < 2; ++finc) + { + while(true) { - // - // All my map entries - // - entry = (java.util.Map.Entry)q.next(); - Ice.Identity id = (Ice.Identity)entry.getValue(); - test(category.equals(id.category)); - - // System.out.println("Key == " + entry.getKey().toString()); + NavigableMap<Integer, Ice.Identity> sub = sm.tailMap(rand.nextInt(1000), finc == 0); + if(sub.firstEntry() == null) + { + continue; + } + NavigableMap<Integer, Ice.Identity> dmap = sub.descendingMap(); + test(dmap.firstKey().equals(sub.lastKey())); + test(dmap.lastKey().equals(sub.firstKey())); + break; + } + } + for(finc = 0; finc < 2; ++finc) + { + for(tinc = 0; tinc < 2; ++tinc) + { + while(true) + { + int f = rand.nextInt(1000); + int t = rand.nextInt(1000); + int from = Math.min(f, t); + int to = Math.max(f, t); + if(to - from < 100) + { + continue; + } + NavigableMap<Integer, Ice.Identity> sub = sm.subMap(from, finc == 0, to, tinc == 0); + if(sub.firstEntry() == null) + { + continue; + } + NavigableMap<Integer, Ice.Identity> dmap = sub.descendingMap(); + test(dmap.firstKey().equals(sub.lastKey())); + test(dmap.lastKey().equals(sub.firstKey())); + break; + } } } - sm.closeAllIterators(); + + { + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> isub, dmap; + java.util.Comparator<? super String> c; + + isub = sm.mapForCategory(); // An iterator for this map visits keys in descending order. + dmap = isub.descendingMap(); // An iterator for this map visits keys in ascending order. + test(dmap.firstKey().equals(isub.lastKey())); + test(dmap.lastKey().equals(isub.firstKey())); + c = dmap.comparator(); + String prev = null; + for(java.util.Map.Entry<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> e : + dmap.entrySet()) + { + if(prev != null) + { + test(c.compare(e.getKey(), prev) > 0); + } + prev = e.getKey(); + } + + dmap = dmap.descendingMap(); + test(dmap.firstKey().equals(isub.firstKey())); + test(dmap.lastKey().equals(isub.lastKey())); + } + + for(tinc = 0; tinc < 2; ++tinc) + { + while(true) + { + String category = String.valueOf(alphabet.charAt(rand.nextInt(1000) % 26)); + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> isub = + sm.headMapForCategory(category, tinc == 0); + if(isub.firstEntry() == null) + { + continue; + } + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> dmap = + isub.descendingMap(); + test(dmap.firstKey().equals(isub.lastKey())); + test(dmap.lastKey().equals(isub.firstKey())); + break; + } + } + + for(finc = 0; finc < 2; ++finc) + { + while(true) + { + String category = String.valueOf(alphabet.charAt(rand.nextInt(1000) % 26)); + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> isub = + sm.tailMapForCategory(category, finc == 0); + if(isub.firstEntry() == null) + { + continue; + } + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> dmap = + isub.descendingMap(); + test(dmap.firstKey().equals(isub.lastKey())); + test(dmap.lastKey().equals(isub.firstKey())); + break; + } + } + + for(finc = 0; finc < 2; ++finc) + { + for(tinc = 0; tinc < 2; ++tinc) + { + while(true) + { + int f = rand.nextInt(1000) % 26; + int t = rand.nextInt(1000) % 26; + int f1 = Math.max(f, t); + int t1 = Math.min(f, t); + if(f1 - t1 < 10) + { + continue; + } + String from = String.valueOf(alphabet.charAt(f1 % 26)); + String to = String.valueOf(alphabet.charAt(t1 % 26)); + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> isub = + sm.subMapForCategory(from, finc == 0, to, tinc == 0); + if(isub.firstEntry() == null) + { + continue; + } + NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> dmap = + isub.descendingMap(); + test(dmap.firstKey().equals(isub.lastKey())); + test(dmap.lastKey().equals(isub.firstKey())); + break; + } + } + } + + { + java.util.Set<Integer> keys = sm.descendingKeySet(); + Integer prev = null; + for(Integer i : keys) + { + if(prev != null) + { + test(i.compareTo(prev) < 0); + } + prev = i; + } + } + + { + java.util.Set<String> keys = sm.mapForCategory().descendingKeySet(); + String prev = null; + for(String category : keys) + { + if(prev != null) + { + test(category.compareTo(prev) > 0); + } + prev = category; + } + } + + sm.close(); + + System.out.println("ok"); + } + + { + SortedMap sm = new SortedMap(connection, "sortedMap", true, less, indexComparators); + + System.out.print("testing empty map... "); + System.out.flush(); + sm.clear(); + + testEmptyMap(sm); + testEmptyMap(sm.headMap(0, false)); + testEmptyMap(sm.headMap(0, false).headMap(0, false)); + testEmptyMap(sm.tailMap(0, false)); + testEmptyMap(sm.tailMap(0, false).tailMap(0, false)); + testEmptyMap(sm.subMap(0, false, 1000, false)); + testEmptyMap(sm.subMap(0, false, 1000, false).subMap(0, false, 1000, false)); + sm.close(); + + System.out.println("ok"); } - System.out.println("ok"); + connection.close(); - + return 0; } + static void + testSortedMap(NavigableMap<Integer, Ice.Identity> sm, boolean ascending) + { + java.util.Comparator<? super Integer> c = sm.comparator(); + java.util.Random rand = new java.util.Random(); + NavigableMap<Integer, Ice.Identity> sub = null; + + final int first = sm.firstKey().intValue(); + final int last = sm.lastKey().intValue(); + + testPrimaryKey(sm, null, false, null, false); + + // + // Head map + // + sub = (NavigableMap<Integer, Ice.Identity>)sm.headMap(last); + test(c.compare(sub.lastKey(), last) < 0); + sub = sm.headMap(last, true); + test(c.compare(sub.lastKey(), last) == 0); + sub = (NavigableMap<Integer, Ice.Identity>)sm.headMap(first); + test(sub.firstEntry() == null); // map is empty + sub = sm.headMap(first, true); + test(c.compare(sub.firstKey(), first) == 0); + test(c.compare(sub.lastKey(), first) == 0); + + sm.headMap(first, true).headMap(first, true); + sm.headMap(first, true).headMap(first); + sm.headMap(first).headMap(first); + try + { + ((NavigableMap<Integer, Ice.Identity>)sm.headMap(first)).headMap(first, true); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + + { + int k = 0; + while(true) + { + k = rand.nextInt(1000); + sub = (NavigableMap<Integer, Ice.Identity>)sm.headMap(k); + if(sub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testPrimaryKey(sub, null, false, k, false); + + try + { + sub.tailMap(k); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + } + + { + int k = 0; + while(true) + { + k = rand.nextInt(1000); + sub = sm.headMap(k, true); + if(sub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testPrimaryKey(sub, null, false, k, true); + + try + { + sub.tailMap(k, false); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + } + + // + // Tail map + // + sub = (NavigableMap<Integer, Ice.Identity>)sm.tailMap(first); + test(c.compare(sub.firstKey(), first) == 0); + sub = sm.tailMap(first, false); + test(c.compare(sub.firstKey(), first) > 0); + sub = (NavigableMap<Integer, Ice.Identity>)sm.tailMap(last); + test(c.compare(sub.firstKey(), last) == 0); + test(c.compare(sub.lastKey(), last) == 0); + sub = sm.tailMap(last, false); + test(sub.firstEntry() == null); // map is empty + + sm.tailMap(last).tailMap(last); + ((NavigableMap<Integer, Ice.Identity>)sm.tailMap(last)).tailMap(last, false); + try + { + sm.tailMap(last, false).tailMap(last); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + + { + int k = 0; + while(true) + { + k = rand.nextInt(1000); + sub = (NavigableMap<Integer, Ice.Identity>)sm.tailMap(k); + if(sub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testPrimaryKey(sub, k, true, null, false); + + try + { + sub.headMap(k); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + } + + { + int k = 0; + while(true) + { + k = rand.nextInt(1000); + sub = sm.tailMap(k, false); + if(sub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testPrimaryKey(sub, k, false, null, false); + + try + { + sub.headMap(k); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + } + + // + // Sub map + // + sub = (NavigableMap<Integer, Ice.Identity>)sm.subMap(first, last); + test(c.compare(sub.firstKey(), first) == 0); + test(c.compare(sub.lastKey(), last) < 0); + sub = sm.subMap(first, false, last, false); + test(c.compare(sub.firstKey(), first) > 0); + sub = sm.subMap(first, true, last, true); + test(c.compare(sub.firstKey(), first) == 0); + test(c.compare(sub.lastKey(), last) == 0); + + try + { + sm.subMap(first, false, first, false); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + + NavigableMap<Integer, Ice.Identity> subsub = null; + + subsub = sub.subMap(first, true, last, true); + test(c.compare(subsub.firstKey(), first) == 0); + test(c.compare(subsub.lastKey(), last) == 0); + + subsub = sub.subMap(first, false, last, false); + test(c.compare(subsub.firstKey(), first) > 0); + test(c.compare(subsub.lastKey(), last) < 0); + + try + { + subsub.subMap(first, true, last, false); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + + try + { + subsub.subMap(first, false, last, true); + test(false); + } + catch(IllegalArgumentException ex) + { + // Expected. + } + + { + final boolean fromInclusive[] = { false, false, true, true }; + final boolean toInclusive[] = { false, true, false, true }; + for(int i = 0; i < 4; ++i) + { + int from = 0, to = 0; + while(true) + { + int f = rand.nextInt(1000); + int t = rand.nextInt(1000); + if(ascending) + { + from = Math.min(f, t); + to = Math.max(f, t); + } + else + { + from = Math.max(f, t); + to = Math.min(f, t); + } + if(Math.abs(to - from) < 100) + { + continue; + } + sub = sm.subMap(from, fromInclusive[i], to, toInclusive[i]); + if(sub.firstEntry() != null) // Make sure submap isn't empty. + { + break; + } + } + + testPrimaryKey(sub, from, fromInclusive[i], to, toInclusive[i]); + } + } + } + + static void + testPrimaryKey(NavigableMap<Integer, Ice.Identity> m, Integer from, boolean fromInclusive, Integer to, + boolean toInclusive) + { + java.util.Comparator<? super Integer> c = m.comparator(); + + Integer first = m.firstKey(); + Integer last = m.lastKey(); + + test(inRange(c, first, from, fromInclusive, to, toInclusive)); + test(inRange(c, last, from, fromInclusive, to, toInclusive)); + + java.util.Random rand = new java.util.Random(); + int i = 0; + while(i < 100) + { + int k = rand.nextInt(1000); + if(!inRange(c, k, from, fromInclusive, to, toInclusive)) + { + continue; + } + + java.util.Map.Entry<Integer, Ice.Identity> e; + Integer key; + + key = m.ceilingKey(k); + if(key == null) + { + test(c.compare(k, last) > 0); + } + else + { + test(c.compare(key, k) >= 0); + } + e = m.ceilingEntry(k); + test((key == null && e == null) || key.equals(e.getKey())); + + key = m.floorKey(k); + if(key == null) + { + test(c.compare(k, first) < 0); + } + else + { + test(c.compare(key, k) <= 0); + } + e = m.floorEntry(k); + test((key == null && e == null) || key.equals(e.getKey())); + + key = m.higherKey(k); + if(key == null) + { + test(c.compare(k, last) >= 0); + } + else + { + test(c.compare(key, k) > 0); + } + e = m.higherEntry(k); + test((key == null && e == null) || key.equals(e.getKey())); + + key = m.lowerKey(k); + if(key == null) + { + test(c.compare(k, first) <= 0); + } + else + { + test(c.compare(key, k) < 0); + } + e = m.lowerEntry(k); + test((key == null && e == null) || key.equals(e.getKey())); + + ++i; + } + + for(java.util.Map.Entry<Integer, Ice.Identity> p : m.entrySet()) + { + test(inRange(c, p.getKey(), from, fromInclusive, to, toInclusive)); + } + } + + static boolean + inRange(java.util.Comparator<? super Integer> c, Integer val, Integer from, boolean fromInclusive, Integer to, + boolean toInclusive) + { + if(from != null) + { + int cmp = c.compare(val, from); + if((fromInclusive && cmp < 0) || (!fromInclusive && cmp <= 0)) + { + return false; + } + } + if(to != null) + { + int cmp = c.compare(val, to); + if((toInclusive && cmp > 0) || (!toInclusive && cmp >= 0)) + { + return false; + } + } + return true; + } + + static void + testSecondaryKey(NavigableMap<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> m, String from, + boolean fromInclusive, String to, boolean toInclusive) + { + java.util.Comparator<? super String> c = m.comparator(); + + String first = m.firstKey(); + String last = m.lastKey(); + + test(inRange(c, first, from, fromInclusive, to, toInclusive)); + test(inRange(c, last, from, fromInclusive, to, toInclusive)); + + java.util.Random rand = new java.util.Random(); + int i = 0; + while(i < 100) + { + String category = String.valueOf(alphabet.charAt(rand.nextInt(1000) % 26)); + if(!inRange(c, category, from, fromInclusive, to, toInclusive)) + { + continue; + } + + java.util.Map.Entry<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> e; + String key; + + key = m.ceilingKey(category); + if(key == null) + { + test(c.compare(category, last) > 0); + } + else + { + test(c.compare(key, category) >= 0); + } + e = m.ceilingEntry(category); + test((key == null && e == null) || key.equals(e.getKey())); + + key = m.floorKey(category); + if(key == null) + { + test(c.compare(category, first) < 0); + } + else + { + test(c.compare(key, category) <= 0); + } + e = m.floorEntry(category); + test((key == null && e == null) || key.equals(e.getKey())); + + key = m.higherKey(category); + if(key == null) + { + test(c.compare(category, last) >= 0); + } + else + { + test(c.compare(key, category) > 0); + } + e = m.higherEntry(category); + test((key == null && e == null) || key.equals(e.getKey())); + + key = m.lowerKey(category); + if(key == null) + { + test(c.compare(category, first) <= 0); + } + else + { + test(c.compare(key, category) < 0); + } + e = m.lowerEntry(category); + test((key == null && e == null) || key.equals(e.getKey())); + + for(java.util.Map.Entry<String, java.util.Set<java.util.Map.Entry<Integer, Ice.Identity>>> p : m.entrySet()) + { + test(inRange(c, p.getKey(), from, fromInclusive, to, toInclusive)); + } + + ++i; + } + } + + static boolean + inRange(java.util.Comparator<? super String> c, String val, String from, boolean fromInclusive, String to, + boolean toInclusive) + { + if(from != null) + { + int cmp = c.compare(val, from); + if((fromInclusive && cmp < 0) || (!fromInclusive && cmp <= 0)) + { + return false; + } + } + if(to != null) + { + int cmp = c.compare(val, to); + if((toInclusive && cmp > 0) || (!toInclusive && cmp >= 0)) + { + return false; + } + } + return true; + } + + static private void + testEmptyMap(NavigableMap<Integer, Ice.Identity> m) + { + test(m.firstEntry() == null); + test(m.lastEntry() == null); + test(m.ceilingEntry(0) == null); + test(m.floorEntry(0) == null); + test(m.higherEntry(0) == null); + test(m.lowerEntry(0) == null); + test(m.pollFirstEntry() == null); + test(m.pollLastEntry() == null); + + try + { + m.firstKey(); + test(false); + } + catch(java.util.NoSuchElementException ex) + { + // Expected. + } + try + { + m.lastKey(); + test(false); + } + catch(java.util.NoSuchElementException ex) + { + // Expected. + } + + test(m.ceilingKey(0) == null); + test(m.floorKey(0) == null); + test(m.higherKey(0) == null); + test(m.lowerKey(0) == null); + } + static public void main(String[] args) { int status; Ice.Communicator communicator = null; String envName = "db"; - + try { Ice.StringSeqHolder holder = new Ice.StringSeqHolder(); @@ -866,7 +2116,7 @@ public class Client envName += "/"; envName += "db"; } - + status = run(args, communicator, envName, "binary"); } catch(Exception ex) diff --git a/java/test/Freeze/evictor/AccountI.java b/java/test/Freeze/evictor/AccountI.java index b2d7823555a..66493858476 100644 --- a/java/test/Freeze/evictor/AccountI.java +++ b/java/test/Freeze/evictor/AccountI.java @@ -19,7 +19,8 @@ public class AccountI extends Account } public void - deposit(int amount, Ice.Current current) throws InsufficientFundsException + deposit(int amount, Ice.Current current) + throws InsufficientFundsException { // // No need to synchronize since everything occurs within its own transaction @@ -72,19 +73,22 @@ public class AccountI extends Account class ResponseThread extends Thread { - synchronized void response() + synchronized void + response() { _response = true; notify(); } - synchronized void exception(Ice.UserException e) + synchronized void + exception(Ice.UserException e) { _exception = e; notify(); } - public synchronized void run() + public synchronized void + run() { if(_response == false && _exception == null) { @@ -131,7 +135,7 @@ public class AccountI extends Account ResponseThread thread = new ResponseThread(); thread.setDaemon(true); - + test(_evictor.getCurrentTransaction() != null); try @@ -159,17 +163,20 @@ public class AccountI extends Account thread.response(); } - public AccountI(int initialBalance, Freeze.TransactionalEvictor evictor) + public + AccountI(int initialBalance, Freeze.TransactionalEvictor evictor) { super(initialBalance); _evictor = evictor; } - public AccountI() + public + AccountI() { } - public void init(Freeze.TransactionalEvictor evictor) + public void + init(Freeze.TransactionalEvictor evictor) { assert _evictor == null; _evictor = evictor; diff --git a/java/test/Freeze/evictor/Client.java b/java/test/Freeze/evictor/Client.java index 84af28ce6c4..1616bd706fa 100644 --- a/java/test/Freeze/evictor/Client.java +++ b/java/test/Freeze/evictor/Client.java @@ -39,10 +39,11 @@ public class Client extends test.Util.Application { ReadThread(ServantPrx[] servants) { - _servants = servants; - } + _servants = servants; + } - public void run() + public void + run() { int loops = 10; while(loops-- > 0) @@ -60,14 +61,14 @@ public class Client extends test.Util.Application { test(false); } - + for(int i = 1; i < _servants.length; ++i) { test(_servants[i].getValue() == i); } } } - + private ServantPrx[] _servants; } @@ -81,7 +82,7 @@ public class Client extends test.Util.Application { _servants = servants; } - + public void run() { @@ -131,13 +132,13 @@ public class Client extends test.Util.Application { return _state; } - + synchronized boolean validEx() { return _state == StateDeactivating || _state == StateDeactivated; } - + synchronized void setEvictorState(int s) { @@ -148,9 +149,8 @@ public class Client extends test.Util.Application private int _state = StateRunning; } - static class AddForeverThread extends Thread - { + { AddForeverThread(RemoteEvictorPrx evictor, int prefix) { _evictor = evictor; @@ -161,7 +161,7 @@ public class Client extends test.Util.Application run() { int index = 0; - + for(;;) { try @@ -221,13 +221,13 @@ public class Client extends test.Util.Application { return _state; } - + synchronized boolean validEx() { return _state == StateDeactivating || _state == StateDeactivated; } - + synchronized void setEvictorState(int s) { @@ -239,16 +239,15 @@ public class Client extends test.Util.Application private int _state = StateRunning; } - static class CreateDestroyThread extends Thread { - CreateDestroyThread(RemoteEvictorPrx evictor, int id, int size) + CreateDestroyThread(RemoteEvictorPrx evictor, int id, int size) { _evictor = evictor; _id = "" + id; _size = size; } - + public void run() { @@ -265,12 +264,12 @@ public class Client extends test.Util.Application // // Create when odd, destroy when even. // - + if(loops % 2 == 0) { ServantPrx servant = _evictor.getServant(id); servant.destroy(); - + // // Twice // @@ -287,7 +286,7 @@ public class Client extends test.Util.Application else { ServantPrx servant = _evictor.createServant(id, i); - + // // Twice // @@ -352,17 +351,17 @@ public class Client extends test.Util.Application for(int i = 0; i < 1000; i++) { // - // Transfer 100 at random between two distinct accounts + // Transfer 100 at random between two distinct accounts // AccountPrx from = _accounts[Math.abs(_random.nextInt() % _accounts.length)]; - + AccountPrx to = null; do { to = _accounts[Math.abs(_random.nextInt() % _accounts.length)]; } while(from == to); - + try { // @@ -370,25 +369,25 @@ public class Client extends test.Util.Application // switch(transferOp) { - case 0: - { - from.transfer(100, to); - break; - } - case 1: - { - from.transfer2(100, to); - break; - } - case 2: - { - from.transfer3(100, to); - break; - } - default: - { - test(false); - } + case 0: + { + from.transfer(100, to); + break; + } + case 1: + { + from.transfer2(100, to); + break; + } + case 2: + { + from.transfer3(100, to); + break; + } + default: + { + test(false); + } } transferOp++; transferOp = transferOp % 3; @@ -406,7 +405,7 @@ public class Client extends test.Util.Application // test(false); } - + /* if(i % 100 == 0) { @@ -420,7 +419,7 @@ public class Client extends test.Util.Application private final AccountPrx[] _accounts; private final java.util.Random _random; } - + private int run(String[] args, PrintWriter out, boolean transactional, boolean shutdown) throws AlreadyRegisteredException, NotRegisteredException, EvictorDeactivatedException @@ -442,12 +441,12 @@ public class Client extends test.Util.Application out.flush(); final int size = 5; - + RemoteEvictorPrx evictor = factory.createEvictor("Test", transactional); evictor.setSize(size); // - // Create some servants + // Create some servants // ServantPrx[] servants = new ServantPrx[size]; for(int i = 0; i < size; i++) @@ -455,7 +454,7 @@ public class Client extends test.Util.Application String id = "" + i; servants[i] = evictor.createServant(id, i); servants[i].ice_ping(); - + FacetPrx facet1 = FacetPrxHelper.uncheckedCast(servants[i], "facet1"); try { @@ -496,7 +495,7 @@ public class Client extends test.Util.Application test(facet2 != null); test(facet2.getData().equals("moreData")); } - + // // Mutate servants. // @@ -510,7 +509,7 @@ public class Client extends test.Util.Application test(facet2 != null); facet2.setValue(100 * i + 100); } - + for(int i = 0; i < size; i++) { test(servants[i].getValue() == i + 100); @@ -521,7 +520,7 @@ public class Client extends test.Util.Application test(facet2 != null); test(facet2.getValue() == 100 * i + 100); } - + // // Evict and verify values. // @@ -540,10 +539,10 @@ public class Client extends test.Util.Application if(!transactional) { - // + // // Test saving while busy // - + AMI_Servant_setValueAsyncI setCB = new AMI_Servant_setValueAsyncI(); for(int i = 0; i < size; i++) { @@ -551,7 +550,7 @@ public class Client extends test.Util.Application // Start a mutating operation so that the object is not idle. // servants[i].setValueAsync_async(setCB, i + 300); - + test(servants[i].getValue() == i + 100); // // This operation modifies the object state but is not saved @@ -559,7 +558,7 @@ public class Client extends test.Util.Application // servants[i].setValue(i + 200); test(servants[i].getValue() == i + 200); - + // // Force the response to setValueAsync // @@ -570,7 +569,7 @@ public class Client extends test.Util.Application // // Add duplicate facet and catch corresponding exception - // + // for(int i = 0; i < size; i++) { try @@ -582,10 +581,10 @@ public class Client extends test.Util.Application { } } - + // // Remove a facet that does not exist - // + // try { servants[0].removeFacet("facet3"); @@ -606,7 +605,7 @@ public class Client extends test.Util.Application evictor.setSize(0); evictor.setSize(size); - + // // Destroy servants and verify ObjectNotExistException. // @@ -632,7 +631,6 @@ public class Client extends test.Util.Application { // Expected } - } // @@ -642,7 +640,7 @@ public class Client extends test.Util.Application // // Recreate servants, set transient value - // + // for(int i = 0; i < size; i++) { String id = "" + i; @@ -665,7 +663,6 @@ public class Client extends test.Util.Application test(servants[i].getTransientValue() == -1); } - if(!transactional) { // @@ -680,7 +677,7 @@ public class Client extends test.Util.Application evictor.saveNow(); evictor.setSize(0); evictor.setSize(size); - + // // Check the transient value // @@ -688,7 +685,7 @@ public class Client extends test.Util.Application { test(servants[i].getTransientValue() == i); } - + // // Again, after one release // @@ -703,7 +700,7 @@ public class Client extends test.Util.Application { test(servants[i].getTransientValue() == i); } - + // // Again, after a second release // @@ -714,12 +711,12 @@ public class Client extends test.Util.Application evictor.saveNow(); evictor.setSize(0); evictor.setSize(size); - + for(int i = 0; i < size; i++) { test(servants[i].getTransientValue() == -1); } - + // // Release one more time // @@ -756,7 +753,7 @@ public class Client extends test.Util.Application threads[i] = new TransferThread(accounts, i); threads[i].start(); } - + for(int i = 0; i < threadCount; i++) { try @@ -768,13 +765,13 @@ public class Client extends test.Util.Application break; // for } } - + // // Check that the total balance did not change! // test(totalBalance == servants[0].getTotalBalance()); } - + // // Deactivate and recreate evictor, to ensure that servants // are restored properly after database close and reopen. @@ -788,7 +785,6 @@ public class Client extends test.Util.Application servants[i] = evictor.getServant(id); test(servants[i].getValue() == i); } - // // Test concurrent lookups with a smaller evictor @@ -796,17 +792,17 @@ public class Client extends test.Util.Application // evictor.setSize(size / 2); servants[0].destroy(); - + { int threadCount = size * 2; - + Thread[] threads = new Thread[threadCount]; for(int i = 0; i < threadCount; i++) { threads[i] = new ReadThread(servants); threads[i].start(); } - + for(int i = 0; i < threadCount; i++) { for(;;) @@ -822,27 +818,27 @@ public class Client extends test.Util.Application } } } - + // // Clean up. // evictor.destroyAllServants(""); evictor.destroyAllServants("facet1"); evictor.destroyAllServants("facet2"); - + // // CreateDestroy threads // { int threadCount = size; - + Thread[] threads = new Thread[threadCount]; for(int i = 0; i < threadCount; i++) { threads[i] = new CreateDestroyThread(evictor, i, size); threads[i].start(); } - + for(int i = 0; i < threadCount; i++) { for(;;) @@ -857,11 +853,11 @@ public class Client extends test.Util.Application } } } - + // // Verify all destroyed - // - for(int i = 0; i < size; i++) + // + for(int i = 0; i < size; i++) { try { @@ -874,31 +870,31 @@ public class Client extends test.Util.Application } } } - + // // Recreate servants. - // + // servants = new ServantPrx[size]; for(int i = 0; i < size; i++) { String id = "" + i; servants[i] = evictor.createServant(id, i); } - + // // Deactivate in the middle of remote AMD operations // (really testing Ice here) // { int threadCount = size; - + Thread[] threads = new Thread[threadCount]; for(int i = 0; i < threadCount; i++) { threads[i] = new ReadForeverThread(servants); threads[i].start(); } - + try { Thread.currentThread().sleep(500); @@ -918,7 +914,7 @@ public class Client extends test.Util.Application ReadForeverThread t = (ReadForeverThread)threads[i]; t.setEvictorState(StateDeactivated); } - + for(int i = 0; i < threadCount; i++) { for(;;) @@ -934,26 +930,26 @@ public class Client extends test.Util.Application } } } - + // // Resurrect // evictor = factory.createEvictor("Test", transactional); evictor.destroyAllServants(""); - + // // Deactivate in the middle of adds // { int threadCount = size; - + Thread[] threads = new Thread[threadCount]; for(int i = 0; i < threadCount; i++) { threads[i] = new AddForeverThread(evictor, i); threads[i].start(); } - + try { Thread.currentThread().sleep(500); @@ -989,8 +985,7 @@ public class Client extends test.Util.Application } } } - - + // // Clean up. // @@ -999,7 +994,7 @@ public class Client extends test.Util.Application evictor.deactivate(); out.println("ok"); - + if(shutdown) { factory.shutdown(); @@ -1039,7 +1034,8 @@ public class Client extends test.Util.Application return status; } - protected Ice.InitializationData getInitData(Ice.StringSeqHolder argsH) + protected Ice.InitializationData + getInitData(Ice.StringSeqHolder argsH) { Ice.InitializationData initData = new Ice.InitializationData(); initData.properties = Ice.Util.createProperties(argsH); @@ -1047,7 +1043,8 @@ public class Client extends test.Util.Application return initData; } - public static void main(String[] args) + public static void + main(String[] args) { Client c = new Client(); int status = c.main("Client", args); diff --git a/java/test/Freeze/evictor/FacetI.java b/java/test/Freeze/evictor/FacetI.java index 0f7cb7a245a..14fa8723ae1 100644 --- a/java/test/Freeze/evictor/FacetI.java +++ b/java/test/Freeze/evictor/FacetI.java @@ -22,7 +22,7 @@ public class FacetI extends ServantI implements _FacetOperations super(tie, remoteEvictor, evictor, value); ((Facet)_tie).data = data; } - + public String getData(Ice.Current current) { diff --git a/java/test/Freeze/evictor/RemoteEvictorFactoryI.java b/java/test/Freeze/evictor/RemoteEvictorFactoryI.java index 7691acdcdfb..a32c099d0ec 100644 --- a/java/test/Freeze/evictor/RemoteEvictorFactoryI.java +++ b/java/test/Freeze/evictor/RemoteEvictorFactoryI.java @@ -17,11 +17,10 @@ public final class RemoteEvictorFactoryI extends _RemoteEvictorFactoryDisp _envName = envName; } - public RemoteEvictorPrx createEvictor(String name, boolean transactional, Ice.Current current) { - RemoteEvictorI remoteEvictor = + RemoteEvictorI remoteEvictor = new RemoteEvictorI(current.adapter.getCommunicator(), _envName, name, transactional); return RemoteEvictorPrxHelper. uncheckedCast(current.adapter.add(remoteEvictor, current.adapter.getCommunicator().stringToIdentity(name))); diff --git a/java/test/Freeze/evictor/RemoteEvictorI.java b/java/test/Freeze/evictor/RemoteEvictorI.java index 4e026509ff1..d42ae449fd0 100644 --- a/java/test/Freeze/evictor/RemoteEvictorI.java +++ b/java/test/Freeze/evictor/RemoteEvictorI.java @@ -44,7 +44,6 @@ public final class RemoteEvictorI extends _RemoteEvictorDisp private Freeze.Evictor _evictor; } - RemoteEvictorI(Ice.Communicator communicator, String envName, String category, boolean transactional) { _envName = envName; @@ -71,7 +70,7 @@ public final class RemoteEvictorI extends _RemoteEvictorDisp } initializer.init(this, _evictor); - + _evictorAdapter.addServantLocator(_evictor, category); _evictorAdapter.activate(); } @@ -141,12 +140,12 @@ public final class RemoteEvictorI extends _RemoteEvictorDisp _evictorAdapter.destroy(); current.adapter.remove(current.adapter.getCommunicator().stringToIdentity(_category)); } - + public void destroyAllServants(String facet, Ice.Current current) { // - // Only for test purpose: don't use such a small value in + // Only for test purpose: don't use such a small value in // a real application! // int batchSize = 2; @@ -158,11 +157,11 @@ public final class RemoteEvictorI extends _RemoteEvictorDisp } } - final public String + final public String envName() { return _envName; - } + } private final String _envName; private String _category; diff --git a/java/test/Freeze/evictor/ServantI.java b/java/test/Freeze/evictor/ServantI.java index faab9eb13f9..d8f6b3c0a67 100644 --- a/java/test/Freeze/evictor/ServantI.java +++ b/java/test/Freeze/evictor/ServantI.java @@ -21,7 +21,6 @@ public class ServantI implements _ServantOperations } } - static class DelayedResponse extends Thread { DelayedResponse(AMD_Servant_slowGetValue cb, int val) @@ -48,7 +47,6 @@ public class ServantI implements _ServantOperations private int _val; } - ServantI(Servant tie) { _tie = tie; diff --git a/java/test/Freeze/evictor/Server.java b/java/test/Freeze/evictor/Server.java index c67f17354f8..e8123b0877c 100644 --- a/java/test/Freeze/evictor/Server.java +++ b/java/test/Freeze/evictor/Server.java @@ -11,7 +11,7 @@ package test.Freeze.evictor; import test.Freeze.evictor.Test.*; public class Server extends test.Util.Application -{ +{ static class AccountFactory implements Ice.ObjectFactory { public Ice.Object @@ -74,7 +74,7 @@ public class Server extends test.Util.Application RemoteEvictorFactoryI factory = new RemoteEvictorFactoryI("db"); adapter.add(factory, communicator.stringToIdentity("factory")); - + adapter.activate(); communicator.waitForShutdown(); @@ -82,7 +82,8 @@ public class Server extends test.Util.Application return 0; } - protected Ice.InitializationData getInitData(Ice.StringSeqHolder argsH) + protected Ice.InitializationData + getInitData(Ice.StringSeqHolder argsH) { Ice.InitializationData initData = new Ice.InitializationData(); initData.properties = Ice.Util.createProperties(argsH); @@ -91,7 +92,8 @@ public class Server extends test.Util.Application return initData; } - public static void main(String[] args) + public static void + main(String[] args) { Server c = new Server(); int status = c.main("Server", args); |