pax_global_header 0000666 0000000 0000000 00000000064 14500014250 0014501 g ustar 00root root 0000000 0000000 52 comment=6b243df155f239b1ed7b1714ca757d9c1ddf810a
jnr-enxio-jnr-enxio-0.32.16/ 0000775 0000000 0000000 00000000000 14500014250 0015472 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/.github/ 0000775 0000000 0000000 00000000000 14500014250 0017032 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/.github/workflows/ 0000775 0000000 0000000 00000000000 14500014250 0021067 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/.github/workflows/ci.yml 0000664 0000000 0000000 00000001432 14500014250 0022205 0 ustar 00root root 0000000 0000000 # This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
jdk8:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 8
uses: actions/setup-java@v1.4.3
with:
java-version: 8
- name: Build with Maven
run: mvn -B package --file pom.xml
jdk11:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1.4.3
with:
java-version: 11
- name: Build with Maven
run: mvn -B package --file pom.xml
jnr-enxio-jnr-enxio-0.32.16/.gitignore 0000664 0000000 0000000 00000000124 14500014250 0017457 0 ustar 00root root 0000000 0000000 build
target
nbproject/private
dist
*.orig$
*.rej$
*.class$
*~
.idea
*.iml
/.redcar/ jnr-enxio-jnr-enxio-0.32.16/LICENSE 0000664 0000000 0000000 00000001036 14500014250 0016477 0 ustar 00root root 0000000 0000000
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. jnr-enxio-jnr-enxio-0.32.16/README.md 0000664 0000000 0000000 00000000256 14500014250 0016754 0 ustar 00root root 0000000 0000000 jnr-enxio
=========
Native I/O access for java
Check out the [examples](https://github.com/jnr/jnr-enxio/tree/master/src/test/java/jnr/enxio/example) for more information.
jnr-enxio-jnr-enxio-0.32.16/pom.xml 0000664 0000000 0000000 00000011261 14500014250 0017010 0 ustar 00root root 0000000 0000000
4.0.0
org.sonatype.oss
oss-parent
7
com.github.jnr
jnr-enxio
jar
0.32.16
jnr-enxio
Native I/O access for java
http://github.com/jnr/jnr-enxio
The Apache Software License, Version 2.0
http://www.apache.org/licenses/LICENSE-2.0.txt
repo
scm:git:git@github.com:jnr/jnr-enxio.git
scm:git:git@github.com:jnr/jnr-enxio.git
git@github.com:jnr/jnr-enxio.git
wmeissner
Wayne Meissner
wmeissner@gmail.com
UTF-8
8
8
junit
junit
4.13.1
test
com.github.jnr
jnr-constants
0.10.4
com.github.jnr
jnr-ffi
2.2.15
org.apache.felix
maven-bundle-plugin
2.3.7
<_nouses>true
*,jnr.ffi.mapper,jnr.ffi.provider.converters,com.kenai.jffi
jnr.enxio
bundle-manifest
process-classes
manifest
org.apache.maven.plugins
maven-jar-plugin
2.3.1
${project.build.outputDirectory}/META-INF/MANIFEST.MF
org.jnrproject.enxio
org.apache.maven.plugins
maven-source-plugin
2.2.1
attach-sources
jar-no-fork
org.apache.maven.plugins
maven-javadoc-plugin
3.2.0
attach-javadocs
jar
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
java9
maven-surefire-plugin
3.0.0-M5
--add-opens java.base/java.io=ALL-UNNAMED
[9,)
8
jnr-enxio-jnr-enxio-0.32.16/src/ 0000775 0000000 0000000 00000000000 14500014250 0016261 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/main/ 0000775 0000000 0000000 00000000000 14500014250 0017205 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/main/java/ 0000775 0000000 0000000 00000000000 14500014250 0020126 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/ 0000775 0000000 0000000 00000000000 14500014250 0020717 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/ 0000775 0000000 0000000 00000000000 14500014250 0022041 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/ 0000775 0000000 0000000 00000000000 14500014250 0023634 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/KQSelectionKey.java 0000664 0000000 0000000 00000003527 14500014250 0027340 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.AbstractSelectionKey;
class KQSelectionKey extends AbstractSelectionKey {
private final KQSelector selector;
private final NativeSelectableChannel channel;
private int interestOps = 0;
private int readyOps = 0;
public KQSelectionKey(KQSelector selector, NativeSelectableChannel channel, int ops) {
this.selector = selector;
this.channel = channel;
this.interestOps = ops;
}
int getFD() {
return channel.getFD();
}
@Override
public SelectableChannel channel() {
return (SelectableChannel) channel;
}
@Override
public Selector selector() {
return selector;
}
@Override
public int interestOps() {
return interestOps;
}
@Override
public SelectionKey interestOps(int ops) {
interestOps = ops;
selector.interestOps(this, ops);
return this;
}
@Override
public int readyOps() {
return readyOps;
}
void readyOps(int readyOps) {
this.readyOps = readyOps;
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/KQSelector.java 0000664 0000000 0000000 00000033606 14500014250 0026523 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import jnr.constants.platform.Errno;
import jnr.ffi.Memory;
import jnr.ffi.Pointer;
import jnr.ffi.StructLayout;
import jnr.ffi.TypeAlias;
import jnr.ffi.provider.jffi.NativeRuntime;
import jnr.ffi.Platform;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* An implementation of a {@link java.nio.channels.Selector} that uses the BSD (including MacOS)
* kqueue(2) mechanism
*/
class KQSelector extends java.nio.channels.spi.AbstractSelector {
private static final boolean DEBUG = false;
private static final int MAX_EVENTS = 100;
private static final int EVFILT_READ = -1;
private static final int EVFILT_WRITE = -2;
private static final int EV_ADD = 0x0001;
private static final int EV_DELETE = 0x0002;
private static final int EV_ENABLE = 0x0004;
private static final int EV_DISABLE = 0x0008;
private static final int EV_CLEAR = 0x0020;
private int kqfd = -1;
private final jnr.ffi.Runtime runtime = NativeRuntime.getSystemRuntime();
private final Pointer changebuf;
private final Pointer eventbuf;
private final EventIO io = EventIO.getInstance();
private final int[] pipefd = { -1, -1 };
private final Object regLock = new Object();
private final Map descriptors = new ConcurrentHashMap();
private final Set selected = new LinkedHashSet();
private final Native.Timespec ZERO_TIMESPEC = new Native.Timespec(0, 0);
public KQSelector(NativeSelectorProvider provider) {
super(provider);
changebuf = Memory.allocateDirect(runtime, MAX_EVENTS * io.size());
eventbuf = Memory.allocateDirect(runtime, MAX_EVENTS * io.size());
Native.libc().pipe(pipefd);
kqfd = Native.libc().kqueue();
io.put(changebuf, 0, pipefd[0], EVFILT_READ, EV_ADD);
Native.libc().kevent(kqfd, changebuf, 1, null, 0, ZERO_TIMESPEC);
}
private static class Descriptor {
private final int fd;
private final Set keys = new HashSet();
private boolean write = false, read = false;
public Descriptor(int fd) {
this.fd = fd;
}
}
@Override
protected void implCloseSelector() throws IOException {
if (kqfd != -1) {
Native.close(kqfd);
}
if (pipefd[0] != -1) {
Native.close(pipefd[0]);
}
if (pipefd[1] != -1) {
Native.close(pipefd[1]);
}
pipefd[0] = pipefd[1] = kqfd = -1;
// deregister all keys
for (Map.Entry entry : descriptors.entrySet()) {
for (KQSelectionKey k : entry.getValue().keys) {
deregister(k);
}
}
}
@Override
protected SelectionKey register(AbstractSelectableChannel ch, int ops, Object att) {
KQSelectionKey k = new KQSelectionKey(this, (NativeSelectableChannel) ch, ops);
synchronized (regLock) {
Descriptor d = new Descriptor(k.getFD());
descriptors.put(k.getFD(), d);
d.keys.add(k);
handleChangedKey(d);
}
k.attach(att);
return k;
}
@Override
public Set keys() {
Set keys = new HashSet();
for (Descriptor fd : descriptors.values()) {
keys.addAll(fd.keys);
}
return Collections.unmodifiableSet(keys);
}
@Override
public Set selectedKeys() {
return selected;
}
@Override
public int selectNow() throws IOException {
return poll(0);
}
@Override
public int select(long timeout) throws IOException {
return poll(timeout);
}
@Override
public int select() throws IOException {
return poll(-1);
}
private int poll(long timeout) {
int nchanged = handleCancelledKeys();
Native.Timespec ts = null;
if (timeout >= 0) {
long sec = TimeUnit.MILLISECONDS.toSeconds(timeout);
long nsec = TimeUnit.MILLISECONDS.toNanos(timeout % 1000);
ts = new Native.Timespec(sec, nsec);
}
if (DEBUG) System.err.printf("nchanged=%d\n", nchanged);
int nready = 0;
try {
begin();
do {
nready = Native.libc().kevent(kqfd, changebuf, nchanged, eventbuf, MAX_EVENTS, ts);
} while (nready < 0 && Errno.EINTR.equals(Errno.valueOf(Native.getRuntime().getLastError())));
if (DEBUG) System.err.println("kevent returned " + nready + " events ready");
} finally {
end();
}
int updatedKeyCount = 0;
synchronized (regLock) {
for (int i = 0; i < nready; ++i) {
int fd = io.getFD(eventbuf, i);
Descriptor d = descriptors.get(fd);
if (d != null) {
int filt = io.getFilter(eventbuf, i);
if (DEBUG) System.err.printf("fd=%d filt=0x%x\n", d.fd, filt);
for (KQSelectionKey k : d.keys) {
int iops = k.interestOps();
int ops = 0;
if (filt == EVFILT_READ) {
ops |= iops & (SelectionKey.OP_ACCEPT | SelectionKey.OP_READ);
}
if (filt == EVFILT_WRITE) {
ops |= iops & (SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE);
}
++updatedKeyCount;
k.readyOps(ops);
if (!selected.contains(k)) {
selected.add(k);
}
}
} else if (fd == pipefd[0]) {
if (DEBUG) System.err.println("Waking up");
wakeupReceived();
}
}
}
return updatedKeyCount;
}
private int handleCancelledKeys() {
Set cancelled = cancelledKeys();
synchronized (cancelled) {
int nchanged = 0;
synchronized (regLock) {
for (SelectionKey k : cancelled) {
KQSelectionKey kqs = (KQSelectionKey) k;
deregister(kqs);
synchronized (selected) {
selected.remove(kqs);
}
Descriptor d = descriptors.get(kqs.getFD());
if (d != null) d.keys.remove(kqs);
if (d == null || d.keys.isEmpty()) {
io.put(changebuf, nchanged++, kqs.getFD(), EVFILT_READ, EV_DELETE);
io.put(changebuf, nchanged++, kqs.getFD(), EVFILT_WRITE, EV_DELETE);
descriptors.remove(kqs.getFD());
}
if (nchanged >= MAX_EVENTS) {
Native.libc().kevent(kqfd, changebuf, nchanged, null, 0, ZERO_TIMESPEC);
nchanged = 0;
}
}
}
cancelled.clear();
return nchanged;
}
}
private void handleChangedKey(Descriptor changed) {
synchronized (regLock) {
int _nchanged = 0;
int writers = 0, readers = 0;
for (KQSelectionKey k : changed.keys) {
if ((k.interestOps() & (SelectionKey.OP_ACCEPT | SelectionKey.OP_READ)) != 0) {
++readers;
}
if ((k.interestOps() & (SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE)) != 0) {
++writers;
}
}
for (Integer filt : new Integer[] { EVFILT_READ, EVFILT_WRITE }) {
int flags = 0;
//
// If no one is interested in events on the fd, disable it
//
if (filt == EVFILT_READ) {
if (readers > 0 && !changed.read) {
flags = EV_ADD |EV_ENABLE | EV_CLEAR;
changed.read = true;
} else if (readers == 0 && changed.read) {
flags = EV_DISABLE;
changed.read = false;
}
}
if (filt == EVFILT_WRITE) {
if (writers > 0 && !changed.write) {
flags = EV_ADD | EV_ENABLE | EV_CLEAR;
changed.write = true;
} else if (writers == 0 && changed.write) {
flags = EV_DISABLE;
changed.write = false;
}
}
if (DEBUG) System.err.printf("Updating fd %d filt=0x%x flags=0x%x\n",
changed.fd, filt, flags);
if (flags != 0) {
io.put(changebuf, _nchanged++, changed.fd, filt, flags);
}
}
Native.libc().kevent(kqfd, changebuf, _nchanged, null, 0, ZERO_TIMESPEC);
}
}
private void wakeupReceived() {
Native.libc().read(pipefd[0], new byte[1], 1);
}
@Override
public Selector wakeup() {
Native.libc().write(pipefd[1], new byte[1], 1);
return this;
}
void interestOps(KQSelectionKey k, int ops) {
synchronized (regLock) {
handleChangedKey(descriptors.get(k.getFD()));
}
}
private static final class EventIO {
private static final EventIO INSTANCE = new EventIO();
private final EventLayout layout;
private final jnr.ffi.Type uintptr_t;
private EventIO() {
boolean is_freebsd_12_or_later = false;
if(Platform.getNativePlatform().getOS() == Platform.OS.FREEBSD) {
String version = System.getProperty("os.version");
if(version != null) {
int tr_i = -1;
for(char c : new char[] { ' ', '_', '-', '+', '.' }) {
int i = version.indexOf(c);
if(i >= 0 && (tr_i == -1 || tr_i > i)) tr_i = i;
}
if(tr_i >= 0) version = version.substring(0, tr_i);
try {
int freebsd_major_version = Integer.parseInt(version);
if(freebsd_major_version > 11) is_freebsd_12_or_later = true;
} catch(NumberFormatException e) {
if(DEBUG) e.printStackTrace();
}
}
}
if(is_freebsd_12_or_later) {
layout = new FreeBSD12EventLayout(NativeRuntime.getSystemRuntime());
} else {
layout = new LegacyEventLayout(NativeRuntime.getSystemRuntime());
}
uintptr_t = layout.getRuntime().findType(TypeAlias.uintptr_t);
}
public static EventIO getInstance() {
return EventIO.INSTANCE;
}
public final void put(Pointer buf, int index, int fd, int filt, int flags) {
buf.putInt(uintptr_t, (index * layout.size()) + layout.ident.offset(), fd);
buf.putShort((index * layout.size()) + layout.filter.offset(), (short) filt);
buf.putShort((index * layout.size()) + layout.flags.offset(), (short)flags);
}
public final int size() {
return layout.size();
}
int getFD(Pointer ptr, int index) {
return (int) ptr.getInt(uintptr_t, (index * layout.size()) + layout.ident.offset());
}
public final void putFilter(Pointer buf, int index, int filter) {
buf.putShort((index * layout.size()) + layout.filter.offset(), (short) filter);
}
public final int getFilter(Pointer buf, int index) {
return buf.getShort((index * layout.size()) + layout.filter.offset());
}
public final void putFlags(Pointer buf, int index, int flags) {
buf.putShort((index * layout.size()) + layout.flags.offset(), (short) flags);
}
}
private static abstract class EventLayout extends StructLayout {
private EventLayout(jnr.ffi.Runtime runtime) {
super(runtime);
}
public final uintptr_t ident = new uintptr_t();
public final int16_t filter = new int16_t();
public final u_int16_t flags = new u_int16_t();
public final u_int32_t fflags = new u_int32_t();
}
private static class LegacyEventLayout extends EventLayout {
private LegacyEventLayout(jnr.ffi.Runtime runtime) {
super(runtime);
}
public final intptr_t data = new intptr_t();
public final Pointer udata = new Pointer();
}
private static class FreeBSD12EventLayout extends EventLayout {
private FreeBSD12EventLayout(jnr.ffi.Runtime runtime) {
super(runtime);
}
public final int64_t data = new int64_t();
public final Pointer udata = new Pointer();
public final u_int64_t[] ext = array(new u_int64_t[4]);
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/Native.java 0000664 0000000 0000000 00000014124 14500014250 0025727 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import jnr.constants.platform.Errno;
import jnr.enxio.channels.WinLibCAdapter.LibMSVCRT;
import jnr.ffi.*;
import jnr.ffi.Platform.OS;
import jnr.ffi.Runtime;
import jnr.ffi.annotations.IgnoreError;
import jnr.ffi.annotations.In;
import jnr.ffi.annotations.Out;
import jnr.ffi.annotations.Transient;
import jnr.ffi.types.size_t;
import jnr.ffi.types.ssize_t;
import jnr.ffi.Platform;
import java.io.IOException;
import java.nio.ByteBuffer;
public final class Native {
public static interface LibC {
public static final int F_GETFL = jnr.constants.platform.Fcntl.F_GETFL.intValue();
public static final int F_SETFL = jnr.constants.platform.Fcntl.F_SETFL.intValue();
public static final int O_NONBLOCK = jnr.constants.platform.OpenFlags.O_NONBLOCK.intValue();
public int close(int fd);
public @ssize_t int read(int fd, @Out ByteBuffer data, @size_t long size);
public @ssize_t int read(int fd, @Out byte[] data, @size_t long size);
public @ssize_t int write(int fd, @In ByteBuffer data, @size_t long size);
public @ssize_t int write(int fd, @In byte[] data, @size_t long size);
public int fcntl(int fd, int cmd, int data);
public int poll(@In @Out ByteBuffer pfds, int nfds, int timeout);
public int poll(@In @Out Pointer pfds, int nfds, int timeout);
public int kqueue();
public int kevent(int kq, @In ByteBuffer changebuf, int nchanges,
@Out ByteBuffer eventbuf, int nevents,
@In @Transient Timespec timeout);
public int kevent(int kq,
@In Pointer changebuf, int nchanges,
@Out Pointer eventbuf, int nevents,
@In @Transient Timespec timeout);
public int pipe(@Out int[] fds);
public int shutdown(int s, int how);
@IgnoreError String strerror(int error);
}
private static final class SingletonHolder {
static final LibC libc;
static final jnr.ffi.Runtime runtime;
static {
Platform platform = Platform.getNativePlatform();
LibraryLoader loader = LibraryLoader.create(LibC.class);
loader.library(platform.getStandardCLibraryName());
if (platform.getOS() == OS.SOLARIS) {
loader.library("socket");
}
LibC straight = loader.load();
if (platform.getOS() == OS.WINDOWS) {
LibMSVCRT mslib = LibraryLoader.create(LibMSVCRT.class).load(platform.getStandardCLibraryName());
libc = new WinLibCAdapter(mslib);
} else {
libc = straight;
}
runtime = Runtime.getRuntime(libc);
}
}
static LibC libc() {
return SingletonHolder.libc;
}
static jnr.ffi.Runtime getRuntime() {
return SingletonHolder.runtime;
}
public static int close(int fd) throws IOException {
int rc;
do {
rc = libc().close(fd);
} while (rc < 0 && Errno.EINTR.equals(getLastError()));
if (rc < 0) {
String message = String.format("Error closing fd %d: %s", fd, getLastErrorString());
throw new NativeException(message, getLastError());
} else {
return rc;
}
}
public static int read(int fd, ByteBuffer dst) throws IOException {
if (dst == null) {
throw new NullPointerException("Destination buffer cannot be null");
}
if (dst.isReadOnly()) {
throw new IllegalArgumentException("Read-only buffer");
}
int n;
do {
n = libc().read(fd, dst, dst.remaining());
} while (n < 0 && Errno.EINTR.equals(getLastError()));
if (n > 0) {
dst.position(dst.position() + n);
}
return n;
}
public static int write(int fd, ByteBuffer src) throws IOException {
if (src == null) {
throw new NullPointerException("Source buffer cannot be null");
}
int n;
do {
n = libc().write(fd, src, src.remaining());
} while (n < 0 && Errno.EINTR.equals(getLastError()));
if (n > 0) {
src.position(src.position() + n);
}
return n;
}
public static void setBlocking(int fd, boolean block) {
int flags = libc().fcntl(fd, LibC.F_GETFL, 0);
if (block) {
flags &= ~LibC.O_NONBLOCK;
} else {
flags |= LibC.O_NONBLOCK;
}
libc().fcntl(fd, LibC.F_SETFL, flags);
}
public static int shutdown(int fd, int how) {
return libc().shutdown(fd, how);
}
public static String getLastErrorString() {
return libc().strerror(LastError.getLastError(getRuntime()));
}
public static Errno getLastError() {
return Errno.valueOf(LastError.getLastError(getRuntime()));
}
public static final class Timespec extends Struct {
public final SignedLong tv_sec = new SignedLong();
public final SignedLong tv_nsec = new SignedLong();
public Timespec() {
super(Native.getRuntime());
}
public Timespec(Runtime runtime) {
super(runtime);
}
public Timespec(long sec, long nsec) {
super(Native.getRuntime());
tv_sec.set(sec);
tv_nsec.set(nsec);
}
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/NativeDeviceChannel.java 0000664 0000000 0000000 00000005661 14500014250 0030346 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;
public class NativeDeviceChannel extends AbstractSelectableChannel implements ByteChannel, NativeSelectableChannel {
private final int fd;
private final int validOps;
private final boolean isFile;
public NativeDeviceChannel(int fd) {
this(fd, false);
}
public NativeDeviceChannel(int fd, boolean isFile) {
this(selectorProvider(isFile), fd, SelectionKey.OP_READ | SelectionKey.OP_WRITE, isFile);
}
public NativeDeviceChannel(SelectorProvider provider, int fd, int ops, boolean isFile) {
super(provider);
this.fd = fd;
this.validOps = ops;
this.isFile = isFile;
}
private static SelectorProvider selectorProvider(boolean isFile) {
return (isFile) ? NativeFileSelectorProvider.getInstance() : NativeSelectorProvider.getInstance();
}
@Override
protected void implCloseSelectableChannel() throws IOException {
int n = Native.close(fd);
if (n < 0) {
throw new IOException(Native.getLastErrorString());
}
}
@Override
protected void implConfigureBlocking(boolean block) throws IOException {
Native.setBlocking(fd, block);
}
@Override
public final int validOps() {
return validOps;
}
public final int getFD() {
return fd;
}
public int read(ByteBuffer dst) throws IOException {
int n = Native.read(fd, dst);
switch (n) {
case 0:
return -1;
case -1:
switch (Native.getLastError()) {
case EAGAIN:
case EWOULDBLOCK:
return 0;
default:
throw new IOException(Native.getLastErrorString());
}
default:
return n;
}
}
public int write(ByteBuffer src) throws IOException {
int n = Native.write(fd, src);
if (n < 0) {
throw new IOException(Native.getLastErrorString());
}
return n;
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/NativeException.java 0000664 0000000 0000000 00000000544 14500014250 0027607 0 ustar 00root root 0000000 0000000 package jnr.enxio.channels;
import jnr.constants.platform.Errno;
import java.io.IOException;
public class NativeException extends IOException {
private final Errno errno;
public NativeException(String message, Errno errno) {
super(message);
this.errno = errno;
}
public Errno getErrno() {
return errno;
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/NativeFileSelectorProvider.java 0000664 0000000 0000000 00000004277 14500014250 0031753 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import jnr.ffi.Platform;
import java.io.IOException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.Pipe;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.AbstractSelector;
import java.nio.channels.spi.SelectorProvider;
public final class NativeFileSelectorProvider extends SelectorProvider {
private static final class SingletonHolder {
static NativeFileSelectorProvider INSTANCE = new NativeFileSelectorProvider();
}
public static final SelectorProvider getInstance() {
return SingletonHolder.INSTANCE;
}
@Override
public DatagramChannel openDatagramChannel() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
public DatagramChannel openDatagramChannel(java.net.ProtocolFamily family) throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Pipe openPipe() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public AbstractSelector openSelector() throws IOException {
return new PollSelector(this);
}
@Override
public ServerSocketChannel openServerSocketChannel() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public SocketChannel openSocketChannel() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/NativeSelectableChannel.java 0000664 0000000 0000000 00000001440 14500014250 0031201 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import java.nio.channels.Channel;
public interface NativeSelectableChannel extends Channel {
public int getFD();
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/NativeSelectorProvider.java 0000664 0000000 0000000 00000004360 14500014250 0031144 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import jnr.ffi.Platform;
import java.io.IOException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.Pipe;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.AbstractSelector;
import java.nio.channels.spi.SelectorProvider;
public final class NativeSelectorProvider extends SelectorProvider {
private static final class SingletonHolder {
static NativeSelectorProvider INSTANCE = new NativeSelectorProvider();
}
public static final SelectorProvider getInstance() {
return SingletonHolder.INSTANCE;
}
@Override
public DatagramChannel openDatagramChannel() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
public DatagramChannel openDatagramChannel(java.net.ProtocolFamily family) throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Pipe openPipe() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public AbstractSelector openSelector() throws IOException {
return Platform.getNativePlatform().isBSD() ? new KQSelector(this) : new PollSelector(this);
}
@Override
public ServerSocketChannel openServerSocketChannel() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public SocketChannel openSocketChannel() throws IOException {
throw new UnsupportedOperationException("Not supported yet.");
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/NativeServerSocketChannel.java 0000664 0000000 0000000 00000003301 14500014250 0031553 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;
public class NativeServerSocketChannel extends AbstractSelectableChannel implements NativeSelectableChannel {
private final int fd;
private final int validOps;
public NativeServerSocketChannel(int fd) {
this(NativeSelectorProvider.getInstance(), fd, SelectionKey.OP_ACCEPT | SelectionKey.OP_READ);
}
public NativeServerSocketChannel(SelectorProvider provider, int fd, int ops) {
super(provider);
this.fd = fd;
this.validOps = ops;
}
@Override
protected void implCloseSelectableChannel() throws IOException {
Native.close(fd);
}
@Override
protected void implConfigureBlocking(boolean block) throws IOException {
Native.setBlocking(fd, block);
}
@Override
public final int validOps() {
return validOps;
}
public final int getFD() {
return fd;
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/NativeSocketChannel.java 0000664 0000000 0000000 00000006536 14500014250 0030401 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import jnr.constants.platform.Shutdown;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;
public class NativeSocketChannel extends AbstractSelectableChannel
implements ByteChannel, NativeSelectableChannel {
private final int fd;
private final int validOps;
public NativeSocketChannel(int fd) {
this(NativeSelectorProvider.getInstance(), fd, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
}
public NativeSocketChannel(int fd, int ops) {
this(NativeSelectorProvider.getInstance(), fd, ops);
}
NativeSocketChannel(SelectorProvider provider, int fd, int ops) {
super(provider);
this.fd = fd;
this.validOps = ops;
}
@Override
protected void implCloseSelectableChannel() throws IOException {
Native.close(fd);
}
@Override
protected void implConfigureBlocking(boolean block) throws IOException {
Native.setBlocking(fd, block);
}
@Override
public final int validOps() {
return validOps;
}
public final int getFD() {
return fd;
}
public int read(ByteBuffer dst) throws IOException {
int n = Native.read(fd, dst);
switch (n) {
case 0:
return -1;
case -1:
switch (Native.getLastError()) {
case EAGAIN:
case EWOULDBLOCK:
return 0;
default:
throw new IOException(Native.getLastErrorString());
}
default:
return n;
}
}
public int write(ByteBuffer src) throws IOException {
int n = Native.write(fd, src);
if (n < 0) {
switch (Native.getLastError()) {
case EAGAIN:
case EWOULDBLOCK:
return 0;
default:
throw new IOException(Native.getLastErrorString());
}
}
return n;
}
public void shutdownInput() throws IOException {
int n = Native.shutdown(fd, SHUT_RD);
if (n < 0) {
throw new IOException(Native.getLastErrorString());
}
}
public void shutdownOutput() throws IOException {
int n = Native.shutdown(fd, SHUT_WR);
if (n < 0) {
throw new IOException(Native.getLastErrorString());
}
}
private final static int SHUT_RD = Shutdown.SHUT_RD.intValue();
private final static int SHUT_WR = Shutdown.SHUT_WR.intValue();
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/PollSelectionKey.java 0000664 0000000 0000000 00000003640 14500014250 0027727 0 ustar 00root root 0000000 0000000 /*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.AbstractSelectionKey;
class PollSelectionKey extends AbstractSelectionKey {
private final PollSelector selector;
private final NativeSelectableChannel channel;
private int interestOps = 0;
private int readyOps = 0;
private int index = -1;
public PollSelectionKey(PollSelector selector, NativeSelectableChannel channel) {
this.selector = selector;
this.channel = channel;
}
void setIndex(int index) {
this.index = index;
}
int getIndex() {
return index;
}
int getFD() {
return channel.getFD();
}
@Override
public SelectableChannel channel() {
return (SelectableChannel) channel;
}
@Override
public Selector selector() {
return selector;
}
@Override
public int interestOps() {
return interestOps;
}
@Override
public SelectionKey interestOps(int ops) {
interestOps = ops;
selector.interestOps(this, ops);
return this;
}
@Override
public int readyOps() {
return readyOps;
}
void readyOps(int readyOps) {
this.readyOps = readyOps;
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/PollSelector.java 0000664 0000000 0000000 00000021045 14500014250 0027110 0 ustar 00root root 0000000 0000000 /*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import jnr.constants.platform.Errno;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* An implementation of a {@link java.nio.channels.Selector} that uses good old
* poll(2)
*/
class PollSelector extends java.nio.channels.spi.AbstractSelector {
private static final int POLLFD_SIZE = 8;
private static final int FD_OFFSET = 0;
private static final int EVENTS_OFFSET = 4;
private static final int REVENTS_OFFSET = 6;
static final int POLLIN = 0x1;
static final int POLLOUT = 0x4;
static final int POLLERR = 0x8;
static final int POLLHUP = 0x10;
private PollSelectionKey[] keyArray = new PollSelectionKey[0];
private ByteBuffer pollData = null;
private int nfds;
private final int[] pipefd = { -1, -1 };
private final Object regLock = new Object();
private final Map keys = new ConcurrentHashMap();
private final Set selected = new HashSet();
public PollSelector(SelectorProvider provider) {
super(provider);
Native.libc().pipe(pipefd);
// Register the wakeup pipe as the first element in the pollfd array
pollData = ByteBuffer.allocateDirect(8).order(ByteOrder.nativeOrder());
putPollFD(0, pipefd[0]);
putPollEvents(0, POLLIN);
nfds = 1;
keyArray = new PollSelectionKey[1];
}
private void putPollFD(int idx, int fd) {
pollData.putInt((idx * POLLFD_SIZE) + FD_OFFSET, fd);
}
private void putPollEvents(int idx, int events) {
pollData.putShort((idx * POLLFD_SIZE) + EVENTS_OFFSET, (short) events);
}
private int getPollFD(int idx) {
return pollData.getInt((idx * POLLFD_SIZE) + FD_OFFSET);
}
private short getPollEvents(int idx) {
return pollData.getShort((idx * POLLFD_SIZE) + EVENTS_OFFSET);
}
private short getPollRevents(int idx) {
return pollData.getShort((idx * POLLFD_SIZE) + REVENTS_OFFSET);
}
private void putPollRevents(int idx, int events) {
pollData.putShort((idx * POLLFD_SIZE) + REVENTS_OFFSET, (short) events);
}
@Override
protected void implCloseSelector() throws IOException {
if (pipefd[0] != -1) {
Native.close(pipefd[0]);
}
if (pipefd[1] != -1) {
Native.close(pipefd[1]);
}
// remove all keys
for (SelectionKey key : keys.keySet()) {
remove((PollSelectionKey)key);
}
}
@Override
protected SelectionKey register(AbstractSelectableChannel ch, int ops, Object att) {
PollSelectionKey key = new PollSelectionKey(this, (NativeSelectableChannel) ch);
add(key);
key.attach(att);
key.interestOps(ops);
return key;
}
@Override
public Set keys() {
return new HashSet(Arrays.asList(keyArray).subList(1, nfds));
}
@Override
public Set selectedKeys() {
return selected;
}
void interestOps(PollSelectionKey k, int ops) {
short events = 0;
if ((ops & (SelectionKey.OP_ACCEPT | SelectionKey.OP_READ)) != 0) {
events |= POLLIN;
}
if ((ops & (SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT)) != 0) {
events |= POLLOUT;
}
putPollEvents(k.getIndex(), events);
}
private void add(PollSelectionKey k) {
synchronized (regLock) {
++nfds;
if (keyArray.length < nfds) {
PollSelectionKey[] newArray = new PollSelectionKey[nfds + (nfds / 2)];
System.arraycopy(keyArray, 0, newArray, 0, nfds - 1);
keyArray = newArray;
ByteBuffer newBuffer = ByteBuffer.allocateDirect(newArray.length * 8);
if (pollData != null) {
newBuffer.put(pollData);
}
newBuffer.position(0);
pollData = newBuffer.order(ByteOrder.nativeOrder());
}
k.setIndex(nfds - 1);
keyArray[nfds - 1] = k;
putPollFD(k.getIndex(), k.getFD());
putPollEvents(k.getIndex(), 0);
keys.put(k, true);
}
}
private void remove(PollSelectionKey k) {
int idx = k.getIndex();
synchronized (regLock) {
//
// If not the last key, swap last one into the removed key's position
//
if (idx < (nfds - 1)) {
PollSelectionKey last = keyArray[nfds - 1];
keyArray[idx] = last;
// Copy the data for the last key into place
putPollFD(idx, getPollFD(last.getIndex()));
putPollEvents(idx, getPollEvents(last.getIndex()));
last.setIndex(idx);
} else {
putPollFD(idx, -1);
putPollEvents(idx, 0);
}
keyArray[nfds - 1] = null;
--nfds;
synchronized (selected) {
selected.remove(k);
}
keys.remove(k);
}
deregister(k);
}
@Override
public int selectNow() throws IOException {
return poll(0);
}
@Override
public int select(long timeout) throws IOException {
return poll(timeout > 0 ? timeout : -1);
}
@Override
public int select() throws IOException {
return poll(-1);
}
private int poll(long timeout) throws IOException {
//
// Remove any cancelled keys
//
Set cancelled = cancelledKeys();
synchronized (cancelled) {
for (SelectionKey k : cancelled) {
remove((PollSelectionKey) k);
}
cancelled.clear();
}
int nready = 0;
try {
begin();
do {
nready = Native.libc().poll(pollData, nfds, (int) timeout);
} while (nready < 0 && Errno.EINTR.equals(Errno.valueOf(Native.getRuntime().getLastError())));
} finally {
end();
}
if (nready < 1) {
return nready;
}
if ((getPollRevents(0) & POLLIN) != 0) {
wakeupReceived();
}
int updatedKeyCount = 0;
for (SelectionKey k : keys.keySet()) {
PollSelectionKey pk = (PollSelectionKey) k;
int revents = getPollRevents(pk.getIndex());
if (revents != 0) {
putPollRevents(pk.getIndex(), 0);
int iops = k.interestOps();
int ops = 0;
if ((revents & POLLIN) != 0) {
ops |= iops & (SelectionKey.OP_ACCEPT | SelectionKey.OP_READ);
}
if ((revents & POLLOUT) != 0) {
ops |= iops & (SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE);
}
// If an error occurred, enable all interested ops and let the
// event handling code deal with it
if ((revents & (POLLHUP | POLLERR)) != 0) {
ops = iops;
}
((PollSelectionKey) k).readyOps(ops);
++updatedKeyCount;
if (!selected.contains(k)) {
selected.add(k);
}
}
}
return updatedKeyCount;
}
private void wakeupReceived() throws IOException {
Native.read(pipefd[0], ByteBuffer.allocate(1));
}
@Override
public Selector wakeup() {
try {
Native.write(pipefd[1], ByteBuffer.allocate(1));
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
return this;
}
}
jnr-enxio-jnr-enxio-0.32.16/src/main/java/jnr/enxio/channels/WinLibCAdapter.java 0000664 0000000 0000000 00000010775 14500014250 0027301 0 ustar 00root root 0000000 0000000 /*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.channels;
import java.nio.ByteBuffer;
import jnr.enxio.channels.Native.LibC;
import jnr.enxio.channels.Native.Timespec;
import jnr.ffi.Pointer;
import jnr.ffi.Runtime;
import jnr.ffi.annotations.IgnoreError;
import jnr.ffi.annotations.In;
import jnr.ffi.annotations.Out;
import jnr.ffi.provider.LoadedLibrary;
import jnr.ffi.types.size_t;
import jnr.ffi.types.ssize_t;
/**
* MSVCRT.DLL only supports some LibC functions, but the symbols are different.
* This adapter maps the MSVCRT.DLL names to standard LibC names
*/
public final class WinLibCAdapter implements LibC, LoadedLibrary {
public static interface LibMSVCRT {
public int _close(int fd);
public @ssize_t int _read(int fd, @Out ByteBuffer data, @size_t long size);
public @ssize_t int _read(int fd, @Out byte[] data, @size_t long size);
public @ssize_t int _write(int fd, @In ByteBuffer data, @size_t long size);
public @ssize_t int _write(int fd, @In byte[] data, @size_t long size);
public int _pipe(@Out int[] fds);
@IgnoreError String _strerror(int error);
// These functions don't exist:
//public int shutdown(int s, int how);
//public int fcntl(int fd, int cmd, int data);
//public int poll(@In @Out ByteBuffer pfds, int nfds, int timeout);
//public int poll(@In @Out Pointer pfds, int nfds, int timeout);
//public int kqueue();
//public int kevent(int kq, @In ByteBuffer changebuf, int nchanges,
// @Out ByteBuffer eventbuf, int nevents,
// @In @Transient Timespec timeout);
//public int kevent(int kq,
// @In Pointer changebuf, int nchanges,
// @Out Pointer eventbuf, int nevents,
// @In @Transient Timespec timeout);
}
private LibMSVCRT win;
public WinLibCAdapter(LibMSVCRT winlibc) { this.win = winlibc; }
@Override public int close(int fd) { return win._close(fd); }
@Override public int read(int fd, ByteBuffer data, long size) { return win._read(fd, data, size); }
@Override public int read(int fd, byte[] data, long size) { return win._read(fd, data, size); }
@Override public int write(int fd, ByteBuffer data, long size) { return win._write(fd, data, size); }
@Override public int write(int fd, byte[] data, long size) { return win._write(fd, data, size); }
@Override public int pipe(int[] fds) { return win._pipe(fds); }
@Override public String strerror(int error) { return win._strerror(error); }
@Override
public Runtime getRuntime() {
return Runtime.getRuntime(win);
}
// Unsupported Operations. Some may be implementable, others like fcntl may not be.
@Override
public int fcntl(int fd, int cmd, int data) {
throw new UnsupportedOperationException("fcntl isn't supported on Windows");
}
@Override
public int poll(ByteBuffer pfds, int nfds, int timeout) {
throw new UnsupportedOperationException("poll isn't supported on Windows");
}
@Override
public int poll(Pointer pfds, int nfds, int timeout) {
throw new UnsupportedOperationException("poll isn't supported on Windows");
}
@Override
public int kqueue() {
throw new UnsupportedOperationException("kqueue isn't supported on Windows");
}
@Override
public int kevent(int kq, ByteBuffer changebuf, int nchanges, ByteBuffer eventbuf, int nevents, Timespec timeout) {
throw new UnsupportedOperationException("kevent isn't supported on Windows");
}
@Override
public int kevent(int kq, Pointer changebuf, int nchanges, Pointer eventbuf, int nevents, Timespec timeout) {
throw new UnsupportedOperationException("kevent isn't supported on Windows");
}
@Override
public int shutdown(int s, int how) {
throw new UnsupportedOperationException("shutdown isn't supported on Windows");
}
} jnr-enxio-jnr-enxio-0.32.16/src/test/ 0000775 0000000 0000000 00000000000 14500014250 0017240 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/test/java/ 0000775 0000000 0000000 00000000000 14500014250 0020161 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/test/java/jnr/ 0000775 0000000 0000000 00000000000 14500014250 0020752 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/test/java/jnr/enxio/ 0000775 0000000 0000000 00000000000 14500014250 0022074 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/test/java/jnr/enxio/channels/ 0000775 0000000 0000000 00000000000 14500014250 0023667 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/test/java/jnr/enxio/channels/NativeTest.java 0000664 0000000 0000000 00000001414 14500014250 0026620 0 ustar 00root root 0000000 0000000 package jnr.enxio.channels;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
public class NativeTest {
@Rule
public ExpectedException expectedEx = ExpectedException.none();
@Test
public void closeThrowsOnNativeError() throws Exception {
FileOutputStream fos = new FileOutputStream("/dev/null");
FileDescriptor descriptor = fos.getFD();
Field fdField = descriptor.getClass().getDeclaredField("fd");
fdField.setAccessible(true);
int fd = (int)(Integer)fdField.get(descriptor);
Native.close(fd);
expectedEx.expect(NativeException.class);
Native.close(fd);
}
}
jnr-enxio-jnr-enxio-0.32.16/src/test/java/jnr/enxio/example/ 0000775 0000000 0000000 00000000000 14500014250 0023527 5 ustar 00root root 0000000 0000000 jnr-enxio-jnr-enxio-0.32.16/src/test/java/jnr/enxio/example/TCPServer.java 0000664 0000000 0000000 00000020145 14500014250 0026211 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2008 Wayne Meissner
*
* This file is part of the JNR project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jnr.enxio.example;
import jnr.enxio.channels.NativeSelectableChannel;
import jnr.enxio.channels.NativeSelectorProvider;
import jnr.enxio.channels.NativeServerSocketChannel;
import jnr.enxio.channels.NativeSocketChannel;
import jnr.ffi.*;
import jnr.ffi.annotations.In;
import jnr.ffi.annotations.Out;
import jnr.ffi.types.size_t;
import jnr.ffi.types.ssize_t;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
/**
*
* @author wayne
*/
public class TCPServer {
static final String[] libnames = Platform.getNativePlatform().getOS() == Platform.OS.SOLARIS
? new String[] { "socket", "nsl", "c" }
: new String[] { Platform.getNativePlatform().getStandardCLibraryName() };
static final LibC libc = Library.loadLibrary(LibC.class, libnames);
static final jnr.ffi.Runtime runtime = jnr.ffi.Runtime.getSystemRuntime();
public static class SockAddr extends Struct {
public SockAddr() {
super(runtime);
}
}
static class BSDSockAddrIN extends SockAddr {
public final Unsigned8 sin_len = new Unsigned8();
public final Unsigned8 sin_family = new Unsigned8();
public final Unsigned16 sin_port = new Unsigned16();
public final Unsigned32 sin_addr = new Unsigned32();
public final Padding sin_zero = new Padding(NativeType.SCHAR, 8);
}
static class SockAddrIN extends SockAddr {
public final Unsigned16 sin_family = new Unsigned16();
public final Unsigned16 sin_port = new Unsigned16();
public final Unsigned32 sin_addr = new Unsigned32();
public final Padding sin_zero = new Padding(NativeType.SCHAR, 8);
}
public static interface LibC {
static final int AF_INET = jnr.constants.platform.AddressFamily.AF_INET.intValue();
static final int SOCK_STREAM = jnr.constants.platform.Sock.SOCK_STREAM.intValue();
int socket(int domain, int type, int protocol);
int close(int fd);
int listen(int fd, int backlog);
int bind(int fd, SockAddr addr, int len);
int accept(int fd, @Out SockAddr addr, int[] len);
@ssize_t int read(int fd, @Out ByteBuffer data, @size_t int len);
@ssize_t int read(int fd, @Out byte[] data, @size_t int len);
@ssize_t int write(int fd, @In ByteBuffer data, @size_t int len);
String strerror(int error);
}
static short htons(short val) {
return Short.reverseBytes(val);
}
static NativeServerSocketChannel serverSocket(int port) {
int fd = libc.socket(LibC.AF_INET, LibC.SOCK_STREAM, 0);
System.out.println("fd=" + fd);
SockAddr addr;
if (Platform.getNativePlatform().isBSD()) {
BSDSockAddrIN sin = new BSDSockAddrIN();
sin.sin_family.set((byte) LibC.AF_INET);
sin.sin_port.set(htons((short) port));
addr = sin;
} else {
SockAddrIN sin = new SockAddrIN();
sin.sin_family.set(htons((short) LibC.AF_INET));
sin.sin_port.set(htons((short) port));
addr = sin;
}
System.out.println("sizeof addr=" + Struct.size(addr));
if (libc.bind(fd, addr, Struct.size(addr)) < 0) {
System.err.println("bind failed: " + libc.strerror(LastError.getLastError(runtime)));
System.exit(1);
}
if (libc.listen(fd, 5) < 0) {
System.err.println("listen failed: " + libc.strerror(LastError.getLastError(runtime)));
System.exit(1);
}
System.out.println("bind+listen succeeded");
return new NativeServerSocketChannel(fd);
}
private static abstract class IO {
protected final SelectableChannel channel;
protected final Selector selector;
public IO(Selector selector, SelectableChannel ch) {
this.selector = selector;
this.channel = ch;
}
public abstract void read();
public abstract void write();
}
private static class Accepter extends IO {
public Accepter(Selector selector, NativeServerSocketChannel ch) {
super(selector, ch);
}
public void read() {
SockAddrIN sin = new SockAddrIN();
int[] addrSize = { Struct.size(sin) };
int clientfd = libc.accept(((NativeSelectableChannel) channel).getFD(), sin, addrSize);
System.out.println("client fd = " + clientfd);
NativeSocketChannel ch = new NativeSocketChannel(clientfd);
try {
ch.configureBlocking(false);
ch.register(selector, SelectionKey.OP_READ, new Client(selector, ch));
selector.wakeup();
} catch (IOException ex) {}
}
public void write() {
SelectionKey k = channel.keyFor(selector);
k.interestOps(SelectionKey.OP_ACCEPT);
}
}
private static class Client extends IO {
private final ByteBuffer buf = ByteBuffer.allocateDirect(1024);
public Client(Selector selector, NativeSocketChannel ch) {
super(selector, ch);
}
public void read() {
int n = libc.read(((NativeSelectableChannel) channel).getFD(), buf, buf.remaining());
System.out.println("Read " + n + " bytes from client");
if (n <= 0) {
SelectionKey k = channel.keyFor(selector);
k.cancel();
libc.close(((NativeSelectableChannel) channel).getFD());
return;
}
buf.position(n);
buf.flip();
channel.keyFor(selector).interestOps(SelectionKey.OP_WRITE);
}
public void write() {
while (buf.hasRemaining()) {
int n = libc.write(((NativeSelectableChannel) channel).getFD(), buf, buf.remaining());
System.out.println("write returned " + n);
if (n > 0) {
buf.position(buf.position() + n);
}
if (n == 0) {
return;
}
if (n < 0) {
channel.keyFor(selector).cancel();
libc.close(((NativeSelectableChannel) channel).getFD());
return;
}
}
System.out.println("outbuf empty");
buf.clear();
channel.keyFor(selector).interestOps(SelectionKey.OP_READ);
}
}
public static void main(String[] args) {
short baseport = 2000;
try {
Selector selector = NativeSelectorProvider.getInstance().openSelector();
for (int i = 0; i < 2; ++i) {
NativeServerSocketChannel ch = serverSocket(baseport + i);
ch.configureBlocking(false);
ch.register(selector, SelectionKey.OP_ACCEPT, new Accepter(selector, ch));
}
while (true) {
selector.select();
for (SelectionKey k : selector.selectedKeys()) {
if ((k.readyOps() & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0) {
((IO) k.attachment()).read();
}
if ((k.readyOps() & (SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT)) != 0) {
((IO) k.attachment()).write();
}
}
}
} catch (IOException ex) {
}
}
}