This commit is contained in:
Phil Race 2018-03-23 11:14:43 -07:00
commit 77e24ab76e
110 changed files with 2141 additions and 5884 deletions

View File

@ -476,3 +476,4 @@ dfa46cfe56346884a61efdc30dc50f7505d66761 jdk-11+1
1fd4d6068f54561cfc67d54fc9ca84af7212c4f8 jdk-11+3
e59941f7247d451fa7df9eaef3fce0f492f8420c jdk-11+4
d5c43e9f08fb9a7c74aae0d48daf17f2ad2afaef jdk-11+5
3acb379b86725c47e7f33358cb22efa8752ae532 jdk-11+6

View File

@ -40,7 +40,7 @@
$ make run-test-jdk_lang JTREG="JOBS=8"
$ make run-test TEST=jdk_lang
$ make run-test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make run-test TEST="jtreg:hotspot/test:hotspot_gc hotspot/test/native_sanity/JniVersion.java"
$ make exploded-run-test TEST=hotspot_tier1</code></pre>
<h3 id="configuration">Configuration</h3>
@ -77,8 +77,8 @@ TEST FAILURE</code></pre>
<h2 id="test-suite-control">Test suite control</h2>
<p>It is possible to control various aspects of the test suites using make control variables.</p>
<p>These variables use a keyword=value approach to allow multiple values to be set. So, for instance, <code>JTREG=&quot;JOBS=1;TIMEOUT=8&quot;</code> will set the JTReg concurrency level to 1 and the timeout factor to 8. This is equivalent to setting <code>JTREG_JOBS=1 JTREG_TIMEOUT=8</code>, but using the keyword format means that the <code>JTREG</code> variable is parsed and verified for correctness, so <code>JTREG=&quot;TMIEOUT=8&quot;</code> would give an error, while <code>JTREG_TMIEOUT=8</code> would just pass unnoticed.</p>
<p>To separate multiple keyword=value pairs, use <code>;</code> (semicolon). Since the shell normally eats <code>;</code>, the recommended usage is to write the assignment inside qoutes, e.g. <code>JTREG=&quot;...;...&quot;</code>. This will also make sure spaces are preserved, as in <code>JTREG=&quot;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug&quot;</code>.</p>
<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
<p>To separate multiple keyword=value pairs, use <code>;</code> (semicolon). Since the shell normally eats <code>;</code>, the recommended usage is to write the assignment inside qoutes, e.g. <code>JTREG=&quot;...;...&quot;</code>. This will also make sure spaces are preserved, as in <code>JTREG=&quot;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug&quot;</code>.</p>
<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
<p>As far as possible, the names of the keywords have been standardized between test suites.</p>
<h3 id="jtreg-keywords">JTReg keywords</h3>
<h4 id="jobs">JOBS</h4>

View File

@ -18,7 +18,7 @@ Some example command-lines:
$ make run-test-jdk_lang JTREG="JOBS=8"
$ make run-test TEST=jdk_lang
$ make run-test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
$ make run-test TEST="jtreg:hotspot/test:hotspot_gc hotspot/test/native_sanity/JniVersion.java"
$ make exploded-run-test TEST=hotspot_tier1
@ -140,11 +140,11 @@ pass unnoticed.
To separate multiple keyword=value pairs, use `;` (semicolon). Since the shell
normally eats `;`, the recommended usage is to write the assignment inside
qoutes, e.g. `JTREG="...;..."`. This will also make sure spaces are preserved,
as in `JTREG="VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"`.
as in `JTREG="VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"`.
(Other ways are possible, e.g. using backslash: `JTREG=JOBS=1\;TIMEOUT=8`.
Also, as a special technique, the string `%20` will be replaced with space for
certain options, e.g. `JTREG=VM_OTIONS=-XshowSettings%20-Xlog:gc+ref=debug`.
certain options, e.g. `JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug`.
This can be useful if you have layers of scripts and have trouble getting
proper quoting of command line arguments through.)

View File

@ -23,101 +23,50 @@
# questions.
#
LIBJSOUND_SRC_DIRS := \
LIBJSOUND_SRC_DIRS := $(wildcard \
$(TOPDIR)/src/java.desktop/share/native/libjsound \
$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjsound \
#
$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libjsound \
)
LIBJSOUND_CFLAGS := \
-I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
$(LIBJAVA_HEADER_FLAGS) \
$(foreach dir, $(LIBJSOUND_SRC_DIRS), -I$(dir)) \
-DUSE_PORTS=TRUE \
-DUSE_DAUDIO=TRUE \
#
LIBJSOUND_SRC_FILES := Utilities.c Platform.c
EXTRA_SOUND_JNI_LIBS :=
LIBJSOUND_MIDIFILES := \
MidiInDevice.c \
MidiInDeviceProvider.c \
MidiOutDevice.c \
MidiOutDeviceProvider.c \
PlatformMidi.c
# files needed for ports
LIBJSOUND_PORTFILES := \
PortMixerProvider.c \
PortMixer.c
# files needed for direct audio
LIBJSOUND_DAUDIOFILES := \
DirectAudioDeviceProvider.c \
DirectAudioDevice.c
ifeq ($(OPENJDK_TARGET_OS), windows)
EXTRA_SOUND_JNI_LIBS += jsoundds
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_WINDOWS \
ifneq ($(OPENJDK_TARGET_OS), solaris)
LIBJSOUND_CFLAGS += \
-DUSE_PLATFORM_MIDI_OUT=TRUE \
-DUSE_PLATFORM_MIDI_IN=TRUE \
-DUSE_PORTS=TRUE
LIBJSOUND_SRC_FILES += \
PLATFORM_API_WinOS_Charset_Util.cpp \
PLATFORM_API_WinOS_MidiIn.cpp \
PLATFORM_API_WinOS_MidiOut.c \
PLATFORM_API_WinOS_Util.c \
PLATFORM_API_WinOS_Ports.c
LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
endif # OPENJDK_TARGET_OS windows
#
endif
ifeq ($(OPENJDK_TARGET_OS), windows)
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_WINDOWS
endif
ifeq ($(OPENJDK_TARGET_OS), linux)
EXTRA_SOUND_JNI_LIBS += jsoundalsa
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_LINUX
endif # OPENJDK_TARGET_OS linux
endif
ifeq ($(OPENJDK_TARGET_OS), aix)
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_AIX
endif # OPENJDK_TARGET_OS aix
endif
ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBJSOUND_TOOLCHAIN := TOOLCHAIN_LINK_CXX
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_MACOSX \
-DUSE_PORTS=TRUE \
-DUSE_DAUDIO=TRUE \
-DUSE_PLATFORM_MIDI_OUT=TRUE \
-DUSE_PLATFORM_MIDI_IN=TRUE
LIBJSOUND_SRC_DIRS += $(TOPDIR)/src/java.desktop/macosx/native/libjsound
LIBJSOUND_SRC_FILES += \
PLATFORM_API_MacOSX_Utils.cpp \
PLATFORM_API_MacOSX_PCM.cpp \
PLATFORM_API_MacOSX_Ports.cpp \
PLATFORM_API_MacOSX_MidiIn.c \
PLATFORM_API_MacOSX_MidiOut.c \
PLATFORM_API_MacOSX_MidiUtils.c
LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_DAUDIOFILES)
endif # OPENJDK_TARGET_OS macosx
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_MACOSX
endif
ifeq ($(OPENJDK_TARGET_OS), solaris)
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_SOLARIS \
-DUSE_PORTS=TRUE \
-DUSE_DAUDIO=TRUE
LIBJSOUND_SRC_FILES += \
PLATFORM_API_SolarisOS_Utils.c \
PLATFORM_API_SolarisOS_Ports.c \
PLATFORM_API_SolarisOS_PCM.c
LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
LIBJSOUND_SRC_FILES += $(LIBJSOUND_DAUDIOFILES)
endif # OPENJDK_TARGET_OS solaris
LIBJSOUND_CFLAGS += -DEXTRA_SOUND_JNI_LIBS='"$(EXTRA_SOUND_JNI_LIBS)"'
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_SOLARIS
endif
$(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \
NAME := jsound, \
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := $(LIBJSOUND_SRC_FILES), \
TOOLCHAIN := $(LIBJSOUND_TOOLCHAIN), \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
@ -127,10 +76,11 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS_unix := -ljava -ljvm, \
LIBS_linux := $(ALSA_LIBS), \
LIBS_macosx := -framework CoreAudio -framework CoreFoundation \
-framework CoreServices -framework AudioUnit $(LIBCXX) \
-framework CoreMIDI -framework AudioToolbox, \
LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib winmm.lib, \
-framework CoreServices -framework AudioUnit \
-framework CoreMIDI -framework AudioToolbox $(LIBCXX), \
LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib dsound.lib winmm.lib user32.lib ole32.lib, \
))
$(BUILD_LIBJSOUND): $(call FindLib, java.base, java)
@ -138,61 +88,3 @@ $(BUILD_LIBJSOUND): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBJSOUND)
##########################################################################################
ifneq ($(filter jsoundalsa, $(EXTRA_SOUND_JNI_LIBS)), )
$(eval $(call SetupJdkLibrary, BUILD_LIBJSOUNDALSA, \
NAME := jsoundalsa, \
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := Utilities.c $(LIBJSOUND_MIDIFILES) $(LIBJSOUND_PORTFILES) \
$(LIBJSOUND_DAUDIOFILES) \
PLATFORM_API_LinuxOS_ALSA_CommonUtils.c \
PLATFORM_API_LinuxOS_ALSA_PCM.c \
PLATFORM_API_LinuxOS_ALSA_PCMUtils.c \
PLATFORM_API_LinuxOS_ALSA_MidiIn.c \
PLATFORM_API_LinuxOS_ALSA_MidiOut.c \
PLATFORM_API_LinuxOS_ALSA_MidiUtils.c \
PLATFORM_API_LinuxOS_ALSA_Ports.c, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(ALSA_CFLAGS) \
$(LIBJSOUND_CFLAGS) \
-DUSE_DAUDIO=TRUE \
-DUSE_PORTS=TRUE \
-DUSE_PLATFORM_MIDI_OUT=TRUE \
-DUSE_PLATFORM_MIDI_IN=TRUE, \
MAPFILE := $(TOPDIR)/make/mapfiles/libjsoundalsa/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(ALSA_LIBS) -ljava -ljvm, \
))
$(BUILD_LIBJSOUNDALSA): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBJSOUNDALSA)
endif
##########################################################################################
ifneq ($(filter jsoundds, $(EXTRA_SOUND_JNI_LIBS)), )
$(eval $(call SetupJdkLibrary, BUILD_LIBJSOUNDDS, \
NAME := jsoundds, \
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := Utilities.c $(LIBJSOUND_DAUDIOFILES) \
PLATFORM_API_WinOS_Charset_Util.cpp \
PLATFORM_API_WinOS_DirectSound.cpp, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJSOUND_CFLAGS) \
-DUSE_DAUDIO=TRUE, \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(JDKLIB_LIBS) dsound.lib winmm.lib user32.lib ole32.lib, \
))
$(BUILD_LIBJSOUNDDS): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBJSOUNDDS)
endif

View File

@ -65,8 +65,6 @@ SUNWprivate_1.1 {
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVendor;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVersion;
Java_com_sun_media_sound_Platform_nGetExtraLibraries;
Java_com_sun_media_sound_Platform_nGetLibraryForFeature;
Java_com_sun_media_sound_Platform_nIsBigEndian;
Java_com_sun_media_sound_PortMixer_nClose;
Java_com_sun_media_sound_PortMixer_nControlGetFloatValue;

View File

@ -1,82 +0,0 @@
#
# Copyright (c) 2005, 2013, Oracle and/or its affiliates. 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. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# Define library interface.
SUNWprivate_1.1 {
global:
Java_com_sun_media_sound_DirectAudioDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_DirectAudioDeviceProvider_nNewDirectAudioDeviceInfo;
Java_com_sun_media_sound_DirectAudioDevice_nAvailable;
Java_com_sun_media_sound_DirectAudioDevice_nClose;
Java_com_sun_media_sound_DirectAudioDevice_nFlush;
Java_com_sun_media_sound_DirectAudioDevice_nGetBufferSize;
Java_com_sun_media_sound_DirectAudioDevice_nGetBytePosition;
Java_com_sun_media_sound_DirectAudioDevice_nGetFormats;
Java_com_sun_media_sound_DirectAudioDevice_nIsStillDraining;
Java_com_sun_media_sound_DirectAudioDevice_nOpen;
Java_com_sun_media_sound_DirectAudioDevice_nRead;
Java_com_sun_media_sound_DirectAudioDevice_nRequiresServicing;
Java_com_sun_media_sound_DirectAudioDevice_nService;
Java_com_sun_media_sound_DirectAudioDevice_nSetBytePosition;
Java_com_sun_media_sound_DirectAudioDevice_nStart;
Java_com_sun_media_sound_DirectAudioDevice_nStop;
Java_com_sun_media_sound_DirectAudioDevice_nWrite;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetDescription;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetName;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetVendor;
Java_com_sun_media_sound_MidiInDeviceProvider_nGetVersion;
Java_com_sun_media_sound_MidiInDevice_nClose;
Java_com_sun_media_sound_MidiInDevice_nGetMessages;
Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp;
Java_com_sun_media_sound_MidiInDevice_nOpen;
Java_com_sun_media_sound_MidiInDevice_nStart;
Java_com_sun_media_sound_MidiInDevice_nStop;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetDescription;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetName;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetNumDevices;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVendor;
Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVersion;
Java_com_sun_media_sound_MidiOutDevice_nClose;
Java_com_sun_media_sound_MidiOutDevice_nGetTimeStamp;
Java_com_sun_media_sound_MidiOutDevice_nOpen;
Java_com_sun_media_sound_MidiOutDevice_nSendLongMessage;
Java_com_sun_media_sound_MidiOutDevice_nSendShortMessage;
Java_com_sun_media_sound_PortMixerProvider_nGetNumDevices;
Java_com_sun_media_sound_PortMixerProvider_nNewPortMixerInfo;
Java_com_sun_media_sound_PortMixer_nClose;
Java_com_sun_media_sound_PortMixer_nControlGetFloatValue;
Java_com_sun_media_sound_PortMixer_nControlGetIntValue;
Java_com_sun_media_sound_PortMixer_nControlSetFloatValue;
Java_com_sun_media_sound_PortMixer_nControlSetIntValue;
Java_com_sun_media_sound_PortMixer_nGetControls;
Java_com_sun_media_sound_PortMixer_nGetPortCount;
Java_com_sun_media_sound_PortMixer_nGetPortName;
Java_com_sun_media_sound_PortMixer_nGetPortType;
Java_com_sun_media_sound_PortMixer_nOpen;
local:
*;
};

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2001, 2018, Oracle and/or its affiliates. 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
@ -37,23 +37,12 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_DatagramDispatcher_readv0;
Java_sun_nio_ch_DatagramDispatcher_write0;
Java_sun_nio_ch_DatagramDispatcher_writev0;
Java_sun_nio_ch_EPollArrayWrapper_epollCreate;
Java_sun_nio_ch_EPollArrayWrapper_epollCtl;
Java_sun_nio_ch_EPollArrayWrapper_epollWait;
Java_sun_nio_ch_EPollArrayWrapper_init;
Java_sun_nio_ch_EPollArrayWrapper_interrupt;
Java_sun_nio_ch_EPollArrayWrapper_offsetofData;
Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent;
Java_sun_nio_ch_EPoll_eventSize;
Java_sun_nio_ch_EPoll_eventsOffset;
Java_sun_nio_ch_EPoll_dataOffset;
Java_sun_nio_ch_EPoll_epollCreate;
Java_sun_nio_ch_EPoll_epollCtl;
Java_sun_nio_ch_EPoll_epollWait;
Java_sun_nio_ch_EPollPort_close0;
Java_sun_nio_ch_EPollPort_drain1;
Java_sun_nio_ch_EPollPort_interrupt;
Java_sun_nio_ch_EPollPort_socketpair;
Java_sun_nio_ch_EPoll_create;
Java_sun_nio_ch_EPoll_ctl;
Java_sun_nio_ch_EPoll_wait;
Java_sun_nio_ch_FileChannelImpl_initIDs;
Java_sun_nio_ch_FileChannelImpl_map0;
Java_sun_nio_ch_FileChannelImpl_position0;
@ -95,6 +84,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_IOUtil_write1;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2001, 2018, Oracle and/or its affiliates. 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
@ -42,7 +42,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_FileChannelImpl_position0;
Java_sun_nio_ch_FileChannelImpl_transferTo0;
Java_sun_nio_ch_FileChannelImpl_unmap0;
Java_sun_nio_ch_FileDispatcherImpl_allocate0;
Java_sun_nio_ch_FileDispatcherImpl_allocate0;
Java_sun_nio_ch_FileDispatcherImpl_close0;
Java_sun_nio_ch_FileDispatcherImpl_closeIntFD;
Java_sun_nio_ch_FileDispatcherImpl_force0;
@ -71,117 +71,115 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_configureBlocking;
Java_sun_nio_ch_IOUtil_drain;
Java_sun_nio_ch_IOUtil_fdVal;
Java_sun_nio_ch_IOUtil_fdLimit;
Java_sun_nio_ch_IOUtil_initIDs;
Java_sun_nio_ch_IOUtil_iovMax;
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_IOUtil_iovMax;
Java_sun_nio_ch_KQueue_kqueue;
Java_sun_nio_ch_KQueue_keventRegister;
Java_sun_nio_ch_KQueue_keventPoll;
Java_sun_nio_ch_KQueue_keventSize;
Java_sun_nio_ch_KQueue_identOffset;
Java_sun_nio_ch_KQueue_filterOffset;
Java_sun_nio_ch_KQueue_flagsOffset;
Java_sun_nio_ch_KQueuePort_socketpair;
Java_sun_nio_ch_KQueuePort_interrupt;
Java_sun_nio_ch_KQueuePort_drain1;
Java_sun_nio_ch_KQueuePort_close0;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0;
Java_sun_nio_ch_Net_canJoin6WithIPv4Group0;
Java_sun_nio_ch_Net_socket0;
Java_sun_nio_ch_Net_bind0;
Java_sun_nio_ch_Net_connect0;
Java_sun_nio_ch_Net_listen;
Java_sun_nio_ch_Net_localPort;
Java_sun_nio_ch_Net_localInetAddress;
Java_sun_nio_ch_Net_getIntOption0;
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_IOUtil_write1;
Java_sun_nio_ch_KQueue_create;
Java_sun_nio_ch_KQueue_register;
Java_sun_nio_ch_KQueue_poll;
Java_sun_nio_ch_KQueue_keventSize;
Java_sun_nio_ch_KQueue_identOffset;
Java_sun_nio_ch_KQueue_filterOffset;
Java_sun_nio_ch_KQueue_flagsOffset;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0;
Java_sun_nio_ch_Net_canJoin6WithIPv4Group0;
Java_sun_nio_ch_Net_socket0;
Java_sun_nio_ch_Net_bind0;
Java_sun_nio_ch_Net_connect0;
Java_sun_nio_ch_Net_listen;
Java_sun_nio_ch_Net_localPort;
Java_sun_nio_ch_Net_localInetAddress;
Java_sun_nio_ch_Net_getIntOption0;
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
Java_sun_nio_ch_Net_isIPv6Available0;
Java_sun_nio_ch_Net_isReusePortAvailable0;
Java_sun_nio_ch_Net_joinOrDrop4;
Java_sun_nio_ch_Net_blockOrUnblock4;
Java_sun_nio_ch_Net_joinOrDrop6;
Java_sun_nio_ch_Net_blockOrUnblock6;
Java_sun_nio_ch_Net_setInterface4;
Java_sun_nio_ch_Net_getInterface4;
Java_sun_nio_ch_Net_setInterface6;
Java_sun_nio_ch_Net_getInterface6;
Java_sun_nio_ch_Net_shutdown;
Java_sun_nio_ch_Net_poll;
Java_sun_nio_ch_Net_pollinValue;
Java_sun_nio_ch_Net_polloutValue;
Java_sun_nio_ch_Net_pollerrValue;
Java_sun_nio_ch_Net_pollhupValue;
Java_sun_nio_ch_Net_pollnvalValue;
Java_sun_nio_ch_Net_pollconnValue;
Java_sun_nio_ch_Net_joinOrDrop4;
Java_sun_nio_ch_Net_blockOrUnblock4;
Java_sun_nio_ch_Net_joinOrDrop6;
Java_sun_nio_ch_Net_blockOrUnblock6;
Java_sun_nio_ch_Net_setInterface4;
Java_sun_nio_ch_Net_getInterface4;
Java_sun_nio_ch_Net_setInterface6;
Java_sun_nio_ch_Net_getInterface6;
Java_sun_nio_ch_Net_shutdown;
Java_sun_nio_ch_Net_poll;
Java_sun_nio_ch_Net_pollinValue;
Java_sun_nio_ch_Net_polloutValue;
Java_sun_nio_ch_Net_pollerrValue;
Java_sun_nio_ch_Net_pollhupValue;
Java_sun_nio_ch_Net_pollnvalValue;
Java_sun_nio_ch_Net_pollconnValue;
Java_sun_nio_ch_Net_isExclusiveBindAvailable;
Java_sun_nio_ch_PollArrayWrapper_interrupt;
Java_sun_nio_ch_PollArrayWrapper_poll0;
Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_SocketChannelImpl_checkConnect;
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
Java_sun_nio_fs_BsdNativeDispatcher_initIDs;
Java_sun_nio_fs_BsdNativeDispatcher_getfsstat;
Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry;
Java_sun_nio_fs_BsdNativeDispatcher_endfsstat;
Java_sun_nio_fs_UnixNativeDispatcher_init;
Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
Java_sun_nio_fs_UnixNativeDispatcher_strerror;
Java_sun_nio_fs_UnixNativeDispatcher_dup;
Java_sun_nio_fs_UnixNativeDispatcher_access0;
Java_sun_nio_fs_UnixNativeDispatcher_exists0;
Java_sun_nio_fs_UnixNativeDispatcher_stat0;
Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
Java_sun_nio_fs_BsdNativeDispatcher_initIDs;
Java_sun_nio_fs_BsdNativeDispatcher_getfsstat;
Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry;
Java_sun_nio_fs_BsdNativeDispatcher_endfsstat;
Java_sun_nio_fs_UnixNativeDispatcher_init;
Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
Java_sun_nio_fs_UnixNativeDispatcher_strerror;
Java_sun_nio_fs_UnixNativeDispatcher_dup;
Java_sun_nio_fs_UnixNativeDispatcher_access0;
Java_sun_nio_fs_UnixNativeDispatcher_exists0;
Java_sun_nio_fs_UnixNativeDispatcher_stat0;
Java_sun_nio_fs_UnixNativeDispatcher_stat1;
Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
Java_sun_nio_fs_UnixNativeDispatcher_fstat;
Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
Java_sun_nio_fs_UnixNativeDispatcher_chown0;
Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
Java_sun_nio_fs_UnixNativeDispatcher_fchown;
Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
Java_sun_nio_fs_UnixNativeDispatcher_futimes;
Java_sun_nio_fs_UnixNativeDispatcher_open0;
Java_sun_nio_fs_UnixNativeDispatcher_openat0;
Java_sun_nio_fs_UnixNativeDispatcher_close0;
Java_sun_nio_fs_UnixNativeDispatcher_read;
Java_sun_nio_fs_UnixNativeDispatcher_write;
Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
Java_sun_nio_fs_UnixNativeDispatcher_fclose;
Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
Java_sun_nio_fs_UnixNativeDispatcher_readdir;
Java_sun_nio_fs_UnixNativeDispatcher_closedir;
Java_sun_nio_fs_UnixNativeDispatcher_link0;
Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
Java_sun_nio_fs_UnixNativeDispatcher_rename0;
Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
Java_sun_nio_fs_UnixCopyFile_transfer;
handleSocketError;
Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
Java_sun_nio_fs_UnixNativeDispatcher_fstat;
Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
Java_sun_nio_fs_UnixNativeDispatcher_chown0;
Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
Java_sun_nio_fs_UnixNativeDispatcher_fchown;
Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
Java_sun_nio_fs_UnixNativeDispatcher_futimes;
Java_sun_nio_fs_UnixNativeDispatcher_open0;
Java_sun_nio_fs_UnixNativeDispatcher_openat0;
Java_sun_nio_fs_UnixNativeDispatcher_close0;
Java_sun_nio_fs_UnixNativeDispatcher_read;
Java_sun_nio_fs_UnixNativeDispatcher_write;
Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
Java_sun_nio_fs_UnixNativeDispatcher_fclose;
Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
Java_sun_nio_fs_UnixNativeDispatcher_readdir;
Java_sun_nio_fs_UnixNativeDispatcher_closedir;
Java_sun_nio_fs_UnixNativeDispatcher_link0;
Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
Java_sun_nio_fs_UnixNativeDispatcher_rename0;
Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
Java_sun_nio_fs_UnixCopyFile_transfer;
handleSocketError;
local:
*;

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2001, 2018, Oracle and/or its affiliates. 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
@ -38,7 +38,6 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_DatagramDispatcher_write0;
Java_sun_nio_ch_DatagramDispatcher_writev0;
Java_sun_nio_ch_DevPollArrayWrapper_init;
Java_sun_nio_ch_DevPollArrayWrapper_interrupt;
Java_sun_nio_ch_DevPollArrayWrapper_poll0;
Java_sun_nio_ch_DevPollArrayWrapper_register;
Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple;
@ -83,6 +82,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_IOUtil_write1;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;

View File

@ -1298,22 +1298,37 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
# Find the common images to compare, prioritizing later build stages
if [ -d "$THIS/install/jdk" ] && [ -d "$OTHER/install/jdk" ]; then
THIS_JDK="$THIS/install/jdk"
THIS_JRE="$THIS/install/jre"
OTHER_JDK="$OTHER/install/jdk"
OTHER_JRE="$OTHER/install/jre"
echo "Selecting install images for compare"
echo "Selecting install images for JDK compare"
if [ -d "$THIS/install/jre" ] && [ -d "$OTHER/install/jre" ]; then
THIS_JRE="$THIS/install/jre"
OTHER_JRE="$OTHER/install/jre"
echo "Also selecting install images for JRE compare"
else
echo "No install JRE image found"
fi
elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/deploy/images/jdk" ]; then
THIS_JDK="$THIS/images/jdk"
THIS_JRE="$THIS/images/jre"
OTHER_JDK="$OTHER/deploy/images/jdk"
OTHER_JRE="$OTHER/deploy/images/jre"
echo "Selecting deploy images for compare"
echo "Selecting deploy images for JDK compare"
if [ -d "$THIS/images/jre" ] && [ -d "$OTHER/deploy/images/jre" ]; then
THIS_JRE="$THIS/images/jre"
OTHER_JRE="$OTHER/deploy/images/jre"
echo "Selecting deploy images for JRE compare"
else
echo "No deploy JRE image found"
fi
elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/images/jdk" ]; then
THIS_JDK="$THIS/images/jdk"
THIS_JRE="$THIS/images/jre"
OTHER_JDK="$OTHER/images/jdk"
OTHER_JRE="$OTHER/images/jre"
echo "Selecting jdk images for compare"
echo "Selecting normal images for JDK compare"
if [ -d "$THIS/images/jre" ] && [ -d "$OTHER/images/jre" ]; then
THIS_JRE="$THIS/images/jre"
OTHER_JRE="$OTHER/images/jre"
echo "Selecting normal images for JRE compare"
else
echo "No normal JRE image found"
fi
elif [ -d "$(ls -d $THIS/licensee-src/build/*/images/jdk 2> /dev/null)" ] \
&& [ -d "$(ls -d $OTHER/licensee-src/build/*/images/jdk 2> /dev/null)" ]
then
@ -1406,9 +1421,11 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
else
OTHER_SEC_DIR="$OTHER/tmp"
fi
OTHER_SEC_BIN="$OTHER_SEC_DIR/sec-bin.zip"
THIS_SEC_DIR="$THIS/images"
THIS_SEC_BIN="$THIS_SEC_DIR/sec-bin.zip"
if [ -f "$THIS_SEC_DIR/sec-bin.zip" ]; then
OTHER_SEC_BIN="$OTHER_SEC_DIR/sec-bin.zip"
THIS_SEC_DIR="$THIS/images"
THIS_SEC_BIN="$THIS_SEC_DIR/sec-bin.zip"
fi
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
if [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
JGSS_WINDOWS_BIN="jgss-windows-x64-bin.zip"
@ -1437,11 +1454,12 @@ if [ "$CMP_NAMES" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
compare_dirs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
echo -n "JRE "
compare_dirs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
echo -n "JDK "
compare_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
echo -n "JRE "
compare_dirs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
echo -n "JRE "
compare_files $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
@ -1480,49 +1498,38 @@ if [ "$CMP_NAMES" = "true" ]; then
fi
fi
if [ "$CMP_PERMS" = "true" ]; then
if [ "$CMP_LIBS" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
compare_permissions $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
echo -n "JRE "
compare_permissions $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
compare_all_libs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_permissions $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
compare_all_libs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_permissions $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
compare_all_libs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
compare_permissions $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
compare_all_libs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi
if [ "$CMP_TYPES" = "true" ]; then
if [ "$CMP_EXECS" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
compare_file_types $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
echo -n "JRE "
compare_file_types $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
if [ -n "$THIS_JDK_BUNDLE" ] && [ -n "$OTHER_JDK_BUNDLE" ]; then
echo -n "JDK Bundle "
compare_file_types $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
echo -n "JRE Bundle "
compare_file_types $THIS_JRE_BUNDLE $OTHER_JRE_BUNDLE $COMPARE_ROOT/jre-bundle
compare_all_execs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_file_types $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
compare_all_execs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_file_types $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
compare_all_execs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
compare_file_types $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
compare_all_execs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi
@ -1530,6 +1537,8 @@ if [ "$CMP_GENERAL" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
compare_general_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
echo -n "JRE "
compare_general_files $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
@ -1601,46 +1610,53 @@ if [ "$CMP_JARS" = "true" ]; then
fi
fi
if [ "$CMP_LIBS" = "true" ]; then
if [ "$CMP_PERMS" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
echo -n "JDK "
compare_all_libs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
echo -n "JRE "
compare_all_libs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
compare_permissions $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
echo -n "JRE "
compare_permissions $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_all_libs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
compare_permissions $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_all_libs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
compare_permissions $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
compare_all_libs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
compare_permissions $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi
if [ "$CMP_EXECS" = "true" ]; then
if [ "$CMP_TYPES" = "true" ]; then
if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
compare_all_execs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
echo -n "JRE "
compare_all_execs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
echo -n "JDK "
compare_file_types $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
fi
if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
echo -n "JRE "
compare_file_types $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
fi
if [ -n "$THIS_JDK_BUNDLE" ] && [ -n "$OTHER_JDK_BUNDLE" ]; then
echo -n "JDK Bundle "
compare_file_types $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
echo -n "JRE Bundle "
compare_file_types $THIS_JRE_BUNDLE $OTHER_JRE_BUNDLE $COMPARE_ROOT/jre-bundle
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_all_execs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
compare_file_types $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_all_execs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
compare_file_types $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
echo -n "Sparkle.framework "
compare_all_execs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
compare_file_types $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
fi
fi

View File

@ -339,7 +339,7 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "sparcv9" ]
DIS_DIFF_FILTER="$SED \
-e 's/^[0-9a-f]\{16\}/<ADDR>:/' \
-e 's/^ *[0-9a-f]\{3,8\}:/ <ADDR>:/' \
-e 's/^ *[0-9a-f]\{3,12\}:/ <ADDR>:/' \
-e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: <NUMS>/' \
-e 's/\$[a-zA-Z0-9_\$]\{15\}\./<SYM>./' \
-e 's/, [0-9a-fx\-]\{1,8\}/, <ADDR>/g' \

View File

@ -109,11 +109,11 @@ class EPoll {
private static native int dataOffset();
static native int epollCreate() throws IOException;
static native int create() throws IOException;
static native int epollCtl(int epfd, int opcode, int fd, int events);
static native int ctl(int epfd, int opcode, int fd, int events);
static native int epollWait(int epfd, long pollAddress, int numfds)
static native int wait(int epfd, long pollAddress, int numfds, int timeout)
throws IOException;
static {

View File

@ -1,309 +0,0 @@
/*
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.ch;
import java.io.IOException;
import java.security.AccessController;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;
import sun.security.action.GetIntegerAction;
/**
* Manipulates a native array of epoll_event structs on Linux:
*
* typedef union epoll_data {
* void *ptr;
* int fd;
* __uint32_t u32;
* __uint64_t u64;
* } epoll_data_t;
*
* struct epoll_event {
* __uint32_t events;
* epoll_data_t data;
* };
*
* The system call to wait for I/O events is epoll_wait(2). It populates an
* array of epoll_event structures that are passed to the call. The data
* member of the epoll_event structure contains the same data as was set
* when the file descriptor was registered to epoll via epoll_ctl(2). In
* this implementation we set data.fd to be the file descriptor that we
* register. That way, we have the file descriptor available when we
* process the events.
*/
class EPollArrayWrapper {
// EPOLL_EVENTS
private static final int EPOLLIN = 0x001;
// opcodes
private static final int EPOLL_CTL_ADD = 1;
private static final int EPOLL_CTL_DEL = 2;
private static final int EPOLL_CTL_MOD = 3;
// Miscellaneous constants
private static final int SIZE_EPOLLEVENT = sizeofEPollEvent();
private static final int EVENT_OFFSET = 0;
private static final int DATA_OFFSET = offsetofData();
private static final int FD_OFFSET = DATA_OFFSET;
private static final int OPEN_MAX = IOUtil.fdLimit();
private static final int NUM_EPOLLEVENTS = Math.min(OPEN_MAX, 8192);
// Special value to indicate that an update should be ignored
private static final byte KILLED = (byte)-1;
// Initial size of arrays for fd registration changes
private static final int INITIAL_PENDING_UPDATE_SIZE = 64;
// maximum size of updatesLow
private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged(
new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024)));
// The fd of the epoll driver
private final int epfd;
// The epoll_event array for results from epoll_wait
private final AllocatedNativeObject pollArray;
// Base address of the epoll_event array
private final long pollArrayAddress;
// The fd of the interrupt line going out
private final int outgoingInterruptFD;
// Number of updated pollfd entries
private int updated;
// object to synchronize fd registration changes
private final Object updateLock = new Object();
// number of file descriptors with registration changes pending
private int updateCount;
// file descriptors with registration changes pending
private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
// events for file descriptors with registration changes pending, indexed
// by file descriptor and stored as bytes for efficiency reasons. For
// file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
// least) then the update is stored in a map.
private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE];
private final Map<Integer,Byte> eventsHigh = new HashMap<>();
// Used by release and updateRegistrations to track whether a file
// descriptor is registered with epoll.
private final BitSet registered = new BitSet();
EPollArrayWrapper(int fd0, int fd1) throws IOException {
// creates the epoll file descriptor
epfd = epollCreate();
// the epoll_event array passed to epoll_wait
int allocationSize = NUM_EPOLLEVENTS * SIZE_EPOLLEVENT;
pollArray = new AllocatedNativeObject(allocationSize, true);
pollArrayAddress = pollArray.address();
outgoingInterruptFD = fd1;
epollCtl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
}
void putEventOps(int i, int event) {
int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
pollArray.putInt(offset, event);
}
void putDescriptor(int i, int fd) {
int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
pollArray.putInt(offset, fd);
}
int getEventOps(int i) {
int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
return pollArray.getInt(offset);
}
int getDescriptor(int i) {
int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
return pollArray.getInt(offset);
}
/**
* Returns {@code true} if updates for the given key (file
* descriptor) are killed.
*/
private boolean isEventsHighKilled(Integer key) {
assert key >= MAX_UPDATE_ARRAY_SIZE;
Byte value = eventsHigh.get(key);
return (value != null && value == KILLED);
}
/**
* Sets the pending update events for the given file descriptor. This
* method has no effect if the update events is already set to KILLED,
* unless {@code force} is {@code true}.
*/
private void setUpdateEvents(int fd, byte events, boolean force) {
if (fd < MAX_UPDATE_ARRAY_SIZE) {
if ((eventsLow[fd] != KILLED) || force) {
eventsLow[fd] = events;
}
} else {
Integer key = Integer.valueOf(fd);
if (!isEventsHighKilled(key) || force) {
eventsHigh.put(key, Byte.valueOf(events));
}
}
}
/**
* Returns the pending update events for the given file descriptor.
*/
private byte getUpdateEvents(int fd) {
if (fd < MAX_UPDATE_ARRAY_SIZE) {
return eventsLow[fd];
} else {
Byte result = eventsHigh.get(Integer.valueOf(fd));
// result should never be null
return result.byteValue();
}
}
/**
* Update the events for a given file descriptor
*/
void setInterest(int fd, int mask) {
synchronized (updateLock) {
// record the file descriptor and events
int oldCapacity = updateDescriptors.length;
if (updateCount == oldCapacity) {
int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
int[] newDescriptors = new int[newCapacity];
System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
updateDescriptors = newDescriptors;
}
updateDescriptors[updateCount++] = fd;
// events are stored as bytes for efficiency reasons
byte b = (byte)mask;
assert (b == mask) && (b != KILLED);
setUpdateEvents(fd, b, false);
}
}
/**
* Add a file descriptor
*/
void add(int fd) {
// force the initial update events to 0 as it may be KILLED by a
// previous registration.
synchronized (updateLock) {
assert !registered.get(fd);
setUpdateEvents(fd, (byte)0, true);
}
}
/**
* Remove a file descriptor
*/
void remove(int fd) {
synchronized (updateLock) {
// kill pending and future update for this file descriptor
setUpdateEvents(fd, KILLED, false);
// remove from epoll
if (registered.get(fd)) {
epollCtl(epfd, EPOLL_CTL_DEL, fd, 0);
registered.clear(fd);
}
}
}
/**
* Close epoll file descriptor and free poll array
*/
void close() throws IOException {
FileDispatcherImpl.closeIntFD(epfd);
pollArray.free();
}
int poll(long timeout) throws IOException {
updateRegistrations();
return epollWait(pollArrayAddress, NUM_EPOLLEVENTS, timeout, epfd);
}
/**
* Update the pending registrations.
*/
private void updateRegistrations() {
synchronized (updateLock) {
int j = 0;
while (j < updateCount) {
int fd = updateDescriptors[j];
short events = getUpdateEvents(fd);
boolean isRegistered = registered.get(fd);
int opcode = 0;
if (events != KILLED) {
if (isRegistered) {
opcode = (events != 0) ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
} else {
opcode = (events != 0) ? EPOLL_CTL_ADD : 0;
}
if (opcode != 0) {
epollCtl(epfd, opcode, fd, events);
if (opcode == EPOLL_CTL_ADD) {
registered.set(fd);
} else if (opcode == EPOLL_CTL_DEL) {
registered.clear(fd);
}
}
}
j++;
}
updateCount = 0;
}
}
public void interrupt() {
interrupt(outgoingInterruptFD);
}
static {
IOUtil.load();
init();
}
private native int epollCreate();
private native void epollCtl(int epfd, int opcode, int fd, int events);
private native int epollWait(long pollAddress, int numfds, long timeout,
int epfd) throws IOException;
private static native int sizeofEPollEvent();
private static native int offsetofData();
private static native void interrupt(int fd);
private static native void init();
}

View File

@ -30,7 +30,13 @@ import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import static sun.nio.ch.EPoll.*;
import static sun.nio.ch.EPoll.EPOLLIN;
import static sun.nio.ch.EPoll.EPOLLONESHOT;
import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
import static sun.nio.ch.EPoll.EPOLL_CTL_DEL;
import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
/**
* AsynchronousChannelGroup implementation based on the Linux epoll facility.
@ -48,6 +54,9 @@ final class EPollPort
// epoll file descriptor
private final int epfd;
// address of the poll array passed to epoll_wait
private final long address;
// true if epoll closed
private boolean closed;
@ -57,9 +66,6 @@ final class EPollPort
// number of wakeups pending
private final AtomicInteger wakeupCount = new AtomicInteger();
// address of the poll array passed to epoll_wait
private final long address;
// encapsulates an event for a channel
static class Event {
final PollableChannel channel;
@ -85,23 +91,21 @@ final class EPollPort
{
super(provider, pool);
// open epoll
this.epfd = epollCreate();
this.epfd = EPoll.create();
this.address = EPoll.allocatePollArray(MAX_EPOLL_EVENTS);
// create socket pair for wakeup mechanism
int[] sv = new int[2];
try {
socketpair(sv);
// register one end with epoll
epollCtl(epfd, EPOLL_CTL_ADD, sv[0], EPOLLIN);
} catch (IOException x) {
close0(epfd);
throw x;
long fds = IOUtil.makePipe(true);
this.sp = new int[]{(int) (fds >>> 32), (int) fds};
} catch (IOException ioe) {
EPoll.freePollArray(address);
FileDispatcherImpl.closeIntFD(epfd);
throw ioe;
}
this.sp = sv;
// allocate the poll array
this.address = allocatePollArray(MAX_EPOLL_EVENTS);
// register one end with epoll
EPoll.ctl(epfd, EPOLL_CTL_ADD, sp[0], EPOLLIN);
// create the queue and offer the special event to ensure that the first
// threads polls
@ -123,17 +127,17 @@ final class EPollPort
return;
closed = true;
}
freePollArray(address);
close0(sp[0]);
close0(sp[1]);
close0(epfd);
try { FileDispatcherImpl.closeIntFD(epfd); } catch (IOException ioe) { }
try { FileDispatcherImpl.closeIntFD(sp[0]); } catch (IOException ioe) { }
try { FileDispatcherImpl.closeIntFD(sp[1]); } catch (IOException ioe) { }
EPoll.freePollArray(address);
}
private void wakeup() {
if (wakeupCount.incrementAndGet() == 1) {
// write byte to socketpair to force wakeup
try {
interrupt(sp[1]);
IOUtil.write1(sp[1], (byte)0);
} catch (IOException x) {
throw new AssertionError(x);
}
@ -171,9 +175,9 @@ final class EPollPort
@Override
void startPoll(int fd, int events) {
// update events (or add to epoll on first usage)
int err = epollCtl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
int err = EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
if (err == ENOENT)
err = epollCtl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
err = EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
if (err != 0)
throw new AssertionError(); // should not happen
}
@ -191,7 +195,11 @@ final class EPollPort
private Event poll() throws IOException {
try {
for (;;) {
int n = epollWait(epfd, address, MAX_EPOLL_EVENTS);
int n;
do {
n = EPoll.wait(epfd, address, MAX_EPOLL_EVENTS, -1);
} while (n == IOStatus.INTERRUPTED);
/*
* 'n' events have been read. Here we map them to their
* corresponding channel in batch and queue n-1 so that
@ -201,14 +209,14 @@ final class EPollPort
fdToChannelLock.readLock().lock();
try {
while (n-- > 0) {
long eventAddress = getEvent(address, n);
int fd = getDescriptor(eventAddress);
long eventAddress = EPoll.getEvent(address, n);
int fd = EPoll.getDescriptor(eventAddress);
// wakeup
if (fd == sp[0]) {
if (wakeupCount.decrementAndGet() == 0) {
// no more wakeups so drain pipe
drain1(sp[0]);
IOUtil.drain(sp[0]);
}
// queue special event if there are more events
@ -222,7 +230,7 @@ final class EPollPort
PollableChannel channel = fdToChannel.get(fd);
if (channel != null) {
int events = getEvents(eventAddress);
int events = EPoll.getEvents(eventAddress);
Event ev = new Event(channel, events);
// n-1 events are queued; This thread handles
@ -306,18 +314,4 @@ final class EPollPort
}
}
}
// -- Native methods --
private static native void socketpair(int[] sv) throws IOException;
private static native void interrupt(int fd) throws IOException;
private static native void drain1(int fd) throws IOException;
private static native void close0(int fd);
static {
IOUtil.load();
}
}

View File

@ -26,33 +26,59 @@
package sun.nio.ch;
import java.io.IOException;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayDeque;
import java.util.BitSet;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static sun.nio.ch.EPoll.EPOLLIN;
import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
import static sun.nio.ch.EPoll.EPOLL_CTL_DEL;
import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
/**
* An implementation of Selector for Linux 2.6+ kernels that uses
* the epoll event notification facility.
* Linux epoll based Selector implementation
*/
class EPollSelectorImpl
extends SelectorImpl
{
// File descriptors used for interrupt
class EPollSelectorImpl extends SelectorImpl {
// maximum number of events to poll in one call to epoll_wait
private static final int NUM_EPOLLEVENTS = Math.min(IOUtil.fdLimit(), 1024);
// epoll file descriptor
private final int epfd;
// address of poll array when polling with epoll_wait
private final long pollArrayAddress;
// file descriptors used for interrupt
private final int fd0;
private final int fd1;
// The poll object
private final EPollArrayWrapper pollWrapper;
// maps file descriptor to selection key, synchronize on selector
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
// Maps from file descriptors to keys
private final Map<Integer, SelectionKeyImpl> fdToKey;
// file descriptors registered with epoll, synchronize on selector
private final BitSet registered = new BitSet();
// True if this Selector has been closed
private volatile boolean closed;
// pending new registrations/updates, queued by implRegister and putEventOps
private final Object updateLock = new Object();
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
private final Deque<Integer> updateOps = new ArrayDeque<>();
// Lock for interrupt triggering and clearing
// interrupt triggering and clearing
private final Object interruptLock = new Object();
private boolean interruptTriggered = false;
private boolean interruptTriggered;
/**
* Package private constructor called by factory method in
@ -60,40 +86,57 @@ class EPollSelectorImpl
*/
EPollSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);
fd1 = (int) pipeFds;
this.epfd = EPoll.create();
this.pollArrayAddress = EPoll.allocatePollArray(NUM_EPOLLEVENTS);
try {
pollWrapper = new EPollArrayWrapper(fd0, fd1);
fdToKey = new HashMap<>();
} catch (Throwable t) {
try {
FileDispatcherImpl.closeIntFD(fd0);
} catch (IOException ioe0) {
t.addSuppressed(ioe0);
}
try {
FileDispatcherImpl.closeIntFD(fd1);
} catch (IOException ioe1) {
t.addSuppressed(ioe1);
}
throw t;
long fds = IOUtil.makePipe(false);
this.fd0 = (int) (fds >>> 32);
this.fd1 = (int) fds;
} catch (IOException ioe) {
EPoll.freePollArray(pollArrayAddress);
FileDispatcherImpl.closeIntFD(epfd);
throw ioe;
}
// register one end of the socket pair for wakeups
EPoll.ctl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
}
private void ensureOpen() {
if (closed)
if (!isOpen())
throw new ClosedSelectorException();
}
@Override
protected int doSelect(long timeout) throws IOException {
ensureOpen();
assert Thread.holdsLock(this);
int numEntries;
processUpdateQueue();
processDeregisterQueue();
try {
begin();
numEntries = pollWrapper.poll(timeout);
// epoll_wait timeout is int
int to = (int) Math.min(timeout, Integer.MAX_VALUE);
boolean timedPoll = (to > 0);
do {
long startTime = timedPoll ? System.nanoTime() : 0;
numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, to);
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
// timed poll interrupted so need to adjust timeout
long adjust = System.nanoTime() - startTime;
to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
if (to <= 0) {
// timeout expired so no retry
numEntries = 0;
}
}
} while (numEntries == IOStatus.INTERRUPTED);
assert IOStatus.check(numEntries);
} finally {
end();
}
@ -101,21 +144,70 @@ class EPollSelectorImpl
return updateSelectedKeys(numEntries);
}
/**
* Process new registrations and changes to the interest ops.
*/
private void processUpdateQueue() {
assert Thread.holdsLock(this);
synchronized (updateLock) {
SelectionKeyImpl ski;
// new registrations
while ((ski = newKeys.pollFirst()) != null) {
if (ski.isValid()) {
SelChImpl ch = ski.channel;
int fd = ch.getFDVal();
SelectionKeyImpl previous = fdToKey.put(fd, ski);
assert previous == null;
assert registered.get(fd) == false;
}
}
// changes to interest ops
assert updateKeys.size() == updateOps.size();
while ((ski = updateKeys.pollFirst()) != null) {
int ops = updateOps.pollFirst();
int fd = ski.channel.getFDVal();
if (ski.isValid() && fdToKey.containsKey(fd)) {
if (registered.get(fd)) {
if (ops == 0) {
// remove from epoll
EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
registered.clear(fd);
} else {
// modify events
EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, ops);
}
} else if (ops != 0) {
// add to epoll
EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, ops);
registered.set(fd);
}
}
}
}
}
/**
* Update the keys whose fd's have been selected by the epoll.
* Add the ready keys to the ready queue.
*/
private int updateSelectedKeys(int numEntries) throws IOException {
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioSelectedKeys());
boolean interrupted = false;
int numKeysUpdated = 0;
for (int i=0; i<numEntries; i++) {
int nextFD = pollWrapper.getDescriptor(i);
if (nextFD == fd0) {
long event = EPoll.getEvent(pollArrayAddress, i);
int fd = EPoll.getDescriptor(event);
if (fd == fd0) {
interrupted = true;
} else {
SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
SelectionKeyImpl ski = fdToKey.get(fd);
if (ski != null) {
int rOps = pollWrapper.getEventOps(i);
int rOps = EPoll.getEvents(event);
if (selectedKeys.contains(ski)) {
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
numKeysUpdated++;
@ -140,16 +232,17 @@ class EPollSelectorImpl
@Override
protected void implClose() throws IOException {
if (closed)
return;
closed = true;
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioKeys());
// prevent further wakeup
synchronized (interruptLock) {
interruptTriggered = true;
}
pollWrapper.close();
FileDispatcherImpl.closeIntFD(epfd);
EPoll.freePollArray(pollArrayAddress);
FileDispatcherImpl.closeIntFD(fd0);
FileDispatcherImpl.closeIntFD(fd1);
@ -167,42 +260,57 @@ class EPollSelectorImpl
@Override
protected void implRegister(SelectionKeyImpl ski) {
assert Thread.holdsLock(nioKeys());
ensureOpen();
SelChImpl ch = ski.channel;
int fd = Integer.valueOf(ch.getFDVal());
fdToKey.put(fd, ski);
pollWrapper.add(fd);
synchronized (updateLock) {
newKeys.addLast(ski);
}
keys.add(ski);
}
@Override
protected void implDereg(SelectionKeyImpl ski) throws IOException {
assert (ski.getIndex() >= 0);
SelChImpl ch = ski.channel;
int fd = ch.getFDVal();
fdToKey.remove(Integer.valueOf(fd));
pollWrapper.remove(fd);
ski.setIndex(-1);
keys.remove(ski);
assert !ski.isValid();
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioKeys());
assert Thread.holdsLock(nioSelectedKeys());
int fd = ski.channel.getFDVal();
fdToKey.remove(fd);
if (registered.get(fd)) {
EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
registered.clear(fd);
}
selectedKeys.remove(ski);
keys.remove(ski);
// remove from channel's key set
deregister(ski);
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
((SelChImpl) selch).kill();
}
@Override
public void putEventOps(SelectionKeyImpl ski, int ops) {
ensureOpen();
SelChImpl ch = ski.channel;
pollWrapper.setInterest(ch.getFDVal(), ops);
synchronized (updateLock) {
updateOps.addLast(ops); // ops first in case adding the key fails
updateKeys.addLast(ski);
}
}
@Override
public Selector wakeup() {
synchronized (interruptLock) {
if (!interruptTriggered) {
pollWrapper.interrupt();
try {
IOUtil.write1(fd1, (byte)0);
} catch (IOException ioe) {
throw new InternalError(ioe);
}
interruptTriggered = true;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. 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
@ -103,8 +103,8 @@ public class LinuxFileSystemProvider extends UnixFileSystemProvider {
@Override
FileTypeDetector getFileTypeDetector() {
String userHome = GetPropertyAction.privilegedGetProperty("user.home");
Path userMimeTypes = Paths.get(userHome, ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
Path userMimeTypes = Path.of(userHome, ".mime.types");
Path etcMimeTypes = Path.of("/etc/mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
new MimeTypesFileTypeDetector(etcMimeTypes));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. 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
@ -23,53 +23,51 @@
* questions.
*/
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio.h"
#include "nio_util.h"
#include "sun_nio_ch_EPoll.h"
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/epoll.h>
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass this)
Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass clazz)
{
return sizeof(struct epoll_event);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass this)
Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct epoll_event, events);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass this)
Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct epoll_event, data);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPoll_epollCreate(JNIEnv *env, jclass c) {
/*
* epoll_create expects a size as a hint to the kernel about how to
* dimension internal structures. We can't predict the size in advance.
*/
Java_sun_nio_ch_EPoll_create(JNIEnv *env, jclass clazz) {
/* size hint not used in modern kernels */
int epfd = epoll_create(256);
if (epfd < 0) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
}
return epfd;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPoll_epollCtl(JNIEnv *env, jclass c, jint epfd,
jint opcode, jint fd, jint events)
Java_sun_nio_ch_EPoll_ctl(JNIEnv *env, jclass clazz, jint epfd,
jint opcode, jint fd, jint events)
{
struct epoll_event event;
int res;
@ -77,21 +75,23 @@ Java_sun_nio_ch_EPoll_epollCtl(JNIEnv *env, jclass c, jint epfd,
event.events = events;
event.data.fd = fd;
RESTARTABLE(epoll_ctl(epfd, (int)opcode, (int)fd, &event), res);
res = epoll_ctl(epfd, (int)opcode, (int)fd, &event);
return (res == 0) ? 0 : errno;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPoll_epollWait(JNIEnv *env, jclass c,
jint epfd, jlong address, jint numfds)
Java_sun_nio_ch_EPoll_wait(JNIEnv *env, jclass clazz, jint epfd,
jlong address, jint numfds, jint timeout)
{
struct epoll_event *events = jlong_to_ptr(address);
int res;
RESTARTABLE(epoll_wait(epfd, events, numfds, -1), res);
int res = epoll_wait(epfd, events, numfds, timeout);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
if (errno == EINTR) {
return IOS_INTERRUPTED;
} else {
JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
return IOS_THROWN;
}
}
return res;
}

View File

@ -1,160 +0,0 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "sun_nio_ch_EPollArrayWrapper.h"
#include <unistd.h>
#include <sys/time.h>
#include <sys/epoll.h>
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
} while((_result == -1) && (errno == EINTR)); \
} while(0)
static int
iepoll(int epfd, struct epoll_event *events, int numfds, jlong timeout)
{
jlong start, now;
int remaining = timeout;
struct timeval t;
int diff;
gettimeofday(&t, NULL);
start = t.tv_sec * 1000 + t.tv_usec / 1000;
for (;;) {
int res = epoll_wait(epfd, events, numfds, remaining);
if (res < 0 && errno == EINTR) {
if (remaining >= 0) {
gettimeofday(&t, NULL);
now = t.tv_sec * 1000 + t.tv_usec / 1000;
diff = now - start;
remaining -= diff;
if (diff < 0 || remaining <= 0) {
return 0;
}
start = now;
}
} else {
return res;
}
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_init(JNIEnv *env, jclass this)
{
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollCreate(JNIEnv *env, jobject this)
{
/*
* epoll_create expects a size as a hint to the kernel about how to
* dimension internal structures. We can't predict the size in advance.
*/
int epfd = epoll_create(256);
if (epfd < 0) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
}
return epfd;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent(JNIEnv* env, jclass this)
{
return sizeof(struct epoll_event);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_offsetofData(JNIEnv* env, jclass this)
{
return offsetof(struct epoll_event, data);
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollCtl(JNIEnv *env, jobject this, jint epfd,
jint opcode, jint fd, jint events)
{
struct epoll_event event;
int res;
event.events = events;
event.data.fd = fd;
RESTARTABLE(epoll_ctl(epfd, (int)opcode, (int)fd, &event), res);
/*
* A channel may be registered with several Selectors. When each Selector
* is polled a EPOLL_CTL_DEL op will be inserted into its pending update
* list to remove the file descriptor from epoll. The "last" Selector will
* close the file descriptor which automatically unregisters it from each
* epoll descriptor. To avoid costly synchronization between Selectors we
* allow pending updates to be processed, ignoring errors. The errors are
* harmless as the last update for the file descriptor is guaranteed to
* be EPOLL_CTL_DEL.
*/
if (res < 0 && errno != EBADF && errno != ENOENT && errno != EPERM) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_ctl failed");
}
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollWait(JNIEnv *env, jobject this,
jlong address, jint numfds,
jlong timeout, jint epfd)
{
struct epoll_event *events = jlong_to_ptr(address);
int res;
if (timeout <= 0) { /* Indefinite or no wait */
RESTARTABLE(epoll_wait(epfd, events, numfds, timeout), res);
} else { /* Bounded wait; bounded restarts */
res = iepoll(epfd, events, numfds, timeout);
}
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
}
return res;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollArrayWrapper_interrupt(JNIEnv *env, jobject this, jint fd)
{
int fakebuf[1];
fakebuf[0] = 1;
if (write(fd, fakebuf, 1) < 0) {
JNU_ThrowIOExceptionWithLastError(env,"write to interrupt fd failed");
}
}

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include "sun_nio_ch_EPollPort.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
int sp[2];
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
} else {
jint res[2];
res[0] = (jint)sp[0];
res[1] = (jint)sp[1];
(*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
int res;
int buf[1];
buf[0] = 1;
RESTARTABLE(write(fd, buf, 1), res);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "write failed");
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
int res;
char buf[1];
RESTARTABLE(read(fd, buf, 1), res);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_EPollPort_close0(JNIEnv *env, jclass c, jint fd) {
int res;
RESTARTABLE(close(fd), res);
}

View File

@ -84,17 +84,17 @@ class KQueue {
}
/**
* Returns the file descriptor from a kevent (assuming to be in ident field)
* Returns the file descriptor from a kevent (assuming it is in the ident field)
*/
static int getDescriptor(long address) {
return unsafe.getInt(address + OFFSET_IDENT);
}
static int getFilter(long address) {
static short getFilter(long address) {
return unsafe.getShort(address + OFFSET_FILTER);
}
static int getFlags(long address) {
static short getFlags(long address) {
return unsafe.getShort(address + OFFSET_FLAGS);
}
@ -108,11 +108,11 @@ class KQueue {
private static native int flagsOffset();
static native int kqueue() throws IOException;
static native int create() throws IOException;
static native int keventRegister(int kqpfd, int fd, int filter, int flags);
static native int register(int kqfd, int fd, int filter, int flags);
static native int keventPoll(int kqpfd, long pollAddress, int nevents)
static native int poll(int kqfd, long pollAddress, int nevents, long timeout)
throws IOException;
static {

View File

@ -1,197 +0,0 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* KQueueArrayWrapper.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollArrayWrapper
*/
package sun.nio.ch;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import sun.security.action.GetPropertyAction;
/*
* struct kevent { // 32-bit 64-bit
* uintptr_t ident; // 4 8
* short filter; // 2 2
* u_short flags; // 2 2
* u_int fflags; // 4 4
* intptr_t data; // 4 8
* void *udata; // 4 8
* } // Total: 20 32
*
* The implementation works in 32-bit and 64-bit world. We do this by calling a
* native function that actually sets the sizes and offsets of the fields based
* on which mode we're in.
*/
class KQueueArrayWrapper {
// kevent filters
static short EVFILT_READ;
static short EVFILT_WRITE;
// kevent struct
// These fields are now set by initStructSizes in the static initializer.
static short SIZEOF_KEVENT;
static short FD_OFFSET;
static short FILTER_OFFSET;
// kevent array size
static final int NUM_KEVENTS = 128;
// Are we in a 64-bit VM?
static boolean is64bit;
// The kevent array (used for outcoming events only)
private final AllocatedNativeObject keventArray;
private final long keventArrayAddress;
// The kqueue fd
private final int kq;
// The fd of the interrupt line going out
private final int outgoingInterruptFD;
static {
IOUtil.load();
initStructSizes();
String datamodel =
GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
is64bit = "64".equals(datamodel);
}
KQueueArrayWrapper(int fd0, int fd1) throws IOException {
int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
keventArray = new AllocatedNativeObject(allocationSize, true);
keventArrayAddress = keventArray.address();
kq = init();
register0(kq, fd0, 1, 0);
outgoingInterruptFD = fd1;
}
// Used to update file description registrations
private static class Update {
SelChImpl channel;
int events;
Update(SelChImpl channel, int events) {
this.channel = channel;
this.events = events;
}
}
private LinkedList<Update> updateList = new LinkedList<Update>();
int getReventOps(int index) {
int result = 0;
int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
short filter = keventArray.getShort(offset);
// This is all that's necessary based on inspection of usage:
// SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
// ServerSocketChannelImpl, SocketChannelImpl
if (filter == EVFILT_READ) {
result |= Net.POLLIN;
} else if (filter == EVFILT_WRITE) {
result |= Net.POLLOUT;
}
return result;
}
int getDescriptor(int index) {
int offset = SIZEOF_KEVENT*index + FD_OFFSET;
/* The ident field is 8 bytes in 64-bit world, however the API wants us
* to return an int. Hence read the 8 bytes but return as an int.
*/
if (is64bit) {
long fd = keventArray.getLong(offset);
assert fd <= Integer.MAX_VALUE;
return (int) fd;
} else {
return keventArray.getInt(offset);
}
}
void setInterest(SelChImpl channel, int events) {
synchronized (updateList) {
// update existing registration
updateList.add(new Update(channel, events));
}
}
void release(SelChImpl channel) {
synchronized (updateList) {
// flush any pending updates
for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {
if (it.next().channel == channel) {
it.remove();
}
}
// remove
register0(kq, channel.getFDVal(), 0, 0);
}
}
void updateRegistrations() {
synchronized (updateList) {
Update u;
while ((u = updateList.poll()) != null) {
SelChImpl ch = u.channel;
if (!ch.isOpen())
continue;
register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);
}
}
}
void close() throws IOException {
FileDispatcherImpl.closeIntFD(kq);
keventArray.free();
}
int poll(long timeout) {
updateRegistrations();
return kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
}
void interrupt() {
interrupt(outgoingInterruptFD);
}
private native int init();
private static native void initStructSizes();
private native void register0(int kq, int fd, int read, int write);
private native int kevent0(int kq, long keventAddress, int keventCount,
long timeout);
private static native void interrupt(int fd);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. 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
@ -30,7 +30,11 @@ import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import static sun.nio.ch.KQueue.*;
import static sun.nio.ch.KQueue.EVFILT_READ;
import static sun.nio.ch.KQueue.EVFILT_WRITE;
import static sun.nio.ch.KQueue.EV_ADD;
import static sun.nio.ch.KQueue.EV_ONESHOT;
/**
* AsynchronousChannelGroup implementation based on the BSD kqueue facility.
@ -45,6 +49,9 @@ final class KQueuePort
// kqueue file descriptor
private final int kqfd;
// address of the poll array passed to kqueue_wait
private final long address;
// true if kqueue closed
private boolean closed;
@ -54,9 +61,6 @@ final class KQueuePort
// number of wakeups pending
private final AtomicInteger wakeupCount = new AtomicInteger();
// address of the poll array passed to kqueue_wait
private final long address;
// encapsulates an event for a channel
static class Event {
final PollableChannel channel;
@ -82,28 +86,25 @@ final class KQueuePort
{
super(provider, pool);
// open kqueue
this.kqfd = kqueue();
this.kqfd = KQueue.create();
this.address = KQueue.allocatePollArray(MAX_KEVENTS_TO_POLL);
// create socket pair for wakeup mechanism
int[] sv = new int[2];
try {
socketpair(sv);
// register one end with kqueue
keventRegister(kqfd, sv[0], EVFILT_READ, EV_ADD);
} catch (IOException x) {
close0(kqfd);
throw x;
long fds = IOUtil.makePipe(true);
this.sp = new int[]{(int) (fds >>> 32), (int) fds};
} catch (IOException ioe) {
KQueue.freePollArray(address);
FileDispatcherImpl.closeIntFD(kqfd);
throw ioe;
}
this.sp = sv;
// allocate the poll array
this.address = allocatePollArray(MAX_KEVENTS_TO_POLL);
// register one end with kqueue
KQueue.register(kqfd, sp[0], EVFILT_READ, EV_ADD);
// create the queue and offer the special event to ensure that the first
// threads polls
this.queue = new ArrayBlockingQueue<Event>(MAX_KEVENTS_TO_POLL);
this.queue = new ArrayBlockingQueue<>(MAX_KEVENTS_TO_POLL);
this.queue.offer(NEED_TO_POLL);
}
@ -121,17 +122,18 @@ final class KQueuePort
return;
closed = true;
}
freePollArray(address);
close0(sp[0]);
close0(sp[1]);
close0(kqfd);
try { FileDispatcherImpl.closeIntFD(kqfd); } catch (IOException ioe) { }
try { FileDispatcherImpl.closeIntFD(sp[0]); } catch (IOException ioe) { }
try { FileDispatcherImpl.closeIntFD(sp[1]); } catch (IOException ioe) { }
KQueue.freePollArray(address);
}
private void wakeup() {
if (wakeupCount.incrementAndGet() == 1) {
// write byte to socketpair to force wakeup
try {
interrupt(sp[1]);
IOUtil.write1(sp[1], (byte)0);
} catch (IOException x) {
throw new AssertionError(x);
}
@ -173,9 +175,9 @@ final class KQueuePort
int err = 0;
int flags = (EV_ADD|EV_ONESHOT);
if ((events & Net.POLLIN) > 0)
err = keventRegister(kqfd, fd, EVFILT_READ, flags);
err = KQueue.register(kqfd, fd, EVFILT_READ, flags);
if (err == 0 && (events & Net.POLLOUT) > 0)
err = keventRegister(kqfd, fd, EVFILT_WRITE, flags);
err = KQueue.register(kqfd, fd, EVFILT_WRITE, flags);
if (err != 0)
throw new InternalError("kevent failed: " + err); // should not happen
}
@ -193,7 +195,11 @@ final class KQueuePort
private Event poll() throws IOException {
try {
for (;;) {
int n = keventPoll(kqfd, address, MAX_KEVENTS_TO_POLL);
int n;
do {
n = KQueue.poll(kqfd, address, MAX_KEVENTS_TO_POLL, -1L);
} while (n == IOStatus.INTERRUPTED);
/*
* 'n' events have been read. Here we map them to their
* corresponding channel in batch and queue n-1 so that
@ -203,14 +209,14 @@ final class KQueuePort
fdToChannelLock.readLock().lock();
try {
while (n-- > 0) {
long keventAddress = getEvent(address, n);
int fd = getDescriptor(keventAddress);
long keventAddress = KQueue.getEvent(address, n);
int fd = KQueue.getDescriptor(keventAddress);
// wakeup
if (fd == sp[0]) {
if (wakeupCount.decrementAndGet() == 0) {
// no more wakeups so drain pipe
drain1(sp[0]);
IOUtil.drain(sp[0]);
}
// queue special event if there are more events
@ -224,7 +230,7 @@ final class KQueuePort
PollableChannel channel = fdToChannel.get(fd);
if (channel != null) {
int filter = getFilter(keventAddress);
int filter = KQueue.getFilter(keventAddress);
int events = 0;
if (filter == EVFILT_READ)
events = Net.POLLIN;
@ -314,18 +320,4 @@ final class KQueuePort
}
}
}
// -- Native methods --
private static native void socketpair(int[] sv) throws IOException;
private static native void interrupt(int fd) throws IOException;
private static native void drain1(int fd) throws IOException;
private static native void close0(int fd);
static {
IOUtil.load();
}
}

View File

@ -23,11 +23,6 @@
* questions.
*/
/*
* KQueueSelectorImpl.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
*/
package sun.nio.ch;
import java.io.IOException;
@ -36,85 +31,111 @@ import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayDeque;
import java.util.BitSet;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
class KQueueSelectorImpl
extends SelectorImpl
{
// File descriptors used for interrupt
import static sun.nio.ch.KQueue.EVFILT_READ;
import static sun.nio.ch.KQueue.EVFILT_WRITE;
import static sun.nio.ch.KQueue.EV_ADD;
import static sun.nio.ch.KQueue.EV_DELETE;
/**
* KQueue based Selector implementation for macOS
*/
class KQueueSelectorImpl extends SelectorImpl {
// maximum number of events to poll in one call to kqueue
private static final int MAX_KEVENTS = 256;
// kqueue file descriptor
private final int kqfd;
// address of poll array (event list) when polling for pending events
private final long pollArrayAddress;
// file descriptors used for interrupt
private final int fd0;
private final int fd1;
// The kqueue manipulator
private final KQueueArrayWrapper kqueueWrapper;
// maps file descriptor to selection key, synchronize on selector
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
// Map from a file descriptor to an entry containing the selection key
private final HashMap<Integer, MapEntry> fdMap;
// file descriptors registered with kqueue, synchronize on selector
private final BitSet registeredReadFilter = new BitSet();
private final BitSet registeredWriteFilter = new BitSet();
// True if this Selector has been closed
private boolean closed;
// pending new registrations/updates, queued by implRegister and putEventOps
private final Object updateLock = new Object();
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
private final Deque<Integer> updateOps = new ArrayDeque<>();
// Lock for interrupt triggering and clearing
// interrupt triggering and clearing
private final Object interruptLock = new Object();
private boolean interruptTriggered;
// used by updateSelectedKeys to handle cases where the same file
// descriptor is polled by more than one filter
private long updateCount;
private int pollCount;
// Used to map file descriptors to a selection key and "update count"
// (see updateSelectedKeys for usage).
private static class MapEntry {
SelectionKeyImpl ski;
long updateCount;
MapEntry(SelectionKeyImpl ski) {
this.ski = ski;
}
}
/**
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
KQueueSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
long fds = IOUtil.makePipe(false);
fd0 = (int)(fds >>> 32);
fd1 = (int)fds;
this.kqfd = KQueue.create();
this.pollArrayAddress = KQueue.allocatePollArray(MAX_KEVENTS);
try {
kqueueWrapper = new KQueueArrayWrapper(fd0, fd1);
fdMap = new HashMap<>();
} catch (Throwable t) {
try {
FileDispatcherImpl.closeIntFD(fd0);
} catch (IOException ioe0) {
t.addSuppressed(ioe0);
}
try {
FileDispatcherImpl.closeIntFD(fd1);
} catch (IOException ioe1) {
t.addSuppressed(ioe1);
}
throw t;
long fds = IOUtil.makePipe(false);
this.fd0 = (int) (fds >>> 32);
this.fd1 = (int) fds;
} catch (IOException ioe) {
KQueue.freePollArray(pollArrayAddress);
FileDispatcherImpl.closeIntFD(kqfd);
throw ioe;
}
// register one end of the socket pair for wakeups
KQueue.register(kqfd, fd0, EVFILT_READ, EV_ADD);
}
private void ensureOpen() {
if (closed)
if (!isOpen())
throw new ClosedSelectorException();
}
@Override
protected int doSelect(long timeout)
throws IOException
{
ensureOpen();
protected int doSelect(long timeout) throws IOException {
assert Thread.holdsLock(this);
int numEntries;
processUpdateQueue();
processDeregisterQueue();
try {
begin();
numEntries = kqueueWrapper.poll(timeout);
long to = Math.min(timeout, Integer.MAX_VALUE); // max kqueue timeout
boolean timedPoll = (to > 0);
do {
long startTime = timedPoll ? System.nanoTime() : 0;
numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, to);
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
// timed poll interrupted so need to adjust timeout
long adjust = System.nanoTime() - startTime;
to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
if (to <= 0) {
// timeout expired so no retry
numEntries = 0;
}
}
} while (numEntries == IOStatus.INTERRUPTED);
assert IOStatus.check(numEntries);
} finally {
end();
}
@ -122,40 +143,101 @@ class KQueueSelectorImpl
return updateSelectedKeys(numEntries);
}
/**
* Process new registrations and changes to the interest ops.
*/
private void processUpdateQueue() {
assert Thread.holdsLock(this);
synchronized (updateLock) {
SelectionKeyImpl ski;
// new registrations
while ((ski = newKeys.pollFirst()) != null) {
if (ski.isValid()) {
SelChImpl ch = ski.channel;
int fd = ch.getFDVal();
SelectionKeyImpl previous = fdToKey.put(fd, ski);
assert previous == null;
assert registeredReadFilter.get(fd) == false;
assert registeredWriteFilter.get(fd) == false;
}
}
// changes to interest ops
assert updateKeys.size() == updateOps.size();
while ((ski = updateKeys.pollFirst()) != null) {
int ops = updateOps.pollFirst();
int fd = ski.channel.getFDVal();
if (ski.isValid() && fdToKey.containsKey(fd)) {
// add or delete interest in read events
if (registeredReadFilter.get(fd)) {
if ((ops & Net.POLLIN) == 0) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
registeredReadFilter.clear(fd);
}
} else if ((ops & Net.POLLIN) != 0) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_ADD);
registeredReadFilter.set(fd);
}
// add or delete interest in write events
if (registeredWriteFilter.get(fd)) {
if ((ops & Net.POLLOUT) == 0) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
registeredWriteFilter.clear(fd);
}
} else if ((ops & Net.POLLOUT) != 0) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_ADD);
registeredWriteFilter.set(fd);
}
}
}
}
}
/**
* Update the keys whose fd's have been selected by kqueue.
* Add the ready keys to the selected key set.
* If the interrupt fd has been selected, drain it and clear the interrupt.
*/
private int updateSelectedKeys(int numEntries)
throws IOException
{
private int updateSelectedKeys(int numEntries) throws IOException {
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioSelectedKeys());
int numKeysUpdated = 0;
boolean interrupted = false;
// A file descriptor may be registered with kqueue with more than one
// filter and so there may be more than one event for a fd. The update
// count in the MapEntry tracks when the fd was last updated and this
// ensures that the ready ops are updated rather than replaced by a
// second or subsequent event.
updateCount++;
// filter and so there may be more than one event for a fd. The poll
// count is incremented here and compared against the SelectionKey's
// "lastPolled" field. This ensures that the ready ops is updated rather
// than replaced when a file descriptor is polled by both the read and
// write filter.
pollCount++;
for (int i = 0; i < numEntries; i++) {
int nextFD = kqueueWrapper.getDescriptor(i);
if (nextFD == fd0) {
long kevent = KQueue.getEvent(pollArrayAddress, i);
int fd = KQueue.getDescriptor(kevent);
if (fd == fd0) {
interrupted = true;
} else {
MapEntry me = fdMap.get(Integer.valueOf(nextFD));
if (me != null) {
int rOps = kqueueWrapper.getReventOps(i);
SelectionKeyImpl ski = me.ski;
SelectionKeyImpl ski = fdToKey.get(fd);
if (ski != null) {
int rOps = 0;
short filter = KQueue.getFilter(kevent);
if (filter == EVFILT_READ) {
rOps |= Net.POLLIN;
} else if (filter == EVFILT_WRITE) {
rOps |= Net.POLLOUT;
}
if (selectedKeys.contains(ski)) {
// first time this file descriptor has been encountered on this
// update?
if (me.updateCount != updateCount) {
// file descriptor may be polled more than once per poll
if (ski.lastPolled != pollCount) {
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
numKeysUpdated++;
me.updateCount = updateCount;
ski.lastPolled = pollCount;
}
} else {
// ready ops have already been set on this update
@ -166,7 +248,7 @@ class KQueueSelectorImpl
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
selectedKeys.add(ski);
numKeysUpdated++;
me.updateCount = updateCount;
ski.lastPolled = pollCount;
}
}
}
@ -181,63 +263,90 @@ class KQueueSelectorImpl
@Override
protected void implClose() throws IOException {
if (!closed) {
closed = true;
assert !isOpen();
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioKeys());
// prevent further wakeup
synchronized (interruptLock) {
interruptTriggered = true;
}
// prevent further wakeup
synchronized (interruptLock) {
interruptTriggered = true;
}
kqueueWrapper.close();
FileDispatcherImpl.closeIntFD(fd0);
FileDispatcherImpl.closeIntFD(fd1);
FileDispatcherImpl.closeIntFD(kqfd);
KQueue.freePollArray(pollArrayAddress);
// Deregister channels
Iterator<SelectionKey> i = keys.iterator();
while (i.hasNext()) {
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
deregister(ski);
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
i.remove();
}
FileDispatcherImpl.closeIntFD(fd0);
FileDispatcherImpl.closeIntFD(fd1);
// Deregister channels
Iterator<SelectionKey> i = keys.iterator();
while (i.hasNext()) {
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
deregister(ski);
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
i.remove();
}
}
@Override
protected void implRegister(SelectionKeyImpl ski) {
assert Thread.holdsLock(nioKeys());
ensureOpen();
int fd = IOUtil.fdVal(ski.channel.getFD());
fdMap.put(Integer.valueOf(fd), new MapEntry(ski));
synchronized (updateLock) {
newKeys.addLast(ski);
}
keys.add(ski);
}
@Override
protected void implDereg(SelectionKeyImpl ski) throws IOException {
assert !ski.isValid();
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioKeys());
assert Thread.holdsLock(nioSelectedKeys());
int fd = ski.channel.getFDVal();
fdMap.remove(Integer.valueOf(fd));
kqueueWrapper.release(ski.channel);
keys.remove(ski);
fdToKey.remove(fd);
if (registeredReadFilter.get(fd)) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
registeredReadFilter.clear(fd);
}
if (registeredWriteFilter.get(fd)) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
registeredWriteFilter.clear(fd);
}
selectedKeys.remove(ski);
keys.remove(ski);
// remove from channel's key set
deregister(ski);
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
((SelChImpl) selch).kill();
}
@Override
public void putEventOps(SelectionKeyImpl ski, int ops) {
ensureOpen();
kqueueWrapper.setInterest(ski.channel, ops);
synchronized (updateLock) {
updateOps.addLast(ops); // ops first in case adding the key fails
updateKeys.addLast(ski);
}
}
@Override
public Selector wakeup() {
synchronized (interruptLock) {
if (!interruptTriggered) {
kqueueWrapper.interrupt();
try {
IOUtil.write1(fd1, (byte)0);
} catch (IOException ioe) {
throw new InternalError(ioe);
}
interruptTriggered = true;
}
}

View File

@ -23,17 +23,10 @@
* questions.
*/
/*
* KQueueSelectorProvider.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollSelectorProvider
*/
package sun.nio.ch;
import java.io.IOException;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.nio.channels.spi.AbstractSelector;
public class KQueueSelectorProvider
extends SelectorProviderImpl

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. 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
@ -26,7 +26,6 @@
package sun.nio.fs;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.spi.FileTypeDetector;
import sun.security.action.GetPropertyAction;
@ -46,7 +45,7 @@ public class MacOSXFileSystemProvider extends BsdFileSystemProvider {
@Override
FileTypeDetector getFileTypeDetector() {
Path userMimeTypes = Paths.get(GetPropertyAction
Path userMimeTypes = Path.of(GetPropertyAction
.privilegedGetProperty("user.home"), ".mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. 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
@ -23,76 +23,91 @@
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include "sun_nio_ch_KQueue.h"
#include <strings.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include "nio.h"
#include "nio_util.h"
#include "sun_nio_ch_KQueue.h"
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueue_keventSize(JNIEnv* env, jclass this)
Java_sun_nio_ch_KQueue_keventSize(JNIEnv* env, jclass clazz)
{
return sizeof(struct kevent);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueue_identOffset(JNIEnv* env, jclass this)
Java_sun_nio_ch_KQueue_identOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct kevent, ident);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueue_filterOffset(JNIEnv* env, jclass this)
Java_sun_nio_ch_KQueue_filterOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct kevent, filter);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueue_flagsOffset(JNIEnv* env, jclass this)
Java_sun_nio_ch_KQueue_flagsOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct kevent, flags);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueue_kqueue(JNIEnv *env, jclass c) {
Java_sun_nio_ch_KQueue_create(JNIEnv *env, jclass clazz) {
int kqfd = kqueue();
if (kqfd < 0) {
JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
return IOS_THROWN;
}
return kqfd;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueue_keventRegister(JNIEnv *env, jclass c, jint kqfd,
jint fd, jint filter, jint flags)
Java_sun_nio_ch_KQueue_register(JNIEnv *env, jclass clazz, jint kqfd,
jint fd, jint filter, jint flags)
{
struct kevent changes[1];
struct timespec timeout = {0, 0};
int res;
EV_SET(&changes[0], fd, filter, flags, 0, 0, 0);
RESTARTABLE(kevent(kqfd, &changes[0], 1, NULL, 0, &timeout), res);
RESTARTABLE(kevent(kqfd, &changes[0], 1, NULL, 0, NULL), res);
return (res == -1) ? errno : 0;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueue_keventPoll(JNIEnv *env, jclass c,
jint kqfd, jlong address, jint nevents)
Java_sun_nio_ch_KQueue_poll(JNIEnv *env, jclass clazz, jint kqfd, jlong address,
jint nevents, jlong timeout)
{
struct kevent *events = jlong_to_ptr(address);
int res;
struct timespec ts;
struct timespec *tsp;
RESTARTABLE(kevent(kqfd, NULL, 0, events, nevents, NULL), res);
if (timeout >= 0) {
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout % 1000) * 1000000;
tsp = &ts;
} else {
tsp = NULL;
}
res = kevent(kqfd, NULL, 0, events, nevents, tsp);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
if (errno == EINTR) {
return IOS_INTERRUPTED;
} else {
JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
return IOS_THROWN;
}
}
return res;
}

View File

@ -1,175 +0,0 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* KQueueArrayWrapper.c
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollArrayWrapper
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
JNIEXPORT void JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_initStructSizes(JNIEnv *env, jclass clazz)
{
#define CHECK_EXCEPTION() { \
if ((*env)->ExceptionCheck(env)) { \
goto exceptionOccurred; \
} \
}
#define CHECK_ERROR_AND_EXCEPTION(_field) { \
if (_field == NULL) { \
goto badField; \
} \
CHECK_EXCEPTION(); \
}
jfieldID field;
field = (*env)->GetStaticFieldID(env, clazz, "EVFILT_READ", "S");
CHECK_ERROR_AND_EXCEPTION(field);
(*env)->SetStaticShortField(env, clazz, field, EVFILT_READ);
CHECK_EXCEPTION();
field = (*env)->GetStaticFieldID(env, clazz, "EVFILT_WRITE", "S");
CHECK_ERROR_AND_EXCEPTION(field);
(*env)->SetStaticShortField(env, clazz, field, EVFILT_WRITE);
CHECK_EXCEPTION();
field = (*env)->GetStaticFieldID(env, clazz, "SIZEOF_KEVENT", "S");
CHECK_ERROR_AND_EXCEPTION(field);
(*env)->SetStaticShortField(env, clazz, field, (short) sizeof(struct kevent));
CHECK_EXCEPTION();
field = (*env)->GetStaticFieldID(env, clazz, "FD_OFFSET", "S");
CHECK_ERROR_AND_EXCEPTION(field);
(*env)->SetStaticShortField(env, clazz, field, (short) offsetof(struct kevent, ident));
CHECK_EXCEPTION();
field = (*env)->GetStaticFieldID(env, clazz, "FILTER_OFFSET", "S");
CHECK_ERROR_AND_EXCEPTION(field);
(*env)->SetStaticShortField(env, clazz, field, (short) offsetof(struct kevent, filter));
CHECK_EXCEPTION();
return;
badField:
return;
exceptionOccurred:
return;
#undef CHECK_EXCEPTION
#undef CHECK_ERROR_AND_EXCEPTION
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_init(JNIEnv *env, jobject this)
{
int kq = kqueue();
if (kq < 0) {
JNU_ThrowIOExceptionWithLastError(env, "KQueueArrayWrapper: kqueue() failed");
}
return kq;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_register0(JNIEnv *env, jobject this,
jint kq, jint fd, jint r, jint w)
{
struct kevent changes[2];
struct kevent errors[2];
struct timespec dontBlock = {0, 0};
// if (r) then { register for read } else { unregister for read }
// if (w) then { register for write } else { unregister for write }
// Ignore errors - they're probably complaints about deleting non-
// added filters - but provide an error array anyway because
// kqueue behaves erratically if some of its registrations fail.
EV_SET(&changes[0], fd, EVFILT_READ, r ? EV_ADD : EV_DELETE, 0, 0, 0);
EV_SET(&changes[1], fd, EVFILT_WRITE, w ? EV_ADD : EV_DELETE, 0, 0, 0);
kevent(kq, changes, 2, errors, 2, &dontBlock);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_kevent0(JNIEnv *env, jobject this, jint kq,
jlong kevAddr, jint kevCount,
jlong timeout)
{
struct kevent *kevs = (struct kevent *)jlong_to_ptr(kevAddr);
struct timespec ts;
struct timespec *tsp;
int result;
// Java timeout is in milliseconds. Convert to struct timespec.
// Java timeout == -1 : wait forever : timespec timeout of NULL
// Java timeout == 0 : return immediately : timespec timeout of zero
if (timeout >= 0) {
// For some indeterminate reason kevent(2) has been found to fail with
// an EINVAL error for timeout values greater than or equal to
// 100000001000L. To avoid this problem, clamp the timeout arbitrarily
// to the maximum value of a 32-bit signed integer which is
// approximately 25 days in milliseconds.
const jlong timeoutMax = 0x7fffffff; // java.lang.Integer.MAX_VALUE
if (timeout > timeoutMax) {
timeout = timeoutMax;
}
ts.tv_sec = timeout / 1000;
ts.tv_nsec = (timeout % 1000) * 1000000; //nanosec = 1 million millisec
tsp = &ts;
} else {
tsp = NULL;
}
RESTARTABLE(kevent(kq, NULL, 0, kevs, kevCount, tsp), result);
if (result < 0) {
JNU_ThrowIOExceptionWithLastError(env,
"KQueueArrayWrapper: kevent poll failed");
}
return result;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_interrupt(JNIEnv *env, jclass cls, jint fd)
{
char c = 1;
if (1 != write(fd, &c, 1)) {
JNU_ThrowIOExceptionWithLastError(env, "KQueueArrayWrapper: interrupt failed");
}
}

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include "sun_nio_ch_KQueuePort.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
JNIEXPORT void JNICALL
Java_sun_nio_ch_KQueuePort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
int sp[2];
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
} else {
jint res[2];
res[0] = (jint)sp[0];
res[1] = (jint)sp[1];
(*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_KQueuePort_interrupt(JNIEnv *env, jclass c, jint fd) {
int res;
int buf[1];
buf[0] = 1;
RESTARTABLE(write(fd, buf, 1), res);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "write failed");
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_KQueuePort_drain1(JNIEnv *env, jclass cl, jint fd) {
int res;
char buf[1];
RESTARTABLE(read(fd, buf, 1), res);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
}
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_KQueuePort_close0(JNIEnv *env, jclass c, jint fd) {
int res;
RESTARTABLE(close(fd), res);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2018, Oracle and/or its affiliates. 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
@ -25,12 +25,15 @@
package java.io;
import java.util.Arrays;
import java.util.Objects;
/**
* A <code>ByteArrayInputStream</code> contains
* A {@code ByteArrayInputStream} contains
* an internal buffer that contains bytes that
* may be read from the stream. An internal
* counter keeps track of the next byte to
* be supplied by the <code>read</code> method.
* be supplied by the {@code read} method.
* <p>
* Closing a {@code ByteArrayInputStream} has no effect. The methods in
* this class can be called after the stream has been closed without
@ -40,15 +43,14 @@ package java.io;
* @see java.io.StringBufferInputStream
* @since 1.0
*/
public
class ByteArrayInputStream extends InputStream {
public class ByteArrayInputStream extends InputStream {
/**
* An array of bytes that was provided
* by the creator of the stream. Elements <code>buf[0]</code>
* through <code>buf[count-1]</code> are the
* by the creator of the stream. Elements {@code buf[0]}
* through {@code buf[count-1]} are the
* only bytes that can ever be read from the
* stream; element <code>buf[pos]</code> is
* stream; element {@code buf[pos]} is
* the next byte to be read.
*/
protected byte buf[];
@ -56,9 +58,9 @@ class ByteArrayInputStream extends InputStream {
/**
* The index of the next character to read from the input stream buffer.
* This value should always be nonnegative
* and not larger than the value of <code>count</code>.
* and not larger than the value of {@code count}.
* The next byte to be read from the input stream buffer
* will be <code>buf[pos]</code>.
* will be {@code buf[pos]}.
*/
protected int pos;
@ -66,9 +68,9 @@ class ByteArrayInputStream extends InputStream {
* The currently marked position in the stream.
* ByteArrayInputStream objects are marked at position zero by
* default when constructed. They may be marked at another
* position within the buffer by the <code>mark()</code> method.
* position within the buffer by the {@code mark()} method.
* The current buffer position is set to this point by the
* <code>reset()</code> method.
* {@code reset()} method.
* <p>
* If no mark has been set, then the value of mark is the offset
* passed to the constructor (or 0 if the offset was not supplied).
@ -81,22 +83,22 @@ class ByteArrayInputStream extends InputStream {
* The index one greater than the last valid character in the input
* stream buffer.
* This value should always be nonnegative
* and not larger than the length of <code>buf</code>.
* and not larger than the length of {@code buf}.
* It is one greater than the position of
* the last byte within <code>buf</code> that
* the last byte within {@code buf} that
* can ever be read from the input stream buffer.
*/
protected int count;
/**
* Creates a <code>ByteArrayInputStream</code>
* so that it uses <code>buf</code> as its
* Creates a {@code ByteArrayInputStream}
* so that it uses {@code buf} as its
* buffer array.
* The buffer array is not copied.
* The initial value of <code>pos</code>
* is <code>0</code> and the initial value
* of <code>count</code> is the length of
* <code>buf</code>.
* The initial value of {@code pos}
* is {@code 0} and the initial value
* of {@code count} is the length of
* {@code buf}.
*
* @param buf the input buffer.
*/
@ -107,12 +109,12 @@ class ByteArrayInputStream extends InputStream {
}
/**
* Creates <code>ByteArrayInputStream</code>
* that uses <code>buf</code> as its
* buffer array. The initial value of <code>pos</code>
* is <code>offset</code> and the initial value
* of <code>count</code> is the minimum of <code>offset+length</code>
* and <code>buf.length</code>.
* Creates {@code ByteArrayInputStream}
* that uses {@code buf} as its
* buffer array. The initial value of {@code pos}
* is {@code offset} and the initial value
* of {@code count} is the minimum of {@code offset+length}
* and {@code buf.length}.
* The buffer array is not copied. The buffer's mark is
* set to the specified offset.
*
@ -129,15 +131,15 @@ class ByteArrayInputStream extends InputStream {
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* byte is returned as an {@code int} in the range
* {@code 0} to {@code 255}. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned.
* {@code -1} is returned.
* <p>
* This <code>read</code> method
* This {@code read} method
* cannot block.
*
* @return the next byte of data, or <code>-1</code> if the end of the
* @return the next byte of data, or {@code -1} if the end of the
* stream has been reached.
*/
public synchronized int read() {
@ -145,40 +147,30 @@ class ByteArrayInputStream extends InputStream {
}
/**
* Reads up to <code>len</code> bytes of data into an array of bytes
* from this input stream.
* If <code>pos</code> equals <code>count</code>,
* then <code>-1</code> is returned to indicate
* end of file. Otherwise, the number <code>k</code>
* of bytes read is equal to the smaller of
* <code>len</code> and <code>count-pos</code>.
* If <code>k</code> is positive, then bytes
* <code>buf[pos]</code> through <code>buf[pos+k-1]</code>
* are copied into <code>b[off]</code> through
* <code>b[off+k-1]</code> in the manner performed
* by <code>System.arraycopy</code>. The
* value <code>k</code> is added into <code>pos</code>
* and <code>k</code> is returned.
* Reads up to {@code len} bytes of data into an array of bytes from this
* input stream. If {@code pos} equals {@code count}, then {@code -1} is
* returned to indicate end of file. Otherwise, the number {@code k} of
* bytes read is equal to the smaller of {@code len} and {@code count-pos}.
* If {@code k} is positive, then bytes {@code buf[pos]} through
* {@code buf[pos+k-1]} are copied into {@code b[off]} through
* {@code b[off+k-1]} in the manner performed by {@code System.arraycopy}.
* The value {@code k} is added into {@code pos} and {@code k} is returned.
* <p>
* This <code>read</code> method cannot block.
* This {@code read} method cannot block.
*
* @param b the buffer into which the data is read.
* @param off the start offset in the destination array <code>b</code>
* @param off the start offset in the destination array {@code b}
* @param len the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or
* <code>-1</code> if there is no more data because the end of
* {@code -1} if there is no more data because the end of
* the stream has been reached.
* @exception NullPointerException If <code>b</code> is <code>null</code>.
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
* @throws NullPointerException If {@code b} is {@code null}.
* @throws IndexOutOfBoundsException If {@code off} is negative,
* {@code len} is negative, or {@code len} is greater than
* {@code b.length - off}
*/
public synchronized int read(byte b[], int off, int len) {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
}
Objects.checkFromIndexSize(off, len, b.length);
if (pos >= count) {
return -1;
@ -196,14 +188,32 @@ class ByteArrayInputStream extends InputStream {
return len;
}
public synchronized byte[] readAllBytes() {
byte[] result = Arrays.copyOfRange(buf, pos, count);
pos = count;
return result;
}
public int readNBytes(byte[] b, int off, int len) {
int n = read(b, off, len);
return n == -1 ? 0 : n;
}
public synchronized long transferTo(OutputStream out) throws IOException {
int len = count - pos;
out.write(buf, pos, len);
pos = count;
return len;
}
/**
* Skips <code>n</code> bytes of input from this input stream. Fewer
* Skips {@code n} bytes of input from this input stream. Fewer
* bytes might be skipped if the end of the input stream is reached.
* The actual number <code>k</code>
* The actual number {@code k}
* of bytes to be skipped is equal to the smaller
* of <code>n</code> and <code>count-pos</code>.
* The value <code>k</code> is added into <code>pos</code>
* and <code>k</code> is returned.
* of {@code n} and {@code count-pos}.
* The value {@code k} is added into {@code pos}
* and {@code k} is returned.
*
* @param n the number of bytes to be skipped.
* @return the actual number of bytes skipped.
@ -222,7 +232,7 @@ class ByteArrayInputStream extends InputStream {
* Returns the number of remaining bytes that can be read (or skipped over)
* from this input stream.
* <p>
* The value returned is <code>count&nbsp;- pos</code>,
* The value returned is {@code count - pos},
* which is the number of bytes remaining to be read from the input buffer.
*
* @return the number of remaining bytes that can be read (or skipped
@ -233,9 +243,9 @@ class ByteArrayInputStream extends InputStream {
}
/**
* Tests if this <code>InputStream</code> supports mark/reset. The
* <code>markSupported</code> method of <code>ByteArrayInputStream</code>
* always returns <code>true</code>.
* Tests if this {@code InputStream} supports mark/reset. The
* {@code markSupported} method of {@code ByteArrayInputStream}
* always returns {@code true}.
*
* @since 1.1
*/
@ -253,7 +263,7 @@ class ByteArrayInputStream extends InputStream {
* offset passed to the constructor (or 0 if the offset was not
* supplied).
*
* <p> Note: The <code>readAheadLimit</code> for this class
* <p> Note: The {@code readAheadLimit} for this class
* has no meaning.
*
* @since 1.1

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. 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
@ -30,7 +30,6 @@ import java.io.FilePermission;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Objects;
@ -63,7 +62,7 @@ final class ProxyClassesDumper {
}
try {
path = path.trim();
final Path dir = Paths.get(path.length() == 0 ? "." : path);
final Path dir = Path.of(path.length() == 0 ? "." : path);
AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public Void run() {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. 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
@ -34,7 +34,6 @@ import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@ -346,11 +345,11 @@ class ProxyGenerator {
int i = name.lastIndexOf('.');
Path path;
if (i > 0) {
Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
Path dir = Path.of(name.substring(0, i).replace('.', File.separatorChar));
Files.createDirectories(dir);
path = dir.resolve(name.substring(i+1, name.length()) + ".class");
} else {
path = Paths.get(name + ".class");
path = Path.of(name + ".class");
}
Files.write(path, classFile);
return null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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
@ -279,6 +279,9 @@ public abstract class DatagramChannel
*
* @return This datagram channel
*
* @throws AlreadyConnectedException
* If this channel is already connected
*
* @throws ClosedChannelException
* If this channel is closed
*
@ -292,6 +295,12 @@ public abstract class DatagramChannel
* closing the channel and setting the current thread's
* interrupt status
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
*
* @throws UnsupportedAddressTypeException
* If the type of the given remote address is not supported
*
* @throws SecurityException
* If a security manager has been installed
* and it does not permit access to the given remote address
@ -444,6 +453,10 @@ public abstract class DatagramChannel
* zero if there was insufficient room for the datagram in the
* underlying output buffer
*
* @throws AlreadyConnectedException
* If this channel is connected to a different address
* from that specified by {@code target}
*
* @throws ClosedChannelException
* If this channel is closed
*
@ -457,6 +470,12 @@ public abstract class DatagramChannel
* closing the channel and setting the current thread's
* interrupt status
*
* @throws UnresolvedAddressException
* If the given remote address is not fully resolved
*
* @throws UnsupportedAddressTypeException
* If the type of the given remote address is not supported
*
* @throws SecurityException
* If a security manager has been installed
* and it does not permit datagrams to be sent

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. 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
@ -28,6 +28,7 @@ package java.nio.file;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.spi.FileSystemProvider;
import java.util.Iterator;
import java.util.NoSuchElementException;
@ -93,12 +94,124 @@ import java.util.NoSuchElementException;
* multiple concurrent threads.
*
* @since 1.7
* @see Paths
*/
public interface Path
extends Comparable<Path>, Iterable<Path>, Watchable
{
/**
* Returns a {@code Path} by converting a path string, or a sequence of
* strings that when joined form a path string. If {@code more} does not
* specify any elements then the value of the {@code first} parameter is
* the path string to convert. If {@code more} specifies one or more
* elements then each non-empty string, including {@code first}, is
* considered to be a sequence of name elements and is joined to form a
* path string. The details as to how the Strings are joined is provider
* specific but typically they will be joined using the
* {@link FileSystem#getSeparator name-separator} as the separator.
* For example, if the name separator is "{@code /}" and
* {@code getPath("/foo","bar","gus")} is invoked, then the path string
* {@code "/foo/bar/gus"} is converted to a {@code Path}. A {@code Path}
* representing an empty path is returned if {@code first} is the empty
* string and {@code more} does not contain any non-empty strings.
*
* <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
* getPath} method of the {@link FileSystems#getDefault default} {@link
* FileSystem}.
*
* <p> Note that while this method is very convenient, using it will imply
* an assumed reference to the default {@code FileSystem} and limit the
* utility of the calling code. Hence it should not be used in library code
* intended for flexible reuse. A more flexible alternative is to use an
* existing {@code Path} instance as an anchor, such as:
* <pre>{@code
* Path dir = ...
* Path path = dir.resolve("file");
* }</pre>
*
* @param first
* the path string or initial part of the path string
* @param more
* additional strings to be joined to form the path string
*
* @return the resulting {@code Path}
*
* @throws InvalidPathException
* if the path string cannot be converted to a {@code Path}
*
* @see FileSystem#getPath
*
* @since 11
*/
public static Path of(String first, String... more) {
return FileSystems.getDefault().getPath(first, more);
}
/**
* Returns a {@code Path} by converting a URI.
*
* <p> This method iterates over the {@link FileSystemProvider#installedProviders()
* installed} providers to locate the provider that is identified by the
* URI {@link URI#getScheme scheme} of the given URI. URI schemes are
* compared without regard to case. If the provider is found then its {@link
* FileSystemProvider#getPath getPath} method is invoked to convert the
* URI.
*
* <p> In the case of the default provider, identified by the URI scheme
* "file", the given URI has a non-empty path component, and undefined query
* and fragment components. Whether the authority component may be present
* is platform specific. The returned {@code Path} is associated with the
* {@link FileSystems#getDefault default} file system.
*
* <p> The default provider provides a similar <em>round-trip</em> guarantee
* to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
* is guaranteed that
* <blockquote>{@code
* Path.of(}<i>p</i>{@code .}{@link Path#toUri() toUri}{@code ()).equals(}
* <i>p</i>{@code .}{@link Path#toAbsolutePath() toAbsolutePath}{@code ())}
* </blockquote>
* so long as the original {@code Path}, the {@code URI}, and the new {@code
* Path} are all created in (possibly different invocations of) the same
* Java virtual machine. Whether other providers make any guarantees is
* provider specific and therefore unspecified.
*
* @param uri
* the URI to convert
*
* @return the resulting {@code Path}
*
* @throws IllegalArgumentException
* if preconditions on the {@code uri} parameter do not hold. The
* format of the URI is provider specific.
* @throws FileSystemNotFoundException
* The file system, identified by the URI, does not exist and
* cannot be created automatically, or the provider identified by
* the URI's scheme component is not installed
* @throws SecurityException
* if a security manager is installed and it denies an unspecified
* permission to access the file system
*
* @since 11
*/
public static Path of(URI uri) {
String scheme = uri.getScheme();
if (scheme == null)
throw new IllegalArgumentException("Missing scheme");
// check for default provider to avoid loading of installed providers
if (scheme.equalsIgnoreCase("file"))
return FileSystems.getDefault().provider().getPath(uri);
// try to find provider
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
if (provider.getScheme().equalsIgnoreCase(scheme)) {
return provider.getPath(uri);
}
}
throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");
}
/**
* Returns the file system that created this object.
*
@ -527,7 +640,7 @@ public interface Path
* to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
* is guaranteed that
* <blockquote>
* {@link Paths#get(URI) Paths.get}{@code (}<i>p</i>{@code .toUri()).equals(}<i>p</i>
* {@link Path#of(URI) Path.of}{@code (}<i>p</i>{@code .toUri()).equals(}<i>p</i>
* {@code .}{@link #toAbsolutePath() toAbsolutePath}{@code ())}
* </blockquote>
* so long as the original {@code Path}, the {@code URI}, and the new {@code

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. 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
@ -32,7 +32,13 @@ import java.net.URI;
* This class consists exclusively of static methods that return a {@link Path}
* by converting a path string or {@link URI}.
*
* @apiNote
* It is recommended to obtain a {@code Path} via the {@code Path.of} methods
* instead of via the {@code get} methods defined in this class as this class
* may be deprecated in a future release.
*
* @since 1.7
* @see Path
*/
public final class Paths {
@ -40,33 +46,11 @@ public final class Paths {
/**
* Converts a path string, or a sequence of strings that when joined form
* a path string, to a {@code Path}. If {@code more} does not specify any
* elements then the value of the {@code first} parameter is the path string
* to convert. If {@code more} specifies one or more elements then each
* non-empty string, including {@code first}, is considered to be a sequence
* of name elements (see {@link Path}) and is joined to form a path string.
* The details as to how the Strings are joined is provider specific but
* typically they will be joined using the {@link FileSystem#getSeparator
* name-separator} as the separator. For example, if the name separator is
* "{@code /}" and {@code getPath("/foo","bar","gus")} is invoked, then the
* path string {@code "/foo/bar/gus"} is converted to a {@code Path}.
* A {@code Path} representing an empty path is returned if {@code first}
* is the empty string and {@code more} does not contain any non-empty
* strings.
* a path string, to a {@code Path}.
*
* <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
* getPath} method of the {@link FileSystems#getDefault default} {@link
* FileSystem}.
*
* <p> Note that while this method is very convenient, using it will imply
* an assumed reference to the default {@code FileSystem} and limit the
* utility of the calling code. Hence it should not be used in library code
* intended for flexible reuse. A more flexible alternative is to use an
* existing {@code Path} instance as an anchor, such as:
* <pre>
* Path dir = ...
* Path path = dir.resolve("file");
* </pre>
* @implSpec
* This method simply invokes {@link Path#of(String,String...)
* Path.of(String, String...)} with the given parameters.
*
* @param first
* the path string or initial part of the path string
@ -79,38 +63,17 @@ public final class Paths {
* if the path string cannot be converted to a {@code Path}
*
* @see FileSystem#getPath
* @see Path#of(String,String...)
*/
public static Path get(String first, String... more) {
return FileSystems.getDefault().getPath(first, more);
return Path.of(first, more);
}
/**
* Converts the given URI to a {@link Path} object.
*
* <p> This method iterates over the {@link FileSystemProvider#installedProviders()
* installed} providers to locate the provider that is identified by the
* URI {@link URI#getScheme scheme} of the given URI. URI schemes are
* compared without regard to case. If the provider is found then its {@link
* FileSystemProvider#getPath getPath} method is invoked to convert the
* URI.
*
* <p> In the case of the default provider, identified by the URI scheme
* "file", the given URI has a non-empty path component, and undefined query
* and fragment components. Whether the authority component may be present
* is platform specific. The returned {@code Path} is associated with the
* {@link FileSystems#getDefault default} file system.
*
* <p> The default provider provides a similar <em>round-trip</em> guarantee
* to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
* is guaranteed that
* <blockquote>{@code
* Paths.get(}<i>p</i>{@code .}{@link Path#toUri() toUri}{@code ()).equals(}
* <i>p</i>{@code .}{@link Path#toAbsolutePath() toAbsolutePath}{@code ())}
* </blockquote>
* so long as the original {@code Path}, the {@code URI}, and the new {@code
* Path} are all created in (possibly different invocations of) the same
* Java virtual machine. Whether other providers make any guarantees is
* provider specific and therefore unspecified.
* @implSpec
* This method simply invokes {@link Path#of(URI) * Path.of(URI)} with the given parameter.
*
* @param uri
* the URI to convert
@ -127,23 +90,10 @@ public final class Paths {
* @throws SecurityException
* if a security manager is installed and it denies an unspecified
* permission to access the file system
*
* @see Path#of(URI)
*/
public static Path get(URI uri) {
String scheme = uri.getScheme();
if (scheme == null)
throw new IllegalArgumentException("Missing scheme");
// check for default provider to avoid loading of installed providers
if (scheme.equalsIgnoreCase("file"))
return FileSystems.getDefault().provider().getPath(uri);
// try to find provider
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
if (provider.getScheme().equalsIgnoreCase(scheme)) {
return provider.getPath(uri);
}
}
throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");
return Path.of(uri);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. 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
@ -46,7 +46,7 @@ class TempFileHelper {
// temporary directory location
private static final Path tmpdir =
Paths.get(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
Path.of(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
private static final boolean isPosix =
FileSystems.getDefault().supportedFileAttributeViews().contains("posix");

View File

@ -93,9 +93,7 @@ public abstract class AbstractSet<E> extends AbstractCollection<E> implements Se
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
} catch (ClassCastException | NullPointerException unused) {
return false;
}
}

View File

@ -70,146 +70,297 @@ class ImmutableCollections {
static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
// ---------- List Implementations ----------
abstract static class AbstractImmutableList<E> extends AbstractList<E>
implements RandomAccess, Serializable {
static abstract class AbstractImmutableCollection<E> extends AbstractCollection<E> {
// all mutating methods throw UnsupportedOperationException
@Override public boolean add(E e) { throw uoe(); }
@Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
@Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
@Override public void clear() { throw uoe(); }
@Override public boolean remove(Object o) { throw uoe(); }
@Override public boolean removeAll(Collection<?> c) { throw uoe(); }
@Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }
@Override public void replaceAll(UnaryOperator<E> operator) { throw uoe(); }
@Override public boolean retainAll(Collection<?> c) { throw uoe(); }
@Override public void sort(Comparator<? super E> c) { throw uoe(); }
}
static final class List0<E> extends AbstractImmutableList<E> {
private static final List0<?> INSTANCE = new List0<>();
// ---------- List Implementations ----------
@SuppressWarnings("unchecked")
static <T> List0<T> instance() {
return (List0<T>) INSTANCE;
}
@SuppressWarnings("unchecked")
static <E> List<E> emptyList() {
return (List<E>) ListN.EMPTY_LIST;
}
private List0() { }
static abstract class AbstractImmutableList<E> extends AbstractImmutableCollection<E>
implements List<E>, RandomAccess {
// all mutating methods throw UnsupportedOperationException
@Override public void add(int index, E element) { throw uoe(); }
@Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
@Override public E remove(int index) { throw uoe(); }
@Override public void replaceAll(UnaryOperator<E> operator) { throw uoe(); }
@Override public E set(int index, E element) { throw uoe(); }
@Override public void sort(Comparator<? super E> c) { throw uoe(); }
@Override
public int size() {
return 0;
public List<E> subList(int fromIndex, int toIndex) {
int size = size();
subListRangeCheck(fromIndex, toIndex, size);
return SubList.fromList(this, fromIndex, toIndex);
}
@Override
public E get(int index) {
Objects.checkIndex(index, 0); // always throws IndexOutOfBoundsException
return null; // but the compiler doesn't know this
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
@Override
public Iterator<E> iterator() {
return Collections.emptyIterator();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST);
return new ListItr<E>(this, size());
}
@Override
public boolean contains(Object o) {
public ListIterator<E> listIterator() {
return listIterator(0);
}
@Override
public ListIterator<E> listIterator(final int index) {
int size = size();
if (index < 0 || index > size) {
throw outOfBounds(index);
}
return new ListItr<E>(this, size, index);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof List)) {
return false;
}
Iterator<?> oit = ((List<?>) o).iterator();
for (int i = 0, s = size(); i < s; i++) {
if (!oit.hasNext() || !get(i).equals(oit.next())) {
return false;
}
}
return !oit.hasNext();
}
@Override
public int indexOf(Object o) {
Objects.requireNonNull(o);
return false;
for (int i = 0, s = size(); i < s; i++) {
if (o.equals(get(i))) {
return i;
}
}
return -1;
}
@Override
public boolean containsAll(Collection<?> o) {
return o.isEmpty(); // implicit nullcheck of o
public int lastIndexOf(Object o) {
Objects.requireNonNull(o);
for (int i = size() - 1; i >= 0; i--) {
if (o.equals(get(i))) {
return i;
}
}
return -1;
}
@Override
public int hashCode() {
return 1;
}
}
static final class List1<E> extends AbstractImmutableList<E> {
@Stable
private final E e0;
List1(E e0) {
this.e0 = Objects.requireNonNull(e0);
}
@Override
public int size() {
return 1;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 1);
return e0;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, e0);
int hash = 1;
for (int i = 0, s = size(); i < s; i++) {
hash = 31 * hash + get(i).hashCode();
}
return hash;
}
@Override
public boolean contains(Object o) {
return o.equals(e0); // implicit nullcheck of o
return indexOf(o) >= 0;
}
@Override
public int hashCode() {
return 31 + e0.hashCode();
IndexOutOfBoundsException outOfBounds(int index) {
return new IndexOutOfBoundsException("Index: " + index + " Size: " + size());
}
}
static final class List2<E> extends AbstractImmutableList<E> {
static final class ListItr<E> implements ListIterator<E> {
@Stable
private final List<E> list;
@Stable
private final int size;
private int cursor;
ListItr(List<E> list, int size) {
this(list, size, 0);
}
ListItr(List<E> list, int size, int index) {
this.list = list;
this.size = size;
this.cursor = index;
}
public boolean hasNext() {
return cursor != size;
}
public E next() {
try {
int i = cursor;
E next = list.get(i);
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
public void remove() {
throw uoe();
}
public boolean hasPrevious() {
return cursor != 0;
}
public E previous() {
try {
int i = cursor - 1;
E previous = list.get(i);
cursor = i;
return previous;
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
public void set(E e) {
throw uoe();
}
public void add(E e) {
throw uoe();
}
}
static final class SubList<E> extends AbstractImmutableList<E>
implements RandomAccess {
@Stable
private final List<E> root;
@Stable
private final int offset;
@Stable
private final int size;
private SubList(List<E> root, int offset, int size) {
this.root = root;
this.offset = offset;
this.size = size;
}
/**
* Constructs a sublist of another SubList.
*/
static <E> SubList<E> fromSubList(SubList<E> parent, int fromIndex, int toIndex) {
return new SubList<E>(parent.root, parent.offset + fromIndex, toIndex - fromIndex);
}
/**
* Constructs a sublist of an arbitrary AbstractImmutableList, which is
* not a SubList itself.
*/
static <E> SubList<E> fromList(List<E> list, int fromIndex, int toIndex) {
return new SubList<E>(list, fromIndex, toIndex - fromIndex);
}
public E get(int index) {
Objects.checkIndex(index, size);
return root.get(offset + index);
}
public int size() {
return size;
}
public Iterator<E> iterator() {
return new ListItr<E>(this, size());
}
public ListIterator<E> listIterator(int index) {
rangeCheck(index);
return new ListItr<E>(this, size(), index);
}
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return SubList.fromSubList(this, fromIndex, toIndex);
}
private void rangeCheck(int index) {
if (index < 0 || index > size) {
throw outOfBounds(index);
}
}
}
static final class List12<E> extends AbstractImmutableList<E>
implements Serializable {
@Stable
private final E e0;
@Stable
private final E e1;
List2(E e0, E e1) {
List12(E e0) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = null;
}
List12(E e0, E e1) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = Objects.requireNonNull(e1);
}
@Override
public int size() {
return 2;
return e1 != null ? 2 : 1;
}
@Override
public E get(int index) {
Objects.checkIndex(index, 2);
if (index == 0) {
return e0;
} else { // index == 1
} else if (index == 1 && e1 != null) {
return e1;
}
}
@Override
public boolean contains(Object o) {
return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
}
@Override
public int hashCode() {
int hash = 31 + e0.hashCode();
return 31 * hash + e1.hashCode();
throw outOfBounds(index);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@ -217,11 +368,20 @@ class ImmutableCollections {
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_LIST, e0, e1);
if (e1 == null) {
return new CollSer(CollSer.IMM_LIST, e0);
} else {
return new CollSer(CollSer.IMM_LIST, e0, e1);
}
}
}
static final class ListN<E> extends AbstractImmutableList<E> {
static final class ListN<E> extends AbstractImmutableList<E>
implements Serializable {
static final List<?> EMPTY_LIST = new ListN<>();
@Stable
private final E[] elements;
@ -233,7 +393,12 @@ class ImmutableCollections {
for (int i = 0; i < input.length; i++) {
tmp[i] = Objects.requireNonNull(input[i]);
}
this.elements = tmp;
elements = tmp;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
@ -243,29 +408,9 @@ class ImmutableCollections {
@Override
public E get(int index) {
Objects.checkIndex(index, elements.length);
return elements[index];
}
@Override
public boolean contains(Object o) {
for (E e : elements) {
if (o.equals(e)) { // implicit nullcheck of o
return true;
}
}
return false;
}
@Override
public int hashCode() {
int hash = 1;
for (E e : elements) {
hash = 31 * hash + e.hashCode();
}
return hash;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
@ -277,105 +422,52 @@ class ImmutableCollections {
// ---------- Set Implementations ----------
abstract static class AbstractImmutableSet<E> extends AbstractSet<E> implements Serializable {
@Override public boolean add(E e) { throw uoe(); }
@Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
@Override public void clear() { throw uoe(); }
@Override public boolean remove(Object o) { throw uoe(); }
@Override public boolean removeAll(Collection<?> c) { throw uoe(); }
@Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }
@Override public boolean retainAll(Collection<?> c) { throw uoe(); }
static abstract class AbstractImmutableSet<E> extends AbstractImmutableCollection<E>
implements Set<E> {
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Set)) {
return false;
}
Collection<?> c = (Collection<?>) o;
if (c.size() != size()) {
return false;
}
for (Object e : c) {
if (e == null || !contains(e)) {
return false;
}
}
return true;
}
@Override
public abstract int hashCode();
}
static final class Set0<E> extends AbstractImmutableSet<E> {
private static final Set0<?> INSTANCE = new Set0<>();
@SuppressWarnings("unchecked")
static <T> Set0<T> instance() {
return (Set0<T>) INSTANCE;
}
private Set0() { }
@Override
public int size() {
return 0;
}
@Override
public boolean contains(Object o) {
Objects.requireNonNull(o);
return false;
}
@Override
public boolean containsAll(Collection<?> o) {
return o.isEmpty(); // implicit nullcheck of o
}
@Override
public Iterator<E> iterator() {
return Collections.emptyIterator();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET);
}
@Override
public int hashCode() {
return 0;
}
@SuppressWarnings("unchecked")
static <E> Set<E> emptySet() {
return (Set<E>) SetN.EMPTY_SET;
}
static final class Set1<E> extends AbstractImmutableSet<E> {
@Stable
private final E e0;
static final class Set12<E> extends AbstractImmutableSet<E>
implements Serializable {
Set1(E e0) {
this.e0 = Objects.requireNonNull(e0);
}
@Override
public int size() {
return 1;
}
@Override
public boolean contains(Object o) {
return o.equals(e0); // implicit nullcheck of o
}
@Override
public Iterator<E> iterator() {
return Collections.singletonIterator(e0);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET, e0);
}
@Override
public int hashCode() {
return e0.hashCode();
}
}
static final class Set2<E> extends AbstractImmutableSet<E> {
@Stable
final E e0;
@Stable
final E e1;
Set2(E e0, E e1) {
Set12(E e0) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = null;
}
Set12(E e0, E e1) {
if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0
throw new IllegalArgumentException("duplicate element: " + e0);
}
@ -391,7 +483,7 @@ class ImmutableCollections {
@Override
public int size() {
return 2;
return (e1 == null) ? 1 : 2;
}
@Override
@ -401,26 +493,26 @@ class ImmutableCollections {
@Override
public int hashCode() {
return e0.hashCode() + e1.hashCode();
return e0.hashCode() + (e1 == null ? 0 : e1.hashCode());
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
private int idx = 0;
return new Iterator<>() {
private int idx = size();
@Override
public boolean hasNext() {
return idx < 2;
return idx > 0;
}
@Override
public E next() {
if (idx == 0) {
idx = 1;
if (idx == 1) {
idx = 0;
return e0;
} else if (idx == 1) {
idx = 2;
} else if (idx == 2) {
idx = 1;
return e1;
} else {
throw new NoSuchElementException();
@ -434,7 +526,11 @@ class ImmutableCollections {
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_SET, e0, e1);
if (e1 == null) {
return new CollSer(CollSer.IMM_SET, e0);
} else {
return new CollSer(CollSer.IMM_SET, e0, e1);
}
}
}
@ -444,7 +540,11 @@ class ImmutableCollections {
* least one null is always present.
* @param <E> the element type
*/
static final class SetN<E> extends AbstractImmutableSet<E> {
static final class SetN<E> extends AbstractImmutableSet<E>
implements Serializable {
static final Set<?> EMPTY_SET = new SetN<>();
@Stable
final E[] elements;
@Stable
@ -474,12 +574,13 @@ class ImmutableCollections {
@Override
public boolean contains(Object o) {
return probe(o) >= 0; // implicit nullcheck of o
Objects.requireNonNull(o);
return size > 0 && probe(o) >= 0;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
return new Iterator<>() {
private int idx = 0;
@Override
@ -549,6 +650,11 @@ class ImmutableCollections {
// ---------- Map Implementations ----------
@SuppressWarnings("unchecked")
static <K,V> Map<K,V> emptyMap() {
return (Map<K,V>) MapN.EMPTY_MAP;
}
abstract static class AbstractImmutableMap<K,V> extends AbstractMap<K,V> implements Serializable {
@Override public void clear() { throw uoe(); }
@Override public V compute(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); }
@ -565,47 +671,6 @@ class ImmutableCollections {
@Override public void replaceAll(BiFunction<? super K,? super V,? extends V> f) { throw uoe(); }
}
static final class Map0<K,V> extends AbstractImmutableMap<K,V> {
private static final Map0<?,?> INSTANCE = new Map0<>();
@SuppressWarnings("unchecked")
static <K,V> Map0<K,V> instance() {
return (Map0<K,V>) INSTANCE;
}
private Map0() { }
@Override
public Set<Map.Entry<K,V>> entrySet() {
return Set.of();
}
@Override
public boolean containsKey(Object o) {
Objects.requireNonNull(o);
return false;
}
@Override
public boolean containsValue(Object o) {
Objects.requireNonNull(o);
return false;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("not serial proxy");
}
private Object writeReplace() {
return new CollSer(CollSer.IMM_MAP);
}
@Override
public int hashCode() {
return 0;
}
}
static final class Map1<K,V> extends AbstractImmutableMap<K,V> {
@Stable
private final K k0;
@ -656,8 +721,12 @@ class ImmutableCollections {
* @param <V> the value type
*/
static final class MapN<K,V> extends AbstractImmutableMap<K,V> {
static final Map<?,?> EMPTY_MAP = new MapN<>();
@Stable
final Object[] table; // pairs of key, value
@Stable
final int size; // number of pairs
@ -689,14 +758,16 @@ class ImmutableCollections {
@Override
public boolean containsKey(Object o) {
return probe(o) >= 0; // implicit nullcheck of o
Objects.requireNonNull(o);
return size > 0 && probe(o) >= 0;
}
@Override
public boolean containsValue(Object o) {
Objects.requireNonNull(o);
for (int i = 1; i < table.length; i += 2) {
Object v = table[i];
if (v != null && o.equals(v)) { // implicit nullcheck of o
if (v != null && o.equals(v)) {
return true;
}
}
@ -718,6 +789,10 @@ class ImmutableCollections {
@Override
@SuppressWarnings("unchecked")
public V get(Object o) {
if (size == 0) {
Objects.requireNonNull(o);
return null;
}
int i = probe(o);
if (i >= 0) {
return (V)table[i+1];
@ -733,7 +808,7 @@ class ImmutableCollections {
@Override
public Set<Map.Entry<K,V>> entrySet() {
return new AbstractSet<Map.Entry<K,V>>() {
return new AbstractSet<>() {
@Override
public int size() {
return MapN.this.size;
@ -741,7 +816,7 @@ class ImmutableCollections {
@Override
public Iterator<Map.Entry<K,V>> iterator() {
return new Iterator<Map.Entry<K,V>>() {
return new Iterator<>() {
int idx = 0;
@Override
@ -948,7 +1023,7 @@ final class CollSer implements Serializable {
return Set.of(array);
case IMM_MAP:
if (array.length == 0) {
return ImmutableCollections.Map0.instance();
return ImmutableCollections.emptyMap();
} else if (array.length == 2) {
return new ImmutableCollections.Map1<>(array[0], array[1]);
} else {

View File

@ -788,7 +788,7 @@ public interface List<E> extends Collection<E> {
* @since 9
*/
static <E> List<E> of() {
return ImmutableCollections.List0.instance();
return ImmutableCollections.emptyList();
}
/**
@ -804,7 +804,7 @@ public interface List<E> extends Collection<E> {
* @since 9
*/
static <E> List<E> of(E e1) {
return new ImmutableCollections.List1<>(e1);
return new ImmutableCollections.List12<>(e1);
}
/**
@ -821,7 +821,7 @@ public interface List<E> extends Collection<E> {
* @since 9
*/
static <E> List<E> of(E e1, E e2) {
return new ImmutableCollections.List2<>(e1, e2);
return new ImmutableCollections.List12<>(e1, e2);
}
/**
@ -1031,11 +1031,11 @@ public interface List<E> extends Collection<E> {
static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.List0.instance();
return ImmutableCollections.emptyList();
case 1:
return new ImmutableCollections.List1<>(elements[0]);
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List2<>(elements[0], elements[1]);
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}

View File

@ -1287,7 +1287,7 @@ public interface Map<K, V> {
* @since 9
*/
static <K, V> Map<K, V> of() {
return ImmutableCollections.Map0.instance();
return ImmutableCollections.emptyMap();
}
/**
@ -1604,11 +1604,11 @@ public interface Map<K, V> {
@SuppressWarnings("varargs")
static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
if (entries.length == 0) { // implicit null check of entries array
return ImmutableCollections.Map0.instance();
return ImmutableCollections.emptyMap();
} else if (entries.length == 1) {
// implicit null check of the array slot
return new ImmutableCollections.Map1<>(entries[0].getKey(),
entries[0].getValue());
entries[0].getValue());
} else {
Object[] kva = new Object[entries.length << 1];
int a = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. 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
@ -2897,7 +2897,7 @@ public final class Scanner implements Iterator<String>, Closeable {
* letters:
*
* <pre>{@code
* try (Scanner sc = new Scanner(Paths.get("input.txt"))) {
* try (Scanner sc = new Scanner(Path.of("input.txt"))) {
* Pattern pat = Pattern.compile("[A-Z]{7,}");
* List<String> capWords = sc.findAll(pat)
* .map(MatchResult::group)

View File

@ -449,7 +449,7 @@ public interface Set<E> extends Collection<E> {
* @since 9
*/
static <E> Set<E> of() {
return ImmutableCollections.Set0.instance();
return ImmutableCollections.emptySet();
}
/**
@ -464,7 +464,7 @@ public interface Set<E> extends Collection<E> {
* @since 9
*/
static <E> Set<E> of(E e1) {
return new ImmutableCollections.Set1<>(e1);
return new ImmutableCollections.Set12<>(e1);
}
/**
@ -481,7 +481,7 @@ public interface Set<E> extends Collection<E> {
* @since 9
*/
static <E> Set<E> of(E e1, E e2) {
return new ImmutableCollections.Set2<>(e1, e2);
return new ImmutableCollections.Set12<>(e1, e2);
}
/**
@ -692,11 +692,11 @@ public interface Set<E> extends Collection<E> {
static <E> Set<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.Set0.instance();
return ImmutableCollections.emptySet();
case 1:
return new ImmutableCollections.Set1<>(elements[0]);
return new ImmutableCollections.Set12<>(elements[0]);
case 2:
return new ImmutableCollections.Set2<>(elements[0], elements[1]);
return new ImmutableCollections.Set12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.SetN<>(elements);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. 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
@ -32,7 +32,6 @@ import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
@ -243,8 +242,8 @@ public class BootLoader {
mn = location.substring(5, location.length());
} else if (location.startsWith("file:/")) {
// named module in exploded image
Path path = Paths.get(URI.create(location));
Path modulesDir = Paths.get(JAVA_HOME, "modules");
Path path = Path.of(URI.create(location));
Path modulesDir = Path.of(JAVA_HOME, "modules");
if (path.startsWith(modulesDir)) {
mn = path.getFileName().toString();
}
@ -267,7 +266,7 @@ public class BootLoader {
private static URL toFileURL(String location) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
public URL run() {
Path path = Paths.get(location);
Path path = Path.of(location);
if (Files.isRegularFile(path)) {
try {
return path.toUri().toURL();
@ -285,7 +284,7 @@ public class BootLoader {
private static Manifest getManifest(String location) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
public Manifest run() {
Path jar = Paths.get(location);
Path jar = Path.of(location);
try (InputStream in = Files.newInputStream(jar);
JarInputStream jis = new JarInputStream(in, false)) {
return jis.getManifest();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. 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
@ -28,7 +28,7 @@ package jdk.internal.loader;
import java.io.IOException;
import java.net.URL;
import java.nio.file.InvalidPathException;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.util.jar.Manifest;
@ -223,7 +223,7 @@ public class ClassLoaders {
// Use an intermediate File object to construct a URI/URL without
// authority component as URLClassPath can't handle URLs with a UNC
// server name in the authority component.
return Paths.get(s).toRealPath().toFile().toURI().toURL();
return Path.of(s).toRealPath().toFile().toURI().toURL();
} catch (InvalidPathException | IOException ignore) {
// malformed path string or class path element does not exist
return null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. 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
@ -34,7 +34,6 @@ import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -539,7 +538,7 @@ public final class ModuleBootstrap {
Path[] paths = new Path[dirs.length];
int i = 0;
for (String dir: dirs) {
paths[i++] = Paths.get(dir);
paths[i++] = Path.of(dir);
}
return ModulePath.of(patcher, paths);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. 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
@ -30,7 +30,6 @@ import java.lang.module.Configuration;
import java.lang.module.ResolvedModule;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
@ -129,7 +128,7 @@ public class ModuleHashesBuilder {
() -> new InternalError("Selected module " + name + " not on module path"));
URI uri = rm.reference().location().get();
Path path = Paths.get(uri);
Path path = Path.of(uri);
String fn = path.getFileName().toString();
if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. 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
@ -43,7 +43,6 @@ import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
@ -360,7 +359,7 @@ public class ModulePath implements ModuleFinder {
URI uri = mref.location().orElse(null);
if (uri != null) {
if (uri.getScheme().equalsIgnoreCase("file")) {
Path file = Paths.get(uri);
Path file = Path.of(uri);
return file.getFileName().toString();
} else {
return uri.toString();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. 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
@ -38,7 +38,6 @@ import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayDeque;
@ -185,7 +184,7 @@ public final class SystemModuleFinders {
// probe to see if this is an images build
String home = System.getProperty("java.home");
Path modules = Paths.get(home, "lib", "modules");
Path modules = Path.of(home, "lib", "modules");
if (Files.isRegularFile(modules)) {
if (USE_FAST_PATH) {
SystemModules systemModules = allSystemModules();
@ -205,7 +204,7 @@ public final class SystemModuleFinders {
}
// exploded build (do not cache module finder)
Path dir = Paths.get(home, "modules");
Path dir = Path.of(home, "modules");
if (!Files.isDirectory(dir))
throw new InternalError("Unable to detect the run-time image");
ModuleFinder f = ModulePath.of(ModuleBootstrap.patcher(), dir);

View File

@ -508,8 +508,7 @@ class DatagramChannelImpl
if (remote != null) {
// connected
if (!target.equals(remote)) {
throw new IllegalArgumentException(
"Connected address not equal to target address");
throw new AlreadyConnectedException();
}
do {
n = IOUtil.write(fd, src, -1, nd);

View File

@ -397,7 +397,9 @@ public class IOUtil {
* The read end of the pipe is returned in the high 32 bits,
* while the write end is returned in the low 32 bits.
*/
static native long makePipe(boolean blocking);
static native long makePipe(boolean blocking) throws IOException;
static native int write1(int fd, byte b) throws IOException;
static native boolean drain(int fd) throws IOException;

View File

@ -33,10 +33,10 @@ import java.nio.channels.spi.AbstractSelectionKey;
/**
* An implementation of SelectionKey for Solaris.
* An implementation of SelectionKey.
*/
public class SelectionKeyImpl
public final class SelectionKeyImpl
extends AbstractSelectionKey
{
@ -54,12 +54,14 @@ public class SelectionKeyImpl
selector = sel;
}
@Override
public SelectableChannel channel() {
return (SelectableChannel)channel;
}
@Override
public Selector selector() {
return selector;
return (Selector)selector;
}
int getIndex() { // package-private
@ -75,16 +77,19 @@ public class SelectionKeyImpl
throw new CancelledKeyException();
}
@Override
public int interestOps() {
ensureValid();
return interestOps;
}
@Override
public SelectionKey interestOps(int ops) {
ensureValid();
return nioInterestOps(ops);
}
@Override
public int readyOps() {
ensureValid();
return readyOps;
@ -131,4 +136,6 @@ public class SelectionKeyImpl
return sb.toString();
}
// used by Selector implementations to record when the key was selected
int lastPolled;
}

View File

@ -78,6 +78,16 @@ public abstract class SelectorImpl
return publicSelectedKeys;
}
/**
* Returns the public view of the key sets
*/
protected final Set<SelectionKey> nioKeys() {
return publicKeys;
}
protected final Set<SelectionKey> nioSelectedKeys() {
return publicSelectedKeys;
}
protected abstract int doSelect(long timeout) throws IOException;
private int lockAndDoSelect(long timeout) throws IOException {
@ -125,8 +135,6 @@ public abstract class SelectorImpl
protected abstract void implClose() throws IOException;
public abstract void putEventOps(SelectionKeyImpl sk, int ops);
@Override
protected final SelectionKey register(AbstractSelectableChannel ch,
int ops,
@ -166,4 +174,9 @@ public abstract class SelectorImpl
}
}
}
/**
* Invoked to change the key's interest set
*/
public abstract void putEventOps(SelectionKeyImpl ski, int ops);
}

View File

@ -210,25 +210,20 @@ class ServerSocketChannelImpl
@Override
public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
acceptLock.lock();
try {
synchronized (stateLock) {
ensureOpen();
if (localAddress != null)
throw new AlreadyBoundException();
InetSocketAddress isa = (local == null)
? new InetSocketAddress(0)
: Net.checkAddress(local);
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkListen(isa.getPort());
NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
Net.bind(fd, isa.getAddress(), isa.getPort());
Net.listen(fd, backlog < 1 ? 50 : backlog);
localAddress = Net.localAddress(fd);
}
} finally {
acceptLock.unlock();
synchronized (stateLock) {
ensureOpen();
if (localAddress != null)
throw new AlreadyBoundException();
InetSocketAddress isa = (local == null)
? new InetSocketAddress(0)
: Net.checkAddress(local);
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkListen(isa.getPort());
NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
Net.bind(fd, isa.getAddress(), isa.getPort());
Net.listen(fd, backlog < 1 ? 50 : backlog);
localAddress = Net.localAddress(fd);
}
return this;
}

View File

@ -30,7 +30,7 @@ import java.lang.reflect.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URI;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.util.*;
import java.security.*;
import java.security.cert.Certificate;
@ -278,7 +278,7 @@ public class PolicyFile extends java.security.Policy {
public URL run() {
String sep = File.separator;
try {
return Paths.get(System.getProperty("java.home"),
return Path.of(System.getProperty("java.home"),
"lib", "security",
"default.policy").toUri().toURL();
} catch (MalformedURLException mue) {

View File

@ -27,7 +27,7 @@ package sun.security.tools.keytool;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.security.CodeSigner;
import java.security.CryptoPrimitive;
import java.security.KeyStore;
@ -2189,7 +2189,7 @@ public final class Main {
inplaceBackupName = srcksfname + ".old" + (n == 1 ? "" : n);
File bkFile = new File(inplaceBackupName);
if (!bkFile.exists()) {
Files.copy(Paths.get(srcksfname), bkFile.toPath());
Files.copy(Path.of(srcksfname), bkFile.toPath());
break;
}
}

View File

@ -244,21 +244,8 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
PUTPROP(props, "line.separator", sprops->line_separator);
/*
* user.language
* user.script, user.country, user.variant (if user's environment specifies them)
* file.encoding
* file encoding for stdout and stderr
*/
PUTPROP(props, "user.language", sprops->language);
if (sprops->script) {
PUTPROP(props, "user.script", sprops->script);
}
if (sprops->country) {
PUTPROP(props, "user.country", sprops->country);
}
if (sprops->variant) {
PUTPROP(props, "user.variant", sprops->variant);
}
PUTPROP(props, "file.encoding", sprops->encoding);
if (sprops->sun_stdout_encoding != NULL) {
PUTPROP(props, "sun.stdout.encoding", sprops->sun_stdout_encoding);
}
@ -314,7 +301,7 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
#endif
/* !!! DO NOT call PUTPROP_ForPlatformNString before this line !!!
* !!! I18n properties have not been set up yet !!!
* !!! The platform native encoding for strings has not been set up yet !!!
*/
InitializeEncoding(env, sprops->sun_jnu_encoding);
@ -379,17 +366,6 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
PUTPROP(props, "sun.desktop", sprops->desktop);
}
/*
* unset "user.language", "user.script", "user.country", and "user.variant"
* in order to tell whether the command line option "-DXXXX=YYYY" is
* specified or not. They will be reset in fillI18nProps() below.
*/
REMOVEPROP(props, "user.language");
REMOVEPROP(props, "user.script");
REMOVEPROP(props, "user.country");
REMOVEPROP(props, "user.variant");
REMOVEPROP(props, "file.encoding");
ret = JVM_InitProperties(env, props);
/* reconstruct i18n related properties */

View File

@ -127,7 +127,7 @@ class DevPollArrayWrapper {
// descriptor is registered with /dev/poll.
private final BitSet registered = new BitSet();
DevPollArrayWrapper() {
DevPollArrayWrapper() throws IOException {
int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
pollArray = new AllocatedNativeObject(allocationSize, true);
pollArrayAddress = pollArray.address();
@ -136,7 +136,7 @@ class DevPollArrayWrapper {
eventsHigh = new HashMap<>();
}
void initInterrupt(int fd0, int fd1) {
void initInterrupt(int fd0, int fd1) throws IOException {
outgoingInterruptFD = fd1;
incomingInterruptFD = fd0;
register(wfd, fd0, POLLIN);
@ -200,7 +200,7 @@ class DevPollArrayWrapper {
}
}
void release(int fd) {
void release(int fd) throws IOException {
synchronized (updateLock) {
// ignore any pending update for this file descriptor
setUpdateEvents(fd, IGNORE);
@ -297,7 +297,11 @@ class DevPollArrayWrapper {
boolean interrupted = false;
public void interrupt() {
interrupt(outgoingInterruptFD);
try {
IOUtil.write1(outgoingInterruptFD, (byte)0);
} catch (IOException ioe) {
throw new InternalError(ioe);
}
}
public int interruptedIndex() {
@ -312,13 +316,12 @@ class DevPollArrayWrapper {
interrupted = false;
}
private native int init();
private native void register(int wfd, int fd, int mask);
private native int init() throws IOException;
private native void register(int wfd, int fd, int mask) throws IOException;
private native void registerMultiple(int wfd, long address, int len)
throws IOException;
private native int poll0(long pollAddress, int numfds, long timeout,
int wfd);
private static native void interrupt(int fd);
private native int poll0(long pollAddress, int numfds, long timeout, int wfd)
throws IOException;
static {
IOUtil.load();

View File

@ -61,7 +61,7 @@ class DevPollSelectorImpl
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
DevPollSelectorImpl(SelectorProvider sp) {
DevPollSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. 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
@ -181,12 +181,26 @@ class EventPortWrapper {
}
// poll for events
int updated = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout);
int numEntries;
long to = timeout;
boolean timedPoll = (to > 0);
do {
long startTime = timedPoll ? System.currentTimeMillis() : 0;
numEntries = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout);
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
// timed poll interrupted so need to adjust timeout
to -= System.currentTimeMillis() - startTime;
if (to <= 0) {
// timeout also expired so no retry
numEntries = 0;
}
}
} while (numEntries == IOStatus.INTERRUPTED);
// after polling we need to queue all polled file descriptors as they
// are candidates to register for the next poll.
synchronized (updateLock) {
for (int i=0; i<updated; i++) {
for (int i=0; i<numEntries; i++) {
if (getSource(i) == PORT_SOURCE_USER) {
interrupted = true;
setDescriptor(i, -1);
@ -199,7 +213,7 @@ class EventPortWrapper {
}
}
return updated;
return numEntries;
}
private void setInterest(int fd) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. 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
@ -164,7 +164,10 @@ class SolarisEventPort
// A error here is fatal (thread will not be replaced)
replaceMe = false;
try {
port_get(port, address);
int n;
do {
n = port_get(port, address);
} while (n == IOStatus.INTERRUPTED);
} catch (IOException x) {
x.printStackTrace();
return;
@ -240,7 +243,7 @@ class SolarisEventPort
/**
* Retrieves a single event from a port
*/
static native void port_get(int port, long pe) throws IOException;
static native int port_get(int port, long address) throws IOException;
/**
* Retrieves at most {@code max} events from a port.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. 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
@ -84,9 +84,9 @@ public class SolarisFileSystemProvider extends UnixFileSystemProvider {
@Override
FileTypeDetector getFileTypeDetector() {
Path userMimeTypes = Paths.get(
Path userMimeTypes = Path.of(
GetPropertyAction.privilegedGetProperty("user.home"), ".mime.types");
Path etcMimeTypes = Paths.get("/etc/mime.types");
Path etcMimeTypes = Path.of("/etc/mime.types");
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
new MimeTypesFileTypeDetector(etcMimeTypes));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. 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
@ -176,14 +176,3 @@ Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
}
return result;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_DevPollArrayWrapper_interrupt(JNIEnv *env, jclass this, jint fd)
{
int fakebuf[1];
fakebuf[0] = 1;
if (write(fd, fakebuf, 1) < 0) {
JNU_ThrowIOExceptionWithLastError(env,
"Write to interrupt fd failed");
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. 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
@ -23,17 +23,18 @@
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <port.h>
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio.h"
#include "nio_util.h"
#include "sun_nio_ch_SolarisEventPort.h"
JNIEXPORT jint JNICALL
@ -51,8 +52,10 @@ JNIEXPORT void JNICALL
Java_sun_nio_ch_SolarisEventPort_port_1close
(JNIEnv* env, jclass clazz, jint port)
{
int res;
RESTARTABLE(close(port), res);
int res = close(port);
if (res < 0 && res != EINTR) {
JNU_ThrowIOExceptionWithLastError(env, "close failed");
}
}
JNIEXPORT jboolean JNICALL
@ -93,17 +96,23 @@ Java_sun_nio_ch_SolarisEventPort_port_1send(JNIEnv* env, jclass clazz,
}
}
JNIEXPORT void JNICALL
JNIEXPORT jint JNICALL
Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz,
jint port, jlong eventAddress)
{
int res;
port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress);
RESTARTABLE(port_get((int)port, ev, NULL), res);
res = port_get((int)port, ev, NULL);
if (res == -1) {
JNU_ThrowIOExceptionWithLastError(env, "port_get");
if (errno == EINTR) {
return IOS_INTERRUPTED;
} else {
JNU_ThrowIOExceptionWithLastError(env, "port_get failed");
return IOS_THROWN;
}
}
return res;
}
JNIEXPORT jint JNICALL
@ -125,9 +134,13 @@ Java_sun_nio_ch_SolarisEventPort_port_1getn(JNIEnv* env, jclass clazz,
}
res = port_getn((int)port, list, (uint_t)max, &n, tsp);
if (res == -1) {
if (errno != ETIME && errno != EINTR)
JNU_ThrowIOExceptionWithLastError(env, "port_getn");
if (res == -1 && errno != ETIME) {
if (errno == EINTR) {
return IOS_INTERRUPTED;
} else {
JNU_ThrowIOExceptionWithLastError(env, "port_getn failed");
return IOS_THROWN;
}
}
return (jint)n;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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
@ -38,7 +38,7 @@ class PipeImpl
private final SourceChannel source;
private final SinkChannel sink;
PipeImpl(SelectorProvider sp) {
PipeImpl(SelectorProvider sp) throws IOException {
long pipeFds = IOUtil.makePipe(true);
int readFd = (int) (pipeFds >>> 32);
int writeFd = (int) pipeFds;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. 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
@ -51,7 +51,7 @@ class PollSelectorImpl
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
PollSelectorImpl(SelectorProvider sp) {
PollSelectorImpl(SelectorProvider sp) throws IOException {
super(sp, 1, 1);
long pipeFds = IOUtil.makePipe(false);
fd0 = (int) (pipeFds >>> 32);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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
@ -25,15 +25,15 @@
package sun.nio.ch;
import java.io.*;
import java.io.FileDescriptor;
import java.io.IOException;
/**
* Allows different platforms to call different native methods
* for read and write operations.
*/
class SocketDispatcher extends NativeDispatcher
{
class SocketDispatcher extends NativeDispatcher {
int read(FileDescriptor fd, long address, int len) throws IOException {
return FileDispatcherImpl.read0(fd, address, len);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2018, Oracle and/or its affiliates. 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
@ -260,7 +260,7 @@ abstract class UnixFileStore
private static Properties loadProperties() {
Properties result = new Properties();
String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
Path file = Paths.get(fstypes);
Path file = Path.of(fstypes);
try {
try (ReadableByteChannel rbc = Files.newByteChannel(file)) {
result.load(Channels.newReader(rbc, "UTF-8"));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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
@ -104,10 +104,19 @@ Java_sun_nio_ch_IOUtil_makePipe(JNIEnv *env, jobject this, jboolean blocking)
return ((jlong) fd[0] << 32) | (jlong) fd[1];
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_IOUtil_write1(JNIEnv *env, jclass cl, jint fd, jbyte b)
{
char c = (char)b;
return convertReturnVal(env, write(fd, &c, 1), JNI_FALSE);
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd)
{
char buf[128];
char buf[16];
int tn = 0;
for (;;) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. 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
@ -38,23 +38,9 @@ import java.util.StringTokenizer;
final class Platform {
// native library we need to load
private static final String libNameMain = "jsound";
private static final String libNameALSA = "jsoundalsa";
private static final String libNameDSound = "jsoundds";
private static final String libName = "jsound";
// extra libs handling: bit flags for each different library
public static final int LIB_MAIN = 1;
public static final int LIB_ALSA = 2;
public static final int LIB_DSOUND = 4;
// bit field of the constants above. Willbe set in loadLibraries
private static int loadedLibs = 0;
// features: the main native library jsound reports which feature is
// contained in which lib
public static final int FEATURE_MIDIIO = 1;
public static final int FEATURE_PORTS = 2;
public static final int FEATURE_DIRECT_AUDIO = 3;
private static boolean isNativeLibLoaded;
// SYSTEM CHARACTERISTICS
// vary according to hardware architecture
@ -66,7 +52,6 @@ final class Platform {
if(Printer.trace)Printer.trace(">> Platform.java: static");
loadLibraries();
readProperties();
}
/**
@ -95,72 +80,37 @@ final class Platform {
private static void loadLibraries() {
if(Printer.trace)Printer.trace(">>Platform.loadLibraries");
// load the main library
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
System.loadLibrary(libNameMain);
return null;
});
// just for the heck of it...
loadedLibs |= LIB_MAIN;
// now try to load extra libs. They are defined at compile time in the Makefile
// with the define EXTRA_SOUND_JNI_LIBS
String extraLibs = nGetExtraLibraries();
// the string is the libraries, separated by white space
StringTokenizer st = new StringTokenizer(extraLibs);
while (st.hasMoreTokens()) {
final String lib = st.nextToken();
try {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
System.loadLibrary(lib);
return null;
});
if (lib.equals(libNameALSA)) {
loadedLibs |= LIB_ALSA;
if (Printer.debug) Printer.debug("Loaded ALSA lib successfully.");
} else if (lib.equals(libNameDSound)) {
loadedLibs |= LIB_DSOUND;
if (Printer.debug) Printer.debug("Loaded DirectSound lib successfully.");
} else {
if (Printer.err) Printer.err("Loaded unknown lib '"+lib+"' successfully.");
}
} catch (Throwable t) {
if (Printer.err) Printer.err("Couldn't load library "+lib+": "+t.toString());
}
// load the native library
isNativeLibLoaded = true;
try {
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
System.loadLibrary(libName);
return null;
});
} catch (Throwable t) {
if (Printer.err) Printer.err("Couldn't load library "+libName+": "+t.toString());
isNativeLibLoaded = false;
}
if (isNativeLibLoaded) {
bigEndian = nIsBigEndian();
}
}
static boolean isMidiIOEnabled() {
return isFeatureLibLoaded(FEATURE_MIDIIO);
if (Printer.debug) Printer.debug("Platform: Checking for MidiIO; library is loaded=" + isNativeLibLoaded);
return isNativeLibLoaded;
}
static boolean isPortsEnabled() {
return isFeatureLibLoaded(FEATURE_PORTS);
if (Printer.debug) Printer.debug("Platform: Checking for Ports; library is loaded=" + isNativeLibLoaded);
return isNativeLibLoaded;
}
static boolean isDirectAudioEnabled() {
return isFeatureLibLoaded(FEATURE_DIRECT_AUDIO);
if (Printer.debug) Printer.debug("Platform: Checking for DirectAudio; library is loaded=" + isNativeLibLoaded);
return isNativeLibLoaded;
}
private static boolean isFeatureLibLoaded(int feature) {
if (Printer.debug) Printer.debug("Platform: Checking for feature "+feature+"...");
int requiredLib = nGetLibraryForFeature(feature);
boolean isLoaded = (requiredLib != 0) && ((loadedLibs & requiredLib) == requiredLib);
if (Printer.debug) Printer.debug(" ...needs library "+requiredLib+". Result is loaded="+isLoaded);
return isLoaded;
}
// the following native methods are implemented in Platform.c
// the following native method is implemented in Platform.c
private static native boolean nIsBigEndian();
private static native String nGetExtraLibraries();
private static native int nGetLibraryForFeature(int feature);
/**
* Read the required system properties.
*/
private static void readProperties() {
// $$fb 2002-03-06: implement check for endianness in native. Facilitates porting !
bigEndian = nIsBigEndian();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. 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
@ -41,83 +41,3 @@ DEF_STATIC_JNI_OnLoad
JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_Platform_nIsBigEndian(JNIEnv *env, jclass clss) {
return UTIL_IsBigEndianPlatform();
}
/*
* Class: com_sun_media_sound_Platform
* Method: nGetExtraLibraries
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_sun_media_sound_Platform_nGetExtraLibraries(JNIEnv *env, jclass clss) {
return (*env)->NewStringUTF(env, EXTRA_SOUND_JNI_LIBS);
}
/*
* Class: com_sun_media_sound_Platform
* Method: nGetLibraryForFeature
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_sun_media_sound_Platform_nGetLibraryForFeature
(JNIEnv *env, jclass clazz, jint feature) {
// for every OS
#if X_PLATFORM == X_WINDOWS
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_DSOUND;
}
#endif
#if (X_PLATFORM == X_SOLARIS)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_MAIN;
}
#endif
#if (X_PLATFORM == X_LINUX)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_ALSA;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_ALSA;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_ALSA;
}
#endif
#if (X_PLATFORM == X_MACOSX)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_MAIN;
}
#endif
#if (X_PLATFORM == X_BSD)
switch (feature) {
case com_sun_media_sound_Platform_FEATURE_MIDIIO:
return com_sun_media_sound_Platform_LIB_MAIN;
#ifdef __FreeBSD__
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_ALSA;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
return com_sun_media_sound_Platform_LIB_ALSA;
#else
case com_sun_media_sound_Platform_FEATURE_PORTS:
return com_sun_media_sound_Platform_LIB_MAIN;
case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
// XXXBSD: When native Direct Audio support is ported change
// this back to returning com_sun_media_sound_Platform_LIB_MAIN
return 0;
#endif
}
#endif
return 0;
}

View File

@ -1,182 +0,0 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
//#define USE_ERROR
//#define USE_TRACE
#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
static void alsaDebugOutput(const char *file, int line, const char *function, int err, const char *fmt, ...) {
#ifdef USE_ERROR
va_list args;
va_start(args, fmt);
printf("%s:%d function %s: error %d: %s\n", file, line, function, err, snd_strerror(err));
if (strlen(fmt) > 0) {
vprintf(fmt, args);
}
va_end(args);
#endif
}
static int alsa_inited = 0;
static int alsa_enumerate_pcm_subdevices = FALSE; // default: no
static int alsa_enumerate_midi_subdevices = FALSE; // default: no
void initAlsaSupport() {
char* enumerate;
if (!alsa_inited) {
alsa_inited = TRUE;
snd_lib_error_set_handler(&alsaDebugOutput);
enumerate = getenv(ENV_ENUMERATE_PCM_SUBDEVICES);
if (enumerate != NULL && strlen(enumerate) > 0
&& (enumerate[0] != 'f') // false
&& (enumerate[0] != 'F') // False
&& (enumerate[0] != 'n') // no
&& (enumerate[0] != 'N')) { // NO
alsa_enumerate_pcm_subdevices = TRUE;
}
#ifdef ALSA_MIDI_ENUMERATE_SUBDEVICES
alsa_enumerate_midi_subdevices = TRUE;
#endif
}
}
/* if true (non-zero), ALSA sub devices should be listed as separate devices
*/
int needEnumerateSubdevices(int isMidi) {
initAlsaSupport();
return isMidi ? alsa_enumerate_midi_subdevices
: alsa_enumerate_pcm_subdevices;
}
/*
* deviceID contains packed card, device and subdevice numbers
* each number takes 10 bits
* "default" device has id == ALSA_DEFAULT_DEVICE_ID
*/
UINT32 encodeDeviceID(int card, int device, int subdevice) {
return (((card & 0x3FF) << 20) | ((device & 0x3FF) << 10)
| (subdevice & 0x3FF)) + 1;
}
void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice,
int isMidi) {
deviceID--;
*card = (deviceID >> 20) & 0x3FF;
*device = (deviceID >> 10) & 0x3FF;
if (needEnumerateSubdevices(isMidi)) {
*subdevice = deviceID & 0x3FF;
} else {
*subdevice = -1; // ALSA will choose any subdevices
}
}
void getDeviceString(char* buffer, int card, int device, int subdevice,
int usePlugHw, int isMidi) {
if (needEnumerateSubdevices(isMidi)) {
sprintf(buffer, "%s:%d,%d,%d",
usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE,
card, device, subdevice);
} else {
sprintf(buffer, "%s:%d,%d",
usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE,
card, device);
}
}
void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID,
int usePlugHw, int isMidi) {
int card, device, subdevice;
if (deviceID == ALSA_DEFAULT_DEVICE_ID) {
strcpy(buffer, ALSA_DEFAULT_DEVICE_NAME);
} else {
decodeDeviceID(deviceID, &card, &device, &subdevice, isMidi);
getDeviceString(buffer, card, device, subdevice, usePlugHw, isMidi);
}
}
static int hasGottenALSAVersion = FALSE;
#define ALSAVersionString_LENGTH 200
static char ALSAVersionString[ALSAVersionString_LENGTH];
void getALSAVersion(char* buffer, int len) {
if (!hasGottenALSAVersion) {
// get alsa version from proc interface
FILE* file;
int curr, len, totalLen, inVersionString;
file = fopen(ALSA_VERSION_PROC_FILE, "r");
ALSAVersionString[0] = 0;
if (file) {
if (NULL != fgets(ALSAVersionString, ALSAVersionString_LENGTH, file)) {
// parse for version number
totalLen = strlen(ALSAVersionString);
inVersionString = FALSE;
len = 0;
curr = 0;
while (curr < totalLen) {
if (!inVersionString) {
// is this char the beginning of a version string ?
if (ALSAVersionString[curr] >= '0'
&& ALSAVersionString[curr] <= '9') {
inVersionString = TRUE;
}
}
if (inVersionString) {
// the version string ends with white space
if (ALSAVersionString[curr] <= 32) {
break;
}
if (curr != len) {
// copy this char to the beginning of the string
ALSAVersionString[len] = ALSAVersionString[curr];
}
len++;
}
curr++;
}
// remove trailing dots
while ((len > 0) && (ALSAVersionString[len - 1] == '.')) {
len--;
}
// null terminate
ALSAVersionString[len] = 0;
}
fclose(file);
hasGottenALSAVersion = TRUE;
}
}
strncpy(buffer, ALSAVersionString, len);
}
/* end */

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <alsa/asoundlib.h>
#include "Utilities.h"
#ifndef PLATFORM_API_BSDOS_ALSA_COMMONUTILS_H_INCLUDED
#define PLATFORM_API_BSDOS_ALSA_COMMONUTILS_H_INCLUDED
#define ALSA_VERSION_PROC_FILE "/proc/asound/version"
#define ALSA_HARDWARE "hw"
#define ALSA_HARDWARE_CARD ALSA_HARDWARE":%d"
#define ALSA_HARDWARE_DEVICE ALSA_HARDWARE_CARD",%d"
#define ALSA_HARDWARE_SUBDEVICE ALSA_HARDWARE_DEVICE",%d"
#define ALSA_PLUGHARDWARE "plughw"
#define ALSA_DEFAULT_DEVICE_NAME "default"
#define ALSA_DEFAULT_DEVICE_ID (0)
#define ALSA_PCM (0)
#define ALSA_RAWMIDI (1)
// for use in info objects
#define ALSA_VENDOR "ALSA (http://www.alsa-project.org)"
// Environment variable for inclusion of subdevices in device listing.
// If this variable is unset or "no", then subdevices are ignored, and
// it's ALSA's choice which one to use (enables hardware mixing)
#define ENV_ENUMERATE_PCM_SUBDEVICES "ALSA_ENUMERATE_PCM_SUBDEVICES"
// if defined, subdevices are listed.
//#undef ALSA_MIDI_ENUMERATE_SUBDEVICES
#define ALSA_MIDI_ENUMERATE_SUBDEVICES
// must be called before any ALSA calls
void initAlsaSupport();
/* if true (non-zero), ALSA sub devices should be listed as separate devices
*/
int needEnumerateSubdevices(int isMidi);
/*
* deviceID contains packed card, device and subdevice numbers
* each number takes 10 bits
* "default" device has id == ALSA_DEFAULT_DEVICE_ID
*/
UINT32 encodeDeviceID(int card, int device, int subdevice);
void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice,
int isMidi);
void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID,
int usePlugHw, int isMidi);
void getALSAVersion(char* buffer, int len);
#endif // PLATFORM_API_BSDOS_ALSA_COMMONUTILS_H_INCLUDED

View File

@ -1,354 +0,0 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#define USE_ERROR
#define USE_TRACE
#if USE_PLATFORM_MIDI_IN == TRUE
#include <alsa/asoundlib.h>
#include "PlatformMidi.h"
#include "PLATFORM_API_BsdOS_ALSA_MidiUtils.h"
#if defined(i586)
#include <sys/utsname.h>
#endif
/*
* Helper methods
*/
static inline UINT32 packMessage(int status, int data1, int data2) {
return ((status & 0xFF) | ((data1 & 0xFF) << 8) | ((data2 & 0xFF) << 16));
}
static void setShortMessage(MidiMessage* message,
int status, int data1, int data2) {
message->type = SHORT_MESSAGE;
message->data.s.packedMsg = packMessage(status, data1, data2);
}
static void setRealtimeMessage(MidiMessage* message, int status) {
setShortMessage(message, status, 0, 0);
}
static void set14bitMessage(MidiMessage* message, int status, int value) {
TRACE3("14bit value: %d, lsb: %d, msb: %d\n", value, value & 0x7F, (value >> 7) & 0x7F);
value &= 0x3FFF;
TRACE3("14bit value (2): %d, lsb: %d, msb: %d\n", value, value & 0x7F, (value >> 7) & 0x7F);
setShortMessage(message, status,
value & 0x7F,
(value >> 7) & 0x7F);
}
/*
* implementation of the platform-dependent
* MIDI in functions declared in PlatformMidi.h
*/
char* MIDI_IN_GetErrorStr(INT32 err) {
return (char*) getErrorStr(err);
}
INT32 MIDI_IN_GetNumDevices() {
/* Workaround for 6842956: 32bit app on 64bit bsd
* gets assertion failure trying to open midiIn ports.
* Untill the issue is fixed in ALSA
* (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4807)
* report no midi in devices in the configuration.
*/
#if defined(i586)
static int jre32onbsd64 = -1;
if (jre32onbsd64 < 0) {
jre32onbsd64 = 0;
/* The workaround may be disabled setting "JAVASOUND_ENABLE_MIDIIN"
* environment variable.
*/
if (getenv("JAVASOUND_ENABLE_MIDIIN") == NULL) {
struct utsname u;
jre32onbsd64 = 0;
if (uname(&u) == 0) {
if (strstr(u.machine, "64") != NULL) {
TRACE0("jre32 on bsd64 detected - report no midiIn devices\n");
jre32onbsd64 = 1;
}
}
}
}
if (jre32onbsd64) {
return 0;
}
#endif
TRACE0("MIDI_IN_GetNumDevices()\n");
return getMidiDeviceCount(SND_RAWMIDI_STREAM_INPUT);
}
INT32 MIDI_IN_GetDeviceName(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceName(SND_RAWMIDI_STREAM_INPUT, deviceIndex,
name, nameLength);
return ret;
}
INT32 MIDI_IN_GetDeviceVendor(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceVendor(deviceIndex, name, nameLength);
return ret;
}
INT32 MIDI_IN_GetDeviceDescription(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceDescription(SND_RAWMIDI_STREAM_INPUT, deviceIndex,
name, nameLength);
return ret;
}
INT32 MIDI_IN_GetDeviceVersion(INT32 deviceIndex, char *name, UINT32 nameLength) {
int ret = getMidiDeviceVersion(deviceIndex, name, nameLength);
return ret;
}
/*************************************************************************/
INT32 MIDI_IN_OpenDevice(INT32 deviceIndex, MidiDeviceHandle** handle) {
INT32 ret;
TRACE0("> MIDI_IN_OpenDevice\n");
ret = openMidiDevice(SND_RAWMIDI_STREAM_INPUT, deviceIndex, handle);
TRACE1("< MIDI_IN_OpenDevice: returning %d\n", (int) ret);
return ret;
}
INT32 MIDI_IN_CloseDevice(MidiDeviceHandle* handle) {
INT32 ret;
TRACE0("> MIDI_IN_CloseDevice\n");
ret = closeMidiDevice(handle);
TRACE1("< MIDI_IN_CloseDevice: returning %d\n", (int) ret);
return ret;
}
INT32 MIDI_IN_StartDevice(MidiDeviceHandle* handle) {
TRACE0("MIDI_IN_StartDevice\n");
return MIDI_SUCCESS;
}
INT32 MIDI_IN_StopDevice(MidiDeviceHandle* handle) {
TRACE0("MIDI_IN_StopDevice\n");
return MIDI_SUCCESS;
}
INT64 MIDI_IN_GetTimeStamp(MidiDeviceHandle* handle) {
return getMidiTimestamp(handle);
}
/* read the next message from the queue */
MidiMessage* MIDI_IN_GetMessage(MidiDeviceHandle* handle) {
snd_seq_event_t alsa_message;
MidiMessage* jdk_message;
int err;
char buffer[1];
int status;
TRACE0("> MIDI_IN_GetMessage\n");
if (!handle) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): handle is NULL\n");
return NULL;
}
if (!handle->deviceHandle) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): native handle is NULL\n");
return NULL;
}
if (!handle->platformData) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): platformData is NULL\n");
return NULL;
}
/* For MIDI In, the device is left in non blocking mode. So if there is
no data from the device, snd_rawmidi_read() returns with -11 (EAGAIN).
This results in jumping back to the Java layer. */
while (TRUE) {
TRACE0("before snd_rawmidi_read()\n");
err = snd_rawmidi_read((snd_rawmidi_t*) handle->deviceHandle, buffer, 1);
TRACE0("after snd_rawmidi_read()\n");
if (err != 1) {
ERROR2("< ERROR: MIDI_IN_GetMessage(): snd_rawmidi_read() returned %d : %s\n", err, snd_strerror(err));
return NULL;
}
// printf("received byte: %d\n", buffer[0]);
err = snd_midi_event_encode_byte((snd_midi_event_t*) handle->platformData,
(int) buffer[0],
&alsa_message);
if (err == 1) {
break;
} else if (err < 0) {
ERROR1("< ERROR: MIDI_IN_GetMessage(): snd_midi_event_encode_byte() returned %d\n", err);
return NULL;
}
}
jdk_message = (MidiMessage*) calloc(sizeof(MidiMessage), 1);
if (!jdk_message) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): out of memory\n");
return NULL;
}
// TODO: tra
switch (alsa_message.type) {
case SND_SEQ_EVENT_NOTEON:
case SND_SEQ_EVENT_NOTEOFF:
case SND_SEQ_EVENT_KEYPRESS:
status = (alsa_message.type == SND_SEQ_EVENT_KEYPRESS) ? 0xA0 :
(alsa_message.type == SND_SEQ_EVENT_NOTEON) ? 0x90 : 0x80;
status |= alsa_message.data.note.channel;
setShortMessage(jdk_message, status,
alsa_message.data.note.note,
alsa_message.data.note.velocity);
break;
case SND_SEQ_EVENT_CONTROLLER:
status = 0xB0 | alsa_message.data.control.channel;
setShortMessage(jdk_message, status,
alsa_message.data.control.param,
alsa_message.data.control.value);
break;
case SND_SEQ_EVENT_PGMCHANGE:
case SND_SEQ_EVENT_CHANPRESS:
status = (alsa_message.type == SND_SEQ_EVENT_PGMCHANGE) ? 0xC0 : 0xD0;
status |= alsa_message.data.control.channel;
setShortMessage(jdk_message, status,
alsa_message.data.control.value, 0);
break;
case SND_SEQ_EVENT_PITCHBEND:
status = 0xE0 | alsa_message.data.control.channel;
// $$mp 2003-09-23:
// possible hack to work around a bug in ALSA. Necessary for
// ALSA 0.9.2. May be fixed in newer versions of ALSA.
// alsa_message.data.control.value ^= 0x2000;
// TRACE1("pitchbend value: %d\n", alsa_message.data.control.value);
set14bitMessage(jdk_message, status,
alsa_message.data.control.value);
break;
/* System exclusive messages */
case SND_SEQ_EVENT_SYSEX:
jdk_message->type = LONG_MESSAGE;
jdk_message->data.l.size = alsa_message.data.ext.len;
jdk_message->data.l.data = malloc(alsa_message.data.ext.len);
if (jdk_message->data.l.data == NULL) {
ERROR0("< ERROR: MIDI_IN_GetMessage(): out of memory\n");
free(jdk_message);
jdk_message = NULL;
} else {
memcpy(jdk_message->data.l.data, alsa_message.data.ext.ptr, alsa_message.data.ext.len);
}
break;
/* System common messages */
case SND_SEQ_EVENT_QFRAME:
setShortMessage(jdk_message, 0xF1,
alsa_message.data.control.value & 0x7F, 0);
break;
case SND_SEQ_EVENT_SONGPOS:
set14bitMessage(jdk_message, 0xF2,
alsa_message.data.control.value);
break;
case SND_SEQ_EVENT_SONGSEL:
setShortMessage(jdk_message, 0xF3,
alsa_message.data.control.value & 0x7F, 0);
break;
case SND_SEQ_EVENT_TUNE_REQUEST:
setRealtimeMessage(jdk_message, 0xF6);
break;
/* System realtime messages */
case SND_SEQ_EVENT_CLOCK:
setRealtimeMessage(jdk_message, 0xF8);
break;
case SND_SEQ_EVENT_START:
setRealtimeMessage(jdk_message, 0xFA);
break;
case SND_SEQ_EVENT_CONTINUE:
setRealtimeMessage(jdk_message, 0xFB);
break;
case SND_SEQ_EVENT_STOP:
setRealtimeMessage(jdk_message, 0xFC);
break;
case SND_SEQ_EVENT_SENSING:
setRealtimeMessage(jdk_message, 0xFE);
break;
case SND_SEQ_EVENT_RESET:
setRealtimeMessage(jdk_message, 0xFF);
break;
default:
ERROR0("< ERROR: MIDI_IN_GetMessage(): unhandled ALSA MIDI message type\n");
free(jdk_message);
jdk_message = NULL;
}
// set timestamp
if (jdk_message != NULL) {
jdk_message->timestamp = getMidiTimestamp(handle);
}
TRACE1("< MIDI_IN_GetMessage: returning %p\n", jdk_message);
return jdk_message;
}
void MIDI_IN_ReleaseMessage(MidiDeviceHandle* handle, MidiMessage* msg) {
if (!msg) {
ERROR0("< ERROR: MIDI_IN_ReleaseMessage(): message is NULL\n");
return;
}
if (msg->type == LONG_MESSAGE && msg->data.l.data) {
free(msg->data.l.data);
}
free(msg);
}
#endif /* USE_PLATFORM_MIDI_IN */

View File

@ -1,179 +0,0 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#define USE_ERROR
#define USE_TRACE
#if USE_PLATFORM_MIDI_OUT == TRUE
#include <alsa/asoundlib.h>
#include "PlatformMidi.h"
#include "PLATFORM_API_BsdOS_ALSA_MidiUtils.h"
static int CHANNEL_MESSAGE_LENGTH[] = {
-1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 3, 3, 2, 2, 3 };
/* 8x 9x Ax Bx Cx Dx Ex */
static int SYSTEM_MESSAGE_LENGTH[] = {
-1, 2, 3, 2, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1 };
/* F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF */
// the returned length includes the status byte.
// for illegal messages, -1 is returned.
static int getShortMessageLength(int status) {
int dataLength = 0;
if (status < 0xF0) { // channel voice message
dataLength = CHANNEL_MESSAGE_LENGTH[(status >> 4) & 0xF];
} else {
dataLength = SYSTEM_MESSAGE_LENGTH[status & 0xF];
}
return dataLength;
}
/*
* implementation of the platform-dependent
* MIDI out functions declared in PlatformMidi.h
*/
char* MIDI_OUT_GetErrorStr(INT32 err) {
return (char*) getErrorStr(err);
}
INT32 MIDI_OUT_GetNumDevices() {
TRACE0("MIDI_OUT_GetNumDevices()\n");
return getMidiDeviceCount(SND_RAWMIDI_STREAM_OUTPUT);
}
INT32 MIDI_OUT_GetDeviceName(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceName()\n");
return getMidiDeviceName(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex,
name, nameLength);
}
INT32 MIDI_OUT_GetDeviceVendor(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceVendor()\n");
return getMidiDeviceVendor(deviceIndex, name, nameLength);
}
INT32 MIDI_OUT_GetDeviceDescription(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceDescription()\n");
return getMidiDeviceDescription(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex,
name, nameLength);
}
INT32 MIDI_OUT_GetDeviceVersion(INT32 deviceIndex, char *name, UINT32 nameLength) {
TRACE0("MIDI_OUT_GetDeviceVersion()\n");
return getMidiDeviceVersion(deviceIndex, name, nameLength);
}
/* *************************** MidiOutDevice implementation *************** */
INT32 MIDI_OUT_OpenDevice(INT32 deviceIndex, MidiDeviceHandle** handle) {
TRACE1("MIDI_OUT_OpenDevice(): deviceIndex: %d\n", (int) deviceIndex);
return openMidiDevice(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex, handle);
}
INT32 MIDI_OUT_CloseDevice(MidiDeviceHandle* handle) {
TRACE0("MIDI_OUT_CloseDevice()\n");
return closeMidiDevice(handle);
}
INT64 MIDI_OUT_GetTimeStamp(MidiDeviceHandle* handle) {
return getMidiTimestamp(handle);
}
INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg,
UINT32 timestamp) {
int err;
int status;
int data1;
int data2;
char buffer[3];
TRACE2("> MIDI_OUT_SendShortMessage() %x, time: %u\n", packedMsg, (unsigned int) timestamp);
if (!handle) {
ERROR0("< ERROR: MIDI_OUT_SendShortMessage(): handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
if (!handle->deviceHandle) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): native handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
status = (packedMsg & 0xFF);
buffer[0] = (char) status;
buffer[1] = (char) ((packedMsg >> 8) & 0xFF);
buffer[2] = (char) ((packedMsg >> 16) & 0xFF);
TRACE4("status: %d, data1: %d, data2: %d, length: %d\n", (int) buffer[0], (int) buffer[1], (int) buffer[2], getShortMessageLength(status));
err = snd_rawmidi_write((snd_rawmidi_t*) handle->deviceHandle, buffer, getShortMessageLength(status));
if (err < 0) {
ERROR1(" ERROR: MIDI_OUT_SendShortMessage(): snd_rawmidi_write() returned %d\n", err);
}
TRACE0("< MIDI_OUT_SendShortMessage()\n");
return err;
}
INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data,
UINT32 size, UINT32 timestamp) {
int err;
TRACE2("> MIDI_OUT_SendLongMessage() size %u, time: %u\n", (unsigned int) size, (unsigned int) timestamp);
if (!handle) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
if (!handle->deviceHandle) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): native handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
if (!data) {
ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): data is NULL\n");
return MIDI_INVALID_HANDLE;
}
err = snd_rawmidi_write((snd_rawmidi_t*) handle->deviceHandle,
data, size);
if (err < 0) {
ERROR1(" ERROR: MIDI_OUT_SendLongMessage(): snd_rawmidi_write() returned %d\n", err);
}
TRACE0("< MIDI_OUT_SendLongMessage()\n");
return err;
}
#endif /* USE_PLATFORM_MIDI_OUT */

View File

@ -1,481 +0,0 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#define USE_ERROR
#define USE_TRACE
#include "PLATFORM_API_BsdOS_ALSA_MidiUtils.h"
#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
#include <string.h>
#include <sys/time.h>
static INT64 getTimeInMicroseconds() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000000UL) + tv.tv_usec;
}
const char* getErrorStr(INT32 err) {
return snd_strerror((int) err);
}
// callback for iteration through devices
// returns TRUE if iteration should continue
typedef int (*DeviceIteratorPtr)(UINT32 deviceID,
snd_rawmidi_info_t* rawmidi_info,
snd_ctl_card_info_t* cardinfo,
void *userData);
// for each ALSA device, call iterator. userData is passed to the iterator
// returns total number of iterations
static int iterateRawmidiDevices(snd_rawmidi_stream_t direction,
DeviceIteratorPtr iterator,
void* userData) {
int count = 0;
int subdeviceCount;
int card, dev, subDev;
char devname[16];
int err;
snd_ctl_t *handle;
snd_rawmidi_t *rawmidi;
snd_rawmidi_info_t *rawmidi_info;
snd_ctl_card_info_t *card_info, *defcardinfo = NULL;
UINT32 deviceID;
int doContinue = TRUE;
snd_rawmidi_info_malloc(&rawmidi_info);
snd_ctl_card_info_malloc(&card_info);
// 1st try "default" device
if (direction == SND_RAWMIDI_STREAM_INPUT) {
err = snd_rawmidi_open(&rawmidi, NULL, ALSA_DEFAULT_DEVICE_NAME,
SND_RAWMIDI_NONBLOCK);
} else if (direction == SND_RAWMIDI_STREAM_OUTPUT) {
err = snd_rawmidi_open(NULL, &rawmidi, ALSA_DEFAULT_DEVICE_NAME,
SND_RAWMIDI_NONBLOCK);
} else {
ERROR0("ERROR: iterateRawmidiDevices(): direction is neither"
" SND_RAWMIDI_STREAM_INPUT nor SND_RAWMIDI_STREAM_OUTPUT\n");
err = MIDI_INVALID_ARGUMENT;
}
if (err < 0) {
ERROR1("ERROR: snd_rawmidi_open (\"default\"): %s\n",
snd_strerror(err));
} else {
err = snd_rawmidi_info(rawmidi, rawmidi_info);
snd_rawmidi_close(rawmidi);
if (err < 0) {
ERROR1("ERROR: snd_rawmidi_info (\"default\"): %s\n",
snd_strerror(err));
} else {
// try to get card info
card = snd_rawmidi_info_get_card(rawmidi_info);
if (card >= 0) {
sprintf(devname, ALSA_HARDWARE_CARD, card);
if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) {
if (snd_ctl_card_info(handle, card_info) >= 0) {
defcardinfo = card_info;
}
snd_ctl_close(handle);
}
}
// call calback function for the device
if (iterator != NULL) {
doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, rawmidi_info,
defcardinfo, userData);
}
count++;
}
}
// iterate cards
card = -1;
TRACE0("testing for cards...\n");
if (snd_card_next(&card) >= 0) {
TRACE1("Found card %d\n", card);
while (doContinue && (card >= 0)) {
sprintf(devname, ALSA_HARDWARE_CARD, card);
TRACE1("Opening control for alsa rawmidi device \"%s\"...\n", devname);
err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK);
if (err < 0) {
ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
} else {
TRACE0("snd_ctl_open() SUCCESS\n");
err = snd_ctl_card_info(handle, card_info);
if (err < 0) {
ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", card, snd_strerror(err));
} else {
TRACE0("snd_ctl_card_info() SUCCESS\n");
dev = -1;
while (doContinue) {
if (snd_ctl_rawmidi_next_device(handle, &dev) < 0) {
ERROR0("snd_ctl_rawmidi_next_device\n");
}
TRACE0("snd_ctl_rawmidi_next_device() SUCCESS\n");
if (dev < 0) {
break;
}
snd_rawmidi_info_set_device(rawmidi_info, dev);
snd_rawmidi_info_set_subdevice(rawmidi_info, 0);
snd_rawmidi_info_set_stream(rawmidi_info, direction);
err = snd_ctl_rawmidi_info(handle, rawmidi_info);
TRACE0("after snd_ctl_rawmidi_info()\n");
if (err < 0) {
if (err != -ENOENT) {
ERROR2("ERROR: snd_ctl_rawmidi_info, card=%d: %s", card, snd_strerror(err));
}
} else {
TRACE0("snd_ctl_rawmidi_info() SUCCESS\n");
subdeviceCount = needEnumerateSubdevices(ALSA_RAWMIDI)
? snd_rawmidi_info_get_subdevices_count(rawmidi_info)
: 1;
if (iterator!=NULL) {
for (subDev = 0; subDev < subdeviceCount; subDev++) {
TRACE3(" Iterating %d,%d,%d\n", card, dev, subDev);
deviceID = encodeDeviceID(card, dev, subDev);
doContinue = (*iterator)(deviceID, rawmidi_info,
card_info, userData);
count++;
TRACE0("returned from iterator\n");
if (!doContinue) {
break;
}
}
} else {
count += subdeviceCount;
}
}
} // of while(doContinue)
}
snd_ctl_close(handle);
}
if (snd_card_next(&card) < 0) {
break;
}
}
} else {
ERROR0("No cards found!\n");
}
snd_ctl_card_info_free(card_info);
snd_rawmidi_info_free(rawmidi_info);
return count;
}
int getMidiDeviceCount(snd_rawmidi_stream_t direction) {
int deviceCount;
TRACE0("> getMidiDeviceCount()\n");
initAlsaSupport();
deviceCount = iterateRawmidiDevices(direction, NULL, NULL);
TRACE0("< getMidiDeviceCount()\n");
return deviceCount;
}
/*
userData is assumed to be a pointer to ALSA_MIDIDeviceDescription.
ALSA_MIDIDeviceDescription->index has to be set to the index of the device
we want to get information of before this method is called the first time via
iterateRawmidiDevices(). On each call of this method,
ALSA_MIDIDeviceDescription->index is decremented. If it is equal to zero,
we have reached the desired device, so action is taken.
So after successful completion of iterateRawmidiDevices(),
ALSA_MIDIDeviceDescription->index is zero. If it isn't, this is an
indication of an error.
*/
static int deviceInfoIterator(UINT32 deviceID, snd_rawmidi_info_t *rawmidi_info,
snd_ctl_card_info_t *cardinfo, void *userData) {
char buffer[300];
ALSA_MIDIDeviceDescription* desc = (ALSA_MIDIDeviceDescription*)userData;
#ifdef ALSA_MIDI_USE_PLUGHW
int usePlugHw = 1;
#else
int usePlugHw = 0;
#endif
TRACE0("deviceInfoIterator\n");
initAlsaSupport();
if (desc->index == 0) {
// we found the device with correct index
desc->deviceID = deviceID;
buffer[0]=' '; buffer[1]='[';
// buffer[300] is enough to store the actual device string w/o overrun
getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_RAWMIDI);
strncat(buffer, "]", sizeof(buffer) - strlen(buffer) - 1);
strncpy(desc->name,
(cardinfo != NULL)
? snd_ctl_card_info_get_id(cardinfo)
: snd_rawmidi_info_get_id(rawmidi_info),
desc->strLen - strlen(buffer));
strncat(desc->name, buffer, desc->strLen - strlen(desc->name));
desc->description[0] = 0;
if (cardinfo != NULL) {
strncpy(desc->description, snd_ctl_card_info_get_name(cardinfo),
desc->strLen);
strncat(desc->description, ", ",
desc->strLen - strlen(desc->description));
}
strncat(desc->description, snd_rawmidi_info_get_id(rawmidi_info),
desc->strLen - strlen(desc->description));
strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
strncat(desc->description, snd_rawmidi_info_get_name(rawmidi_info),
desc->strLen - strlen(desc->description));
TRACE2("Returning %s, %s\n", desc->name, desc->description);
return FALSE; // do not continue iteration
}
desc->index--;
return TRUE;
}
static int getMIDIDeviceDescriptionByIndex(snd_rawmidi_stream_t direction,
ALSA_MIDIDeviceDescription* desc) {
initAlsaSupport();
TRACE1(" getMIDIDeviceDescriptionByIndex (index = %d)\n", desc->index);
iterateRawmidiDevices(direction, &deviceInfoIterator, desc);
return (desc->index == 0) ? MIDI_SUCCESS : MIDI_INVALID_DEVICEID;
}
int initMIDIDeviceDescription(ALSA_MIDIDeviceDescription* desc, int index) {
int ret = MIDI_SUCCESS;
desc->index = index;
desc->strLen = 200;
desc->name = (char*) calloc(desc->strLen + 1, 1);
desc->description = (char*) calloc(desc->strLen + 1, 1);
if (! desc->name ||
! desc->description) {
ret = MIDI_OUT_OF_MEMORY;
}
return ret;
}
void freeMIDIDeviceDescription(ALSA_MIDIDeviceDescription* desc) {
if (desc->name) {
free(desc->name);
}
if (desc->description) {
free(desc->description);
}
}
int getMidiDeviceName(snd_rawmidi_stream_t direction, int index, char *name,
UINT32 nameLength) {
ALSA_MIDIDeviceDescription desc;
int ret;
TRACE1("getMidiDeviceName: nameLength: %d\n", (int) nameLength);
ret = initMIDIDeviceDescription(&desc, index);
if (ret == MIDI_SUCCESS) {
TRACE0("getMidiDeviceName: initMIDIDeviceDescription() SUCCESS\n");
ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
if (ret == MIDI_SUCCESS) {
TRACE1("getMidiDeviceName: desc.name: %s\n", desc.name);
strncpy(name, desc.name, nameLength - 1);
name[nameLength - 1] = 0;
}
}
freeMIDIDeviceDescription(&desc);
return ret;
}
int getMidiDeviceVendor(int index, char *name, UINT32 nameLength) {
strncpy(name, ALSA_VENDOR, nameLength - 1);
name[nameLength - 1] = 0;
return MIDI_SUCCESS;
}
int getMidiDeviceDescription(snd_rawmidi_stream_t direction,
int index, char *name, UINT32 nameLength) {
ALSA_MIDIDeviceDescription desc;
int ret;
ret = initMIDIDeviceDescription(&desc, index);
if (ret == MIDI_SUCCESS) {
ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
if (ret == MIDI_SUCCESS) {
strncpy(name, desc.description, nameLength - 1);
name[nameLength - 1] = 0;
}
}
freeMIDIDeviceDescription(&desc);
return ret;
}
int getMidiDeviceVersion(int index, char *name, UINT32 nameLength) {
getALSAVersion(name, nameLength);
return MIDI_SUCCESS;
}
static int getMidiDeviceID(snd_rawmidi_stream_t direction, int index,
UINT32* deviceID) {
ALSA_MIDIDeviceDescription desc;
int ret;
ret = initMIDIDeviceDescription(&desc, index);
if (ret == MIDI_SUCCESS) {
ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
if (ret == MIDI_SUCCESS) {
// TRACE1("getMidiDeviceName: desc.name: %s\n", desc.name);
*deviceID = desc.deviceID;
}
}
freeMIDIDeviceDescription(&desc);
return ret;
}
/*
direction has to be either SND_RAWMIDI_STREAM_INPUT or
SND_RAWMIDI_STREAM_OUTPUT.
Returns 0 on success. Otherwise, MIDI_OUT_OF_MEMORY, MIDI_INVALID_ARGUMENT
or a negative ALSA error code is returned.
*/
INT32 openMidiDevice(snd_rawmidi_stream_t direction, INT32 deviceIndex,
MidiDeviceHandle** handle) {
snd_rawmidi_t* native_handle;
snd_midi_event_t* event_parser = NULL;
int err;
UINT32 deviceID = 0;
char devicename[100];
#ifdef ALSA_MIDI_USE_PLUGHW
int usePlugHw = 1;
#else
int usePlugHw = 0;
#endif
TRACE0("> openMidiDevice()\n");
(*handle) = (MidiDeviceHandle*) calloc(sizeof(MidiDeviceHandle), 1);
if (!(*handle)) {
ERROR0("ERROR: openDevice: out of memory\n");
return MIDI_OUT_OF_MEMORY;
}
// TODO: iterate to get dev ID from index
err = getMidiDeviceID(direction, deviceIndex, &deviceID);
TRACE1(" openMidiDevice(): deviceID: %d\n", (int) deviceID);
getDeviceStringFromDeviceID(devicename, deviceID,
usePlugHw, ALSA_RAWMIDI);
TRACE1(" openMidiDevice(): deviceString: %s\n", devicename);
// finally open the device
if (direction == SND_RAWMIDI_STREAM_INPUT) {
err = snd_rawmidi_open(&native_handle, NULL, devicename,
SND_RAWMIDI_NONBLOCK);
} else if (direction == SND_RAWMIDI_STREAM_OUTPUT) {
err = snd_rawmidi_open(NULL, &native_handle, devicename,
SND_RAWMIDI_NONBLOCK);
} else {
ERROR0(" ERROR: openMidiDevice(): direction is neither SND_RAWMIDI_STREAM_INPUT nor SND_RAWMIDI_STREAM_OUTPUT\n");
err = MIDI_INVALID_ARGUMENT;
}
if (err < 0) {
ERROR1("< ERROR: openMidiDevice(): snd_rawmidi_open() returned %d\n", err);
free(*handle);
(*handle) = NULL;
return err;
}
/* We opened with non-blocking behaviour to not get hung if the device
is used by a different process. Writing, however, should
be blocking. So we change it here. */
if (direction == SND_RAWMIDI_STREAM_OUTPUT) {
err = snd_rawmidi_nonblock(native_handle, 0);
if (err < 0) {
ERROR1(" ERROR: openMidiDevice(): snd_rawmidi_nonblock() returned %d\n", err);
snd_rawmidi_close(native_handle);
free(*handle);
(*handle) = NULL;
return err;
}
}
if (direction == SND_RAWMIDI_STREAM_INPUT) {
err = snd_midi_event_new(EVENT_PARSER_BUFSIZE, &event_parser);
if (err < 0) {
ERROR1(" ERROR: openMidiDevice(): snd_midi_event_new() returned %d\n", err);
snd_rawmidi_close(native_handle);
free(*handle);
(*handle) = NULL;
return err;
}
}
(*handle)->deviceHandle = (void*) native_handle;
(*handle)->startTime = getTimeInMicroseconds();
(*handle)->platformData = event_parser;
TRACE0("< openMidiDevice(): succeeded\n");
return err;
}
INT32 closeMidiDevice(MidiDeviceHandle* handle) {
int err;
TRACE0("> closeMidiDevice()\n");
if (!handle) {
ERROR0("< ERROR: closeMidiDevice(): handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
if (!handle->deviceHandle) {
ERROR0("< ERROR: closeMidiDevice(): native handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
err = snd_rawmidi_close((snd_rawmidi_t*) handle->deviceHandle);
TRACE1(" snd_rawmidi_close() returns %d\n", err);
if (handle->platformData) {
snd_midi_event_free((snd_midi_event_t*) handle->platformData);
}
free(handle);
TRACE0("< closeMidiDevice: succeeded\n");
return err;
}
INT64 getMidiTimestamp(MidiDeviceHandle* handle) {
if (!handle) {
ERROR0("< ERROR: closeMidiDevice(): handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
return getTimeInMicroseconds() - handle->startTime;
}
/* end */

View File

@ -1,85 +0,0 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <alsa/asoundlib.h>
#include "Utilities.h"
#include "PlatformMidi.h"
#ifndef PLATFORM_API_BSDOS_ALSA_MIDIUTILS_H_INCLUDED
#define PLATFORM_API_BSDOS_ALSA_MIDIUTILS_H_INCLUDED
#define EVENT_PARSER_BUFSIZE (2048)
// if this is defined, use plughw: devices
//#define ALSA_MIDI_USE_PLUGHW
#undef ALSA_MIDI_USE_PLUGHW
typedef struct tag_ALSA_MIDIDeviceDescription {
int index; // in
int strLen; // in
INT32 deviceID; // out
char* name; // out
char* description; // out
} ALSA_MIDIDeviceDescription;
const char* getErrorStr(INT32 err);
/* Returns the number of devices. */
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
int getMidiDeviceCount(snd_rawmidi_stream_t direction);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
int getMidiDeviceName(snd_rawmidi_stream_t direction, int index,
char *name, UINT32 nameLength);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
int getMidiDeviceVendor(int index, char *name, UINT32 nameLength);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
int getMidiDeviceDescription(snd_rawmidi_stream_t direction, int index,
char *name, UINT32 nameLength);
/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
int getMidiDeviceVersion(int index, char *name, UINT32 nameLength);
// returns 0 on success, otherwise MIDI_OUT_OF_MEMORY or ALSA error code
/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
SND_RAWMIDI_STREAM_INPUT. */
INT32 openMidiDevice(snd_rawmidi_stream_t direction, INT32 deviceIndex,
MidiDeviceHandle** handle);
// returns 0 on success, otherwise a (negative) ALSA error code
INT32 closeMidiDevice(MidiDeviceHandle* handle);
INT64 getMidiTimestamp(MidiDeviceHandle* handle);
#endif // PLATFORM_API_BSDOS_ALSA_MIDIUTILS_H_INCLUDED

View File

@ -1,941 +0,0 @@
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#define USE_ERROR
#define USE_TRACE
#include "PLATFORM_API_BsdOS_ALSA_PCMUtils.h"
#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
#include "DirectAudio.h"
#if USE_DAUDIO == TRUE
// GetPosition method 1: based on how many bytes are passed to the kernel driver
// + does not need much processor resources
// - not very exact, "jumps"
// GetPosition method 2: ask kernel about actual position of playback.
// - very exact
// - switch to kernel layer for each call
// GetPosition method 3: use snd_pcm_avail() call - not yet in official ALSA
// quick tests on a Pentium 200MMX showed max. 1.5% processor usage
// for playing back a CD-quality file and printing 20x per second a line
// on the console with the current time. So I guess performance is not such a
// factor here.
//#define GET_POSITION_METHOD1
#define GET_POSITION_METHOD2
// The default time for a period in microseconds.
// For very small buffers, only 2 periods are used.
#define DEFAULT_PERIOD_TIME 20000 /* 20ms */
///// implemented functions of DirectAudio.h
INT32 DAUDIO_GetDirectAudioDeviceCount() {
return (INT32) getAudioDeviceCount();
}
INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* description) {
ALSA_AudioDeviceDescription adesc;
adesc.index = (int) mixerIndex;
adesc.strLen = DAUDIO_STRING_LENGTH;
adesc.maxSimultaneousLines = (int*) (&(description->maxSimulLines));
adesc.deviceID = &(description->deviceID);
adesc.name = description->name;
adesc.vendor = description->vendor;
adesc.description = description->description;
adesc.version = description->version;
return getAudioDeviceDescriptionByIndex(&adesc);
}
#define MAX_BIT_INDEX 6
// returns
// 6: for anything above 24-bit
// 5: for 4 bytes sample size, 24-bit
// 4: for 3 bytes sample size, 24-bit
// 3: for 3 bytes sample size, 20-bit
// 2: for 2 bytes sample size, 16-bit
// 1: for 1 byte sample size, 8-bit
// 0: for anything else
int getBitIndex(int sampleSizeInBytes, int significantBits) {
if (significantBits > 24) return 6;
if (sampleSizeInBytes == 4 && significantBits == 24) return 5;
if (sampleSizeInBytes == 3) {
if (significantBits == 24) return 4;
if (significantBits == 20) return 3;
}
if (sampleSizeInBytes == 2 && significantBits == 16) return 2;
if (sampleSizeInBytes == 1 && significantBits == 8) return 1;
return 0;
}
int getSampleSizeInBytes(int bitIndex, int sampleSizeInBytes) {
switch(bitIndex) {
case 1: return 1;
case 2: return 2;
case 3: /* fall through */
case 4: return 3;
case 5: return 4;
}
return sampleSizeInBytes;
}
int getSignificantBits(int bitIndex, int significantBits) {
switch(bitIndex) {
case 1: return 8;
case 2: return 16;
case 3: return 20;
case 4: /* fall through */
case 5: return 24;
}
return significantBits;
}
void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
snd_pcm_t* handle;
snd_pcm_format_mask_t* formatMask;
snd_pcm_format_t format;
snd_pcm_hw_params_t* hwParams;
int handledBits[MAX_BIT_INDEX+1];
int ret;
int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc;
int origSampleSizeInBytes, origSignificantBits;
unsigned int channels, minChannels, maxChannels;
int rate, bitIndex;
for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE;
if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) {
return;
}
ret = snd_pcm_format_mask_malloc(&formatMask);
if (ret != 0) {
ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret);
} else {
ret = snd_pcm_hw_params_malloc(&hwParams);
if (ret != 0) {
ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
} else {
ret = snd_pcm_hw_params_any(handle, hwParams);
/* snd_pcm_hw_params_any can return a positive value on success too */
if (ret < 0) {
ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
} else {
/* for the logic following this code, set ret to 0 to indicate success */
ret = 0;
}
}
snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
if (ret == 0) {
ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels);
if (ret != 0) {
ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret);
}
}
if (ret == 0) {
ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels);
if (ret != 0) {
ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret);
}
}
// since we queried the hw: device, for many soundcards, it will only
// report the maximum number of channels (which is the only way to talk
// to the hw: device). Since we will, however, open the plughw: device
// when opening the Source/TargetDataLine, we can safely assume that
// also the channels 1..maxChannels are available.
#ifdef ALSA_PCM_USE_PLUGHW
minChannels = 1;
#endif
if (ret == 0) {
// plughw: supports any sample rate
rate = -1;
for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
if (snd_pcm_format_mask_test(formatMask, format)) {
// format exists
if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes,
&origSignificantBits,
&isSigned, &isBigEndian, &enc)) {
// now if we use plughw:, we can use any bit size below the
// natively supported ones. Some ALSA drivers only support the maximum
// bit size, so we add any sample rates below the reported one.
// E.g. this iteration reports support for 16-bit.
// getBitIndex will return 2, so it will add entries for
// 16-bit (bitIndex=2) and in the next do-while loop iteration,
// it will decrease bitIndex and will therefore add 8-bit support.
bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits);
do {
if (bitIndex == 0
|| bitIndex == MAX_BIT_INDEX
|| !handledBits[bitIndex]) {
handledBits[bitIndex] = TRUE;
sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes);
significantBits = getSignificantBits(bitIndex, origSignificantBits);
if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) {
// avoid too many channels explicitly listed
// just add -1, min, and max
DAUDIO_AddAudioFormat(creator, significantBits,
-1, -1, rate,
enc, isSigned, isBigEndian);
DAUDIO_AddAudioFormat(creator, significantBits,
sampleSizeInBytes * minChannels,
minChannels, rate,
enc, isSigned, isBigEndian);
DAUDIO_AddAudioFormat(creator, significantBits,
sampleSizeInBytes * maxChannels,
maxChannels, rate,
enc, isSigned, isBigEndian);
} else {
for (channels = minChannels; channels <= maxChannels; channels++) {
DAUDIO_AddAudioFormat(creator, significantBits,
sampleSizeInBytes * channels,
channels, rate,
enc, isSigned, isBigEndian);
}
}
}
#ifndef ALSA_PCM_USE_PLUGHW
// without plugin, do not add fake formats
break;
#endif
} while (--bitIndex > 0);
} else {
TRACE1("could not get format from alsa for format %d\n", format);
}
} else {
//TRACE1("Format %d not supported\n", format);
}
} // for loop
snd_pcm_hw_params_free(hwParams);
}
snd_pcm_format_mask_free(formatMask);
}
snd_pcm_close(handle);
}
/** Workaround for cr 7033899, 7030629:
* dmix plugin doesn't like flush (snd_pcm_drop) when the buffer is empty
* (just opened, underruned or already flushed).
* Sometimes it causes PCM falls to -EBADFD error,
* sometimes causes bufferSize change.
* To prevent unnecessary flushes AlsaPcmInfo::isRunning & isFlushed are used.
*/
/* ******* ALSA PCM INFO ******************** */
typedef struct tag_AlsaPcmInfo {
snd_pcm_t* handle;
snd_pcm_hw_params_t* hwParams;
snd_pcm_sw_params_t* swParams;
int bufferSizeInBytes;
int frameSize; // storage size in Bytes
unsigned int periods;
snd_pcm_uframes_t periodSize;
short int isRunning; // see comment above
short int isFlushed; // see comment above
#ifdef GET_POSITION_METHOD2
// to be used exclusively by getBytePosition!
snd_pcm_status_t* positionStatus;
#endif
} AlsaPcmInfo;
int setStartThresholdNoCommit(AlsaPcmInfo* info, int useThreshold) {
int ret;
int threshold;
if (useThreshold) {
// start device whenever anything is written to the buffer
threshold = 1;
} else {
// never start the device automatically
threshold = 2000000000; /* near UINT_MAX */
}
ret = snd_pcm_sw_params_set_start_threshold(info->handle, info->swParams, threshold);
if (ret < 0) {
ERROR1("Unable to set start threshold mode: %s\n", snd_strerror(ret));
return FALSE;
}
return TRUE;
}
int setStartThreshold(AlsaPcmInfo* info, int useThreshold) {
int ret = 0;
if (!setStartThresholdNoCommit(info, useThreshold)) {
ret = -1;
}
if (ret == 0) {
// commit it
ret = snd_pcm_sw_params(info->handle, info->swParams);
if (ret < 0) {
ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
}
}
return (ret == 0)?TRUE:FALSE;
}
// returns TRUE if successful
int setHWParams(AlsaPcmInfo* info,
float sampleRate,
int channels,
int bufferSizeInFrames,
snd_pcm_format_t format) {
unsigned int rrate, periodTime, periods;
int ret, dir;
snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames;
/* choose all parameters */
ret = snd_pcm_hw_params_any(info->handle, info->hwParams);
if (ret < 0) {
ERROR1("Broken configuration: no configurations available: %s\n", snd_strerror(ret));
return FALSE;
}
/* set the interleaved read/write format */
ret = snd_pcm_hw_params_set_access(info->handle, info->hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
if (ret < 0) {
ERROR1("SND_PCM_ACCESS_RW_INTERLEAVED access type not available: %s\n", snd_strerror(ret));
return FALSE;
}
/* set the sample format */
ret = snd_pcm_hw_params_set_format(info->handle, info->hwParams, format);
if (ret < 0) {
ERROR1("Sample format not available: %s\n", snd_strerror(ret));
return FALSE;
}
/* set the count of channels */
ret = snd_pcm_hw_params_set_channels(info->handle, info->hwParams, channels);
if (ret < 0) {
ERROR2("Channels count (%d) not available: %s\n", channels, snd_strerror(ret));
return FALSE;
}
/* set the stream rate */
rrate = (int) (sampleRate + 0.5f);
dir = 0;
ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir);
if (ret < 0) {
ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret));
return FALSE;
}
if ((rrate-sampleRate > 2) || (rrate-sampleRate < - 2)) {
ERROR2("Rate doesn't match (requested %2.2fHz, got %dHz)\n", sampleRate, rrate);
return FALSE;
}
/* set the buffer time */
ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames);
if (ret < 0) {
ERROR2("Unable to set buffer size to %d frames: %s\n",
(int) alsaBufferSizeInFrames, snd_strerror(ret));
return FALSE;
}
bufferSizeInFrames = (int) alsaBufferSizeInFrames;
/* set the period time */
if (bufferSizeInFrames > 1024) {
dir = 0;
periodTime = DEFAULT_PERIOD_TIME;
ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir);
if (ret < 0) {
ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret));
return FALSE;
}
} else {
/* set the period count for very small buffer sizes to 2 */
dir = 0;
periods = 2;
ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir);
if (ret < 0) {
ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret));
return FALSE;
}
}
/* write the parameters to device */
ret = snd_pcm_hw_params(info->handle, info->hwParams);
if (ret < 0) {
ERROR1("Unable to set hw params: %s\n", snd_strerror(ret));
return FALSE;
}
return TRUE;
}
// returns 1 if successful
int setSWParams(AlsaPcmInfo* info) {
int ret;
/* get the current swparams */
ret = snd_pcm_sw_params_current(info->handle, info->swParams);
if (ret < 0) {
ERROR1("Unable to determine current swparams: %s\n", snd_strerror(ret));
return FALSE;
}
/* never start the transfer automatically */
if (!setStartThresholdNoCommit(info, FALSE /* don't use threshold */)) {
return FALSE;
}
/* allow the transfer when at least period_size samples can be processed */
ret = snd_pcm_sw_params_set_avail_min(info->handle, info->swParams, info->periodSize);
if (ret < 0) {
ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret));
return FALSE;
}
/* write the parameters to the playback device */
ret = snd_pcm_sw_params(info->handle, info->swParams);
if (ret < 0) {
ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
return FALSE;
}
return TRUE;
}
static snd_output_t* ALSA_OUTPUT = NULL;
void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
int encoding, float sampleRate, int sampleSizeInBits,
int frameSize, int channels,
int isSigned, int isBigEndian, int bufferSizeInBytes) {
snd_pcm_format_mask_t* formatMask;
snd_pcm_format_t format;
int dir;
int ret = 0;
AlsaPcmInfo* info = NULL;
/* snd_pcm_uframes_t is 64 bit on 64-bit systems */
snd_pcm_uframes_t alsaBufferSizeInFrames = 0;
TRACE0("> DAUDIO_Open\n");
#ifdef USE_TRACE
// for using ALSA debug dump methods
if (ALSA_OUTPUT == NULL) {
snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
}
#endif
if (channels <= 0) {
ERROR1("ERROR: Invalid number of channels=%d!\n", channels);
return NULL;
}
info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
if (!info) {
ERROR0("Out of memory\n");
return NULL;
}
memset(info, 0, sizeof(AlsaPcmInfo));
// initial values are: stopped, flushed
info->isRunning = 0;
info->isFlushed = 1;
ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
if (ret == 0) {
// set to blocking mode
snd_pcm_nonblock(info->handle, 0);
ret = snd_pcm_hw_params_malloc(&(info->hwParams));
if (ret != 0) {
ERROR1(" snd_pcm_hw_params_malloc returned error %d\n", ret);
} else {
ret = -1;
if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
isSigned, isBigEndian, encoding)) {
if (setHWParams(info,
sampleRate,
channels,
bufferSizeInBytes / frameSize,
format)) {
info->frameSize = frameSize;
ret = snd_pcm_hw_params_get_period_size(info->hwParams, &info->periodSize, &dir);
if (ret < 0) {
ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
}
snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
TRACE3(" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
(int) info->periodSize, info->periods, info->bufferSizeInBytes);
}
}
}
if (ret == 0) {
// set software parameters
ret = snd_pcm_sw_params_malloc(&(info->swParams));
if (ret != 0) {
ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
} else {
if (!setSWParams(info)) {
ret = -1;
}
}
}
if (ret == 0) {
// prepare device
ret = snd_pcm_prepare(info->handle);
if (ret < 0) {
ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
}
}
#ifdef GET_POSITION_METHOD2
if (ret == 0) {
ret = snd_pcm_status_malloc(&(info->positionStatus));
if (ret != 0) {
ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
}
}
#endif
}
if (ret != 0) {
DAUDIO_Close((void*) info, isSource);
info = NULL;
} else {
// set to non-blocking mode
snd_pcm_nonblock(info->handle, 1);
TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
(void*) info->handle);
}
return (void*) info;
}
#ifdef USE_TRACE
void printState(snd_pcm_state_t state) {
if (state == SND_PCM_STATE_OPEN) {
TRACE0("State: SND_PCM_STATE_OPEN\n");
}
else if (state == SND_PCM_STATE_SETUP) {
TRACE0("State: SND_PCM_STATE_SETUP\n");
}
else if (state == SND_PCM_STATE_PREPARED) {
TRACE0("State: SND_PCM_STATE_PREPARED\n");
}
else if (state == SND_PCM_STATE_RUNNING) {
TRACE0("State: SND_PCM_STATE_RUNNING\n");
}
else if (state == SND_PCM_STATE_XRUN) {
TRACE0("State: SND_PCM_STATE_XRUN\n");
}
else if (state == SND_PCM_STATE_DRAINING) {
TRACE0("State: SND_PCM_STATE_DRAINING\n");
}
else if (state == SND_PCM_STATE_PAUSED) {
TRACE0("State: SND_PCM_STATE_PAUSED\n");
}
else if (state == SND_PCM_STATE_SUSPENDED) {
TRACE0("State: SND_PCM_STATE_SUSPENDED\n");
}
}
#endif
int DAUDIO_Start(void* id, int isSource) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
int ret;
snd_pcm_state_t state;
TRACE0("> DAUDIO_Start\n");
// set to blocking mode
snd_pcm_nonblock(info->handle, 0);
// set start mode so that it always starts as soon as data is there
setStartThreshold(info, TRUE /* use threshold */);
state = snd_pcm_state(info->handle);
if (state == SND_PCM_STATE_PAUSED) {
// in case it was stopped previously
TRACE0(" Un-pausing...\n");
ret = snd_pcm_pause(info->handle, FALSE);
if (ret != 0) {
ERROR2(" NOTE: error in snd_pcm_pause:%d: %s\n", ret, snd_strerror(ret));
}
}
if (state == SND_PCM_STATE_SUSPENDED) {
TRACE0(" Resuming...\n");
ret = snd_pcm_resume(info->handle);
if (ret < 0) {
if ((ret != -EAGAIN) && (ret != -ENOSYS)) {
ERROR2(" ERROR: error in snd_pcm_resume:%d: %s\n", ret, snd_strerror(ret));
}
}
}
if (state == SND_PCM_STATE_SETUP) {
TRACE0("need to call prepare again...\n");
// prepare device
ret = snd_pcm_prepare(info->handle);
if (ret < 0) {
ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
}
}
// in case there is still data in the buffers
ret = snd_pcm_start(info->handle);
if (ret != 0) {
if (ret != -EPIPE) {
ERROR2(" NOTE: error in snd_pcm_start: %d: %s\n", ret, snd_strerror(ret));
}
}
// set to non-blocking mode
ret = snd_pcm_nonblock(info->handle, 1);
if (ret != 0) {
ERROR1(" ERROR in snd_pcm_nonblock: %s\n", snd_strerror(ret));
}
state = snd_pcm_state(info->handle);
#ifdef USE_TRACE
printState(state);
#endif
ret = (state == SND_PCM_STATE_PREPARED)
|| (state == SND_PCM_STATE_RUNNING)
|| (state == SND_PCM_STATE_XRUN)
|| (state == SND_PCM_STATE_SUSPENDED);
if (ret) {
info->isRunning = 1;
// source line should keep isFlushed value until Write() is called;
// for target data line reset it right now.
if (!isSource) {
info->isFlushed = 0;
}
}
TRACE1("< DAUDIO_Start %s\n", ret?"success":"error");
return ret?TRUE:FALSE;
}
int DAUDIO_Stop(void* id, int isSource) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
int ret;
TRACE0("> DAUDIO_Stop\n");
// set to blocking mode
snd_pcm_nonblock(info->handle, 0);
setStartThreshold(info, FALSE /* don't use threshold */); // device will not start after buffer xrun
ret = snd_pcm_pause(info->handle, 1);
// set to non-blocking mode
snd_pcm_nonblock(info->handle, 1);
if (ret != 0) {
ERROR1("ERROR in snd_pcm_pause: %s\n", snd_strerror(ret));
return FALSE;
}
info->isRunning = 0;
TRACE0("< DAUDIO_Stop success\n");
return TRUE;
}
void DAUDIO_Close(void* id, int isSource) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
TRACE0("DAUDIO_Close\n");
if (info != NULL) {
if (info->handle != NULL) {
snd_pcm_close(info->handle);
}
if (info->hwParams) {
snd_pcm_hw_params_free(info->hwParams);
}
if (info->swParams) {
snd_pcm_sw_params_free(info->swParams);
}
#ifdef GET_POSITION_METHOD2
if (info->positionStatus) {
snd_pcm_status_free(info->positionStatus);
}
#endif
free(info);
}
}
/*
* Underrun and suspend recovery
* returns
* 0: exit native and return 0
* 1: try again to write/read
* -1: error - exit native with return value -1
*/
int xrun_recovery(AlsaPcmInfo* info, int err) {
int ret;
if (err == -EPIPE) { /* underrun / overflow */
TRACE0("xrun_recovery: underrun/overflow.\n");
ret = snd_pcm_prepare(info->handle);
if (ret < 0) {
ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
return -1;
}
return 1;
} else if (err == -ESTRPIPE) {
TRACE0("xrun_recovery: suspended.\n");
ret = snd_pcm_resume(info->handle);
if (ret < 0) {
if (ret == -EAGAIN) {
return 0; /* wait until the suspend flag is released */
}
return -1;
}
ret = snd_pcm_prepare(info->handle);
if (ret < 0) {
ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
return -1;
}
return 1;
} else if (err == -EAGAIN) {
TRACE0("xrun_recovery: EAGAIN try again flag.\n");
return 0;
}
TRACE2("xrun_recovery: unexpected error %d: %s\n", err, snd_strerror(err));
return -1;
}
// returns -1 on error
int DAUDIO_Write(void* id, char* data, int byteSize) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
int ret, count;
snd_pcm_sframes_t frameSize, writtenFrames;
TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
/* sanity */
if (byteSize <= 0 || info->frameSize <= 0) {
ERROR2(" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
(int) byteSize, (int) info->frameSize);
TRACE0("< DAUDIO_Write returning -1\n");
return -1;
}
count = 2; // maximum number of trials to recover from underrun
//frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
do {
writtenFrames = snd_pcm_writei(info->handle, (const void*) data, (snd_pcm_uframes_t) frameSize);
if (writtenFrames < 0) {
ret = xrun_recovery(info, (int) writtenFrames);
if (ret <= 0) {
TRACE1("DAUDIO_Write: xrun recovery returned %d -> return.\n", ret);
return ret;
}
if (count-- <= 0) {
ERROR0("DAUDIO_Write: too many attempts to recover from xrun/suspend\n");
return -1;
}
} else {
break;
}
} while (TRUE);
//ret = snd_pcm_frames_to_bytes(info->handle, writtenFrames);
if (writtenFrames > 0) {
// reset "flushed" flag
info->isFlushed = 0;
}
ret = (int) (writtenFrames * info->frameSize);
TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
return ret;
}
// returns -1 on error
int DAUDIO_Read(void* id, char* data, int byteSize) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
int ret, count;
snd_pcm_sframes_t frameSize, readFrames;
TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
/*TRACE3(" info=%p, data=%p, byteSize=%d\n",
(void*) info, (void*) data, (int) byteSize);
TRACE2(" info->frameSize=%d, info->handle=%p\n",
(int) info->frameSize, (void*) info->handle);
*/
/* sanity */
if (byteSize <= 0 || info->frameSize <= 0) {
ERROR2(" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
(int) byteSize, (int) info->frameSize);
TRACE0("< DAUDIO_Read returning -1\n");
return -1;
}
if (!info->isRunning && info->isFlushed) {
// PCM has nothing to read
return 0;
}
count = 2; // maximum number of trials to recover from error
//frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
do {
readFrames = snd_pcm_readi(info->handle, (void*) data, (snd_pcm_uframes_t) frameSize);
if (readFrames < 0) {
ret = xrun_recovery(info, (int) readFrames);
if (ret <= 0) {
TRACE1("DAUDIO_Read: xrun recovery returned %d -> return.\n", ret);
return ret;
}
if (count-- <= 0) {
ERROR0("DAUDIO_Read: too many attempts to recover from xrun/suspend\n");
return -1;
}
} else {
break;
}
} while (TRUE);
//ret = snd_pcm_frames_to_bytes(info->handle, readFrames);
ret = (int) (readFrames * info->frameSize);
TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
return ret;
}
int DAUDIO_GetBufferSize(void* id, int isSource) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
return info->bufferSizeInBytes;
}
int DAUDIO_StillDraining(void* id, int isSource) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
snd_pcm_state_t state;
state = snd_pcm_state(info->handle);
//printState(state);
//TRACE1("Still draining: %s\n", (state != SND_PCM_STATE_XRUN)?"TRUE":"FALSE");
return (state == SND_PCM_STATE_RUNNING)?TRUE:FALSE;
}
int DAUDIO_Flush(void* id, int isSource) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
int ret;
TRACE0("DAUDIO_Flush\n");
if (info->isFlushed) {
// nothing to drop
return 1;
}
ret = snd_pcm_drop(info->handle);
if (ret != 0) {
ERROR1("ERROR in snd_pcm_drop: %s\n", snd_strerror(ret));
return FALSE;
}
info->isFlushed = 1;
if (info->isRunning) {
ret = DAUDIO_Start(id, isSource);
}
return ret;
}
int DAUDIO_GetAvailable(void* id, int isSource) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
snd_pcm_sframes_t availableInFrames;
snd_pcm_state_t state;
int ret;
state = snd_pcm_state(info->handle);
if (info->isFlushed || state == SND_PCM_STATE_XRUN) {
// if in xrun state then we have the entire buffer available,
// not 0 as alsa reports
ret = info->bufferSizeInBytes;
} else {
availableInFrames = snd_pcm_avail_update(info->handle);
if (availableInFrames < 0) {
ret = 0;
} else {
//ret = snd_pcm_frames_to_bytes(info->handle, availableInFrames);
ret = (int) (availableInFrames * info->frameSize);
}
}
TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
return ret;
}
INT64 estimatePositionFromAvail(AlsaPcmInfo* info, int isSource, INT64 javaBytePos, int availInBytes) {
// estimate the current position with the buffer size and
// the available bytes to read or write in the buffer.
// not an elegant solution - bytePos will stop on xruns,
// and in race conditions it may jump backwards
// Advantage is that it is indeed based on the samples that go through
// the system (rather than time-based methods)
if (isSource) {
// javaBytePos is the position that is reached when the current
// buffer is played completely
return (INT64) (javaBytePos - info->bufferSizeInBytes + availInBytes);
} else {
// javaBytePos is the position that was when the current buffer was empty
return (INT64) (javaBytePos + availInBytes);
}
}
INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
AlsaPcmInfo* info = (AlsaPcmInfo*) id;
int ret;
INT64 result = javaBytePos;
snd_pcm_state_t state;
state = snd_pcm_state(info->handle);
if (!info->isFlushed && state != SND_PCM_STATE_XRUN) {
#ifdef GET_POSITION_METHOD2
snd_timestamp_t* ts;
snd_pcm_uframes_t framesAvail;
// note: slight race condition if this is called simultaneously from 2 threads
ret = snd_pcm_status(info->handle, info->positionStatus);
if (ret != 0) {
ERROR1("ERROR in snd_pcm_status: %s\n", snd_strerror(ret));
result = javaBytePos;
} else {
// calculate from time value, or from available bytes
framesAvail = snd_pcm_status_get_avail(info->positionStatus);
result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
}
#endif
#ifdef GET_POSITION_METHOD3
snd_pcm_uframes_t framesAvail;
ret = snd_pcm_avail(info->handle, &framesAvail);
if (ret != 0) {
ERROR1("ERROR in snd_pcm_avail: %s\n", snd_strerror(ret));
result = javaBytePos;
} else {
result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
}
#endif
#ifdef GET_POSITION_METHOD1
result = estimatePositionFromAvail(info, isSource, javaBytePos, DAUDIO_GetAvailable(id, isSource));
#endif
}
//printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
return result;
}
void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
/* save to ignore, since GetBytePosition
* takes the javaBytePos param into account
*/
}
int DAUDIO_RequiresServicing(void* id, int isSource) {
// never need servicing on Bsd
return FALSE;
}
void DAUDIO_Service(void* id, int isSource) {
// never need servicing on Bsd
}
#endif // USE_DAUDIO

View File

@ -1,292 +0,0 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
//#define USE_ERROR
//#define USE_TRACE
#include "PLATFORM_API_BsdOS_ALSA_PCMUtils.h"
#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
// callback for iteration through devices
// returns TRUE if iteration should continue
// NOTE: cardinfo may be NULL (for "default" device)
typedef int (*DeviceIteratorPtr)(UINT32 deviceID, snd_pcm_info_t* pcminfo,
snd_ctl_card_info_t* cardinfo, void *userData);
// for each ALSA device, call iterator. userData is passed to the iterator
// returns total number of iterations
int iteratePCMDevices(DeviceIteratorPtr iterator, void* userData) {
int count = 0;
int subdeviceCount;
int card, dev, subDev;
char devname[16];
int err;
snd_ctl_t *handle;
snd_pcm_t *pcm;
snd_pcm_info_t* pcminfo;
snd_ctl_card_info_t *cardinfo, *defcardinfo = NULL;
UINT32 deviceID;
int doContinue = TRUE;
snd_pcm_info_malloc(&pcminfo);
snd_ctl_card_info_malloc(&cardinfo);
// 1st try "default" device
err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if (err < 0) {
// try with the other direction
err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
}
if (err < 0) {
ERROR1("ERROR: snd_pcm_open (\"default\"): %s\n", snd_strerror(err));
} else {
err = snd_pcm_info(pcm, pcminfo);
snd_pcm_close(pcm);
if (err < 0) {
ERROR1("ERROR: snd_pcm_info (\"default\"): %s\n",
snd_strerror(err));
} else {
// try to get card info
card = snd_pcm_info_get_card(pcminfo);
if (card >= 0) {
sprintf(devname, ALSA_HARDWARE_CARD, card);
if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) {
if (snd_ctl_card_info(handle, cardinfo) >= 0) {
defcardinfo = cardinfo;
}
snd_ctl_close(handle);
}
}
// call callback function for the device
if (iterator != NULL) {
doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, pcminfo,
defcardinfo, userData);
}
count++;
}
}
// iterate cards
card = -1;
while (doContinue) {
if (snd_card_next(&card) < 0) {
break;
}
if (card < 0) {
break;
}
sprintf(devname, ALSA_HARDWARE_CARD, card);
TRACE1("Opening alsa device \"%s\"...\n", devname);
err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK);
if (err < 0) {
ERROR2("ERROR: snd_ctl_open, card=%d: %s\n",
card, snd_strerror(err));
} else {
err = snd_ctl_card_info(handle, cardinfo);
if (err < 0) {
ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n",
card, snd_strerror(err));
} else {
dev = -1;
while (doContinue) {
if (snd_ctl_pcm_next_device(handle, &dev) < 0) {
ERROR0("snd_ctl_pcm_next_device\n");
}
if (dev < 0) {
break;
}
snd_pcm_info_set_device(pcminfo, dev);
snd_pcm_info_set_subdevice(pcminfo, 0);
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
err = snd_ctl_pcm_info(handle, pcminfo);
if (err == -ENOENT) {
// try with the other direction
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
err = snd_ctl_pcm_info(handle, pcminfo);
}
if (err < 0) {
if (err != -ENOENT) {
ERROR2("ERROR: snd_ctl_pcm_info, card=%d: %s",
card, snd_strerror(err));
}
} else {
subdeviceCount = needEnumerateSubdevices(ALSA_PCM) ?
snd_pcm_info_get_subdevices_count(pcminfo) : 1;
if (iterator!=NULL) {
for (subDev = 0; subDev < subdeviceCount; subDev++) {
deviceID = encodeDeviceID(card, dev, subDev);
doContinue = (*iterator)(deviceID, pcminfo,
cardinfo, userData);
count++;
if (!doContinue) {
break;
}
}
} else {
count += subdeviceCount;
}
}
} // of while(doContinue)
}
snd_ctl_close(handle);
}
}
snd_ctl_card_info_free(cardinfo);
snd_pcm_info_free(pcminfo);
return count;
}
int getAudioDeviceCount() {
initAlsaSupport();
return iteratePCMDevices(NULL, NULL);
}
int deviceInfoIterator(UINT32 deviceID, snd_pcm_info_t* pcminfo,
snd_ctl_card_info_t* cardinfo, void* userData) {
char buffer[300];
ALSA_AudioDeviceDescription* desc = (ALSA_AudioDeviceDescription*)userData;
#ifdef ALSA_PCM_USE_PLUGHW
int usePlugHw = 1;
#else
int usePlugHw = 0;
#endif
initAlsaSupport();
if (desc->index == 0) {
// we found the device with correct index
*(desc->maxSimultaneousLines) = needEnumerateSubdevices(ALSA_PCM) ?
1 : snd_pcm_info_get_subdevices_count(pcminfo);
*desc->deviceID = deviceID;
buffer[0]=' '; buffer[1]='[';
// buffer[300] is enough to store the actual device string w/o overrun
getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_PCM);
strncat(buffer, "]", sizeof(buffer) - strlen(buffer) - 1);
strncpy(desc->name,
(cardinfo != NULL)
? snd_ctl_card_info_get_id(cardinfo)
: snd_pcm_info_get_id(pcminfo),
desc->strLen - strlen(buffer));
strncat(desc->name, buffer, desc->strLen - strlen(desc->name));
strncpy(desc->vendor, "ALSA (http://www.alsa-project.org)", desc->strLen);
strncpy(desc->description,
(cardinfo != NULL)
? snd_ctl_card_info_get_name(cardinfo)
: snd_pcm_info_get_name(pcminfo),
desc->strLen);
strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
strncat(desc->description, snd_pcm_info_get_id(pcminfo), desc->strLen - strlen(desc->description));
strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
strncat(desc->description, snd_pcm_info_get_name(pcminfo), desc->strLen - strlen(desc->description));
getALSAVersion(desc->version, desc->strLen);
TRACE4("Returning %s, %s, %s, %s\n", desc->name, desc->vendor, desc->description, desc->version);
return FALSE; // do not continue iteration
}
desc->index--;
return TRUE;
}
// returns 0 if successful
int openPCMfromDeviceID(int deviceID, snd_pcm_t** handle, int isSource, int hardware) {
char buffer[200];
int ret;
initAlsaSupport();
getDeviceStringFromDeviceID(buffer, deviceID, !hardware, ALSA_PCM);
TRACE1("Opening ALSA device %s\n", buffer);
ret = snd_pcm_open(handle, buffer,
isSource?SND_PCM_STREAM_PLAYBACK:SND_PCM_STREAM_CAPTURE,
SND_PCM_NONBLOCK);
if (ret != 0) {
ERROR1("snd_pcm_open returned error code %d \n", ret);
*handle = NULL;
}
return ret;
}
int getAudioDeviceDescriptionByIndex(ALSA_AudioDeviceDescription* desc) {
initAlsaSupport();
TRACE1(" getAudioDeviceDescriptionByIndex(mixerIndex = %d\n", desc->index);
iteratePCMDevices(&deviceInfoIterator, desc);
return (desc->index == 0)?TRUE:FALSE;
}
// returns 1 if successful
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
int* sampleSizeInBytes, int* significantBits,
int* isSigned, int* isBigEndian, int* enc) {
*sampleSizeInBytes = (snd_pcm_format_physical_width(alsaFormat) + 7) / 8;
*significantBits = snd_pcm_format_width(alsaFormat);
// defaults
*enc = 0; // PCM
*isSigned = (snd_pcm_format_signed(alsaFormat) > 0);
*isBigEndian = (snd_pcm_format_big_endian(alsaFormat) > 0);
// non-PCM formats
if (alsaFormat == SND_PCM_FORMAT_MU_LAW) { // Mu-Law
*sampleSizeInBytes = 8; *enc = 1; *significantBits = *sampleSizeInBytes;
}
else if (alsaFormat == SND_PCM_FORMAT_A_LAW) { // A-Law
*sampleSizeInBytes = 8; *enc = 2; *significantBits = *sampleSizeInBytes;
}
else if (snd_pcm_format_linear(alsaFormat) < 1) {
return 0;
}
return (*sampleSizeInBytes > 0);
}
// returns 1 if successful
int getAlsaFormatFromFormat(snd_pcm_format_t* alsaFormat,
int sampleSizeInBytes, int significantBits,
int isSigned, int isBigEndian, int enc) {
*alsaFormat = SND_PCM_FORMAT_UNKNOWN;
if (enc == 0) {
*alsaFormat = snd_pcm_build_linear_format(significantBits,
sampleSizeInBytes * 8,
isSigned?0:1,
isBigEndian?1:0);
}
else if ((sampleSizeInBytes == 1) && (significantBits == 8)) {
if (enc == 1) { // ULAW
*alsaFormat = SND_PCM_FORMAT_MU_LAW;
}
else if (enc == 2) { // ALAW
*alsaFormat = SND_PCM_FORMAT_A_LAW;
}
}
return (*alsaFormat == SND_PCM_FORMAT_UNKNOWN)?0:1;
}
/* end */

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// define this with a later version of ALSA than 0.9.0rc3
// (starting from 1.0.0 it became default behaviour)
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include "Utilities.h"
#ifndef PLATFORM_API_BSDOS_ALSA_PCMUTILS_H_INCLUDED
#define PLATFORM_API_BSDOS_ALSA_PCMUTILS_H_INCLUDED
// if this is defined, use plughw: devices
#define ALSA_PCM_USE_PLUGHW
//#undef ALSA_PCM_USE_PLUGHW
// maximum number of channels that is listed in the formats. If more, than
// just -1 for channel count is used.
#define MAXIMUM_LISTED_CHANNELS 32
typedef struct tag_ALSA_AudioDeviceDescription {
int index; // in
int strLen; // in
INT32* deviceID; // out
int* maxSimultaneousLines; // out
char* name; // out
char* vendor; // out
char* description; // out
char* version; // out
} ALSA_AudioDeviceDescription;
int getAudioDeviceCount();
int getAudioDeviceDescriptionByIndex(ALSA_AudioDeviceDescription* desc);
// returns ALSA error code, or 0 if successful
int openPCMfromDeviceID(int deviceID, snd_pcm_t** handle, int isSource, int hardware);
// returns 1 if successful
// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
int* sampleSizeInBytes, int* significantBits,
int* isSigned, int* isBigEndian, int* enc);
int getAlsaFormatFromFormat(snd_pcm_format_t* alsaFormat,
int sampleSizeInBytes, int significantBits,
int isSigned, int isBigEndian, int enc);
#endif // PLATFORM_API_BSDOS_ALSA_PCMUTILS_H_INCLUDED

View File

@ -1,724 +0,0 @@
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#define USE_ERROR
//#define USE_TRACE
#include "Ports.h"
#include "PLATFORM_API_BsdOS_ALSA_CommonUtils.h"
#include <alsa/asoundlib.h>
#if USE_PORTS == TRUE
#define MAX_ELEMS (300)
#define MAX_CONTROLS (MAX_ELEMS * 4)
#define CHANNELS_MONO (SND_MIXER_SCHN_LAST + 1)
#define CHANNELS_STEREO (SND_MIXER_SCHN_LAST + 2)
typedef struct {
snd_mixer_elem_t* elem;
INT32 portType; /* one of PORT_XXX_xx */
char* controlType; /* one of CONTROL_TYPE_xx */
/* Values: either SND_MIXER_SCHN_FRONT_xx, CHANNELS_MONO or CHANNELS_STEREO.
For SND_MIXER_SCHN_FRONT_xx, exactly this channel is set/retrieved directly.
For CHANNELS_MONO, ALSA channel SND_MIXER_SCHN_MONO is set/retrieved directly.
For CHANNELS_STEREO, ALSA channels SND_MIXER_SCHN_FRONT_LEFT and SND_MIXER_SCHN_FRONT_RIGHT
are set after a calculation that takes balance into account. Retrieved? Average of both
channels? (Using a cached value is not a good idea since the value in the HW may have been
altered.) */
INT32 channel;
} PortControl;
typedef struct tag_PortMixer {
snd_mixer_t* mixer_handle;
/* Number of array elements used in elems and types. */
int numElems;
snd_mixer_elem_t** elems;
/* Array of port types (PORT_SRC_UNKNOWN etc.). Indices are the same as in elems. */
INT32* types;
/* Number of array elements used in controls. */
int numControls;
PortControl* controls;
} PortMixer;
///// implemented functions of Ports.h
INT32 PORT_GetPortMixerCount() {
INT32 mixerCount;
int card;
char devname[16];
int err;
snd_ctl_t *handle;
snd_ctl_card_info_t* info;
TRACE0("> PORT_GetPortMixerCount\n");
initAlsaSupport();
snd_ctl_card_info_malloc(&info);
card = -1;
mixerCount = 0;
if (snd_card_next(&card) >= 0) {
while (card >= 0) {
sprintf(devname, ALSA_HARDWARE_CARD, card);
TRACE1("PORT_GetPortMixerCount: Opening alsa device \"%s\"...\n", devname);
err = snd_ctl_open(&handle, devname, 0);
if (err < 0) {
ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
} else {
mixerCount++;
snd_ctl_close(handle);
}
if (snd_card_next(&card) < 0) {
break;
}
}
}
snd_ctl_card_info_free(info);
TRACE0("< PORT_GetPortMixerCount\n");
return mixerCount;
}
INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
snd_ctl_t* handle;
snd_ctl_card_info_t* card_info;
char devname[16];
int err;
char buffer[100];
TRACE0("> PORT_GetPortMixerDescription\n");
snd_ctl_card_info_malloc(&card_info);
sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
TRACE1("Opening alsa device \"%s\"...\n", devname);
err = snd_ctl_open(&handle, devname, 0);
if (err < 0) {
ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
return FALSE;
}
err = snd_ctl_card_info(handle, card_info);
if (err < 0) {
ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
}
strncpy(description->name, snd_ctl_card_info_get_id(card_info), PORT_STRING_LENGTH - 1);
sprintf(buffer, " [%s]", devname);
strncat(description->name, buffer, PORT_STRING_LENGTH - 1 - strlen(description->name));
strncpy(description->vendor, "ALSA (http://www.alsa-project.org)", PORT_STRING_LENGTH - 1);
strncpy(description->description, snd_ctl_card_info_get_name(card_info), PORT_STRING_LENGTH - 1);
strncat(description->description, ", ", PORT_STRING_LENGTH - 1 - strlen(description->description));
strncat(description->description, snd_ctl_card_info_get_mixername(card_info), PORT_STRING_LENGTH - 1 - strlen(description->description));
getALSAVersion(description->version, PORT_STRING_LENGTH - 1);
snd_ctl_close(handle);
snd_ctl_card_info_free(card_info);
TRACE0("< PORT_GetPortMixerDescription\n");
return TRUE;
}
void* PORT_Open(INT32 mixerIndex) {
char devname[16];
snd_mixer_t* mixer_handle;
int err;
PortMixer* handle;
TRACE0("> PORT_Open\n");
sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
ERROR2("Mixer %s open error: %s", devname, snd_strerror(err));
return NULL;
}
if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) {
ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err));
snd_mixer_close(mixer_handle);
return NULL;
}
if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) {
ERROR1("Mixer register error: %s", snd_strerror(err));
snd_mixer_close(mixer_handle);
return NULL;
}
err = snd_mixer_load(mixer_handle);
if (err < 0) {
ERROR2("Mixer %s load error: %s", devname, snd_strerror(err));
snd_mixer_close(mixer_handle);
return NULL;
}
handle = (PortMixer*) calloc(1, sizeof(PortMixer));
if (handle == NULL) {
ERROR0("malloc() failed.");
snd_mixer_close(mixer_handle);
return NULL;
}
handle->numElems = 0;
handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*));
if (handle->elems == NULL) {
ERROR0("malloc() failed.");
snd_mixer_close(mixer_handle);
free(handle);
return NULL;
}
handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32));
if (handle->types == NULL) {
ERROR0("malloc() failed.");
snd_mixer_close(mixer_handle);
free(handle->elems);
free(handle);
return NULL;
}
handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl));
if (handle->controls == NULL) {
ERROR0("malloc() failed.");
snd_mixer_close(mixer_handle);
free(handle->elems);
free(handle->types);
free(handle);
return NULL;
}
handle->mixer_handle = mixer_handle;
// necessary to initialize data structures
PORT_GetPortCount(handle);
TRACE0("< PORT_Open\n");
return handle;
}
void PORT_Close(void* id) {
TRACE0("> PORT_Close\n");
if (id != NULL) {
PortMixer* handle = (PortMixer*) id;
if (handle->mixer_handle != NULL) {
snd_mixer_close(handle->mixer_handle);
}
if (handle->elems != NULL) {
free(handle->elems);
}
if (handle->types != NULL) {
free(handle->types);
}
if (handle->controls != NULL) {
free(handle->controls);
}
free(handle);
}
TRACE0("< PORT_Close\n");
}
INT32 PORT_GetPortCount(void* id) {
PortMixer* portMixer;
snd_mixer_elem_t *elem;
TRACE0("> PORT_GetPortCount\n");
if (id == NULL) {
// $$mp: Should become a descriptive error code (invalid handle).
return -1;
}
portMixer = (PortMixer*) id;
if (portMixer->numElems == 0) {
for (elem = snd_mixer_first_elem(portMixer->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
if (!snd_mixer_selem_is_active(elem))
continue;
TRACE2("Simple mixer control '%s',%i\n",
snd_mixer_selem_get_name(elem),
snd_mixer_selem_get_index(elem));
if (snd_mixer_selem_has_playback_volume(elem)) {
portMixer->elems[portMixer->numElems] = elem;
portMixer->types[portMixer->numElems] = PORT_DST_UNKNOWN;
portMixer->numElems++;
}
// to prevent buffer overflow
if (portMixer->numElems >= MAX_ELEMS) {
break;
}
/* If an element has both playback an capture volume, it is put into the arrays
twice. */
if (snd_mixer_selem_has_capture_volume(elem)) {
portMixer->elems[portMixer->numElems] = elem;
portMixer->types[portMixer->numElems] = PORT_SRC_UNKNOWN;
portMixer->numElems++;
}
// to prevent buffer overflow
if (portMixer->numElems >= MAX_ELEMS) {
break;
}
}
}
TRACE0("< PORT_GetPortCount\n");
return portMixer->numElems;
}
INT32 PORT_GetPortType(void* id, INT32 portIndex) {
PortMixer* portMixer;
INT32 type;
TRACE0("> PORT_GetPortType\n");
if (id == NULL) {
// $$mp: Should become a descriptive error code (invalid handle).
return -1;
}
portMixer = (PortMixer*) id;
if (portIndex < 0 || portIndex >= portMixer->numElems) {
// $$mp: Should become a descriptive error code (index out of bounds).
return -1;
}
type = portMixer->types[portIndex];
TRACE0("< PORT_GetPortType\n");
return type;
}
INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
PortMixer* portMixer;
const char* nam;
TRACE0("> PORT_GetPortName\n");
if (id == NULL) {
// $$mp: Should become a descriptive error code (invalid handle).
return -1;
}
portMixer = (PortMixer*) id;
if (portIndex < 0 || portIndex >= portMixer->numElems) {
// $$mp: Should become a descriptive error code (index out of bounds).
return -1;
}
nam = snd_mixer_selem_get_name(portMixer->elems[portIndex]);
strncpy(name, nam, len - 1);
name[len - 1] = 0;
TRACE0("< PORT_GetPortName\n");
return TRUE;
}
static int isPlaybackFunction(INT32 portType) {
return (portType & PORT_DST_MASK);
}
/* Sets portControl to a pointer to the next free array element in the PortControl (pointer)
array of the passed portMixer. Returns TRUE if successful. May return FALSE if there is no
free slot. In this case, portControl is not altered */
static int getControlSlot(PortMixer* portMixer, PortControl** portControl) {
if (portMixer->numControls >= MAX_CONTROLS) {
return FALSE;
} else {
*portControl = &(portMixer->controls[portMixer->numControls]);
portMixer->numControls++;
return TRUE;
}
}
/* Protect against illegal min-max values, preventing divisions by zero.
*/
inline static long getRange(long min, long max) {
if (max > min) {
return max - min;
} else {
return 1;
}
}
/* Idea: we may specify that if unit is an empty string, the values are linear and if unit is "dB",
the values are logarithmic.
*/
static void* createVolumeControl(PortControlCreator* creator,
PortControl* portControl,
snd_mixer_elem_t* elem, int isPlayback) {
void* control;
float precision;
long min, max;
if (isPlayback) {
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
} else {
snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
}
/* $$mp: The volume values retrieved with the ALSA API are strongly supposed to be logarithmic.
So the following calculation is wrong. However, there is no correct calculation, since
for equal-distant logarithmic steps, the precision expressed in linear varies over the
scale. */
precision = 1.0F / getRange(min, max);
control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_VOLUME, 0.0F, +1.0F, precision, "");
return control;
}
void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
PortMixer* portMixer;
snd_mixer_elem_t* elem;
void* control;
PortControl* portControl;
void* controls[10];
int numControls;
char* portName;
int isPlayback = 0;
int isMono;
int isStereo;
char* type;
snd_mixer_selem_channel_id_t channel;
memset(controls, 0, sizeof(controls));
TRACE0("> PORT_GetControls\n");
if (id == NULL) {
ERROR0("Invalid handle!");
// $$mp: an error code should be returned.
return;
}
portMixer = (PortMixer*) id;
if (portIndex < 0 || portIndex >= portMixer->numElems) {
ERROR0("Port index out of range!");
// $$mp: an error code should be returned.
return;
}
numControls = 0;
elem = portMixer->elems[portIndex];
if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) {
/* Since we've split/duplicated elements with both playback and capture on the recovery
of elements, we now can assume that we handle only to deal with either playback or
capture. */
isPlayback = isPlaybackFunction(portMixer->types[portIndex]);
isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) ||
(!isPlayback && snd_mixer_selem_is_capture_mono(elem));
isStereo = (isPlayback &&
snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) ||
(!isPlayback &&
snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT));
// single volume control
if (isMono || isStereo) {
if (getControlSlot(portMixer, &portControl)) {
portControl->elem = elem;
portControl->portType = portMixer->types[portIndex];
portControl->controlType = CONTROL_TYPE_VOLUME;
if (isMono) {
portControl->channel = CHANNELS_MONO;
} else {
portControl->channel = CHANNELS_STEREO;
}
control = createVolumeControl(creator, portControl, elem, isPlayback);
if (control != NULL) {
controls[numControls++] = control;
}
}
} else { // more than two channels, each channels has its own control.
for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) {
if (isPlayback && snd_mixer_selem_has_playback_channel(elem, channel) ||
!isPlayback && snd_mixer_selem_has_capture_channel(elem, channel)) {
if (getControlSlot(portMixer, &portControl)) {
portControl->elem = elem;
portControl->portType = portMixer->types[portIndex];
portControl->controlType = CONTROL_TYPE_VOLUME;
portControl->channel = channel;
control = createVolumeControl(creator, portControl, elem, isPlayback);
// We wrap in a compound control to provide the channel name.
if (control != NULL) {
/* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
to take a const char* parameter. */
control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1);
}
if (control != NULL) {
controls[numControls++] = control;
}
}
}
}
}
// BALANCE control
if (isStereo) {
if (getControlSlot(portMixer, &portControl)) {
portControl->elem = elem;
portControl->portType = portMixer->types[portIndex];
portControl->controlType = CONTROL_TYPE_BALANCE;
portControl->channel = CHANNELS_STEREO;
/* $$mp: The value for precision is chosen more or less arbitrarily. */
control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, "");
if (control != NULL) {
controls[numControls++] = control;
}
}
}
}
if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) {
if (getControlSlot(portMixer, &portControl)) {
type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT;
portControl->elem = elem;
portControl->portType = portMixer->types[portIndex];
portControl->controlType = type;
control = (creator->newBooleanControl)(creator, portControl, type);
if (control != NULL) {
controls[numControls++] = control;
}
}
}
/* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
to take a const char* parameter. */
portName = (char*) snd_mixer_selem_get_name(elem);
control = (creator->newCompoundControl)(creator, portName, controls, numControls);
if (control != NULL) {
(creator->addControl)(creator, control);
}
TRACE0("< PORT_GetControls\n");
}
INT32 PORT_GetIntValue(void* controlIDV) {
PortControl* portControl = (PortControl*) controlIDV;
int value = 0;
snd_mixer_selem_channel_id_t channel;
if (portControl != NULL) {
switch (portControl->channel) {
case CHANNELS_MONO:
channel = SND_MIXER_SCHN_MONO;
break;
case CHANNELS_STEREO:
channel = SND_MIXER_SCHN_FRONT_LEFT;
break;
default:
channel = portControl->channel;
}
if (portControl->controlType == CONTROL_TYPE_MUTE ||
portControl->controlType == CONTROL_TYPE_SELECT) {
if (isPlaybackFunction(portControl->portType)) {
snd_mixer_selem_get_playback_switch(portControl->elem, channel, &value);
} else {
snd_mixer_selem_get_capture_switch(portControl->elem, channel, &value);
}
if (portControl->controlType == CONTROL_TYPE_MUTE) {
value = ! value;
}
} else {
ERROR1("PORT_GetIntValue(): inappropriate control type: %s\n",
portControl->controlType);
}
}
return (INT32) value;
}
void PORT_SetIntValue(void* controlIDV, INT32 value) {
PortControl* portControl = (PortControl*) controlIDV;
snd_mixer_selem_channel_id_t channel;
if (portControl != NULL) {
if (portControl->controlType == CONTROL_TYPE_MUTE) {
value = ! value;
}
if (portControl->controlType == CONTROL_TYPE_MUTE ||
portControl->controlType == CONTROL_TYPE_SELECT) {
if (isPlaybackFunction(portControl->portType)) {
snd_mixer_selem_set_playback_switch_all(portControl->elem, value);
} else {
snd_mixer_selem_set_capture_switch_all(portControl->elem, value);
}
} else {
ERROR1("PORT_SetIntValue(): inappropriate control type: %s\n",
portControl->controlType);
}
}
}
static float scaleVolumeValueToNormalized(long value, long min, long max) {
return (float) (value - min) / getRange(min, max);
}
static long scaleVolumeValueToHardware(float value, long min, long max) {
return (long)(value * getRange(min, max) + min);
}
float getRealVolume(PortControl* portControl,
snd_mixer_selem_channel_id_t channel) {
float fValue;
long lValue = 0;
long min = 0;
long max = 0;
if (isPlaybackFunction(portControl->portType)) {
snd_mixer_selem_get_playback_volume_range(portControl->elem,
&min, &max);
snd_mixer_selem_get_playback_volume(portControl->elem,
channel, &lValue);
} else {
snd_mixer_selem_get_capture_volume_range(portControl->elem,
&min, &max);
snd_mixer_selem_get_capture_volume(portControl->elem,
channel, &lValue);
}
fValue = scaleVolumeValueToNormalized(lValue, min, max);
return fValue;
}
void setRealVolume(PortControl* portControl,
snd_mixer_selem_channel_id_t channel, float value) {
long lValue = 0;
long min = 0;
long max = 0;
if (isPlaybackFunction(portControl->portType)) {
snd_mixer_selem_get_playback_volume_range(portControl->elem,
&min, &max);
lValue = scaleVolumeValueToHardware(value, min, max);
snd_mixer_selem_set_playback_volume(portControl->elem,
channel, lValue);
} else {
snd_mixer_selem_get_capture_volume_range(portControl->elem,
&min, &max);
lValue = scaleVolumeValueToHardware(value, min, max);
snd_mixer_selem_set_capture_volume(portControl->elem,
channel, lValue);
}
}
static float getFakeBalance(PortControl* portControl) {
float volL, volR;
// pan is the ratio of left and right
volL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
volR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
if (volL > volR) {
return -1.0f + (volR / volL);
}
else if (volR > volL) {
return 1.0f - (volL / volR);
}
return 0.0f;
}
static float getFakeVolume(PortControl* portControl) {
float valueL;
float valueR;
float value;
valueL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
valueR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
// volume is the greater value of both
value = valueL > valueR ? valueL : valueR ;
return value;
}
/*
* sets the unsigned values for left and right volume according to
* the given volume (0...1) and balance (-1..0..+1)
*/
static void setFakeVolume(PortControl* portControl, float vol, float bal) {
float volumeLeft;
float volumeRight;
if (bal < 0.0f) {
volumeLeft = vol;
volumeRight = vol * (bal + 1.0f);
} else {
volumeLeft = vol * (1.0f - bal);
volumeRight = vol;
}
setRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT, volumeLeft);
setRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT, volumeRight);
}
float PORT_GetFloatValue(void* controlIDV) {
PortControl* portControl = (PortControl*) controlIDV;
float value = 0.0F;
if (portControl != NULL) {
if (portControl->controlType == CONTROL_TYPE_VOLUME) {
switch (portControl->channel) {
case CHANNELS_MONO:
value = getRealVolume(portControl, SND_MIXER_SCHN_MONO);
break;
case CHANNELS_STEREO:
value = getFakeVolume(portControl);
break;
default:
value = getRealVolume(portControl, portControl->channel);
}
} else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
if (portControl->channel == CHANNELS_STEREO) {
value = getFakeBalance(portControl);
} else {
ERROR0("PORT_GetFloatValue(): Balance only allowed for stereo channels!\n");
}
} else {
ERROR1("PORT_GetFloatValue(): inappropriate control type: %s!\n",
portControl->controlType);
}
}
return value;
}
void PORT_SetFloatValue(void* controlIDV, float value) {
PortControl* portControl = (PortControl*) controlIDV;
if (portControl != NULL) {
if (portControl->controlType == CONTROL_TYPE_VOLUME) {
switch (portControl->channel) {
case CHANNELS_MONO:
setRealVolume(portControl, SND_MIXER_SCHN_MONO, value);
break;
case CHANNELS_STEREO:
setFakeVolume(portControl, value, getFakeBalance(portControl));
break;
default:
setRealVolume(portControl, portControl->channel, value);
}
} else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
if (portControl->channel == CHANNELS_STEREO) {
setFakeVolume(portControl, getFakeVolume(portControl), value);
} else {
ERROR0("PORT_SetFloatValue(): Balance only allowed for stereo channels!\n");
}
} else {
ERROR1("PORT_SetFloatValue(): inappropriate control type: %s!\n",
portControl->controlType);
}
}
}
#endif // USE_PORTS

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. 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
@ -231,7 +231,7 @@ static const char* translate_error(jint err) {
int table_size = sizeof(error_messages) / sizeof(error_messages[0]);
int i;
for (i=0; i<table_size; i++) {
for (i = 0; i < table_size; i++) {
if (err == error_messages[i].err) {
return error_messages[i].msg;
}
@ -293,7 +293,7 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue
*/
arg_count = (*env)->GetArrayLength(env, args);
for (i=0; i<arg_count; i++) {
for (i = 0; i < arg_count; i++) {
jobject obj = (*env)->GetObjectArrayElement(env, args, i);
if (obj != NULL) {
cstr = JNU_GetStringPlatformChars(env, obj, &isCopy);
@ -314,6 +314,15 @@ JNIEXPORT jint JNICALL Java_sun_tools_attach_VirtualMachineImpl_enqueue
return -1;
}
}
} else {
char* newbuf = (char*)realloc(buf, size + 1);
if (newbuf == NULL) {
free(buf);
JNU_ThrowOutOfMemoryError(env, "realloc failed");
return -1;
}
buf = newbuf;
buf[size++] = 0;
}
if ((*env)->ExceptionOccurred(env)) {
free(buf);

View File

@ -828,7 +828,7 @@ public class Check {
return buf.toList();
}
boolean checkDenotable(Type t) {
public boolean checkDenotable(Type t) {
return denotableChecker.visit(t, null);
}
// where

View File

@ -43,6 +43,7 @@ import com.sun.tools.javac.code.Directive.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.file.PathFileObject;
import com.sun.tools.javac.jvm.Pool.DynamicMethod;
import com.sun.tools.javac.jvm.Pool.Method;
@ -101,6 +102,8 @@ public class ClassWriter extends ClassFile {
/** Type utilities. */
private Types types;
private Check check;
/**
* If true, class files will be written in module-specific subdirectories
* of the CLASS_OUTPUT location.
@ -178,6 +181,7 @@ public class ClassWriter extends ClassFile {
target = Target.instance(context);
source = Source.instance(context);
types = Types.instance(context);
check = Check.instance(context);
fileManager = context.get(JavaFileManager.class);
signatureGen = new CWSignatureGenerator(types);
@ -1294,10 +1298,10 @@ public class ClassWriter extends ClassFile {
//where
private boolean needsLocalVariableTypeEntry(Type t) {
//a local variable needs a type-entry if its type T is generic
//(i.e. |T| != T) and if it's not an intersection type (not supported
//in signature attribute grammar)
return (!types.isSameType(t, types.erasure(t)) &&
!t.isCompound());
//(i.e. |T| != T) and if it's not an non-denotable type (non-denotable
// types are not supported in signature attribute grammar!)
return !types.isSameType(t, types.erasure(t)) &&
check.checkDenotable(t);
}
void writeStackMap(Code code) {

View File

@ -44,6 +44,7 @@ compiler/ciReplay/TestSAServer.java 8029528 generic-all
compiler/codecache/stress/OverloadCompileQueueTest.java 8166554 generic-all
compiler/codegen/Test6896617.java 8193479 generic-all
compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8140405 generic-all
compiler/jvmci/compilerToVM/GetExceptionTableTest.java 8200135 generic-all
compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java 8158860 generic-all
compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java 8163894 generic-all
compiler/tiered/LevelTransitionTest.java 8067651 generic-all

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. 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.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import java.util.Random;
import jdk.test.lib.RandomFactory;
/* @test
* @library /test/lib
* @build jdk.test.lib.RandomFactory
* @run main ReadAllReadNTransferTo
* @bug 8180451
* @summary Verify ByteArrayInputStream readAllBytes, readNBytes, and transferTo
* @key randomness
*/
public class ReadAllReadNTransferTo {
private static final int SIZE = 0x4d4d;
private static Random random = RandomFactory.getRandom();
public static void main(String... args) throws IOException {
byte[] buf = new byte[SIZE];
random.nextBytes(buf);
int position = random.nextInt(SIZE/2);
int size = random.nextInt(SIZE - position);
ByteArrayInputStream bais =
new ByteArrayInputStream(buf, position, size);
int off = random.nextInt(size / 2);
int len = random.nextInt(size - off);
byte[] bN = new byte[off + len];
if (bais.readNBytes(bN, off, len) != len) {
throw new RuntimeException("readNBytes return value");
}
if (!Arrays.equals(bN, off, off + len,
buf, position, position + len)) {
throw new RuntimeException("readNBytes content");
}
byte[] bAll = bais.readAllBytes();
Objects.requireNonNull(bAll, "readAllBytes return value");
if (bAll.length != size - len) {
throw new RuntimeException("readAllBytes return value length");
}
if (!Arrays.equals(bAll, 0, bAll.length,
buf, position + len, position + len + bAll.length)) {
throw new RuntimeException("readAllBytes content");
}
// XXX transferTo()
bais = new ByteArrayInputStream(buf);
ByteArrayOutputStream baos = new ByteArrayOutputStream(buf.length);
if (bais.transferTo(baos) != buf.length) {
throw new RuntimeException("transferTo return value length");
}
if (!Arrays.equals(buf, baos.toByteArray())) {
throw new RuntimeException("transferTo content");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. 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
@ -102,7 +102,7 @@ public class Connect {
try {
dc.send(bb, bogus);
throw new RuntimeException("Allowed bogus send while connected");
} catch (IllegalArgumentException iae) {
} catch (AlreadyConnectedException ace) {
// Correct behavior
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. 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.
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @bug 8198753
* @summary Test DatagramChannel connect exceptions
* @library ..
* @run testng ConnectExceptions
*/
import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ConnectExceptions {
static DatagramChannel sndChannel;
static DatagramChannel rcvChannel;
static InetSocketAddress sender;
static InetSocketAddress receiver;
@BeforeTest
public static void setup() throws Exception {
sndChannel = DatagramChannel.open();
sndChannel.bind(null);
InetAddress address = InetAddress.getLocalHost();
if (address.isLoopbackAddress()) {
address = InetAddress.getLoopbackAddress();
}
sender = new InetSocketAddress(address,
sndChannel.socket().getLocalPort());
rcvChannel = DatagramChannel.open();
rcvChannel.bind(null);
receiver = new InetSocketAddress(address,
rcvChannel.socket().getLocalPort());
}
@Test(expectedExceptions = UnsupportedAddressTypeException.class)
public static void unsupportedAddressTypeException() throws Exception {
rcvChannel.connect(sender);
sndChannel.connect(new SocketAddress() {});
}
@Test(expectedExceptions = UnresolvedAddressException.class)
public static void unresolvedAddressException() throws Exception {
String host = TestUtil.UNRESOLVABLE_HOST;
InetSocketAddress unresolvable = new InetSocketAddress (host, 37);
sndChannel.connect(unresolvable);
}
@Test(expectedExceptions = AlreadyConnectedException.class)
public static void alreadyConnectedException() throws Exception {
sndChannel.connect(receiver);
InetSocketAddress random = new InetSocketAddress(0);
sndChannel.connect(random);
}
@AfterTest
public static void cleanup() throws Exception {
rcvChannel.close();
sndChannel.close();
}
}

Some files were not shown because too many files have changed in this diff Show More