Author: mturk
Date: Sat Nov 21 13:11:32 2009
New Revision: 882894
URL: http://svn.apache.org/viewvc?rev=882894&view=rev
Log:
Implement posix pipe creation
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Pipe.java
commons/sandbox/runtime/trunk/src/main/native/include/acr_pipe.h
commons/sandbox/runtime/trunk/src/main/native/os/unix/pipe.c
Modified:
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Pipe.java
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Pipe.java?rev=882894&r1=882893&r2=882894&view=diff
==============================================================================
---
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Pipe.java
(original)
+++
commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Pipe.java
Sat Nov 21 13:11:32 2009
@@ -39,7 +39,7 @@
* <p>
* </p>
*/
-public final class Pipe
+public final class Pipe implements Device, Syncable
{
private Descriptor fd;
@@ -64,6 +64,11 @@
mode = PipeIoMode.valueOf(type & 0xff);
}
+ PipeIoMode getMode()
+ {
+ return mode;
+ }
+
/**
* Return the {...@link Descriptor} accosicated with this pipe.
*
@@ -74,4 +79,107 @@
return fd;
}
+ public static native Pipe[] create0(int mode)
+ throws IOException;
+ /**
+ * Creates a pipe, a unidirectional data channel that can be used
+ * for interprocess communication.
+ * <p>
+ * The returned array is used to return two file descriptors
+ * referring to the ends of the pipe.<br/>
+ * Pipe[0] refers to the read end of the pipe.<br/>
+ * Pipe[1] refers to the write end of the pipe.<br/>
+ * Data written to the write end of the
+ * pipe is buffered by the kernel until it is read from the
+ * read end of the pipe.
+ * </p>
+ */
+ public Pipe[] create(PipeIoMode mode)
+ throws IOException
+ {
+ return create0(mode.valueOf());
+ }
+
+ /**
+ * Test the pipe blocking mode.
+ *
+ * @return {...@code true} if pipe operations are blocking.
+ *
+ * @throws ClosedDescriptorException
+ * If this pipe is closed.
+ * @throws IOException
+ * If some other I/O error occurs.
+ */
+ @Override
+ public boolean isBlocking()
+ throws IOException
+ {
+ if (!valid())
+ throw new ClosedDescriptorException();
+ return mode != PipeIoMode.FULL_NONBLOCK;
+ }
+
+ @Override
+ public boolean valid()
+ {
+ if (fd != null)
+ return fd.valid();
+ else
+ return false;
+ }
+
+ /**
+ * Close this pipe.
+ * @see java.io.Closeable#close()
+ * @throws IOException if an I/O error occurs.
+ */
+ @Override
+ public final void close()
+ throws IOException
+ {
+ fd.close();
+ }
+
+ /**
+ * Flush the underlying pipe metadata.
+ * <p>
+ * {...@code flush} transfers all modified metadata of the file object
+ * referred to by {...@code this} file to the disk device
+ * (or other permanent storage device) where that object resides.
+ * The call blocks until the device reports that the transfer has
+ * completed. It also flushes metadata information associated with
+ * {...@code this} Descriptor.
+ * </p>
+ *
+ * @throws SyncFailedException when the object cannot be flushed.
+ * @throws IOException if an I/O error occurs.
+ */
+ @Override
+ public final void flush()
+ throws SyncFailedException, IOException
+ {
+ fd.flush();
+ }
+
+ /**
+ * Sync the underlying pipe by writing any buffered data.
+ * <p>
+ * {...@code sync} transfers all modified in-core data of the file object
+ * referred to by {...@code this} file to the disk device
+ * (or other permanent storage device) where that object resides.
+ * The call blocks until the device reports that the transfer has
+ * completed. It also flushes metadata information associated with
+ * {...@code this} Descriptor.
+ * </p>
+ *
+ * @throws SyncFailedException when the object cannot be flushed.
+ * @throws IOException if an I/O error occurs.
+ */
+ @Override
+ public final void sync()
+ throws SyncFailedException, IOException
+ {
+ fd.sync();
+ }
+
}
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_pipe.h
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_pipe.h?rev=882894&r1=882893&r2=882894&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_pipe.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_pipe.h Sat Nov 21
13:11:32 2009
@@ -31,6 +31,16 @@
*
*/
+/** PipeIoMode flags
+ */
+#define ACR_PIPE_FULL_BLOCK 1
+#define ACR_PIPE_FULL_NONBLOCK 2
+#define ACR_PIPE_PARENT_BLOCK 3
+#define ACR_PIPE_CHILD_BLOCK 4
+
+#define ACR_PIPE_IN 0x0100
+#define ACR_PIPE_OUT 0x0200
+
/**
* Create new Pipe object.
*/
Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/pipe.c
URL:
http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/pipe.c?rev=882894&r1=882893&r2=882894&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/pipe.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/pipe.c Sat Nov 21
13:11:32 2009
@@ -21,10 +21,15 @@
#include "acr_error.h"
#include "acr_clazz.h"
#include "acr_string.h"
+#include "acr_memory.h"
#include "acr_descriptor.h"
#include "acr_file.h"
#include "acr_pipe.h"
+/* Platform includes
+ */
+#include <sys/time.h>
+
/**
* Posix pipe functions
*
@@ -75,3 +80,189 @@
else
return NULL;
}
+
+static int file_cleanup(void *file, int type, unsigned int flags)
+{
+ int rc = ACR_EBADF;
+ acr_file_t *fp = (acr_file_t *)file;
+
+ if (type != ACR_DT_FILE) {
+ return ACR_EBADF;
+ }
+ if (fp->fd >= 0) {
+ if (close(fp->fd))
+ rc = ACR_GET_OS_ERROR();
+ else
+ rc = ACR_SUCCESS;
+ }
+ if (flags & ACR_IOH_CLEAR)
+ x_free(fp);
+ else
+ fp->fd = -1;
+ return rc;
+}
+
+static int descriptor_cleanup(ACR_JNISTDARGS,
+ acr_descriptor_cb_type_e cm,
+ acr_descriptor_cb_t *dp)
+{
+ int rc = ACR_SUCCESS;
+ switch (cm) {
+ case ACR_DESC_FINALIZE:
+ if (dp->di > 0) {
+ acr_file_t *fp = ACR_IOH_FDATA(dp->di);
+ if (fp->descriptor) {
+ (*_E)->DeleteWeakGlobalRef(_E, fp->descriptor);
+ fp->descriptor = NULL;
+ }
+ rc = acr_ioh_clear(dp->di);
+ }
+ else
+ rc = ACR_EBADF;
+ break;
+ case ACR_DESC_CLOSE:
+ if (dp->di > 0) {
+ acr_file_t *fp = ACR_IOH_FDATA(dp->di);
+ if (fp->descriptor) {
+ (*_E)->DeleteWeakGlobalRef(_E, fp->descriptor);
+ fp->descriptor = NULL;
+ }
+ rc = acr_ioh_close(dp->di);
+ }
+ else
+ rc = ACR_EBADF;
+ break;
+ case ACR_DESC_FLUSH:
+ if (dp->di > 0) {
+ acr_file_t *fp = ACR_IOH_FDATA(dp->di);
+ if (fdatasync(fp->fd) < 0)
+ rc = ACR_GET_OS_ERROR();
+ }
+ else
+ rc = ACR_EBADF;
+ break;
+ case ACR_DESC_SYNC:
+ if (dp->di > 0) {
+ acr_file_t *fp = ACR_IOH_FDATA(dp->di);
+ if (fsync(fp->fd) < 0)
+ rc = ACR_GET_OS_ERROR();
+ }
+ else
+ rc = ACR_EBADF;
+ break;
+ default:
+ rc = ACR_ENOTIMPL;
+ break;
+ }
+ return rc;
+}
+
+static int do_popen(JNIEnv *_E, int fd, int flags,
+ jobject *fdo)
+{
+ int rc = 0;
+ int fo;
+ acr_file_t *fp = NULL;
+
+ if ((flags & 0xFF) == ACR_PIPE_FULL_NONBLOCK) {
+#ifdef O_NONBLOCK
+ /* Use non-blocking I/O
+ */
+ int mode;
+ if ((mode = fcntl(fd, F_GETFL, 0)) == -1) {
+ rc = ACR_GET_OS_ERROR();
+ goto finally;
+ }
+ mode |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, mode) == -1) {
+ rc = ACR_GET_OS_ERROR();
+ goto finally;
+ }
+#else
+ /* Non blocking files are unsupported.
+ */
+ rc = ACR_ENOTIMPL;
+ goto finally;
+#endif
+ }
+ fp = ACR_CALLOC(acr_file_t, 1);
+ if (!fp) {
+ rc = ACR_ENOMEM;
+ goto finally;
+ }
+ fp->fd = fd;
+ fp->name = NULL;
+ fp->flags = flags;
+ fp->type = ACR_FT_PIPE;
+ if ((flags & 0xFF) == ACR_PIPE_FULL_NONBLOCK) {
+ fp->blocking = BLK_OFF;
+ fp->timeout = 0;
+ }
+ else {
+ fp->blocking = BLK_ON;
+ fp->timeout = -1;
+ }
+ fo = acr_ioh_open(fp, ACR_DT_FILE, 0, file_cleanup);
+ if (fo < 0) {
+ rc = ACR_GET_OS_ERROR();
+ goto finally;
+ }
+ /* Create File Descriptor Object */
+ *fdo = ACR_DescriptorCreate(_E, ACR_DT_FILE, fo, NULL,
+ descriptor_cleanup);
+ if (!*fdo) {
+ rc = ACR_GET_OS_ERROR();
+ goto finally;
+ }
+ fp->descriptor = (*_E)->NewWeakGlobalRef(_E, *fdo);
+finally:
+ if (rc) {
+ if (fd >= 0)
+ close(fd);
+ x_free(fp);
+ }
+
+ return rc;
+}
+
+ACR_IO_EXPORT_DECLARE(jobjectArray, Pipe, create0)(ACR_JNISTDARGS,
+ jint flags)
+{
+ int rc = 0;
+ jobjectArray pa = NULL;
+ jobject fd[2];
+ int pd[2] = { -1, -1 };
+
+ if (pipe(pd) == -1) {
+ ACR_THROW_IO_ERRNO();
+ return NULL;
+ }
+ pa = ACR_NewPipeArray(_E, 2);
+ if (pa == NULL) {
+ close(pd[0]);
+ close(pd[1]);
+ }
+ rc = do_popen(_E, pd[0], flags & ACR_PIPE_IN, &fd[0]);
+ if (rc) {
+ goto cleanup;
+ }
+ rc = do_popen(_E, pd[1], flags & ACR_PIPE_OUT, &fd[1]);
+ if (rc) {
+ /* ### fd[0] will be closed by GC ?
+ */
+ pd[0] = -1;
+ goto cleanup;
+ }
+ (*_E)->SetObjectArrayElement(_E, pa, 0, fd[0]);
+ (*_E)->SetObjectArrayElement(_E, pa, 1, fd[1]);
+ return pa;
+
+cleanup:
+ if (pd[0] != -1)
+ close(pd[0]);
+ if (pd[1] != -1)
+ close(pd[1]);
+
+ ACR_THROW_IO_IF_ERR(rc);
+ return NULL;
+}