提交 4dde5214 编写于 作者: A asaha

Merge

^build/
^dist/
^nbproject/private/
^make/netbeans/.*/nbproject/private/
^make/netbeans/.*/build/
^make/netbeans/.*/dist/
......@@ -43,3 +43,4 @@ a50217eb3ee10b9f9547e0708e5c9625405083ef jdk7-b64
bd31b30a5b21f20e42965b1633f18a5c7946d398 jdk7-b66
a952aafd5181af953b0ef3010dbd2fcc28460e8a jdk7-b67
b23d905cb5d3b382295240d28ab0bfb266b4503c jdk7-b68
226b20019b1f020c09ea97d137d98e011ce65d76 jdk7-b69
......@@ -67,15 +67,14 @@ ifeq ($(STANDALONE),true)
$(ZIPOBJDIR)/deflate.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/trees.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/zadler32.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/compress.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/zutil.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/inflate.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/infblock.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/infcodes.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/infback.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/inftrees.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/infutil.$(OBJECT_SUFFIX) \
$(ZIPOBJDIR)/inffast.$(OBJECT_SUFFIX)
ZINCLUDE=-I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
ZINCLUDE=-I$(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
OTHER_CXXFLAGS += $(ZINCLUDE)
LDDFLAGS += $(ZIPOBJS)
else
......
......@@ -242,6 +242,12 @@ DEVTOOLS_FT_DIR_EXISTS = $(shell \
endif
endif
#
# zlib version
#
ZLIB_VERSION = 1.2.3
#
# Localizations for the different parts of the product beyond English
#
......
......@@ -44,7 +44,6 @@ MS_RUNTIME_STATIC = true
include $(BUILDDIR)/common/Defs.gmk
ZLIB_VERSION = 1.1.3
ZIP_SRC = $(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
LAUNCHER_SHARE_SRC = $(SHARE_SRC)/bin
LAUNCHER_PLATFORM_SRC = $(PLATFORM_SRC)/bin
......@@ -68,12 +67,10 @@ FILES_c = \
wildcard.c \
jli_util.c \
inflate.c \
infblock.c \
inftrees.c \
infcodes.c \
inffast.c \
infutil.c \
zadler32.c \
zcrc32.c \
zutil.c
ifneq ($(PLATFORM), windows)
......
......@@ -160,7 +160,6 @@ FILES_src = \
\
sun/nio/ByteBuffered.java \
\
sun/nio/ch/AbstractFuture.java \
sun/nio/ch/AbstractPollArrayWrapper.java \
sun/nio/ch/AllocatedNativeObject.java \
sun/nio/ch/AsynchronousChannelGroupImpl.java \
......
......@@ -29,15 +29,16 @@ FILES_c = \
Deflater.c \
Inflater.c \
ZipFile.c \
zadler32.c \
zcrc32.c \
zip_util.c \
compress.c \
deflate.c \
trees.c \
zutil.c \
gzio.c \
infback.c \
inffast.c \
inflate.c \
infblock.c \
inftrees.c \
infcodes.c \
infutil.c \
inffast.c \
zip_util.c
trees.c \
uncompr.c \
zadler32.c \
zcrc32.c \
zutil.c
......@@ -30,7 +30,9 @@ LIBRARY = zip
PRODUCT = sun
include $(BUILDDIR)/common/Defs.gmk
ZLIB_VERSION = 1.1.3
#
# ZLIB_VERSION is defined in make/common/Defs.gmk
#
#
# Files to compile.
......
......@@ -32,38 +32,17 @@ text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_;
text: .text%zcalloc;
text: .text%inflate_blocks_new;
text: .text%inflate_blocks_reset;
text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate;
text: .text%inflate_blocks;
text: .text%inflate_flush;
text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read;
text: .text%inflate_trees_bits;
text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj/inftrees.o;
text: .text%zcfree;
text: .text%inflate_trees_dynamic;
text: .text%inflate_codes_new;
text: .text%inflate_codes;
text: .text%inflate_fast;
text: .text%inflate_codes_free;
text: .text%inflate_trees_fixed;
# Test Exit
# Test Hello
# Test Sleep
# Test IntToString
# Test LoadToolkit
text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
text: .text%ZIP_ReadEntry;
text: .text%InflateFully;
text: .text%inflateEnd;
text: .text%inflate_blocks_free;
# Test LoadFrame
# Test LoadJFrame
# Test JHello
# SwingSet
text: .text%Java_java_util_zip_Inflater_reset;
text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close;
......
......@@ -31,37 +31,13 @@ text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_;
text: .text%zcalloc;
text: .text%inflate_blocks_new;
text: .text%inflate_blocks_reset;
text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate;
text: .text%inflate_blocks;
text: .text%inflate_flush;
text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read;
text: .text%inflate_trees_bits;
text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj/inftrees.o;
text: .text%zcfree;
text: .text%inflate_trees_dynamic;
text: .text%inflate_codes_new;
text: .text%inflate_codes;
text: .text%inflate_fast;
text: .text%inflate_codes_free;
text: .text%inflate_trees_fixed;
# Test Exit
# Test Hello
# Test Sleep
# Test IntToString
# Test LoadToolkit
text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
# Test LoadFrame
# Test LoadJFrame
# Test JHello
# SwingSet
text: .text%Java_java_util_zip_Inflater_reset;
text: .text%Java_java_util_zip_Inflater_end;
text: .text%inflateEnd;
text: .text%inflate_blocks_free;
text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close;
data = R0x2000;
text = LOAD ?RXO;
# Test Null
text: .text%ZIP_Open;
text: .text%ZIP_Open_Generic;
text: .text%InitializeZip;
......@@ -32,38 +31,17 @@ text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_;
text: .text%zcalloc;
text: .text%inflate_blocks_new;
text: .text%inflate_blocks_reset;
text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate;
text: .text%inflate_blocks;
text: .text%inflate_flush;
text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read;
text: .text%inflate_trees_bits;
text: .text%huft_build: OUTPUTDIR/tmp/sun/java.util.zip/zip/obj64/inftrees.o;
text: .text%zcfree;
text: .text%inflate_trees_dynamic;
text: .text%inflate_codes_new;
text: .text%inflate_codes;
text: .text%inflate_fast;
text: .text%inflate_codes_free;
text: .text%inflate_trees_fixed;
# Test Exit
# Test Hello
# Test Sleep
# Test IntToString
# Test LoadToolkit
text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
text: .text%ZIP_ReadEntry;
text: .text%InflateFully;
text: .text%inflateEnd;
text: .text%inflate_blocks_free;
# Test LoadFrame
# Test LoadJFrame
# Test JHello
# SwingSet
text: .text%Java_java_util_zip_Inflater_reset;
text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close;
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See commented blocks below for -->
<!-- some examples of how to customize the build. -->
<!-- (If you delete it and reopen the project it will be recreated.) -->
<!-- By default, only the Clean and Build commands use this build script. -->
<!-- Commands such as Run, Debug, and Test only use this build script if -->
<!-- the Compile on Save feature is turned off for the project. -->
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
<!-- in the project's Project Properties dialog box.-->
<project name="jdwpgen" default="default" basedir=".">
<description>Builds, tests, and runs the project jdwpgen.</description>
<import file="nbproject/build-impl.xml"/>
<!--
There exist several targets which are by default empty and which can be
used for execution of your tasks. These targets are usually executed
before and after some main targets. They are:
-pre-init: called before initialization of project properties
-post-init: called after initialization of project properties
-pre-compile: called before javac compilation
-post-compile: called after javac compilation
-pre-compile-single: called before javac compilation of single file
-post-compile-single: called after javac compilation of single file
-pre-compile-test: called before javac compilation of JUnit tests
-post-compile-test: called after javac compilation of JUnit tests
-pre-compile-test-single: called before javac compilation of single JUnit test
-post-compile-test-single: called after javac compilation of single JUunit test
-pre-jar: called before JAR building
-post-jar: called after JAR building
-post-clean: called after cleaning build products
(Targets beginning with '-' are not intended to be called on their own.)
Example of inserting an obfuscator after compilation could look like this:
<target name="-post-compile">
<obfuscate>
<fileset dir="${build.classes.dir}"/>
</obfuscate>
</target>
For list of available properties check the imported
nbproject/build-impl.xml file.
Another way to customize the build is by overriding existing main targets.
The targets of interest are:
-init-macrodef-javac: defines macro for javac compilation
-init-macrodef-junit: defines macro for junit execution
-init-macrodef-debug: defines macro for class debugging
-init-macrodef-java: defines macro for class execution
-do-jar-with-manifest: JAR building (if you are using a manifest)
-do-jar-without-manifest: JAR building (if you are not using a manifest)
run: execution of project
-javadoc-build: Javadoc generation
test-report: JUnit report generation
An example of overriding the target for project execution could look like this:
<target name="run" depends="jdwpgen-impl.jar">
<exec dir="bin" executable="launcher.exe">
<arg file="${dist.jar}"/>
</exec>
</target>
Notice that the overridden target depends on the jar target and not only on
the compile target as the regular run target does. Again, for a list of available
properties which you can use, check the target you are overriding in the
nbproject/build-impl.xml file.
-->
</project>
此差异已折叠。
#FindBugs User Preferences
#Mon Jun 15 13:37:16 PDT 2009
detectorAbnormalFinallyBlockReturn=AbnormalFinallyBlockReturn|false
detectorAbstractClassEmptyMethods=AbstractClassEmptyMethods|false
detectorAbstractOverriddenMethod=AbstractOverriddenMethod|false
detectorArrayBasedCollections=ArrayBasedCollections|false
detectorArrayWrappedCallByReference=ArrayWrappedCallByReference|false
detectorBloatedAssignmentScope=BloatedAssignmentScope|false
detectorBloatedSynchronizedBlock=BloatedSynchronizedBlock|false
detectorClassEnvy=ClassEnvy|false
detectorCollectStatistics=CollectStatistics|false
detectorConfusingAutoboxedOverloading=ConfusingAutoboxedOverloading|false
detectorConstantListIndex=ConstantListIndex|false
detectorCopiedOverriddenMethod=CopiedOverriddenMethod|false
detectorCustomBuiltXML=CustomBuiltXML|false
detectorCyclomaticComplexity=CyclomaticComplexity|false
detectorDateComparison=DateComparison|false
detectorDeclaredRuntimeException=DeclaredRuntimeException|false
detectorDeletingWhileIterating=DeletingWhileIterating|false
detectorDubiousListCollection=DubiousListCollection|false
detectorFieldCouldBeLocal=FieldCouldBeLocal|false
detectorFinalParameters=FinalParameters|false
detectorFloatingPointLoops=FloatingPointLoops|false
detectorInefficientStringBuffering=InefficientStringBuffering|false
detectorInheritanceTypeChecking=InheritanceTypeChecking|false
detectorJDBCVendorReliance=JDBCVendorReliance|false
detectorListIndexedIterating=ListIndexedIterating|false
detectorLiteralStringComparison=LiteralStringComparison|false
detectorLocalSynchronizedCollection=LocalSynchronizedCollection|false
detectorLostExceptionStackTrace=LostExceptionStackTrace|false
detectorManualArrayCopy=ManualArrayCopy|false
detectorMethodReturnsConstant=MethodReturnsConstant|false
detectorNeedlessAutoboxing=NeedlessAutoboxing|false
detectorNeedlessCustomSerialization=NeedlessCustomSerialization|false
detectorNeedlessInstanceRetrieval=NeedlessInstanceRetrieval|false
detectorNeedlessMemberCollectionSynchronization=NeedlessMemberCollectionSynchronization|false
detectorNonCollectionMethodUse=NonCollectionMethodUse|false
detectorNonOwnedSynchronization=NonOwnedSynchronization|false
detectorNonRecycleableTaglibs=NonRecycleableTaglibs|false
detectorOrphanedDOMNode=OrphanedDOMNode|false
detectorOverlyConcreteParameter=OverlyConcreteParameter|false
detectorParallelLists=ParallelLists|false
detectorPartiallyConstructedObjectAccess=PartiallyConstructedObjectAccess|false
detectorPossibleIncompleteSerialization=PossibleIncompleteSerialization|false
detectorPossibleMemoryBloat=PossibleMemoryBloat|false
detectorPossiblyRedundantMethodCalls=PossiblyRedundantMethodCalls|false
detectorSQLInLoop=SQLInLoop|false
detectorSection508Compliance=Section508Compliance|false
detectorSillynessPotPourri=SillynessPotPourri|false
detectorSloppyClassReflection=SloppyClassReflection|false
detectorSluggishGui=SluggishGui|false
detectorSpoiledChildInterfaceImplementor=SpoiledChildInterfaceImplementor|false
detectorSpuriousThreadStates=SpuriousThreadStates|false
detectorStaticArrayCreatedInMethod=StaticArrayCreatedInMethod|false
detectorStaticMethodInstanceInvocation=StaticMethodInstanceInvocation|false
detectorSuspiciousComparatorReturnValues=SuspiciousComparatorReturnValues|false
detectorSuspiciousJDKVersionUse=SuspiciousJDKVersionUse|false
detectorSuspiciousWaitOnConcurrentObject=SuspiciousWaitOnConcurrentObject|false
detectorSyncCollectionIterators=SyncCollectionIterators|false
detectorTailRecursion=TailRecursion|false
detectorUnnecessaryStoreBeforeReturn=UnnecessaryStoreBeforeReturn|false
detectorUnrelatedCollectionContents=UnrelatedCollectionContents|false
detectorUnrelatedReturnValues=UnrelatedReturnValues|false
detectorUseAddAll=UseAddAll|false
detectorUseCharacterParameterizedMethod=UseCharacterParameterizedMethod|false
detectorUseEnumCollections=UseEnumCollections|false
detectorUseSplit=UseSplit|false
detectorUseToArray=UseToArray|false
detector_threshold=2
effort=default
filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,I18N,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false
filter_settings_neg=|
build.xml.data.CRC32=b40e775f
build.xml.script.CRC32=af8dc3cb
build.xml.stylesheet.CRC32=958a1d3e
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=b40e775f
nbproject/build-impl.xml.script.CRC32=624d12c5
nbproject/build-impl.xml.stylesheet.CRC32=65b8de21
application.title=jdwpgen
application.vendor=sun
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
build.dir=build
build.generated.dir=${build.dir}/generated
# Only compile against the classpath explicitly listed here:
build.sysclasspath=ignore
build.test.classes.dir=${build.dir}/test/classes
build.test.results.dir=${build.dir}/test/results
# Uncomment to specify the preferred debugger connection transport:
#debug.transport=dt_socket
debug.classpath=\
${run.classpath}
debug.test.classpath=\
${run.test.classpath}
# This directory is removed when the project is cleaned:
dist.dir=dist
dist.jar=${dist.dir}/jdwpgen.jar
dist.javadoc.dir=${dist.dir}/javadoc
excludes=
file.reference.tools-jdwpgen=../../tools/src/build/tools/jdwpgen
file.reference.tools-src=../../tools/src
includes=build/tools/jdwpgen/**
jar.compress=false
javac.classpath=
# Space-separated list of extra javac options
javac.compilerargs=-Xlint:all
javac.deprecation=false
javac.source=1.5
javac.target=1.5
javac.test.classpath=\
${javac.classpath}:\
${build.classes.dir}:\
${libs.junit.classpath}:\
${libs.junit_4.classpath}
javadoc.additionalparam=
javadoc.author=false
javadoc.encoding=${source.encoding}
javadoc.noindex=true
javadoc.nonavbar=true
javadoc.notree=true
javadoc.private=true
javadoc.splitindex=false
javadoc.use=false
javadoc.version=false
javadoc.windowtitle=
main.class=jdwpgen.Main
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
platform.active=default_platform
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
# Space-separated list of JVM arguments used when running the project
# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
# or test-sys-prop.name=value to set system properties for unit tests):
run.jvmargs=
run.test.classpath=\
${javac.test.classpath}:\
${build.test.classes.dir}
source.encoding=UTF-8
src.src.dir=${file.reference.tools-src}
test.src.dir=test
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.java.j2seproject</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
<name>jdwpgen</name>
<minimum-ant-version>1.6.5</minimum-ant-version>
<source-roots>
<root id="src.src.dir"/>
</source-roots>
<test-roots>
<root id="test.src.dir"/>
</test-roots>
</data>
</configuration>
</project>
#Path to FindbugsSettingsFile (relative)
findbugs.settings.file=findbugs.settings
......@@ -52,12 +52,10 @@ FILES_c = \
compress.c \
deflate.c \
gzio.c \
infblock.c \
infcodes.c \
infback.c \
inffast.c \
inflate.c \
inftrees.c \
infutil.c \
trees.c \
uncompr.c \
zadler32.c \
......
......@@ -77,13 +77,13 @@ endif # PLATFORM
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/splashscreen
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/giflib
vpath %.c $(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
vpath %.c $(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/libpng
vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/image/jpeg
vpath %.c $(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen
CPPFLAGS += -I$(PLATFORM_SRC)/native/$(PKGDIR)/splashscreen -I$(SHARE_SRC)/native/$(PKGDIR)/splashscreen
CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/image/jpeg -I$(SHARE_SRC)/native/java/util/zip/zlib-1.1.3
CPPFLAGS += -I$(SHARE_SRC)/native/$(PKGDIR)/image/jpeg -I$(SHARE_SRC)/native/java/util/zip/zlib-$(ZLIB_VERSION)
# Shun the less than portable MMX assembly code in pnggccrd.c,
# and use alternative implementations in C.
......
......@@ -30,7 +30,7 @@ import java.io.*;
abstract class AbstractNamedNode extends Node {
NameNode nameNode;
NameNode nameNode = null;
String name;
public String name() {
......
......@@ -30,7 +30,7 @@ import java.io.*;
class AltNode extends AbstractGroupNode implements TypeNode {
SelectNode select;
SelectNode select = null;
void constrain(Context ctx) {
super.constrain(ctx);
......
......@@ -33,13 +33,7 @@ class ConstantSetNode extends AbstractNamedNode {
/**
* The mapping between a constant and its value.
*/
protected static Map<String, String> constantMap;
ConstantSetNode(){
if (constantMap == null) {
constantMap = new HashMap<String, String>();
}
}
protected static final Map<String, String> constantMap = new HashMap<String, String>();
void prune() {
List<Node> addons = new ArrayList<Node>();
......@@ -95,9 +89,6 @@ class ConstantSetNode extends AbstractNamedNode {
}
public static String getConstant(String key){
if (constantMap == null) {
return "";
}
String com = constantMap.get(key);
if(com == null){
return "";
......
......@@ -25,13 +25,11 @@
package build.tools.jdwpgen;
import java.util.*;
import java.io.*;
class Main {
static String specSource;
static Map nameMap = new HashMap();
static boolean genDebug = true;
static void usage() {
......@@ -43,7 +41,6 @@ class Main {
System.err.println("-doc <doc_output>");
System.err.println("-jdi <java_output>");
System.err.println("-include <include_file_output>");
System.exit(1);
}
public static void main(String args[]) throws IOException {
......@@ -66,6 +63,7 @@ class Main {
} else {
System.err.println("Invalid option: " + arg);
usage();
return;
}
} else {
specSource = arg;
......@@ -75,6 +73,7 @@ class Main {
if (reader == null) {
System.err.println("<spec_input> must be specified");
usage();
return;
}
Parse parse = new Parse(reader);
......
......@@ -36,7 +36,7 @@ abstract class Node {
int lineno;
List<String> commentList = new ArrayList<String>();
Node parent = null;
Context context;
Context context = null;
static final int maxStructIndent = 5;
static int structIndent = 0; // horrible hack
......@@ -82,7 +82,7 @@ abstract class Node {
}
void indent(PrintWriter writer, int depth) {
for (int i = depth; i > 0; --i) {
for (int i = 0; i < depth; i++) {
writer.print(" ");
}
}
......@@ -195,6 +195,6 @@ abstract class Node {
System.err.println(Main.specSource + ":" + lineno + ": " +
kind + " - " + errmsg);
System.err.println();
System.exit(1);
throw new RuntimeException("Error: " + errmsg);
}
}
......@@ -146,8 +146,12 @@ class Parse {
Node node = (Node)proto.getClass().newInstance();
node.set(kind, list, izer.lineno());
return node;
} catch (Exception exc) {
} catch (InstantiationException exc) {
error(exc.toString());
return null;
} catch (IllegalAccessException exc) {
error(exc.toString());
return null;
}
}
} else {
......@@ -166,6 +170,6 @@ class Parse {
void error(String errmsg) {
System.err.println(Main.specSource + ":" + izer.lineno() +
": " + errmsg);
System.exit(1);
throw new RuntimeException("Error: " + errmsg);
}
}
......@@ -30,7 +30,7 @@ import java.io.*;
class RepeatNode extends AbstractTypeNode {
Node member;
Node member = null;
void constrain(Context ctx) {
super.constrain(ctx);
......
......@@ -30,7 +30,7 @@ import java.io.*;
class SelectNode extends AbstractGroupNode implements TypeNode {
AbstractSimpleTypeNode typeNode;
AbstractSimpleTypeNode typeNode = null;
void prune() {
super.prune();
......
......@@ -28,8 +28,12 @@ package java.lang;
/**
* Thrown when an application tries to access an enum constant by name
* and the enum type contains no constant with the specified name.
* This exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class EnumConstantNotPresentException extends RuntimeException {
......
......@@ -35,8 +35,12 @@ package java.lang;
* <p>Note that this exception may be used when undefined type variables
* are accessed as well as when types (e.g., classes, interfaces or
* annotation types) are loaded.
* In particular, this exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class TypeNotPresentException extends RuntimeException {
......
......@@ -28,8 +28,12 @@ package java.lang.annotation;
/**
* Thrown when the annotation parser attempts to read an annotation
* from a class file and determines that the annotation is malformed.
* This error can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class AnnotationFormatError extends Error {
......
......@@ -30,8 +30,12 @@ import java.lang.reflect.Method;
* Thrown to indicate that a program has attempted to access an element of
* an annotation whose type has changed after the annotation was compiled
* (or serialized).
* This exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class AnnotationTypeMismatchException extends RuntimeException {
......
......@@ -30,8 +30,12 @@ package java.lang.annotation;
* an annotation type that was added to the annotation type definition after
* the annotation was compiled (or serialized). This exception will not be
* thrown if the new element has a default value.
* This exception can be thrown by the {@linkplain
* java.lang.reflect.AnnotatedElement API used to read annotations
* reflectively}.
*
* @author Josh Bloch
* @see java.lang.reflect.AnnotatedElement
* @since 1.5
*/
public class IncompleteAnnotationException extends RuntimeException {
......
......@@ -50,6 +50,11 @@ import java.lang.annotation.Annotation;
* java.lang.annotation.AnnotationTypeMismatchException} or an
* {@link java.lang.annotation.IncompleteAnnotationException}.
*
* @see java.lang.EnumConstantNotPresentException
* @see java.lang.TypeNotPresentException
* @see java.lang.annotation.AnnotationFormatError
* @see java.lang.annotation.AnnotationTypeMismatchException
* @see java.lang.annotation.IncompleteAnnotationException
* @since 1.5
* @author Josh Bloch
*/
......
......@@ -56,18 +56,18 @@ public interface AsynchronousByteChannel
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* <p> This method initiates an operation to read a sequence of bytes from
* this channel into the given buffer. The method returns a {@link Future}
* representing the pending result of the operation. The result of the
* operation, obtained by invoking the {@code Future} 's {@link
* Future#get() get} method, is the number of bytes read or {@code -1} if
* all bytes have been read and the channel has reached end-of-stream.
*
* <p> This method initiates a read operation to read up to <i>r</i> bytes
* from the channel, where <i>r</i> is the number of bytes remaining in the
* buffer, that is, {@code dst.remaining()} at the time that the read is
* attempted. Where <i>r</i> is 0, the read operation completes immediately
* with a result of {@code 0} without initiating an I/O operation.
* <p> This method initiates an asynchronous read operation to read a
* sequence of bytes from this channel into the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the read
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes read or {@code -1} if no bytes could be
* read because the channel has reached end-of-stream.
*
* <p> The read operation may read up to <i>r</i> bytes from the channel,
* where <i>r</i> is the number of bytes remaining in the buffer, that is,
* {@code dst.remaining()} at the time that the read is attempted. Where
* <i>r</i> is 0, the read operation completes immediately with a result of
* {@code 0} without initiating an I/O operation.
*
* <p> Suppose that a byte sequence of length <i>n</i> is read, where
* <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
......@@ -79,44 +79,46 @@ public interface AsynchronousByteChannel
* <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
*
* <p> Buffers are not safe for use by multiple concurrent threads so care
* should be taken to not to access the buffer until the operaton has completed.
* should be taken to not access the buffer until the operation has
* completed.
*
* <p> This method may be invoked at any time. Some channel types may not
* allow more than one read to be outstanding at any given time. If a thread
* initiates a read operation before a previous read operation has
* completed then a {@link ReadPendingException} will be thrown.
*
* <p> The <tt>handler</tt> parameter is used to specify a {@link
* CompletionHandler}. When the read operation completes the handler's
* {@link CompletionHandler#completed completed} method is executed.
*
*
* @param dst
* The buffer into which bytes are to be transferred
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The completion handler object; can be {@code null}
*
* @return A Future representing the result of the operation
* The completion handler
*
* @throws IllegalArgumentException
* If the buffer is read-only
* @throws ReadPendingException
* If the channel does not allow more than one read to be outstanding
* and a previous read has not completed
* @throws ShutdownChannelGroupException
* If the channel is associated with a {@link AsynchronousChannelGroup
* group} that has terminated
*/
<A> Future<Integer> read(ByteBuffer dst,
<A> void read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* <p> An invocation of this method of the form <tt>c.read(dst)</tt>
* behaves in exactly the same manner as the invocation
* <blockquote><pre>
* c.read(dst, null, null);</pre></blockquote>
* <p> This method initiates an asynchronous read operation to read a
* sequence of bytes from this channel into the given buffer. The method
* behaves in exactly the same manner as the {@link
* #read(ByteBuffer,Object,CompletionHandler)
* read(ByteBuffer,Object,CompletionHandler)} method except that instead
* of specifying a completion handler, this method returns a {@code Future}
* representing the pending result. The {@code Future}'s {@link Future#get()
* get} method returns the number of bytes read or {@code -1} if no bytes
* could be read because the channel has reached end-of-stream.
*
* @param dst
* The buffer into which bytes are to be transferred
......@@ -134,17 +136,17 @@ public interface AsynchronousByteChannel
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
* <p> This method initiates an operation to write a sequence of bytes to
* this channel from the given buffer. This method returns a {@link
* Future} representing the pending result of the operation. The result
* of the operation, obtained by invoking the <tt>Future</tt>'s {@link
* Future#get() get} method, is the number of bytes written, possibly zero.
* <p> This method initiates an asynchronous write operation to write a
* sequence of bytes to this channel from the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the write
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes written.
*
* <p> This method initiates a write operation to write up to <i>r</i> bytes
* to the channel, where <i>r</i> is the number of bytes remaining in the
* buffer, that is, {@code src.remaining()} at the moment the write is
* attempted. Where <i>r</i> is 0, the write operation completes immediately
* with a result of {@code 0} without initiating an I/O operation.
* <p> The write operation may write up to <i>r</i> bytes to the channel,
* where <i>r</i> is the number of bytes remaining in the buffer, that is,
* {@code src.remaining()} at the time that the write is attempted. Where
* <i>r</i> is 0, the write operation completes immediately with a result of
* {@code 0} without initiating an I/O operation.
*
* <p> Suppose that a byte sequence of length <i>n</i> is written, where
* <tt>0</tt>&nbsp;<tt>&lt;</tt>&nbsp;<i>n</i>&nbsp;<tt>&lt;=</tt>&nbsp;<i>r</i>.
......@@ -156,41 +158,43 @@ public interface AsynchronousByteChannel
* <i>p</i>&nbsp;<tt>+</tt>&nbsp;<i>n</i>; its limit will not have changed.
*
* <p> Buffers are not safe for use by multiple concurrent threads so care
* should be taken to not to access the buffer until the operaton has completed.
* should be taken to not access the buffer until the operation has
* completed.
*
* <p> This method may be invoked at any time. Some channel types may not
* allow more than one write to be outstanding at any given time. If a thread
* initiates a write operation before a previous write operation has
* completed then a {@link WritePendingException} will be thrown.
*
* <p> The <tt>handler</tt> parameter is used to specify a {@link
* CompletionHandler}. When the write operation completes the handler's
* {@link CompletionHandler#completed completed} method is executed.
*
* @param src
* The buffer from which bytes are to be retrieved
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The completion handler object; can be {@code null}
*
* @return A Future representing the result of the operation
* The completion handler object
*
* @throws WritePendingException
* If the channel does not allow more than one write to be outstanding
* and a previous write has not completed
* @throws ShutdownChannelGroupException
* If the channel is associated with a {@link AsynchronousChannelGroup
* group} that has terminated
*/
<A> Future<Integer> write(ByteBuffer src,
<A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler);
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
* <p> An invocation of this method of the form <tt>c.write(src)</tt>
* behaves in exactly the same manner as the invocation
* <blockquote><pre>
* c.write(src, null, null);</pre></blockquote>
* <p> This method initiates an asynchronous write operation to write a
* sequence of bytes to this channel from the given buffer. The method
* behaves in exactly the same manner as the {@link
* #write(ByteBuffer,Object,CompletionHandler)
* write(ByteBuffer,Object,CompletionHandler)} method except that instead
* of specifying a completion handler, this method returns a {@code Future}
* representing the pending result. The {@code Future}'s {@link Future#get()
* get} method returns the number of bytes written.
*
* @param src
* The buffer from which bytes are to be retrieved
......
......@@ -34,7 +34,8 @@ import java.util.concurrent.Future; // javadoc
*
* <ol>
* <li><pre>{@link Future}&lt;V&gt; <em>operation</em>(<em>...</em>)</pre></li>
* <li><pre>Future&lt;V&gt; <em>operation</em>(<em>...</em> A attachment, {@link CompletionHandler}&lt;V,? super A&gt handler)</pre></li>
* <li><pre>void <em>operation</em>(<em>...</em> A attachment, {@link
* CompletionHandler}&lt;V,? super A&gt; handler)</pre></li>
* </ol>
*
* where <i>operation</i> is the name of the I/O operation (read or write for
......@@ -48,7 +49,7 @@ import java.util.concurrent.Future; // javadoc
* interface may be used to check if the operation has completed, wait for its
* completion, and to retrieve the result. In the second form, a {@link
* CompletionHandler} is invoked to consume the result of the I/O operation when
* it completes, fails, or is cancelled.
* it completes or fails.
*
* <p> A channel that implements this interface is <em>asynchronously
* closeable</em>: If an I/O operation is outstanding on the channel and the
......@@ -63,33 +64,33 @@ import java.util.concurrent.Future; // javadoc
* <h4>Cancellation</h4>
*
* <p> The {@code Future} interface defines the {@link Future#cancel cancel}
* method to cancel execution of a task.
*
* <p> Where the {@code cancel} method is invoked with the {@code
* method to cancel execution. This causes all threads waiting on the result of
* the I/O operation to throw {@link java.util.concurrent.CancellationException}.
* Whether the underlying I/O operation can be cancelled is highly implementation
* specific and therefore not specified. Where cancellation leaves the channel,
* or the entity to which it is connected, in an inconsistent state, then the
* channel is put into an implementation specific <em>error state</em> that
* prevents further attempts to initiate I/O operations that are <i>similar</i>
* to the operation that was cancelled. For example, if a read operation is
* cancelled but the implementation cannot guarantee that bytes have not been
* read from the channel then it puts the channel into an error state; further
* attempts to initiate a {@code read} operation cause an unspecified runtime
* exception to be thrown. Similarly, if a write operation is cancelled but the
* implementation cannot guarantee that bytes have not been written to the
* channel then subsequent attempts to initiate a {@code write} will fail with
* an unspecified runtime exception.
*
* <p> Where the {@link Future#cancel cancel} method is invoked with the {@code
* mayInterruptIfRunning} parameter set to {@code true} then the I/O operation
* may be interrupted by closing the channel. This will cause any other I/O
* operations outstanding on the channel to complete with the exception {@link
* AsynchronousCloseException}.
*
* <p> If a {@code CompletionHandler} is specified when initiating an I/O
* operation, and the {@code cancel} method is invoked to cancel the I/O
* operation before it completes, then the {@code CompletionHandler}'s {@link
* CompletionHandler#cancelled cancelled} method is invoked.
*
* <p> If an implementation of this interface supports a means to cancel I/O
* operations, and where cancellation may leave the channel, or the entity to
* which it is connected, in an inconsistent state, then the channel is put into
* an implementation specific <em>error state</em> that prevents further
* attempts to initiate I/O operations on the channel. For example, if a read
* operation is cancelled but the implementation cannot guarantee that bytes
* have not been read from the channel then it puts the channel into error state
* state; further attempts to initiate a {@code read} operation causes an
* unspecified runtime exception to be thrown.
* may be interrupted by closing the channel. In that case all threads waiting
* on the result of the I/O operation throw {@code CancellationException} and
* any other I/O operations outstanding on the channel complete with the
* exception {@link AsynchronousCloseException}.
*
* <p> Where the {@code cancel} method is invoked to cancel read or write
* operations then it recommended that all buffers used in the I/O operations be
* discarded or care taken to ensure that the buffers are not accessed while the
* channel remains open.
* operations then it is recommended that all buffers used in the I/O operations
* be discarded or care taken to ensure that the buffers are not accessed while
* the channel remains open.
*
* @since 1.7
*/
......@@ -102,7 +103,7 @@ public interface AsynchronousChannel
*
* <p> Any outstanding asynchronous operations upon this channel will
* complete with the exception {@link AsynchronousCloseException}. After a
* channel is closed then further attempts to initiate asynchronous I/O
* channel is closed, further attempts to initiate asynchronous I/O
* operations complete immediately with cause {@link ClosedChannelException}.
*
* <p> This method otherwise behaves exactly as specified by the {@link
......
......@@ -85,9 +85,6 @@ import java.io.IOException;
* public void failed(Throwable exc, Void att) {
* ...
* }
* public void cancelled(Void att) {
* ...
* }
* });
* </pre>
*
......@@ -240,11 +237,11 @@ public abstract class AsynchronousServerSocketChannel
/**
* Accepts a connection.
*
* <p> This method initiates accepting a connection made to this channel's
* socket, returning a {@link Future} representing the pending result
* of the operation. The {@code Future}'s {@link Future#get() get}
* method will return the {@link AsynchronousSocketChannel} for the new
* connection on successful completion.
* <p> This method initiates an asynchronous operation to accept a
* connection made to this channel's socket. The {@code handler} parameter is
* a completion handler that is invoked when a connection is accepted (or
* the operation fails). The result passed to the completion handler is
* the {@link AsynchronousSocketChannel} to the new connection.
*
* <p> When a new connection is accepted then the resulting {@code
* AsynchronousSocketChannel} will be bound to the same {@link
......@@ -269,35 +266,35 @@ public abstract class AsynchronousServerSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return an <tt>Future</tt> object representing the pending result
* The handler for consuming the result
*
* @throws AcceptPendingException
* If an accept operation is already in progress on this channel
* @throws NotYetBoundException
* If this channel's socket has not yet been bound
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<AsynchronousSocketChannel>
accept(A attachment, CompletionHandler<AsynchronousSocketChannel,? super A> handler);
public abstract <A> void accept(A attachment,
CompletionHandler<AsynchronousSocketChannel,? super A> handler);
/**
* Accepts a connection.
*
* <p> This method is equivalent to invoking {@link
* #accept(Object,CompletionHandler)} with the {@code attachment}
* and {@code handler} parameters set to {@code null}.
* <p> This method initiates an asynchronous operation to accept a
* connection made to this channel's socket. The method behaves in exactly
* the same manner as the {@link #accept(Object, CompletionHandler)} method
* except that instead of specifying a completion handler, this method
* returns a {@code Future} representing the pending result. The {@code
* Future}'s {@link Future#get() get} method returns the {@link
* AsynchronousSocketChannel} to the new connection on successful completion.
*
* @return an <tt>Future</tt> object representing the pending result
* @return a {@code Future} object representing the pending result
*
* @throws AcceptPendingException
* If an accept operation is already in progress on this channel
* @throws NotYetBoundException
* If this channel's socket has not yet been bound
*/
public final Future<AsynchronousSocketChannel> accept() {
return accept(null, null);
}
public abstract Future<AsynchronousSocketChannel> accept();
}
......@@ -274,14 +274,11 @@ public abstract class AsynchronousSocketChannel
/**
* Connects this channel.
*
* <p> This method initiates an operation to connect this channel, returning
* a {@code Future} representing the pending result of the operation. If
* the connection is successfully established then the {@code Future}'s
* {@link Future#get() get} method will return {@code null}. If the
* connection cannot be established then the channel is closed. In that case,
* invoking the {@code get} method throws {@link
* java.util.concurrent.ExecutionException} with an {@code IOException} as
* the cause.
* <p> This method initiates an operation to connect this channel. The
* {@code handler} parameter is a completion handler that is invoked when
* the connection is successfully established or connection cannot be
* established. If the connection cannot be established then the channel is
* closed.
*
* <p> This method performs exactly the same security checks as the {@link
* java.net.Socket} class. That is, if a security manager has been
......@@ -294,9 +291,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
......@@ -307,23 +302,26 @@ public abstract class AsynchronousSocketChannel
* @throws ConnectionPendingException
* If a connection operation is already in progress on this channel
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
* @throws SecurityException
* If a security manager has been installed
* and it does not permit access to the given remote endpoint
*
* @see #getRemoteAddress
*/
public abstract <A> Future<Void> connect(SocketAddress remote,
public abstract <A> void connect(SocketAddress remote,
A attachment,
CompletionHandler<Void,? super A> handler);
/**
* Connects this channel.
*
* <p> This method is equivalent to invoking {@link
* #connect(SocketAddress,Object,CompletionHandler)} with the {@code attachment}
* and handler parameters set to {@code null}.
* <p> This method initiates an operation to connect this channel. This
* method behaves in exactly the same manner as the {@link
* #connect(SocketAddress, Object, CompletionHandler)} method except that
* instead of specifying a completion handler, this method returns a {@code
* Future} representing the pending result. The {@code Future}'s {@link
* Future#get() get} method returns {@code null} on successful completion.
*
* @param remote
* The remote address to which this channel is to be connected
......@@ -342,18 +340,17 @@ public abstract class AsynchronousSocketChannel
* If a security manager has been installed
* and it does not permit access to the given remote endpoint
*/
public final Future<Void> connect(SocketAddress remote) {
return connect(remote, null, null);
}
public abstract Future<Void> connect(SocketAddress remote);
/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* <p> This method initiates the reading of a sequence of bytes from this
* channel into the given buffer, returning a {@code Future} representing
* the pending result of the operation. The {@code Future}'s {@link
* Future#get() get} method returns the number of bytes read or {@code -1}
* if all bytes have been read and channel has reached end-of-stream.
* <p> This method initiates an asynchronous read operation to read a
* sequence of bytes from this channel into the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the read
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes read or {@code -1} if no bytes could be
* read because the channel has reached end-of-stream.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then the operation completes with the exception {@link
......@@ -376,9 +373,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative or the buffer is
......@@ -388,9 +383,9 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Integer> read(ByteBuffer dst,
public abstract <A> void read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
......@@ -402,14 +397,14 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
@Override
public final <A> Future<Integer> read(ByteBuffer dst,
public final <A> void read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
return read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
read(dst, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
......@@ -419,16 +414,18 @@ public abstract class AsynchronousSocketChannel
* If this channel is not yet connected
*/
@Override
public final Future<Integer> read(ByteBuffer dst) {
return read(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
public abstract Future<Integer> read(ByteBuffer dst);
/**
* Reads a sequence of bytes from this channel into a subsequence of the
* given buffers. This operation, sometimes called a <em>scattering read</em>,
* is often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a
* variable-length body.
* variable-length body. The {@code handler} parameter is a completion
* handler that is invoked when the read operation completes (or fails). The
* result passed to the completion handler is the number of bytes read or
* {@code -1} if no bytes could be read because the channel has reached
* end-of-stream.
*
* <p> This method initiates a read of up to <i>r</i> bytes from this channel,
* where <i>r</i> is the total number of bytes remaining in the specified
......@@ -456,11 +453,6 @@ public abstract class AsynchronousSocketChannel
* I/O operation is performed with the maximum number of buffers allowed by
* the operating system.
*
* <p> The return value from this method is a {@code Future} representing
* the pending result of the operation. The {@code Future}'s {@link
* Future#get() get} method returns the number of bytes read or {@code -1L}
* if all bytes have been read and the channel has reached end-of-stream.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the
......@@ -485,9 +477,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length}
......@@ -500,9 +490,9 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Long> read(ByteBuffer[] dsts,
public abstract <A> void read(ByteBuffer[] dsts,
int offset,
int length,
long timeout,
......@@ -513,10 +503,11 @@ public abstract class AsynchronousSocketChannel
/**
* Writes a sequence of bytes to this channel from the given buffer.
*
* <p> This method initiates the writing of a sequence of bytes to this channel
* from the given buffer, returning a {@code Future} representing the
* pending result of the operation. The {@code Future}'s {@link Future#get()
* get} method will return the number of bytes written.
* <p> This method initiates an asynchronous write operation to write a
* sequence of bytes to this channel from the given buffer. The {@code
* handler} parameter is a completion handler that is invoked when the write
* operation completes (or fails). The result passed to the completion
* handler is the number of bytes written.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
......@@ -539,9 +530,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IllegalArgumentException
* If the {@code timeout} parameter is negative
......@@ -550,9 +539,9 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Integer> write(ByteBuffer src,
public abstract <A> void write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
......@@ -563,15 +552,15 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
@Override
public final <A> Future<Integer> write(ByteBuffer src,
public final <A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
return write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
write(src, 0L, TimeUnit.MILLISECONDS, attachment, handler);
}
/**
......@@ -580,16 +569,16 @@ public abstract class AsynchronousSocketChannel
* If this channel is not yet connected
*/
@Override
public final Future<Integer> write(ByteBuffer src) {
return write(src, 0L, TimeUnit.MILLISECONDS, null, null);
}
public abstract Future<Integer> write(ByteBuffer src);
/**
* Writes a sequence of bytes to this channel from a subsequence of the given
* buffers. This operation, sometimes called a <em>gathering write</em>, is
* often useful when implementing network protocols that group data into
* segments consisting of one or more fixed-length headers followed by a
* variable-length body.
* variable-length body. The {@code handler} parameter is a completion
* handler that is invoked when the write operation completes (or fails).
* The result passed to the completion handler is the number of bytes written.
*
* <p> This method initiates a write of up to <i>r</i> bytes to this channel,
* where <i>r</i> is the total number of bytes remaining in the specified
......@@ -616,10 +605,6 @@ public abstract class AsynchronousSocketChannel
* remaining), exceeds this limit, then the I/O operation is performed with
* the maximum number of buffers allowed by the operating system.
*
* <p> The return value from this method is a {@code Future} representing
* the pending result of the operation. The {@code Future}'s {@link
* Future#get() get} method will return the number of bytes written.
*
* <p> If a timeout is specified and the timeout elapses before the operation
* completes then it completes with the exception {@link
* InterruptedByTimeoutException}. Where a timeout occurs, and the
......@@ -644,9 +629,7 @@ public abstract class AsynchronousSocketChannel
* @param attachment
* The object to attach to the I/O operation; can be {@code null}
* @param handler
* The handler for consuming the result; can be {@code null}
*
* @return A {@code Future} object representing the pending result
* The handler for consuming the result
*
* @throws IndexOutOfBoundsException
* If the pre-conditions for the {@code offset} and {@code length}
......@@ -658,9 +641,9 @@ public abstract class AsynchronousSocketChannel
* @throws NotYetConnectedException
* If this channel is not yet connected
* @throws ShutdownChannelGroupException
* If a handler is specified, and the channel group is shutdown
* If the channel group has terminated
*/
public abstract <A> Future<Long> write(ByteBuffer[] srcs,
public abstract <A> void write(ByteBuffer[] srcs,
int offset,
int length,
long timeout,
......
......@@ -182,7 +182,6 @@ public final class Channels {
}
/**
* {@note new}
* Constructs a stream that reads bytes from the given channel.
*
* <p> The stream will not be buffered, and it will not support the {@link
......@@ -258,7 +257,6 @@ public final class Channels {
}
/**
* {@note new}
* Constructs a stream that writes bytes to the given channel.
*
* <p> The stream will not be buffered. The stream will be safe for access
......
......@@ -32,11 +32,9 @@ package java.nio.channels;
* handler to be specified to consume the result of an asynchronous operation.
* The {@link #completed completed} method is invoked when the I/O operation
* completes successfully. The {@link #failed failed} method is invoked if the
* I/O operations fails. The {@link #cancelled cancelled} method is invoked when
* the I/O operation is cancelled by invoking the {@link
* java.util.concurrent.Future#cancel cancel} method. The implementations of
* these methods should complete in a timely manner so as to avoid keeping the
* invoking thread from dispatching to other completion handlers.
* I/O operations fails. The implementations of these methods should complete
* in a timely manner so as to avoid keeping the invoking thread from dispatching
* to other completion handlers.
*
* @param <V> The result type of the I/O operation
* @param <A> The type of the object attached to the I/O operation
......@@ -65,13 +63,4 @@ public interface CompletionHandler<V,A> {
* The object attached to the I/O operation when it was initiated.
*/
void failed(Throwable exc, A attachment);
/**
* Invoked when an operation is cancelled by invoking the {@link
* java.util.concurrent.Future#cancel cancel} method.
*
* @param attachment
* The object attached to the I/O operation when it was initiated.
*/
void cancelled(A attachment);
}
......@@ -39,8 +39,7 @@ import java.util.Collections;
/**
* A channel for reading, writing, mapping, and manipulating a file.
*
* <p> {@note revised}
* A file channel is a {@link SeekableByteChannel} that is connected to
* <p> A file channel is a {@link SeekableByteChannel} that is connected to
* a file. It has a current <i>position</i> within its file which can
* be both {@link #position() <i>queried</i>} and {@link #position(long)
* <i>modified</i>}. The file itself contains a variable-length sequence
......@@ -151,7 +150,6 @@ import java.util.Collections;
* @author Mike McCloskey
* @author JSR-51 Expert Group
* @since 1.4
* @updated 1.7
*/
public abstract class FileChannel
......@@ -164,7 +162,6 @@ public abstract class FileChannel
protected FileChannel() { }
/**
* {@note new}
* Opens or creates a file, returning a file channel to access the file.
*
* <p> The {@code options} parameter determines how the file is opened.
......@@ -293,7 +290,6 @@ public abstract class FileChannel
private static final FileAttribute<?>[] NO_ATTRIBUTES = new FileAttribute[0];
/**
* {@note new}
* Opens or creates a file, returning a file channel to access the file.
*
* <p> An invocation of this method behaves in exactly the same way as the
......
......@@ -114,7 +114,6 @@ import java.io.IOException;
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
* @updated 1.7
*/
public abstract class FileLock {
......@@ -161,7 +160,7 @@ public abstract class FileLock {
}
/**
* {@note new} Initializes a new instance of this class.
* Initializes a new instance of this class.
*
* @param channel
* The channel upon whose file this lock is held
......@@ -199,7 +198,6 @@ public abstract class FileLock {
}
/**
* {@note revised}
* Returns the file channel upon whose file this lock was acquired.
*
* <p> This method has been superseded by the {@link #acquiredBy acquiredBy}
......@@ -213,7 +211,6 @@ public abstract class FileLock {
}
/**
* {@note new}
* Returns the channel upon whose file this lock was acquired.
*
* @return The channel upon whose file this lock was acquired.
......
......@@ -190,5 +190,5 @@ gen WritePendingException "
gen ShutdownChannelGroupException "
* Unchecked exception thrown when an attempt is made to construct a channel in
* a group that is shutdown or the completion handler for an I/O operation
* cannot be invoked because the channel group is shutdown." \
* cannot be invoked because the channel group has terminated." \
-3903801676350154157L
......@@ -285,7 +285,6 @@
* java.lang.NullPointerException NullPointerException} to be thrown.
*
* @since 1.4
* @updated 1.7
* @author Mark Reinhold
* @author JSR-51 Expert Group
*/
......
......@@ -39,8 +39,6 @@ import java.io.IOException;
* metadata or file attributes.
*
* @since 1.7
* @see java.io.Inputs
* @see java.io.Outputs
* @see java.nio.file.attribute.Attributes
* @see java.io.File#toPath
*/
......
......@@ -101,12 +101,12 @@ import java.io.BufferedWriter;
* &lt;!ATTLIST entry key CDATA #REQUIRED&gt;
* </pre>
*
* @see <a href="../../../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
* @see <a href="../../../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
*
* <p>This class is thread-safe: multiple threads can share a single
* <tt>Properties</tt> object without the need for external synchronization.
*
* @see <a href="../../../technotes/tools/solaris/native2ascii.html">native2ascii tool for Solaris</a>
* @see <a href="../../../technotes/tools/windows/native2ascii.html">native2ascii tool for Windows</a>
*
* @author Arthur van Hoff
* @author Michael McCloskey
* @author Xueming Shen
......
......@@ -674,7 +674,6 @@ public final class Scanner implements Iterator<String> {
}
/**
* {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into
* characters using the underlying platform's
......@@ -694,7 +693,6 @@ public final class Scanner implements Iterator<String> {
}
/**
* {@note new}
* Constructs a new <code>Scanner</code> that produces values scanned
* from the specified file. Bytes from the file are converted into
* characters using the specified charset.
......
......@@ -766,19 +766,21 @@ public class LinkedBlockingQueue<E> extends AbstractQueue<E>
}
/**
* Unlike other traversal methods, iterators need to handle:
* Returns the next live successor of p, or null if no such.
*
* Unlike other traversal methods, iterators need to handle both:
* - dequeued nodes (p.next == p)
* - interior removed nodes (p.item == null)
* - (possibly multiple) interior removed nodes (p.item == null)
*/
private Node<E> nextNode(Node<E> p) {
for (;;) {
Node<E> s = p.next;
if (p == s)
if (s == p)
return head.next;
// Skip over removed nodes.
// May be necessary if multiple interior Nodes are removed.
while (s != null && s.item == null)
s = s.next;
if (s == null || s.item != null)
return s;
p = s;
}
}
public E next() {
......
/*
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.nio.ch;
import java.nio.channels.AsynchronousChannel;
import java.util.concurrent.Future;
/**
* Base implementation of Future used for asynchronous I/O
*/
abstract class AbstractFuture<V,A>
implements Future<V>
{
private final AsynchronousChannel channel;
private final A attachment;
protected AbstractFuture(AsynchronousChannel channel, A attachment) {
this.channel = channel;
this.attachment = attachment;
}
final AsynchronousChannel channel() {
return channel;
}
final A attachment() {
return attachment;
}
/**
* Returns the result of the operation if it has completed successfully.
*/
abstract V value();
/**
* Returns the exception if the operation has failed.
*/
abstract Throwable exception();
}
......@@ -32,8 +32,8 @@ import java.io.IOException;
import java.io.FileDescriptor;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicBoolean;
import java.security.PrivilegedAction;
import java.security.AccessController;
import java.security.AccessControlContext;
......@@ -65,11 +65,8 @@ abstract class AsynchronousChannelGroupImpl
private final Queue<Runnable> taskQueue;
// group shutdown
// shutdownLock is RW lock so as to allow for concurrent queuing of tasks
// when using a fixed thread pool.
private final ReadWriteLock shutdownLock = new ReentrantReadWriteLock();
private final AtomicBoolean shutdown = new AtomicBoolean();
private final Object shutdownNowLock = new Object();
private volatile boolean shutdown;
private volatile boolean terminateInitiated;
AsynchronousChannelGroupImpl(AsynchronousChannelProvider provider,
......@@ -214,7 +211,7 @@ abstract class AsynchronousChannelGroupImpl
@Override
public final boolean isShutdown() {
return shutdown;
return shutdown.get();
}
@Override
......@@ -260,17 +257,10 @@ abstract class AsynchronousChannelGroupImpl
@Override
public final void shutdown() {
shutdownLock.writeLock().lock();
try {
if (shutdown) {
if (shutdown.getAndSet(true)) {
// already shutdown
return;
}
shutdown = true;
} finally {
shutdownLock.writeLock().unlock();
}
// if there are channels in the group then shutdown will continue
// when the last channel is closed
if (!isEmpty()) {
......@@ -289,12 +279,7 @@ abstract class AsynchronousChannelGroupImpl
@Override
public final void shutdownNow() throws IOException {
shutdownLock.writeLock().lock();
try {
shutdown = true;
} finally {
shutdownLock.writeLock().unlock();
}
shutdown.set(true);
synchronized (shutdownNowLock) {
if (!terminateInitiated) {
terminateInitiated = true;
......@@ -305,6 +290,18 @@ abstract class AsynchronousChannelGroupImpl
}
}
/**
* For use by AsynchronousFileChannel to release resources without shutting
* down the thread pool.
*/
final void detachFromThreadPool() {
if (shutdown.getAndSet(true))
throw new AssertionError("Already shutdown");
if (!isEmpty())
throw new AssertionError("Group not empty");
shutdownHandlerTasks();
}
@Override
public final boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException
......
......@@ -25,8 +25,10 @@
package sun.nio.ch;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.locks.*;
import java.io.FileDescriptor;
import java.io.IOException;
......@@ -101,6 +103,33 @@ abstract class AsynchronousFileChannelImpl
// -- file locking --
abstract <A> Future<FileLock> implLock(long position,
long size,
boolean shared,
A attachment,
CompletionHandler<FileLock,? super A> handler);
@Override
public final Future<FileLock> lock(long position,
long size,
boolean shared)
{
return implLock(position, size, shared, null, null);
}
@Override
public final <A> void lock(long position,
long size,
boolean shared,
A attachment,
CompletionHandler<FileLock,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implLock(position, size, shared, attachment, handler);
}
private volatile FileLockTable fileLockTable;
final void ensureFileLockTableInitialized() throws IOException {
......@@ -175,4 +204,50 @@ abstract class AsynchronousFileChannelImpl
end();
}
}
// -- reading and writing --
abstract <A> Future<Integer> implRead(ByteBuffer dst,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler);
@Override
public final Future<Integer> read(ByteBuffer dst, long position) {
return implRead(dst, position, null, null);
}
@Override
public final <A> void read(ByteBuffer dst,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implRead(dst, position, attachment, handler);
}
abstract <A> Future<Integer> implWrite(ByteBuffer src,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler);
@Override
public final Future<Integer> write(ByteBuffer src, long position) {
return implWrite(src, position, null, null);
}
@Override
public final <A> void write(ByteBuffer src,
long position,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implWrite(src, position, attachment, handler);
}
}
......@@ -35,6 +35,7 @@ import java.io.IOException;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import sun.net.NetHooks;
......@@ -108,6 +109,29 @@ abstract class AsynchronousServerSocketChannelImpl
implClose();
}
/**
* Invoked by accept to accept connection
*/
abstract Future<AsynchronousSocketChannel>
implAccept(Object attachment,
CompletionHandler<AsynchronousSocketChannel,Object> handler);
@Override
public final Future<AsynchronousSocketChannel> accept() {
return implAccept(null, null);
}
@Override
@SuppressWarnings("unchecked")
public final <A> void accept(A attachment,
CompletionHandler<AsynchronousSocketChannel,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implAccept(attachment, (CompletionHandler<AsynchronousSocketChannel,Object>)handler);
}
final boolean isAcceptKilled() {
return acceptKilled;
}
......
......@@ -183,29 +183,54 @@ abstract class AsynchronousSocketChannelImpl
killWriting();
}
/**
* Invoked by connect to initiate the connect operation.
*/
abstract <A> Future<Void> implConnect(SocketAddress remote,
A attachment,
CompletionHandler<Void,? super A> handler);
@Override
public final Future<Void> connect(SocketAddress remote) {
return implConnect(remote, null, null);
}
@Override
public final <A> void connect(SocketAddress remote,
A attachment,
CompletionHandler<Void,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implConnect(remote, attachment, handler);
}
/**
* Invoked by read to initiate the I/O operation.
*/
abstract <V extends Number,A> Future<V> readImpl(ByteBuffer[] dsts,
boolean isScatteringRead,
abstract <V extends Number,A> Future<V> implRead(boolean isScatteringRead,
ByteBuffer dst,
ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked")
private <V extends Number,A> Future<V> read(ByteBuffer[] dsts,
boolean isScatteringRead,
private <V extends Number,A> Future<V> read(boolean isScatteringRead,
ByteBuffer dst,
ByteBuffer[] dsts,
long timeout,
TimeUnit unit,
A attachment,
A att,
CompletionHandler<V,? super A> handler)
{
if (!isOpen()) {
CompletedFuture<V,A> result = CompletedFuture
.withFailure(this, new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable e = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(e);
Invoker.invoke(this, handler, att, null, e);
return null;
}
if (remoteAddress == null)
......@@ -213,13 +238,13 @@ abstract class AsynchronousSocketChannelImpl
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
boolean hasSpaceToRead = isScatteringRead || dsts[0].hasRemaining();
boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
boolean shutdown = false;
// check and update state
synchronized (readLock) {
if (readKilled)
throw new RuntimeException("Reading not allowed due to timeout or cancellation");
throw new IllegalStateException("Reading not allowed due to timeout or cancellation");
if (reading)
throw new ReadPendingException();
if (readShutdown) {
......@@ -234,37 +259,44 @@ abstract class AsynchronousSocketChannelImpl
// immediately complete with -1 if shutdown for read
// immediately complete with 0 if no space remaining
if (shutdown || !hasSpaceToRead) {
CompletedFuture<V,A> result;
Number result;
if (isScatteringRead) {
Long value = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
result = (shutdown) ? Long.valueOf(-1L) : Long.valueOf(0L);
} else {
int value = (shutdown) ? -1 : 0;
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, value, attachment);
result = (shutdown) ? -1 : 0;
}
if (handler == null)
return CompletedFuture.withResult((V)result);
Invoker.invoke(this, handler, att, (V)result, null);
return null;
}
Invoker.invoke(handler, result);
return result;
return implRead(isScatteringRead, dst, dsts, timeout, unit, att, handler);
}
return readImpl(dsts, isScatteringRead, timeout, unit, attachment, handler);
@Override
public final Future<Integer> read(ByteBuffer dst) {
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public final <A> Future<Integer> read(ByteBuffer dst,
public final <A> void read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
ByteBuffer[] bufs = new ByteBuffer[1];
bufs[0] = dst;
return read(bufs, false, timeout, unit, attachment, handler);
read(false, dst, null, timeout, unit, attachment, handler);
}
@Override
public final <A> Future<Long> read(ByteBuffer[] dsts,
public final <A> void read(ByteBuffer[] dsts,
int offset,
int length,
long timeout,
......@@ -272,6 +304,8 @@ abstract class AsynchronousSocketChannelImpl
A attachment,
CompletionHandler<Long,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
throw new IndexOutOfBoundsException();
ByteBuffer[] bufs = Util.subsequence(dsts, offset, length);
......@@ -279,28 +313,30 @@ abstract class AsynchronousSocketChannelImpl
if (bufs[i].isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
}
return read(bufs, true, timeout, unit, attachment, handler);
read(true, null, bufs, timeout, unit, attachment, handler);
}
/**
* Invoked by write to initiate the I/O operation.
*/
abstract <V extends Number,A> Future<V> writeImpl(ByteBuffer[] srcs,
boolean isGatheringWrite,
abstract <V extends Number,A> Future<V> implWrite(boolean isGatheringWrite,
ByteBuffer src,
ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<V,? super A> handler);
@SuppressWarnings("unchecked")
private <V extends Number,A> Future<V> write(ByteBuffer[] srcs,
boolean isGatheringWrite,
private <V extends Number,A> Future<V> write(boolean isGatheringWrite,
ByteBuffer src,
ByteBuffer[] srcs,
long timeout,
TimeUnit unit,
A attachment,
A att,
CompletionHandler<V,? super A> handler)
{
boolean hasDataToWrite = isGatheringWrite || srcs[0].hasRemaining();
boolean hasDataToWrite = isGatheringWrite || src.hasRemaining();
boolean closed = false;
if (isOpen()) {
......@@ -311,7 +347,7 @@ abstract class AsynchronousSocketChannelImpl
// check and update state
synchronized (writeLock) {
if (writeKilled)
throw new RuntimeException("Writing not allowed due to timeout or cancellation");
throw new IllegalStateException("Writing not allowed due to timeout or cancellation");
if (writing)
throw new WritePendingException();
if (writeShutdown) {
......@@ -327,41 +363,44 @@ abstract class AsynchronousSocketChannelImpl
// channel is closed or shutdown for write
if (closed) {
CompletedFuture<V,A> result = CompletedFuture
.withFailure(this, new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable e = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(e);
Invoker.invoke(this, handler, att, null, e);
return null;
}
// nothing to write so complete immediately
if (!hasDataToWrite) {
CompletedFuture<V,A> result;
if (isGatheringWrite) {
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0L, attachment);
} else {
result = (CompletedFuture<V,A>)CompletedFuture.withResult(this, 0, attachment);
Number result = (isGatheringWrite) ? (Number)0L : (Number)0;
if (handler == null)
return CompletedFuture.withResult((V)result);
Invoker.invoke(this, handler, att, (V)result, null);
return null;
}
Invoker.invoke(handler, result);
return result;
return implWrite(isGatheringWrite, src, srcs, timeout, unit, att, handler);
}
return writeImpl(srcs, isGatheringWrite, timeout, unit, attachment, handler);
@Override
public final Future<Integer> write(ByteBuffer src) {
return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public final <A> Future<Integer> write(ByteBuffer src,
public final <A> void write(ByteBuffer src,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
ByteBuffer[] bufs = new ByteBuffer[1];
bufs[0] = src;
return write(bufs, false, timeout, unit, attachment, handler);
if (handler == null)
throw new NullPointerException("'handler' is null");
write(false, src, null, timeout, unit, attachment, handler);
}
@Override
public final <A> Future<Long> write(ByteBuffer[] srcs,
public final <A> void write(ByteBuffer[] srcs,
int offset,
int length,
long timeout,
......@@ -369,10 +408,12 @@ abstract class AsynchronousSocketChannelImpl
A attachment,
CompletionHandler<Long,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
throw new IndexOutOfBoundsException();
srcs = Util.subsequence(srcs, offset, length);
return write(srcs, true, timeout, unit, attachment, handler);
write(true, null, srcs, timeout, unit, attachment, handler);
}
@Override
......@@ -461,7 +502,6 @@ abstract class AsynchronousSocketChannelImpl
}
@Override
@SuppressWarnings("unchecked")
public final SocketAddress getRemoteAddress() throws IOException {
if (!isOpen())
throw new ClosedChannelException();
......
......@@ -25,7 +25,7 @@
package sun.nio.ch;
import java.nio.channels.AsynchronousChannel;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ExecutionException;
import java.io.IOException;
......@@ -35,39 +35,35 @@ import java.io.IOException;
* completed.
*/
final class CompletedFuture<V,A>
extends AbstractFuture<V,A>
{
final class CompletedFuture<V> implements Future<V> {
private final V result;
private final Throwable exc;
private CompletedFuture(AsynchronousChannel channel,
V result,
Throwable exc,
A attachment)
{
super(channel, attachment);
private CompletedFuture(V result, Throwable exc) {
this.result = result;
this.exc = exc;
}
@SuppressWarnings("unchecked")
static <V,A> CompletedFuture<V,A> withResult(AsynchronousChannel channel,
V result,
A attachment)
{
return new CompletedFuture<V,A>(channel, result, null, attachment);
static <V> CompletedFuture<V> withResult(V result) {
return new CompletedFuture<V>(result, null);
}
@SuppressWarnings("unchecked")
static <V,A> CompletedFuture<V,A> withFailure(AsynchronousChannel channel,
Throwable exc,
A attachment)
{
static <V> CompletedFuture<V> withFailure(Throwable exc) {
// exception must be IOException or SecurityException
if (!(exc instanceof IOException) && !(exc instanceof SecurityException))
exc = new IOException(exc);
return new CompletedFuture(channel, null, exc, attachment);
return new CompletedFuture(null, exc);
}
@SuppressWarnings("unchecked")
static <V> CompletedFuture<V> withResult(V result, Throwable exc) {
if (exc == null) {
return withResult(result);
} else {
return withFailure(exc);
}
}
@Override
......@@ -100,14 +96,4 @@ final class CompletedFuture<V,A>
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
Throwable exception() {
return exc;
}
@Override
V value() {
return result;
}
}
......@@ -117,33 +117,32 @@ class Invoker {
* Invoke handler without checking the thread identity or number of handlers
* on the thread stack.
*/
@SuppressWarnings("unchecked")
static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler,
AbstractFuture<V,A> result)
A attachment,
V value,
Throwable exc)
{
if (handler != null && !result.isCancelled()) {
Throwable exc = result.exception();
if (exc == null) {
handler.completed(result.value(), result.attachment());
handler.completed(value, attachment);
} else {
handler.failed(exc, result.attachment());
handler.failed(exc, attachment);
}
// clear interrupt
Thread.interrupted();
}
}
/**
* Invoke handler after incrementing the invoke count.
* Invoke handler assuming thread identity already checked
*/
static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
CompletionHandler<V,? super A> handler,
AbstractFuture<V,A> result)
A attachment,
V result,
Throwable exc)
{
myGroupAndInvokeCount.incrementInvokeCount();
invokeUnchecked(handler, result);
Invoker.invokeUnchecked(handler, attachment, result, exc);
}
/**
......@@ -151,15 +150,16 @@ class Invoker {
* thread pool then the handler is invoked directly, otherwise it is
* invoked indirectly.
*/
static <V,A> void invoke(CompletionHandler<V,? super A> handler,
AbstractFuture<V,A> result)
static <V,A> void invoke(AsynchronousChannel channel,
CompletionHandler<V,? super A> handler,
A attachment,
V result,
Throwable exc)
{
if (handler != null) {
boolean invokeDirect = false;
boolean identityOkay = false;
GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
if (thisGroupAndInvokeCount != null) {
AsynchronousChannel channel = result.channel();
if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
identityOkay = true;
if (identityOkay &&
......@@ -170,32 +170,32 @@ class Invoker {
}
}
if (invokeDirect) {
thisGroupAndInvokeCount.incrementInvokeCount();
invokeUnchecked(handler, result);
invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc);
} else {
try {
invokeIndirectly(handler, result);
invokeIndirectly(channel, handler, attachment, result, exc);
} catch (RejectedExecutionException ree) {
// channel group shutdown; fallback to invoking directly
// if the current thread has the right identity.
if (identityOkay) {
invokeUnchecked(handler, result);
invokeDirect(thisGroupAndInvokeCount,
handler, attachment, result, exc);
} else {
throw new ShutdownChannelGroupException();
}
}
}
}
}
/**
* Invokes the handler "indirectly" in the channel group's thread pool.
* Invokes the handler indirectly via the channel group's thread pool.
*/
static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
final AbstractFuture<V,A> result)
static <V,A> void invokeIndirectly(AsynchronousChannel channel,
final CompletionHandler<V,? super A> handler,
final A attachment,
final V result,
final Throwable exc)
{
if (handler != null) {
AsynchronousChannel channel = result.channel();
try {
((Groupable)channel).group().executeOnPooledThread(new Runnable() {
public void run() {
......@@ -203,34 +203,33 @@ class Invoker {
myGroupAndInvokeCount.get();
if (thisGroupAndInvokeCount != null)
thisGroupAndInvokeCount.setInvokeCount(1);
invokeUnchecked(handler, result);
invokeUnchecked(handler, attachment, result, exc);
}
});
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
}
}
/**
* Invokes the handler "indirectly" in the given Executor
*/
static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
final AbstractFuture<V,A> result,
final A attachment,
final V value,
final Throwable exc,
Executor executor)
{
if (handler != null) {
try {
executor.execute(new Runnable() {
public void run() {
invokeUnchecked(handler, result);
invokeUnchecked(handler, attachment, value, exc);
}
});
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
}
}
/**
* Invokes the given task on the thread pool associated with the given
......@@ -258,4 +257,52 @@ class Invoker {
throw new ShutdownChannelGroupException();
}
}
/**
* Invoke handler with completed result. This method does not check the
* thread identity or the number of handlers on the thread stack.
*/
static <V,A> void invokeUnchecked(PendingFuture<V,A> future) {
assert future.isDone();
CompletionHandler<V,? super A> handler = future.handler();
if (handler != null) {
invokeUnchecked(handler,
future.attachment(),
future.value(),
future.exception());
}
}
/**
* Invoke handler with completed result. If the current thread is in the
* channel group's thread pool then the handler is invoked directly,
* otherwise it is invoked indirectly.
*/
static <V,A> void invoke(PendingFuture<V,A> future) {
assert future.isDone();
CompletionHandler<V,? super A> handler = future.handler();
if (handler != null) {
invoke(future.channel(),
handler,
future.attachment(),
future.value(),
future.exception());
}
}
/**
* Invoke handler with completed result. The handler is invoked indirectly,
* via the channel group's thread pool.
*/
static <V,A> void invokeIndirectly(PendingFuture<V,A> future) {
assert future.isDone();
CompletionHandler<V,? super A> handler = future.handler();
if (handler != null) {
invokeIndirectly(future.channel(),
handler,
future.attachment(),
future.value(),
future.exception());
}
}
}
......@@ -34,13 +34,13 @@ import java.io.IOException;
* attachment of an additional arbitrary context object and a timer task.
*/
final class PendingFuture<V,A>
extends AbstractFuture<V,A>
{
final class PendingFuture<V,A> implements Future<V> {
private static final CancellationException CANCELLED =
new CancellationException();
private final AsynchronousChannel channel;
private final CompletionHandler<V,? super A> handler;
private final A attachment;
// true if result (or exception) is available
private volatile boolean haveResult;
......@@ -56,14 +56,14 @@ final class PendingFuture<V,A>
// optional context object
private volatile Object context;
PendingFuture(AsynchronousChannel channel,
CompletionHandler<V,? super A> handler,
A attachment,
Object context)
{
super(channel, attachment);
this.channel = channel;
this.handler = handler;
this.attachment = attachment;
this.context = context;
}
......@@ -71,14 +71,31 @@ final class PendingFuture<V,A>
CompletionHandler<V,? super A> handler,
A attachment)
{
super(channel, attachment);
this.channel = channel;
this.handler = handler;
this.attachment = attachment;
}
PendingFuture(AsynchronousChannel channel) {
this(channel, null, null);
}
PendingFuture(AsynchronousChannel channel, Object context) {
this(channel, null, null, context);
}
AsynchronousChannel channel() {
return channel;
}
CompletionHandler<V,? super A> handler() {
return handler;
}
A attachment() {
return attachment;
}
void setContext(Object context) {
this.context = context;
}
......@@ -113,36 +130,45 @@ final class PendingFuture<V,A>
/**
* Sets the result, or a no-op if the result or exception is already set.
*/
boolean setResult(V res) {
void setResult(V res) {
synchronized (this) {
if (haveResult)
return false;
return;
result = res;
haveResult = true;
if (timeoutTask != null)
timeoutTask.cancel(false);
if (latch != null)
latch.countDown();
return true;
}
}
/**
* Sets the result, or a no-op if the result or exception is already set.
*/
boolean setFailure(Throwable x) {
void setFailure(Throwable x) {
if (!(x instanceof IOException) && !(x instanceof SecurityException))
x = new IOException(x);
synchronized (this) {
if (haveResult)
return false;
return;
exc = x;
haveResult = true;
if (timeoutTask != null)
timeoutTask.cancel(false);
if (latch != null)
latch.countDown();
return true;
}
}
/**
* Sets the result
*/
void setResult(V res, Throwable x) {
if (x == null) {
setResult(res);
} else {
setFailure(x);
}
}
......@@ -178,12 +204,10 @@ final class PendingFuture<V,A>
return result;
}
@Override
Throwable exception() {
return (exc != CANCELLED) ? exc : null;
}
@Override
V value() {
return result;
}
......@@ -204,33 +228,6 @@ final class PendingFuture<V,A>
if (haveResult)
return false; // already completed
// A shutdown of the channel group will close all channels and
// shutdown the executor. To ensure that the completion handler
// is executed we queue the task while holding the lock.
if (handler != null) {
prepareForWait();
Runnable cancelTask = new Runnable() {
public void run() {
while (!haveResult) {
try {
latch.await();
} catch (InterruptedException ignore) { }
}
handler.cancelled(attachment());
}
};
AsynchronousChannel ch = channel();
if (ch instanceof Groupable) {
((Groupable)ch).group().executeOnPooledThread(cancelTask);
} else {
if (ch instanceof AsynchronousFileChannelImpl) {
((AsynchronousFileChannelImpl)ch).executor().execute(cancelTask);
} else {
throw new AssertionError("Should not get here");
}
}
}
// notify channel
if (channel() instanceof Cancellable)
((Cancellable)channel()).onCancel(this);
......@@ -249,7 +246,7 @@ final class PendingFuture<V,A>
} catch (IOException ignore) { }
}
// release waiters (this also releases the invoker)
// release waiters
if (latch != null)
latch.countDown();
return true;
......
......@@ -317,51 +317,71 @@ class SimpleAsynchronousDatagramChannelImpl
return new WrappedMembershipKey(this, key);
}
@Override
public <A> Future<Integer> send(ByteBuffer src,
private <A> Future<Integer> implSend(ByteBuffer src,
SocketAddress target,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
CompletedFuture<Integer,A> result;
int n = 0;
Throwable exc = null;
try {
int n = dc.send(src, target);
result = CompletedFuture.withResult(this, n, attachment);
n = dc.send(src, target);
} catch (IOException ioe) {
result = CompletedFuture.withFailure(this, ioe, attachment);
exc = ioe;
}
Invoker.invoke(handler, result);
return result;
if (handler == null)
return CompletedFuture.withResult(n, exc);
Invoker.invoke(this, handler, attachment, n, exc);
return null;
}
@Override
public <A> Future<Integer> write(ByteBuffer src,
long timeout,
TimeUnit unit,
public Future<Integer> send(ByteBuffer src, SocketAddress target) {
return implSend(src, target, null, null);
}
@Override
public <A> void send(ByteBuffer src,
SocketAddress target,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (timeout < 0L)
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
if (handler == null)
throw new NullPointerException("'handler' is null");
implSend(src, target, attachment, handler);
}
CompletedFuture<Integer,A> result;
private <A> Future<Integer> implWrite(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
int n = 0;
Throwable exc = null;
try {
int n = dc.write(src);
result = CompletedFuture.withResult(this, n, attachment);
n = dc.write(src);
} catch (IOException ioe) {
result = CompletedFuture.withFailure(this, ioe, attachment);
exc = ioe;
}
Invoker.invoke(handler, result);
return result;
if (handler == null)
return CompletedFuture.withResult(n, exc);
Invoker.invoke(this, handler, attachment, n, exc);
return null;
}
@Override
public Future<Integer> write(ByteBuffer src) {
return implWrite(src, null, null);
}
@Override
public <A> void write(ByteBuffer src,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implWrite(src, attachment, handler);
}
/**
......@@ -390,8 +410,7 @@ class SimpleAsynchronousDatagramChannelImpl
}
}
@Override
public <A> Future<SocketAddress> receive(final ByteBuffer dst,
private <A> Future<SocketAddress> implReceive(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
......@@ -406,10 +425,11 @@ class SimpleAsynchronousDatagramChannelImpl
// complete immediately if channel closed
if (!isOpen()) {
CompletedFuture<SocketAddress,A> result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invoke(this, handler, attachment, null, exc);
return null;
}
final AccessControlContext acc = (System.getSecurityManager() == null) ?
......@@ -471,7 +491,7 @@ class SimpleAsynchronousDatagramChannelImpl
x = new AsynchronousCloseException();
result.setFailure(x);
}
Invoker.invokeUnchecked(handler, result);
Invoker.invokeUnchecked(result);
}
};
try {
......@@ -483,7 +503,23 @@ class SimpleAsynchronousDatagramChannelImpl
}
@Override
public <A> Future<Integer> read(final ByteBuffer dst,
public Future<SocketAddress> receive(ByteBuffer dst) {
return implReceive(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public <A> void receive(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<SocketAddress,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implReceive(dst, timeout, unit, attachment, handler);
}
private <A> Future<Integer> implRead(final ByteBuffer dst,
final long timeout,
final TimeUnit unit,
A attachment,
......@@ -495,18 +531,20 @@ class SimpleAsynchronousDatagramChannelImpl
throw new IllegalArgumentException("Negative timeout");
if (unit == null)
throw new NullPointerException();
// another thread may disconnect before read is initiated
if (!dc.isConnected())
throw new NotYetConnectedException();
// complete immediately if channel closed
if (!isOpen()) {
CompletedFuture<Integer,A> result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
Invoker.invoke(handler, result);
return result;
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invoke(this, handler, attachment, null, exc);
return null;
}
// another thread may disconnect before read is initiated
if (!dc.isConnected())
throw new NotYetConnectedException();
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
Runnable task = new Runnable() {
......@@ -563,7 +601,7 @@ class SimpleAsynchronousDatagramChannelImpl
x = new AsynchronousCloseException();
result.setFailure(x);
}
Invoker.invokeUnchecked(handler, result);
Invoker.invokeUnchecked(result);
}
};
try {
......@@ -574,6 +612,23 @@ class SimpleAsynchronousDatagramChannelImpl
return result;
}
@Override
public Future<Integer> read(ByteBuffer dst) {
return implRead(dst, 0L, TimeUnit.MILLISECONDS, null, null);
}
@Override
public <A> void read(ByteBuffer dst,
long timeout,
TimeUnit unit,
A attachment,
CompletionHandler<Integer,? super A> handler)
{
if (handler == null)
throw new NullPointerException("'handler' is null");
implRead(dst, timeout, unit, attachment, handler);
}
@Override
public AsynchronousDatagramChannel bind(SocketAddress local)
throws IOException
......
......@@ -50,9 +50,6 @@ public class SimpleAsynchronousFileChannelImpl
// Used to make native read and write calls
private static final FileDispatcher nd = new FileDispatcherImpl();
// indicates if the associated thread pool is the default thread pool
private final boolean isDefaultExecutor;
// Thread-safe set of IDs of native threads, for signalling
private final NativeThreadSet threads = new NativeThreadSet(2);
......@@ -60,11 +57,9 @@ public class SimpleAsynchronousFileChannelImpl
SimpleAsynchronousFileChannelImpl(FileDescriptor fdObj,
boolean reading,
boolean writing,
ExecutorService executor,
boolean isDefaultexecutor)
ExecutorService executor)
{
super(fdObj, reading, writing, executor);
this.isDefaultExecutor = isDefaultexecutor;
}
public static AsynchronousFileChannel open(FileDescriptor fdo,
......@@ -73,17 +68,9 @@ public class SimpleAsynchronousFileChannelImpl
ThreadPool pool)
{
// Executor is either default or based on pool parameters
ExecutorService executor;
boolean isDefaultexecutor;
if (pool == null) {
executor = DefaultExecutorHolder.defaultExecutor;
isDefaultexecutor = true;
} else {
executor = pool.executor();
isDefaultexecutor = false;
}
return new SimpleAsynchronousFileChannelImpl(fdo,
reading, writing, executor, isDefaultexecutor);
ExecutorService executor = (pool == null) ?
DefaultExecutorHolder.defaultExecutor : pool.executor();
return new SimpleAsynchronousFileChannelImpl(fdo, reading, writing, executor);
}
@Override
......@@ -114,16 +101,6 @@ public class SimpleAsynchronousFileChannelImpl
// close file
nd.close(fdObj);
// shutdown executor if specific to this channel
if (!isDefaultExecutor) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
executor.shutdown();
return null;
}
});
}
}
@Override
......@@ -194,10 +171,10 @@ public class SimpleAsynchronousFileChannelImpl
}
@Override
public <A> Future<FileLock> lock(final long position,
<A> Future<FileLock> implLock(final long position,
final long size,
final boolean shared,
A attachment,
final A attachment,
final CompletionHandler<FileLock,? super A> handler)
{
if (shared && !reading)
......@@ -208,16 +185,19 @@ public class SimpleAsynchronousFileChannelImpl
// add to lock table
final FileLockImpl fli = addToFileLockTable(position, size, shared);
if (fli == null) {
CompletedFuture<FileLock,A> result = CompletedFuture
.withFailure(this, new ClosedChannelException(), attachment);
Invoker.invokeIndirectly(handler, result, executor);
return result;
Throwable exc = new ClosedChannelException();
if (handler == null)
return CompletedFuture.withFailure(exc);
Invoker.invokeIndirectly(handler, attachment, null, exc, executor);
return null;
}
final PendingFuture<FileLock,A> result =
new PendingFuture<FileLock,A>(this, handler, attachment);
final PendingFuture<FileLock,A> result = (handler == null) ?
new PendingFuture<FileLock,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
Throwable exc = null;
int ti = threads.add();
try {
int n;
......@@ -226,31 +206,36 @@ public class SimpleAsynchronousFileChannelImpl
do {
n = nd.lock(fdObj, true, position, size, shared);
} while ((n == FileDispatcher.INTERRUPTED) && isOpen());
if (n == FileDispatcher.LOCKED && isOpen()) {
result.setResult(fli);
} else {
if (n != FileDispatcher.LOCKED || !isOpen()) {
throw new AsynchronousCloseException();
}
} catch (IOException x) {
removeFromFileLockTable(fli);
if (!isOpen())
x = new AsynchronousCloseException();
result.setFailure(x);
exc = x;
} finally {
end();
}
} finally {
threads.remove(ti);
}
Invoker.invokeUnchecked(handler, result);
if (handler == null) {
result.setResult(fli, exc);
} else {
Invoker.invokeUnchecked(handler, attachment, fli, exc);
}
}
};
boolean executed = false;
try {
executor.execute(task);
} catch (RejectedExecutionException ree) {
executed = true;
} finally {
if (!executed) {
// rollback
removeFromFileLockTable(fli);
throw new ShutdownChannelGroupException();
}
}
return result;
}
......@@ -301,9 +286,9 @@ public class SimpleAsynchronousFileChannelImpl
}
@Override
public <A> Future<Integer> read(final ByteBuffer dst,
<A> Future<Integer> implRead(final ByteBuffer dst,
final long position,
A attachment,
final A attachment,
final CompletionHandler<Integer,? super A> handler)
{
if (position < 0)
......@@ -315,54 +300,51 @@ public class SimpleAsynchronousFileChannelImpl
// complete immediately if channel closed or no space remaining
if (!isOpen() || (dst.remaining() == 0)) {
CompletedFuture<Integer,A> result;
if (isOpen()) {
result = CompletedFuture.withResult(this, 0, attachment);
} else {
result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
}
Invoker.invokeIndirectly(handler, result, executor);
return result;
Throwable exc = (isOpen()) ? null : new ClosedChannelException();
if (handler == null)
return CompletedFuture.withResult(0, exc);
Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
return null;
}
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
final PendingFuture<Integer,A> result = (handler == null) ?
new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
int n = 0;
Throwable exc = null;
int ti = threads.add();
try {
begin();
int n;
do {
n = IOUtil.read(fdObj, dst, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen())
throw new AsynchronousCloseException();
result.setResult(n);
} catch (IOException x) {
if (!isOpen())
x = new AsynchronousCloseException();
result.setFailure(x);
exc = x;
} finally {
end();
threads.remove(ti);
}
Invoker.invokeUnchecked(handler, result);
if (handler == null) {
result.setResult(n, exc);
} else {
Invoker.invokeUnchecked(handler, attachment, n, exc);
}
}
};
try {
executor.execute(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
return result;
}
@Override
public <A> Future<Integer> write(final ByteBuffer src,
<A> Future<Integer> implWrite(final ByteBuffer src,
final long position,
A attachment,
final A attachment,
final CompletionHandler<Integer,? super A> handler)
{
if (position < 0)
......@@ -372,47 +354,44 @@ public class SimpleAsynchronousFileChannelImpl
// complete immediately if channel is closed or no bytes remaining
if (!isOpen() || (src.remaining() == 0)) {
CompletedFuture<Integer,A> result;
if (isOpen()) {
result = CompletedFuture.withResult(this, 0, attachment);
} else {
result = CompletedFuture.withFailure(this,
new ClosedChannelException(), attachment);
}
Invoker.invokeIndirectly(handler, result, executor);
return result;
Throwable exc = (isOpen()) ? null : new ClosedChannelException();
if (handler == null)
return CompletedFuture.withResult(0, exc);
Invoker.invokeIndirectly(handler, attachment, 0, exc, executor);
return null;
}
final PendingFuture<Integer,A> result =
new PendingFuture<Integer,A>(this, handler, attachment);
final PendingFuture<Integer,A> result = (handler == null) ?
new PendingFuture<Integer,A>(this) : null;
Runnable task = new Runnable() {
public void run() {
int n = 0;
Throwable exc = null;
int ti = threads.add();
try {
begin();
int n;
do {
n = IOUtil.write(fdObj, src, position, nd, null);
} while ((n == IOStatus.INTERRUPTED) && isOpen());
if (n < 0 && !isOpen())
throw new AsynchronousCloseException();
result.setResult(n);
} catch (IOException x) {
if (!isOpen())
x = new AsynchronousCloseException();
result.setFailure(x);
exc = x;
} finally {
end();
threads.remove(ti);
}
Invoker.invokeUnchecked(handler, result);
if (handler == null) {
result.setResult(n, exc);
} else {
Invoker.invokeUnchecked(handler, attachment, n, exc);
}
}
};
try {
executor.execute(task);
} catch (RejectedExecutionException ree) {
throw new ShutdownChannelGroupException();
}
return result;
}
}
......@@ -41,6 +41,7 @@ import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.util.Comparator;
import java.util.StringTokenizer;
/**
......@@ -229,10 +230,11 @@ public class KeyTab implements KeyTabConstants {
/**
* Reads the service key from the keytab file.
* @param service the PrincipalName of the requested service.
* @return the last service key in the keytab
* @return the last service key in the keytab with the highest kvno
*/
public EncryptionKey readServiceKey(PrincipalName service) {
KeyTabEntry entry = null;
EncryptionKey key = null;
if (entries != null) {
// Find latest entry for this service that has an etype
// that has been configured for use
......@@ -240,9 +242,12 @@ public class KeyTab implements KeyTabConstants {
entry = entries.elementAt(i);
if (entry.service.match(service)) {
if (EType.isSupported(entry.keyType)) {
return new EncryptionKey(entry.keyblock,
if (key == null ||
entry.keyVersion > key.getKeyVersionNumber()) {
key = new EncryptionKey(entry.keyblock,
entry.keyType,
new Integer(entry.keyVersion));
}
} else if (DEBUG) {
System.out.println("Found unsupported keytype (" +
entry.keyType + ") for " + service);
......@@ -250,12 +255,13 @@ public class KeyTab implements KeyTabConstants {
}
}
}
return null;
return key;
}
/**
* Reads all keys for a service from the keytab file that have
* etypes that have been configured for use.
* etypes that have been configured for use. If there are multiple
* keys with same etype, the one with the highest kvno is returned.
* @param service the PrincipalName of the requested service
* @return an array containing all the service keys
*/
......@@ -288,49 +294,39 @@ public class KeyTab implements KeyTabConstants {
size = keys.size();
if (size == 0)
return null;
EncryptionKey[] retVal = new EncryptionKey[size];
EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
// Sort keys according to default_tkt_enctypes
int pos = 0;
EncryptionKey k;
if (DEBUG) {
System.out.println("Ordering keys wrt default_tkt_enctypes list");
}
int[] etypes = EType.getDefaults("default_tkt_enctypes");
if (etypes == null || etypes == EType.getBuiltInDefaults()) {
// Either no supported types specified in default_tkt_enctypes
// or no default_tkt_enctypes entry at all. For both cases,
// just return supported keys in the order retrieved
for (int i = 0; i < size; i++) {
retVal[pos++] = keys.get(i);
}
} else {
for (int j = 0; j < etypes.length && pos < size; j++) {
int target = etypes[j];
for (int i = 0; i < size && pos < size; i++) {
k = keys.get(i);
if (k != null && k.getEType() == target) {
if (DEBUG) {
System.out.println(pos + ": " + k);
}
retVal[pos++] = k;
keys.set(i, null); // Cleared from consideration
}
}
final int[] etypes = EType.getDefaults("default_tkt_enctypes");
// Sort the keys, k1 is preferred than k2 if:
// 1. k1's etype appears earlier in etypes than k2's
// 2. If same, k1's KVNO is higher
Arrays.sort(retVal, new Comparator<EncryptionKey>() {
@Override
public int compare(EncryptionKey o1, EncryptionKey o2) {
if (etypes != null && etypes != EType.getBuiltInDefaults()) {
int o1EType = o1.getEType();
int o2EType = o2.getEType();
if (o1EType != o2EType) {
for (int i=0; i<etypes.length; i++) {
if (etypes[i] == o1EType) {
return -1;
} else if (etypes[i] == o2EType) {
return 1;
}
// copy the rest
for (int i = 0; i < size && pos < size; i++) {
k = keys.get(i);
if (k != null) {
retVal[pos++] = k;
}
}
}
if (pos != size) {
throw new RuntimeException(
"Internal Error: did not copy all keys;expecting " + size +
"; got " + pos);
return o2.getKeyVersionNumber().intValue()
- o1.getKeyVersionNumber().intValue();
}
});
return retVal;
}
......
1. Compression algorithm (deflate)
The deflation algorithm used by gzip (also zip and zlib) is a variation of
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
the input data. The second occurrence of a string is replaced by a
pointer to the previous string, in the form of a pair (distance,
length). Distances are limited to 32K bytes, and lengths are limited
to 258 bytes. When a string does not occur anywhere in the previous
32K bytes, it is emitted as a sequence of literal bytes. (In this
description, `string' must be taken as an arbitrary sequence of bytes,
and is not restricted to printable characters.)
Literals or match lengths are compressed with one Huffman tree, and
match distances are compressed with another tree. The trees are stored
in a compact form at the start of each block. The blocks can have any
size (except that the compressed data for one block must fit in
available memory). A block is terminated when deflate() determines that
it would be useful to start another block with fresh trees. (This is
somewhat similar to the behavior of LZW-based _compress_.)
Duplicated strings are found using a hash table. All input strings of
length 3 are inserted in the hash table. A hash index is computed for
the next 3 bytes. If the hash chain for this index is not empty, all
strings in the chain are compared with the current input string, and
the longest match is selected.
The hash chains are searched starting with the most recent strings, to
favor small distances and thus take advantage of the Huffman encoding.
The hash chains are singly linked. There are no deletions from the
hash chains, the algorithm simply discards matches that are too old.
To avoid a worst-case situation, very long hash chains are arbitrarily
truncated at a certain length, determined by a runtime option (level
parameter of deflateInit). So deflate() does not always find the longest
possible match but generally finds a match which is long enough.
deflate() also defers the selection of matches with a lazy evaluation
mechanism. After a match of length N has been found, deflate() searches for
a longer match at the next input byte. If a longer match is found, the
previous match is truncated to a length of one (thus producing a single
literal byte) and the process of lazy evaluation begins again. Otherwise,
the original match is kept, and the next match search is attempted only N
steps later.
The lazy match evaluation is also subject to a runtime parameter. If
the current match is long enough, deflate() reduces the search for a longer
match, thus speeding up the whole process. If compression ratio is more
important than speed, deflate() attempts a complete second search even if
the first match is already long enough.
The lazy match evaluation is not performed for the fastest compression
modes (level parameter 1 to 3). For these fast modes, new strings
are inserted in the hash table only when no match was found, or
when the match is not too long. This degrades the compression ratio
but saves time since there are both fewer insertions and fewer searches.
2. Decompression algorithm (inflate)
2.1 Introduction
The real question is, given a Huffman tree, how to decode fast. The most
important realization is that shorter codes are much more common than
longer codes, so pay attention to decoding the short codes fast, and let
the long codes take longer to decode.
inflate() sets up a first level table that covers some number of bits of
input less than the length of longest code. It gets that many bits from the
stream, and looks it up in the table. The table will tell if the next
code is that many bits or less and how many, and if it is, it will tell
the value, else it will point to the next level table for which inflate()
grabs more bits and tries to decode a longer code.
How many bits to make the first lookup is a tradeoff between the time it
takes to decode and the time it takes to build the table. If building the
table took no time (and if you had infinite memory), then there would only
be a first level table to cover all the way to the longest code. However,
building the table ends up taking a lot longer for more bits since short
codes are replicated many times in such a table. What inflate() does is
simply to make the number of bits in the first table a variable, and set it
for the maximum speed.
inflate() sends new trees relatively often, so it is possibly set for a
smaller first level table than an application that has only one tree for
all the data. For inflate, which has 286 possible codes for the
literal/length tree, the size of the first table is nine bits. Also the
distance trees have 30 possible values, and the size of the first table is
six bits. Note that for each of those cases, the table ended up one bit
longer than the ``average'' code length, i.e. the code length of an
approximately flat code which would be a little more than eight bits for
286 symbols and a little less than five bits for 30 symbols. It would be
interesting to see if optimizing the first level table for other
applications gave values within a bit or two of the flat code size.
2.2 More details on the inflate table lookup
Ok, you want to know what this cleverly obfuscated inflate tree actually
looks like. You are correct that it's not a Huffman tree. It is simply a
lookup table for the first, let's say, nine bits of a Huffman symbol. The
symbol could be as short as one bit or as long as 15 bits. If a particular
symbol is shorter than nine bits, then that symbol's translation is duplicated
in all those entries that start with that symbol's bits. For example, if the
symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
symbol is nine bits long, it appears in the table once.
If the symbol is longer than nine bits, then that entry in the table points
to another similar table for the remaining bits. Again, there are duplicated
entries as needed. The idea is that most of the time the symbol will be short
and there will only be one table look up. (That's whole idea behind data
compression in the first place.) For the less frequent long symbols, there
will be two lookups. If you had a compression method with really long
symbols, you could have as many levels of lookups as is efficient. For
inflate, two is enough.
So a table entry either points to another table (in which case nine bits in
the above example are gobbled), or it contains the translation for the symbol
and the number of bits to gobble. Then you start again with the next
ungobbled bit.
You may wonder: why not just have one lookup table for how ever many bits the
longest symbol is? The reason is that if you do that, you end up spending
more time filling in duplicate symbol entries than you do actually decoding.
At least for deflate's output that generates new trees every several 10's of
kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
would take too long if you're only decoding several thousand symbols. At the
other extreme, you could make a new table for every bit in the code. In fact,
that's essentially a Huffman tree. But then you spend two much time
traversing the tree while decoding, even for short symbols.
So the number of bits for the first lookup table is a trade of the time to
fill out the table vs. the time spent looking at the second level and above of
the table.
Here is an example, scaled down:
The code being decoded, with 10 symbols, from 1 to 6 bits long:
A: 0
B: 10
C: 1100
D: 11010
E: 11011
F: 11100
G: 11101
H: 11110
I: 111110
J: 111111
Let's make the first table three bits long (eight entries):
000: A,1
001: A,1
010: A,1
011: A,1
100: B,2
101: B,2
110: -> table X (gobble 3 bits)
111: -> table Y (gobble 3 bits)
Each entry is what the bits decode to and how many bits that is, i.e. how
many bits to gobble. Or the entry points to another table, with the number of
bits to gobble implicit in the size of the table.
Table X is two bits long since the longest code starting with 110 is five bits
long:
00: C,1
01: C,1
10: D,2
11: E,2
Table Y is three bits long since the longest code starting with 111 is six
bits long:
000: F,2
001: F,2
010: G,2
011: G,2
100: H,2
101: H,2
110: I,3
111: J,3
So what we have here are three tables with a total of 20 entries that had to
be constructed. That's compared to 64 entries for a single table. Or
compared to 16 entries for a Huffman tree (six two entry tables and one four
entry table). Assuming that the code ideally represents the probability of
the symbols, it takes on the average 1.25 lookups per symbol. That's compared
to one lookup for the single table, or 1.66 lookups per symbol for the
Huffman tree.
There, I think that gives you a picture of what's going on. For inflate, the
meaning of a particular symbol is often more than just a letter. It can be a
byte (a "literal"), or it can be either a length or a distance which
indicates a base value and a number of bits to fetch after the code that is
added to the base value. Or it might be the special end-of-block code. The
data structures created in inftrees.c try to encode all that information
compactly in the tables.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
References:
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
pp. 337-343.
``DEFLATE Compressed Data Format Specification'' available in
ftp://ds.internic.net/rfc/rfc1951.txt
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
* infcodes.c -- process literals and length/distance pairs
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
START, /* x: set up for LEN */
LEN, /* i: get length/literal/eob next */
LENEXT, /* i: getting length extra (have base) */
DIST, /* i: get distance next */
DISTEXT, /* i: getting distance extra */
COPY, /* o: copying bytes in window, waiting for space */
LIT, /* o: got literal, waiting for output space */
WASH, /* o: got eob, possibly still output waiting */
END, /* x: got eob and all data flushed */
BADCODE} /* x: got error */
inflate_codes_mode;
/* inflate codes private state */
struct inflate_codes_state {
/* mode */
inflate_codes_mode mode; /* current inflate_codes mode */
/* mode dependent information */
uInt len;
union {
struct {
inflate_huft *tree; /* pointer into tree */
uInt need; /* bits needed */
} code; /* if LEN or DIST, where in tree */
uInt lit; /* if LIT, literal */
struct {
uInt get; /* bits to get for extra */
uInt dist; /* distance back to copy from */
} copy; /* if EXT or COPY, where and how much */
} sub; /* submode */
/* mode independent information */
Byte lbits; /* ltree bits decoded per branch */
Byte dbits; /* dtree bits decoder per branch */
inflate_huft *ltree; /* literal/length/eob tree */
inflate_huft *dtree; /* distance tree */
};
inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
uInt bl, bd;
inflate_huft *tl;
inflate_huft *td; /* need separate declaration for Borland C++ */
z_streamp z;
{
inflate_codes_statef *c;
if ((c = (inflate_codes_statef *)
ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
{
c->mode = START;
c->lbits = (Byte)bl;
c->dbits = (Byte)bd;
c->ltree = tl;
c->dtree = td;
Tracev((stderr, "inflate: codes new\n"));
}
return c;
}
int inflate_codes(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
uInt j; /* temporary storage */
inflate_huft *t; /* temporary pointer */
uInt e; /* extra bits or operation */
uLong b; /* bit buffer */
uInt k; /* bits in bit buffer */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
Bytef *f; /* pointer to copy strings from */
inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
/* copy input/output information to locals (UPDATE macro restores) */
LOAD
/* process input and output based on current state */
while (1) switch (c->mode)
{ /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
case START: /* x: set up for LEN */
#ifndef SLOW
if (m >= 258 && n >= 10)
{
UPDATE
r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
LOAD
if (r != Z_OK)
{
c->mode = r == Z_STREAM_END ? WASH : BADCODE;
break;
}
}
#endif /* !SLOW */
c->sub.code.need = c->lbits;
c->sub.code.tree = c->ltree;
c->mode = LEN;
case LEN: /* i: get length/literal/eob next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e == 0) /* literal */
{
c->sub.lit = t->base;
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", t->base));
c->mode = LIT;
break;
}
if (e & 16) /* length */
{
c->sub.copy.get = e & 15;
c->len = t->base;
c->mode = LENEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
if (e & 32) /* end of block */
{
Tracevv((stderr, "inflate: end of block\n"));
c->mode = WASH;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid literal/length code";
r = Z_DATA_ERROR;
LEAVE
case LENEXT: /* i: getting length extra (have base) */
j = c->sub.copy.get;
NEEDBITS(j)
c->len += (uInt)b & inflate_mask[j];
DUMPBITS(j)
c->sub.code.need = c->dbits;
c->sub.code.tree = c->dtree;
Tracevv((stderr, "inflate: length %u\n", c->len));
c->mode = DIST;
case DIST: /* i: get distance next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (uInt)(t->exop);
if (e & 16) /* distance */
{
c->sub.copy.get = e & 15;
c->sub.copy.dist = t->base;
c->mode = DISTEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t + t->base;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid distance code";
r = Z_DATA_ERROR;
LEAVE
case DISTEXT: /* i: getting distance extra */
j = c->sub.copy.get;
NEEDBITS(j)
c->sub.copy.dist += (uInt)b & inflate_mask[j];
DUMPBITS(j)
Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
c->mode = COPY;
case COPY: /* o: copying bytes in window, waiting for space */
#ifndef __TURBOC__ /* Turbo C bug for following expression */
f = (uInt)(q - s->window) < c->sub.copy.dist ?
s->end - (c->sub.copy.dist - (q - s->window)) :
q - c->sub.copy.dist;
#else
f = q - c->sub.copy.dist;
if ((uInt)(q - s->window) < c->sub.copy.dist)
f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
#endif
while (c->len)
{
NEEDOUT
OUTBYTE(*f++)
if (f == s->end)
f = s->window;
c->len--;
}
c->mode = START;
break;
case LIT: /* o: got literal, waiting for output space */
NEEDOUT
OUTBYTE(c->sub.lit)
c->mode = START;
break;
case WASH: /* o: got eob, possibly more output */
if (k > 7) /* return unused byte, if any */
{
Assert(k < 16, "inflate_codes grabbed too many bytes")
k -= 8;
n++;
p--; /* can always return one */
}
FLUSH
if (s->read != s->write)
LEAVE
c->mode = END;
case END:
r = Z_STREAM_END;
LEAVE
case BADCODE: /* x: got error */
r = Z_DATA_ERROR;
LEAVE
default:
r = Z_STREAM_ERROR;
LEAVE
}
#ifdef NEED_DUMMY_RETURN
return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
#endif
}
void inflate_codes_free(c, z)
inflate_codes_statef *c;
z_streamp z;
{
ZFREE(z, c);
Tracev((stderr, "inflate: codes free\n"));
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
(1)renamed
adler32.c -> zadler32.c
zcrc32c -> zcrc32.c
(2)added _LP64 to make uLong a 32-bit int on 64-bit platform
zconf.h:
uLong -> 32-bit int
(3)updated crc32.c/crc32()
unsigned long -> uLong
(4)updated zlib.h (to support > 4G zipfile):
total_in/out: uLong -> long long
(5)updated upinflate.c/inflateSync()
unsigned long in, out; --> long long in, out;
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册