Revision: 7834
Author: j...@google.com
Date: Wed Mar 31 20:30:31 2010
Log: Initial work on adding pluggable transports on the Java side, adding
prebuilt binaries for Linux JNI code, build changes.
http://code.google.com/p/google-web-toolkit/source/detail?r=7834
Added:
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/DefaultTransport.java
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/ShmFutexTransport.java
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/ShmFutexTransportTestServer.java
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/SocketTransport.java
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/Transport.java
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/TransportFactory.java
/changes/jat/csproto/jni/linux/prebuilt/libShmFutex_Linux_x86.so
/changes/jat/csproto/jni/linux/prebuilt/libShmFutex_Linux_x86_64.so
Modified:
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
/changes/jat/csproto/distro-source/build.xml
/changes/jat/csproto/jni/build.xml
/changes/jat/csproto/jni/linux/Makefile
=======================================
--- /dev/null
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/DefaultTransport.java
Wed Mar 31 20:30:31 2010
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.dev.shell;
+
+import com.google.gwt.util.tools.Utility;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Default transport implementation over regular streams, which it buffers.
+ */
+public class DefaultTransport implements Transport {
+
+ private final InputStream istr;
+ private final OutputStream ostr;
+
+ public DefaultTransport(InputStream istr, OutputStream ostr) {
+ this.istr = new BufferedInputStream(istr);
+ this.ostr = new BufferedOutputStream(ostr);
+ }
+
+ public boolean beginReadMessage() {
+ return true;
+ }
+
+ public boolean beginWriteMessage() {
+ return true;
+ }
+
+ public void closeChannel() {
+ Utility.close(istr);
+ Utility.close(ostr);
+ }
+
+ public void endReadMessage() {
+ }
+
+ public void endWriteMessage() {
+ try {
+ getOutputStream().flush();
+ } catch (IOException e) {
+ // silently ignore, will get caught later
+ }
+ }
+
+ public InputStream getInputStream() {
+ return istr;
+ }
+
+ public OutputStream getOutputStream() {
+ return ostr;
+ }
+}
=======================================
--- /dev/null
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/ShmFutexTransport.java
Wed Mar 31 20:30:31 2010
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.dev.shell;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.MappedByteBuffer;
+
+/**
+ * Transport that uses shared memory and Futexes for communication between
the
+ * browser and the server.
+ */
+public class ShmFutexTransport implements Transport {
+
+ /**
+ * InputStream for the server side of the shm+futex transport.
+ */
+ private class ShmFutexInputStream extends InputStream {
+
+ public boolean beginRead() {
+ boolean success = false;
+ // HACK: retry for a while, need to handle fragmentation
+ for (int i = 0; i < 100; ++i) {
+ success = nativeBeginServerRead(shmFutexAddr);
+ if (success) {
+ break;
+ }
+ }
+ if (success) {
+ clientToServerBuf.position(0);
+ } else {
+ // make sure any accesses fail if we didn't lock the buffer
+ clientToServerBuf.limit(0);
+ }
+ return success;
+ }
+
+ public void endRead() {
+ nativeEndServerRead(shmFutexAddr);
+ if (!readMessage) {
+ readMessage = true;
+ removeKey();
+ }
+ }
+
+ @Override
+ public int read() {
+ try {
+ return clientToServerBuf.get();
+ } catch (BufferUnderflowException e) {
+ return -1;
+ }
+ }
+ }
+
+ /**
+ * OutputStream for the server side of the shm+futex transport.
+ */
+ private class ShmFutexOutputStream extends OutputStream {
+
+ public boolean beginWrite() {
+ boolean success = false;
+ // HACK: retry for a while, need to handle fragmentation
+ for (int i = 0; i < 100; ++i) {
+ success = nativeBeginServerWrite(shmFutexAddr);
+ if (success) {
+ break;
+ }
+ }
+ if (success) {
+ serverToClientBuf.position(0);
+ } else {
+ // make sure any accesses fail if we didn't lock the buffer
+ serverToClientBuf.limit(0);
+ }
+ return success;
+ }
+
+ public void endWrite() {
+ try {
+ flush();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ nativeEndServerWrite(shmFutexAddr);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ try {
+ serverToClientBuf.put((byte) b);
+ } catch (BufferOverflowException e) {
+ throw new IOException(e);
+ }
+ }
+ }
+
+ /**
+ * Connect to an existing ShmFutex channel.
+ *
+ * @param key shm key of segment, provided by a previous
+ * {...@link #createNewChannel} call
+ * @return a ShmFutexTransport instance, or null on an error
+ */
+ public static ShmFutexTransport connectToChannel(String key) {
+ long shmFutexAddr = nativeConnect(key);
+ if (shmFutexAddr == 0) {
+ return null;
+ }
+ return new ShmFutexTransport(shmFutexAddr, key);
+ }
+
+ /**
+ * Connect to an existing ShmFutex channel.
+ *
+ * @param outputKey output array of a single String element, which will
get
+ * the shm key of segment to be used with a later
+ * {...@link #connectToChannel} call
+ * @return a ShmFutexTransport instance, or null on an error
+ */
+ public static ShmFutexTransport createNewChannel(String[] outputKey) {
+ if (outputKey.length != 1) {
+ throw new IllegalArgumentException(
+ "Expected 1-element array for returned argument value");
+ }
+ long shmFutexAddr = nativeCreate(outputKey);
+ if (shmFutexAddr == 0) {
+ return null;
+ }
+ ShmFutexTransport shm = new ShmFutexTransport(shmFutexAddr,
outputKey[0]);
+ shm.ownsShm = true;
+ return shm;
+ }
+
+ /**
+ * Wait until we have a full server->client buffer.
+ *
+ * @return true on success
+ */
+ @SuppressWarnings("unused")
+ private static native boolean nativeBeginClientRead(long shmFutexAddr);
+
+ /**
+ * Wait until we have an empty client->server buffer.
+ *
+ * @return true on success
+ */
+ @SuppressWarnings("unused")
+ private static native boolean nativeBeginClientWrite(long shmFutexAddr);
+
+ /**
+ * Wait until we have a full client->server buffer.
+ *
+ * @return true on success
+ */
+ private static native boolean nativeBeginServerRead(long shmFutexAddr);
+
+ /**
+ * Wait until we have an empty server->client buffer.
+ *
+ * @return true on success
+ */
+ private static native boolean nativeBeginServerWrite(long shmFutexAddr);
+
+ /**
+ * Initialize Shm + Futex channel, setting all the fields.
+ *
+ * @param key SHM key of existing shared memory segment
+ * @return the address of a native object, or 0 on error
+ */
+ private static native long nativeConnect(String key);
+
+ /**
+ * Initialize Shm + Futex channel, setting all the fields.
+ *
+ * @param outputKey an array used to return the argument to use for a
later
+ * nativeConnect call in another process/thread
+ * @return the address of a native object, or 0 on error
+ */
+ private static native long nativeCreate(String[] outputKey);
+
+ /**
+ * Indicate we are done with the server->client buffer contents.
+ */
+ @SuppressWarnings("unused")
+ private static native void nativeEndClientRead(long shmFutexAddr);
+
+ /**
+ * Indicate we have filled the client->server buffer contents.
+ */
+ @SuppressWarnings("unused")
+ private static native void nativeEndClientWrite(long shmFutexAddr);
+
+ /**
+ * Indicate we are done with the client->server buffer contents.
+ */
+ private static native void nativeEndServerRead(long shmFutexAddr);
+
+ /**
+ * Indicate we have filled the server->client buffer contents.
+ */
+ private static native void nativeEndServerWrite(long shmFutexAddr);
+
+ private static native MappedByteBuffer nativeGetClientToServerBuf(
+ long shmFutexAddr);
+
+ private static native MappedByteBuffer nativeGetServerToClientBuf(
+ long shmFutexAddr);
+
+ /**
+ * Remove the shm key (existing mappings will keep the segment around
+ * until they are detached).
+ *
+ * @param key
+ */
+ private static native void nativeRemoveKey(String key);
+
+ /**
+ * Free the native objects.
+ *
+ * @param ownsShm true if this instance owns the shm segment
+ */
+ private static native void nativeShutdown(long shmFutexAddr, boolean
ownsShm);
+
+ private boolean readMessage = false;
+
+ /**
+ * Address of the underlying native object, 0 when it has been freed.
+ */
+ private long shmFutexAddr;
+
+ private final ShmFutexInputStream istr;
+
+ private final ShmFutexOutputStream ostr;
+
+ private final MappedByteBuffer serverToClientBuf;
+
+ private final MappedByteBuffer clientToServerBuf;
+
+ private boolean ownsShm;
+
+ private final String key;
+
+ private ShmFutexTransport(long shmFutexAddr, String key) {
+ this.shmFutexAddr = shmFutexAddr;
+ this.key = key;
+ serverToClientBuf = nativeGetServerToClientBuf(shmFutexAddr);
+ clientToServerBuf = nativeGetClientToServerBuf(shmFutexAddr);
+ istr = new ShmFutexInputStream();
+ ostr = new ShmFutexOutputStream();
+ }
+
+ public boolean beginReadMessage() {
+ return istr.beginRead();
+ }
+
+ public boolean beginWriteMessage() {
+ return ostr.beginWrite();
+ }
+
+ public void closeChannel() {
+ try {
+ istr.close();
+ } catch (IOException ignored) {
+ }
+ try {
+ ostr.close();
+ } catch (IOException ignored) {
+ }
+ if (shmFutexAddr != 0) {
+ nativeShutdown(shmFutexAddr, ownsShm);
+ shmFutexAddr = 0;
+ }
+ }
+
+ public void endReadMessage() {
+ istr.endRead();
+ }
+
+ public void endWriteMessage() {
+ ostr.endWrite();
+ }
+
+ public InputStream getInputStream() {
+ return istr;
+ }
+
+ public OutputStream getOutputStream() {
+ return ostr;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ if (shmFutexAddr != 0) {
+ nativeShutdown(shmFutexAddr, ownsShm);
+ shmFutexAddr = 0;
+ }
+ }
+
+ protected void removeKey() {
+ nativeRemoveKey(key);
+ }
+}
=======================================
--- /dev/null
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/ShmFutexTransportTestServer.java
Wed Mar 31 20:30:31 2010
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.dev.shell;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class ShmFutexTransportTestServer {
+
+ private static final int NUM_PACKETS = 800000;
+ private static final int PACKET_SIZE_CS = 96;
+ private static final int PACKET_SIZE_SC = 151;
+
+ /**
+ * @param args
+ */
+ public static void main(String[] args) {
+ String os = System.getProperty("os.name");
+ String arch = System.getProperty("os.arch");
+ if (arch.matches("i?\\d86")) {
+ arch = "x86";
+ } else if ("amd64".equals(arch)) {
+ arch = "x86_64";
+ }
+ String library = "ShmFutex_" + os + "_" + arch;
+ String platformLibrary = System.mapLibraryName(library);
+ System.out.println("Mapped name = " + platformLibrary);
+ System.load("/tmp/" + platformLibrary);
+ String[] outputKey = new String[1];
+ ShmFutexTransport shm = ShmFutexTransport.createNewChannel(outputKey);
+ if (shm == null) {
+ System.err.println("Unable to create shared memory segment");
+ }
+ System.out.println("Connect to key " + outputKey[0]);
+ try {
+ runServer(shm);
+ } finally {
+ shm.closeChannel();
+ }
+ }
+
+ private static void runServer(Transport shm) {
+ InputStream istr = shm.getInputStream();
+ OutputStream ostr = shm.getOutputStream();
+ for (int i = 0; i < NUM_PACKETS; ++i) {
+ shm.beginReadMessage();
+ readPacket(istr, PACKET_SIZE_CS);
+ shm.endReadMessage();
+ shm.beginWriteMessage();
+ writePacket(ostr, PACKET_SIZE_SC);
+ shm.endWriteMessage();
+ }
+ }
+
+ private static void writePacket(OutputStream ostr, int len) {
+ while (len-- > 0) {
+ try {
+ ostr.write((byte) len);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private static void readPacket(InputStream istr, int len) {
+ while (len-- > 0) {
+ try {
+ int b = istr.read();
+ if ((byte) b != (byte) len) {
+ throw new IllegalStateException("Expected " + (byte) len + ",
got "
+ + (byte) b);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+}
=======================================
--- /dev/null
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/SocketTransport.java
Wed Mar 31 20:30:31 2010
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.dev.shell;
+
+import com.google.gwt.util.tools.Utility;
+
+import java.io.IOException;
+import java.net.Socket;
+
+/**
+ * Transport implementation using TCP sockets.
+ */
+public class SocketTransport extends DefaultTransport {
+
+ private final Socket socket;
+
+ public SocketTransport(Socket socket) throws IOException {
+ super(socket.getInputStream(), socket.getOutputStream());
+ this.socket = socket;
+ }
+
+ @Override
+ public void closeChannel() {
+ Utility.close(socket);
+ }
+
+ public String getRemoteEndpoint() {
+ return socket.getInetAddress().getCanonicalHostName() + ":"
+ + socket.getPort();
+ }
+}
=======================================
--- /dev/null
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/Transport.java
Wed Mar 31 20:30:31 2010
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.dev.shell;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Describes alternate transports that can be used for the code server
protocol.
+ */
+public interface Transport {
+
+ /**
+ * @return the InputStream for this transport (only valid after
createChannel
+ * has been called).
+ */
+ InputStream getInputStream();
+
+ /**
+ * @return the OutputStream for this transport (only valid after
createChannel
+ * has been called).
+ */
+ OutputStream getOutputStream();
+
+ /**
+ * Close this transport channel. Must be called to free up held
resources.
+ */
+ void closeChannel();
+
+ /**
+ * Begin reading a message. Must be called before reading any bytes from
the
+ * input stream for a message.
+ *
+ * @return true on success
+ */
+ boolean beginReadMessage();
+
+ /**
+ * Begin writing a message. Must be called before writing any bytes to
the
+ * input stream for a message.
+ *
+ * @return true on success
+ */
+ boolean beginWriteMessage();
+
+ /**
+ * Finishes reading a message. Must be called after the last byte of a
+ * message is read and before the next call to {...@link
#beginReadMessage()}.
+ */
+ void endReadMessage();
+
+ /**
+ * Finishes writing a message. Must be called after the last byte of a
+ * message is written and before the next call to
+ * {...@link #beginWriteMessage()}.
+ */
+ void endWriteMessage();
+}
=======================================
--- /dev/null
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/TransportFactory.java
Wed Mar 31 20:30:31 2010
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * 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 com.google.gwt.dev.shell;
+
+public interface TransportFactory {
+
+ public class TransportArgs {
+ public String transportArgs;
+ }
+
+ Transport connectTransport(String args);
+
+ Transport createTransport(TransportArgs args);
+
+ String getName();
+
+ boolean isAvailable();
+}
=======================================
--- /dev/null
+++ /changes/jat/csproto/jni/linux/prebuilt/libShmFutex_Linux_x86.so Wed
Mar 31 20:30:31 2010
Binary file, no diff available.
=======================================
--- /dev/null
+++ /changes/jat/csproto/jni/linux/prebuilt/libShmFutex_Linux_x86_64.so Wed
Mar 31 20:30:31 2010
Binary file, no diff available.
=======================================
---
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
Fri Feb 19 06:35:15 2010
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/BrowserChannel.java
Wed Mar 31 20:30:31 2010
@@ -20,8 +20,6 @@
import com.google.gwt.dev.shell.BrowserChannel.Value.ValueType;
import com.google.gwt.util.tools.Utility;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -35,17 +33,6 @@
*
*/
public abstract class BrowserChannel {
-
- /**
- * An error indicating that the remote side died and we should unroll the
- * call stack as painlessly as possible to allow cleanup.
- */
- public static class RemoteDeathError extends Error {
-
- public RemoteDeathError(Throwable cause) {
- super("Remote connection lost", cause);
- }
- }
/**
* Class representing a reference to a Java object.
@@ -181,6 +168,17 @@
return id;
}
}
+
+ /**
+ * An error indicating that the remote side died and we should unroll the
+ * call stack as painlessly as possible to allow cleanup.
+ */
+ public static class RemoteDeathError extends Error {
+
+ public RemoteDeathError(Throwable cause) {
+ super("Remote connection lost", cause);
+ }
+ }
/**
* Represents an object on the other side of the channel, known to this
side
@@ -616,6 +614,7 @@
int minVersion = stream.readInt();
int maxVersion = stream.readInt();
String hostedHtmlVersion = readUtf8String(stream);
+ channel.endReadMessage();
return new CheckVersionsMessage(channel, minVersion, maxVersion,
hostedHtmlVersion);
}
@@ -649,11 +648,13 @@
@Override
public void send() throws IOException {
DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.CHECK_VERSIONS.getId());
stream.writeInt(minVersion);
stream.writeInt(maxVersion);
writeUtf8String(stream, hostedHtmlVersion);
stream.flush();
+ getBrowserChannel().endWriteMessage();
}
}
@@ -671,6 +672,7 @@
for (int i = 0; i < n; ++i) {
transports[i] = readUtf8String(stream);
}
+ channel.endReadMessage();
return new ChooseTransportMessage(channel, transports);
}
@@ -689,11 +691,13 @@
@Override
public void send() throws IOException {
DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.CHOOSE_TRANSPORT.getId());
stream.writeInt(transports.length);
for (String transport : transports) {
writeUtf8String(stream, transport);
}
+ getBrowserChannel().endWriteMessage();
}
}
@@ -707,6 +711,7 @@
DataInputStream stream = channel.getStreamFromOtherSide();
// NOTE: Tag has already been read.
String error = readUtf8String(stream);
+ channel.endReadMessage();
return new FatalErrorMessage(channel, error);
}
@@ -724,8 +729,10 @@
@Override
public void send() throws IOException {
DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.FATAL_ERROR.getId());
writeUtf8String(stream, error);
+ getBrowserChannel().endWriteMessage();
}
}
@@ -744,18 +751,21 @@
for (int i = 0; i < numIds; ++i) {
ids[i] = stream.readInt();
}
+ channel.endReadMessage();
return new FreeMessage(channel, ids);
}
public static void send(BrowserChannel channel, int[] ids)
throws IOException {
DataOutputStream stream = channel.getStreamToOtherSide();
+ channel.beginWriteMessage();
stream.writeByte(MessageType.FREE_VALUE.getId());
stream.writeInt(ids.length);
for (int id : ids) {
stream.writeInt(id);
}
stream.flush();
+ channel.endWriteMessage();
}
private final int ids[];
@@ -800,6 +810,7 @@
for (int i = 0; i < argLen; i++) {
args[i] = channel.readValue(stream);
}
+ channel.endReadMessage();
return new InvokeOnClientMessage(channel, methodName, thisRef, args);
}
@@ -830,7 +841,7 @@
@Override
public void send() throws IOException {
final DataOutputStream stream =
getBrowserChannel().getStreamToOtherSide();
-
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.INVOKE.getId());
writeUtf8String(stream, methodName);
getBrowserChannel().writeValue(stream, thisRef);
@@ -839,6 +850,7 @@
getBrowserChannel().writeValue(stream, args[i]);
}
stream.flush();
+ getBrowserChannel().endWriteMessage();
}
}
@@ -862,6 +874,7 @@
for (int i = 0; i < argLen; i++) {
args[i] = channel.readValue(stream);
}
+ channel.endReadMessage();
return new InvokeOnServerMessage(channel, methodDispatchId, thisRef,
args);
}
@@ -893,7 +906,7 @@
@Override
public void send() throws IOException {
final DataOutputStream stream =
getBrowserChannel().getStreamToOtherSide();
-
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.INVOKE.getId());
stream.writeInt(methodDispatchId);
getBrowserChannel().writeValue(stream, thisRef);
@@ -902,6 +915,7 @@
getBrowserChannel().writeValue(stream, args[i]);
}
stream.flush();
+ getBrowserChannel().endWriteMessage();
}
}
@@ -925,6 +939,7 @@
for (int i = 0; i < argLen; i++) {
args[i] = channel.readValue(stream);
}
+ channel.endReadMessage();
return new InvokeSpecialMessage(channel, dispatchId, args);
}
@@ -950,6 +965,7 @@
public void send() throws IOException {
final DataOutputStream stream =
getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.INVOKE_SPECIAL.getId());
stream.writeByte(dispatchId.getId());
stream.writeInt(args.length);
@@ -957,6 +973,7 @@
getBrowserChannel().writeValue(stream, args[i]);
}
stream.flush();
+ getBrowserChannel().endWriteMessage();
}
}
@@ -970,15 +987,18 @@
throws IOException {
DataInputStream stream = channel.getStreamFromOtherSide();
String js = readUtf8String(stream);
+ channel.endReadMessage();
return new LoadJsniMessage(channel, js);
}
public static void send(BrowserChannel channel, String js)
throws IOException {
DataOutputStream stream = channel.getStreamToOtherSide();
+ channel.beginWriteMessage();
stream.write(MessageType.LOAD_JSNI.getId());
writeUtf8String(stream, js);
stream.flush();
+ channel.endWriteMessage();
}
private final String js;
@@ -1016,6 +1036,7 @@
String sessionKey = readUtf8String(stream);
String moduleName = readUtf8String(stream);
String userAgent = readUtf8String(stream);
+ channel.endReadMessage();
return new LoadModuleMessage(channel, url, tabKey, sessionKey,
moduleName,
userAgent);
}
@@ -1080,6 +1101,7 @@
@Override
public void send() throws IOException {
DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.LOAD_MODULE.getId());
writeUtf8String(stream, url);
writeUtf8String(stream, tabKey);
@@ -1087,6 +1109,7 @@
writeUtf8String(stream, moduleName);
writeUtf8String(stream, userAgent);
stream.flush();
+ getBrowserChannel().endWriteMessage();
}
}
@@ -1158,6 +1181,7 @@
int protoVersion = stream.readInt();
String moduleName = readUtf8String(stream);
String userAgent = readUtf8String(stream);
+ channel.endReadMessage();
return new OldLoadModuleMessage(channel, protoVersion, moduleName,
userAgent);
}
@@ -1191,11 +1215,13 @@
@Override
public void send() throws IOException {
DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.OLD_LOAD_MODULE.getId());
stream.writeInt(protoVersion);
writeUtf8String(stream, moduleName);
writeUtf8String(stream, userAgent);
stream.flush();
+ getBrowserChannel().endWriteMessage();
}
}
@@ -1208,6 +1234,7 @@
throws IOException {
DataInputStream stream = channel.getStreamFromOtherSide();
int protocolVersion = stream.readInt();
+ channel.endReadMessage();
return new ProtocolVersionMessage(channel, protocolVersion);
}
@@ -1225,9 +1252,11 @@
@Override
public void send() throws IOException {
DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.PROTOCOL_VERSION.getId());
stream.writeInt(protocolVersion);
stream.flush();
+ getBrowserChannel().endWriteMessage();
}
}
@@ -1236,13 +1265,16 @@
*/
protected static class QuitMessage extends Message {
public static QuitMessage receive(BrowserChannel channel) {
+ channel.endReadMessage();
return new QuitMessage(channel);
}
public static void send(BrowserChannel channel) throws IOException {
final DataOutputStream stream = channel.getStreamToOtherSide();
+ channel.beginWriteMessage();
stream.writeByte(MessageType.QUIT.getId());
stream.flush();
+ channel.endWriteMessage();
}
public QuitMessage(BrowserChannel channel) {
@@ -1269,14 +1301,17 @@
*/
public static RequestIconMessage receive(BrowserChannel channel)
throws IOException {
+ channel.endReadMessage();
return new RequestIconMessage(channel);
}
public static void send(BrowserChannel channel)
throws IOException {
DataOutputStream stream = channel.getStreamToOtherSide();
+ channel.beginWriteMessage();
stream.writeByte(MessageType.REQUEST_ICON.getId());
stream.flush();
+ channel.endWriteMessage();
}
public RequestIconMessage(BrowserChannel channel) {
@@ -1298,15 +1333,18 @@
final DataInputStream stream = channel.getStreamFromOtherSide();
final boolean isException = stream.readBoolean();
final Value returnValue = channel.readValue(stream);
+ channel.endReadMessage();
return new ReturnMessage(channel, isException, returnValue);
}
public static void send(BrowserChannel channel, boolean isException,
Value returnValue) throws IOException {
final DataOutputStream stream = channel.getStreamToOtherSide();
+ channel.beginWriteMessage();
stream.writeByte(MessageType.RETURN.getId());
stream.writeBoolean(isException);
channel.writeValue(stream, returnValue);
+ channel.endWriteMessage();
stream.flush();
}
@@ -1351,6 +1389,7 @@
DataInputStream stream = channel.getStreamFromOtherSide();
String transport = readUtf8String(stream);
String transportArgs = readUtf8String(stream);
+ channel.endReadMessage();
return new SwitchTransportMessage(channel, transport, transportArgs);
}
@@ -1383,9 +1422,11 @@
@Override
public void send() throws IOException {
DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
+ getBrowserChannel().beginWriteMessage();
stream.writeByte(MessageType.SWITCH_TRANSPORT.getId());
writeUtf8String(stream, transport);
writeUtf8String(stream, transportArgs);
+ getBrowserChannel().endWriteMessage();
}
}
@@ -1406,12 +1447,14 @@
iconBytes[i] = stream.readByte();
}
}
+ channel.endReadMessage();
return new UserAgentIconMessage(channel, iconBytes);
}
public static void send(BrowserChannel channel, byte[] iconBytes)
throws IOException {
DataOutputStream stream = channel.getStreamToOtherSide();
+ channel.beginWriteMessage();
stream.writeByte(MessageType.USER_AGENT_ICON.getId());
if (iconBytes == null) {
stream.writeInt(0);
@@ -1421,6 +1464,7 @@
stream.writeByte(b);
}
}
+ channel.endWriteMessage();
stream.flush();
}
@@ -1450,14 +1494,14 @@
* The oldest protocol version supported by this code.
*/
public static final int PROTOCOL_VERSION_OLDEST = 2;
-
+
/**
* The protocol version that added the GetIcon message.
*/
public static final int PROTOCOL_VERSION_GET_ICON = 3;
public static final int SPECIAL_CLIENTMETHODS_OBJECT = 0;
-
+
public static final int SPECIAL_SERVERMETHODS_OBJECT = 0;
protected static JavaObjectRef getJavaObjectRef(int refId) {
@@ -1565,32 +1609,58 @@
private final ObjectRefFactory objectRefFactory;
- private Socket socket;
-
- private final DataInputStream streamFromOtherSide;
-
- private final DataOutputStream streamToOtherSide;
+ private DataInputStream streamFromOtherSide;
+
+ private DataOutputStream streamToOtherSide;
+
+ private SocketTransport socketTransport;
+
+ private Transport transport;
public BrowserChannel(Socket socket, ObjectRefFactory objectRefFactory)
throws IOException {
- this(new BufferedInputStream(socket.getInputStream()),
- new BufferedOutputStream(socket.getOutputStream()),
- objectRefFactory);
- this.socket = socket;
+ this(new SocketTransport(socket), objectRefFactory);
+ socketTransport = (SocketTransport) transport;
+ }
+
+ public BrowserChannel(Transport transport, ObjectRefFactory
objectRefFactory) {
+ streamFromOtherSide = new DataInputStream(transport.getInputStream());
+ streamToOtherSide = new DataOutputStream(transport.getOutputStream());
+ this.transport = transport;
+ this.objectRefFactory = objectRefFactory;
+ if (transport instanceof SocketTransport) {
+ this.socketTransport = (SocketTransport) transport;
+ }
}
protected BrowserChannel(InputStream inputStream, OutputStream
outputStream,
ObjectRefFactory objectRefFactory) {
- streamFromOtherSide = new DataInputStream(inputStream);
- streamToOtherSide = new DataOutputStream(outputStream);
- socket = null;
- this.objectRefFactory = objectRefFactory;
+ this(new DefaultTransport(inputStream, outputStream),
objectRefFactory);
+ }
+
+ public void beginReadMessage() {
+ transport.beginReadMessage();
+ }
+
+ public void beginWriteMessage() {
+ transport.beginWriteMessage();
+ }
+
+ public void endReadMessage() {
+ transport.endReadMessage();
}
public void endSession() {
Utility.close(streamFromOtherSide);
Utility.close(streamToOtherSide);
- Utility.close(socket);
+ transport.closeChannel();
+ if (socketTransport != null) {
+ socketTransport.closeChannel();
+ }
+ }
+
+ public void endWriteMessage() {
+ transport.endWriteMessage();
}
/**
@@ -1601,11 +1671,28 @@
}
public String getRemoteEndpoint() {
- if (socket == null) {
+ if (socketTransport == null) {
return "";
}
- return socket.getInetAddress().getCanonicalHostName() + ":"
- + socket.getPort();
+ return socketTransport.getRemoteEndpoint();
+ }
+
+ protected void changeTransport(Transport transport) {
+ this.transport = transport;
+ try {
+ streamToOtherSide.flush();
+ } catch (IOException e) {
+ // silently ignore
+ }
+ streamFromOtherSide = new DataInputStream(transport.getInputStream());
+ streamToOtherSide = new DataOutputStream(transport.getOutputStream());
+ }
+
+ protected void closeTransports() {
+ transport.closeChannel();
+ if (socketTransport != null) {
+ socketTransport.closeChannel();
+ }
}
protected DataInputStream getStreamFromOtherSide() {
=======================================
---
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
Fri Feb 19 06:35:15 2010
+++
/changes/jat/csproto/dev/core/src/com/google/gwt/dev/shell/BrowserChannelServer.java
Wed Mar 31 20:30:31 2010
@@ -19,6 +19,7 @@
import com.google.gwt.core.ext.TreeLogger.HelpInfo;
import
com.google.gwt.dev.shell.BrowserChannel.SessionHandler.ExceptionOrReturnValue;
import com.google.gwt.dev.shell.JsValue.DispatchObject;
+import com.google.gwt.dev.shell.TransportFactory.TransportArgs;
import java.io.IOException;
import java.io.InputStream;
@@ -268,7 +269,7 @@
public void reactToMessages(SessionHandlerServer handler) {
do {
try {
- getStreamToOtherSide().flush();
+ beginReadMessage();
MessageType messageType = Message.readMessageType(
getStreamFromOtherSide());
switch (messageType) {
@@ -312,6 +313,7 @@
do {
try {
getStreamToOtherSide().flush();
+ beginReadMessage();
MessageType messageType = Message.readMessageType(
getStreamFromOtherSide());
switch (messageType) {
@@ -451,12 +453,23 @@
// the client to stay in this channel.
if (type == MessageType.CHOOSE_TRANSPORT) {
ChooseTransportMessage chooseTransport =
ChooseTransportMessage.receive(this);
- String transport =
selectTransport(chooseTransport.getTransports());
+ TransportFactory factory = selectTransport(
+ chooseTransport.getTransports());
+ String transportName = null;
String transportArgs = null;
- if (transport != null) {
- transportArgs = createTransport(transport);
- }
- new SwitchTransportMessage(this, transport,
transportArgs).send();
+ Transport newTransport = null;
+ if (factory != null) {
+ TransportArgs args = new TransportArgs();
+ newTransport = factory.createTransport(args);
+ if (newTransport != null) {
+ transportName = factory.getName();
+ transportArgs = args.transportArgs;
+ }
+ }
+ new SwitchTransportMessage(this, transportName,
transportArgs).send();
+ if (newTransport != null) {
+ changeTransport(newTransport);
+ }
type = Message.readMessageType(getStreamFromOtherSide());
}
@@ -535,6 +548,7 @@
}
} finally {
handler.unloadModule(this, moduleName);
+ closeTransports();
}
}
@@ -631,20 +645,6 @@
break;
}
}
-
- /**
- * Create the requested transport and return the appropriate information
so
- * the client can connect to the same transport.
- *
- * @param transport transport name to create
- * @return transport-specific arguments for the client to use in
attaching
- * to this transport
- */
- private String createTransport(String transport) {
- // TODO(jat): implement support for additional transports
- throw new UnsupportedOperationException(
- "No alternate transports supported");
- }
private void handleInvokeSpecial(SessionHandlerServer handler) throws
IOException,
BrowserChannelException {
@@ -682,7 +682,7 @@
* @param transports array of supported transports
* @return null to continue in-band, or a transport type
*/
- private String selectTransport(String[] transports) {
+ private TransportFactory selectTransport(String[] transports) {
// TODO(jat): add support for shared memory, others
return null;
}
=======================================
--- /changes/jat/csproto/distro-source/build.xml Fri Oct 30 12:00:05 2009
+++ /changes/jat/csproto/distro-source/build.xml Wed Mar 31 20:30:31 2010
@@ -28,6 +28,7 @@
<!-- jni libs-->
<zipfileset dir="${gwt.build.jni}/windows"
prefix="${project.distname}" />
+ <zipfileset dir="${gwt.build.jni}/linux"
prefix="${project.distname}" />
<!-- raw files -->
<zipfileset dir="${dist.resources}" prefix="${project.distname}" />
=======================================
--- /changes/jat/csproto/jni/build.xml Fri Oct 16 07:16:57 2009
+++ /changes/jat/csproto/jni/build.xml Wed Mar 31 20:30:31 2010
@@ -5,5 +5,6 @@
<target name="build" description="Build each platforms">
<gwt.ant dir="windows" target="build"/>
+ <gwt.ant dir="linux" target="build"/>
</target>
</project>
=======================================
--- /changes/jat/csproto/jni/linux/Makefile Wed Mar 31 18:19:25 2010
+++ /changes/jat/csproto/jni/linux/Makefile Wed Mar 31 20:30:31 2010
@@ -18,8 +18,10 @@
#JAVA_HOME
#JAVA_HOME=/usr/lib/j2sdk1.5-sun
-ARCH = -m32 -march=i686
-ARCHNAME = x86
+#ARCH = -m32 -march=i686
+#ARCHNAME = x86
+ARCH = -m64
+ARCHNAME = x86_64
# set GWT_TOOLS only if it is not already defined
GWT_TOOLS ?= ../../../tools
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors
To unsubscribe, reply using "remove me" as the subject.