From 1d300d365c91b7fdc89bb93ee4d7b4b3241c734a Mon Sep 17 00:00:00 2001
From: Georg Weiss pvAccessJava is the Java implementation of pvAccess, which is one of a
-related set of products:EPICS pvAccessJava
Release 4.0.2, 10-Nov-2014
+
Matej Sekoranja, CosyLabAbstract
+related set of products:
relatedDocumentsV4.html
Implementation of ChannelGetRequester:
The implementation above issues actual get request on success by calling
"channelGet.get()".
User can always destroy a request by calling
-"channelGet.destroy()".
+"channelGet.destroy()".
ChannelGetRequester.getDone gets called on get operation completion.
On success indicated by status parameter, pvStructure holds the latest data.
Context.
+ * Implementation of PVAJ JCA Context.
+ *
* @author Matej Sekoranja
* @version $Id$
*/
-public class ClientContextImpl implements Context/*, Configurable*/ {
+public class ClientContextImpl implements Context {
- static
- {
+ static {
// force only IPv4 sockets, since EPICS does not work right with IPv6 sockets
// see http://java.sun.com/j2se/1.5.0/docs/guide/net/properties.html
System.setProperty("java.net.preferIPv4Stack", "true");
}
-
+
/**
* Name if the provider this context provides.
*/
public static final String PROVIDER_NAME = "pva";
-
- /**
- * Version.
- */
- public static final Version VERSION = new Version(
- "pvAccess Client", "Java",
- PVAVersion.VERSION_MAJOR, PVAVersion.VERSION_MINOR,
- PVAVersion.VERSION_MAINTENANCE, PVAVersion.VERSION_DEVELOPMENT);
-
- /**
- * Server state enum.
- */
- enum State {
+
+ /**
+ * Version.
+ */
+ public static final Version VERSION = new Version("pvAccess Client", "Java", PVAVersion.VERSION_MAJOR,
+ PVAVersion.VERSION_MINOR, PVAVersion.VERSION_MAINTENANCE, PVAVersion.VERSION_DEVELOPMENT);
+
+ /**
+ * Server state enum.
+ */
+ enum State {
/**
* State value of non-initialized context.
*/
NOT_INITIALIZED,
-
+
/**
* State value of initialized context.
*/
INITIALIZED,
-
+
/**
* State value of destroyed context.
*/
DESTROYED;
- }
-
+ }
+
/**
* Initialization status.
*/
private volatile State state = State.NOT_INITIALIZED;
-
+
/**
* Context logger.
*/
protected Logger logger;
-
+
/**
* Debug level.
*/
protected int debugLevel;
/**
- * A space-separated list of broadcast address for process variable name resolution.
- * Each address must be of the form: ip.number:port or host.name:port
+ * A space-separated list of broadcast address for process variable name
+ * resolution. Each address must be of the form: ip.number:port or
+ * host.name:port
*/
protected String addressList = "";
-
+
/**
- * Define whether or not the network interfaces should be discovered at runtime.
+ * Define whether or not the network interfaces should be discovered at runtime.
*/
protected boolean autoAddressList = true;
-
+
/**
* If the context doesn't see a beacon from a server that it is connected to for
- * connectionTimeout seconds then a state-of-health message is sent to the server over TCP/IP.
- * If this state-of-health message isn't promptly replied to then the context will assume that
- * the server is no longer present on the network and disconnect.
+ * connectionTimeout seconds then a state-of-health message is sent to the
+ * server over TCP/IP. If this state-of-health message isn't promptly replied to
+ * then the context will assume that the server is no longer present on the
+ * network and disconnect.
*/
protected float connectionTimeout = 30.0f;
-
+
/**
* Period in second between two beacon signals.
*/
protected float beaconPeriod = 15.0f;
-
+
/**
* Broadcast (beacon, search) port number to listen to.
*/
protected int broadcastPort = PVAConstants.PVA_BROADCAST_PORT;
-
+
/**
* Receive buffer size (max size of payload).
*/
protected int receiveBufferSize = PVAConstants.MAX_TCP_RECV;
-
+
/**
* Timer.
*/
protected Timer timer = null;
- /**
- * Reactor.
- */
- //protected Reactor reactor = null;
-
- /**
- * Leader/followers thread pool.
- */
- //protected LeaderFollowersThreadPool leaderFollowersThreadPool = null;
-
/**
* Broadcast transport needed to listen for broadcasts.
*/
-// protected UDPTransport broadcastTransport = null;
+
protected BlockingUDPTransport broadcastTransport = null;
-
+
/**
* UDP transport needed for channel searches.
*/
-// protected UDPTransport searchTransport = null;
+
protected BlockingUDPTransport searchTransport = null;
/**
* Local multicast address.
*/
protected InetSocketAddress localBroadcastAddress = null;
-
+
/**
* PVA connector (creates PVA virtual circuit).
*/
protected BlockingTCPConnector connector = null;
-// protected TCPConnector connector = null;
/**
- * PVA transport (virtual circuit) registry.
- * This registry contains all active transports - connections to PVA servers.
+ * PVA transport (virtual circuit) registry. This registry contains all active
+ * transports - connections to PVA servers.
*/
protected TransportRegistry transportRegistry = null;
@@ -226,39 +214,35 @@ enum State {
/**
* Context instance.
*/
- private static final int LOCK_TIMEOUT = 20 * 1000; // 20s
+ private static final int LOCK_TIMEOUT = 20 * 1000; // 20s
/**
* Map of channels (keys are CIDs).
*/
- // TODO consider using WeakHashMap (and call Channel.destroy() in finalize() method).
- protected final IntHashMap channelsByCID = new IntHashMap();
-
- /**
- * Map of channels (keys are names).
- */
- // TODO consider using WeakHashMap (and call Channel.destroy() in finalize() method).
- //protected final Mapnull if non-existent.
*/
- public ChannelImpl getChannel(int channelID)
- {
- synchronized (channelsByCID)
- {
- return (ChannelImpl)channelsByCID.get(channelID);
- }
+ public ChannelImpl getChannel(int channelID) {
+
+ return (ChannelImpl) channelsByCID.get(channelID);
}
-
- /*
- * Generate unique channel string from channel name and priority.
- * @param name channel name.
- * @param priority channel priority.
- * @return unique channel string.
- *
- private final String getUniqueChannelName(String name, short priority)
- {
- // this name is illegal for PVA, so this function is unique
- return name + '\0' + priority;
- }*/
-
- /*
- * Searches for a channel with given channel name.
- * @param name channel name.
- * @param priority channel priority.
- * @param acquire whether to acquire ownership (increment ref. counting)
- * @return channel with given name, null if non-existant.
- *
- public ChannelImpl getChannel(String name, short priority, boolean acquire)
- {
- synchronized (channelsByName)
- {
- ChannelImpl channel = (ChannelImpl)channelsByName.get(getUniqueChannelName(name, priority));
- if (channel != null && acquire)
- channel.acquire();
- return channel;
- }
- }*/
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.epics.pvaccess.client.ClientContext#printInfo()
*/
public void printInfo() {
printInfo(System.out);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.epics.pvaccess.client.ClientContext#printInfo(java.io.PrintStream)
*/
- public void printInfo(PrintStream out) {
+ public void printInfo(PrintStream out) {
out.println("CLASS : " + getClass().getName());
out.println("VERSION : " + getVersion());
out.println("ADDR_LIST : " + addressList);
@@ -886,26 +683,26 @@ public void printInfo(PrintStream out) {
out.println("BEACON_PERIOD : " + beaconPeriod);
out.println("BROADCAST_PORT : " + broadcastPort);
out.println("RCV_BUFFER_SIZE : " + receiveBufferSize);
- //out.println("EVENT_DISPATCHER: " + eventDispatcher);
+ // out.println("EVENT_DISPATCHER: " + eventDispatcher);
out.print("STATE : ");
- switch (state)
- {
- case NOT_INITIALIZED:
- out.println("NOT_INITIALIZED");
- break;
- case INITIALIZED:
- out.println("INITIALIZED");
- break;
- case DESTROYED:
- out.println("DESTROYED");
- break;
- default:
- out.println("UNKNOWN");
+ switch (state) {
+ case NOT_INITIALIZED:
+ out.println("NOT_INITIALIZED");
+ break;
+ case INITIALIZED:
+ out.println("INITIALIZED");
+ break;
+ case DESTROYED:
+ out.println("DESTROYED");
+ break;
+ default:
+ out.println("UNKNOWN");
}
}
/**
* Get initialization status.
+ *
* @return initialization status.
*/
public boolean isInitialized() {
@@ -914,14 +711,16 @@ public boolean isInitialized() {
/**
* Get destruction status.
+ *
* @return destruction status.
*/
public boolean isDestroyed() {
return state == State.DESTROYED;
}
-
+
/**
* Get search address list.
+ *
* @return get search address list.
*/
public String getAddressList() {
@@ -930,6 +729,7 @@ public String getAddressList() {
/**
* Get auto search-list flag.
+ *
* @return auto search-list flag.
*/
public boolean isAutoAddressList() {
@@ -938,6 +738,7 @@ public boolean isAutoAddressList() {
/**
* Get beacon period (in seconds).
+ *
* @return beacon period (in seconds).
*/
public float getBeaconPeriod() {
@@ -946,7 +747,8 @@ public float getBeaconPeriod() {
/**
* Get connection timeout (in seconds).
- * @return connection timeout (in seconds).
+ *
+ * @return connection timeout (in seconds).
*/
public float getConnectionTimeout() {
return connectionTimeout;
@@ -954,6 +756,7 @@ public float getConnectionTimeout() {
/**
* Get logger.
+ *
* @return logger.
*/
public Logger getLogger() {
@@ -967,6 +770,7 @@ public int getDebugLevel() {
/**
* Get receive buffer size (max size of payload).
+ *
* @return receive buffer size (max size of payload).
*/
public int getReceiveBufferSize() {
@@ -975,6 +779,7 @@ public int getReceiveBufferSize() {
/**
* Get broadcast port.
+ *
* @return broadcast port.
*/
public int getBroadcastPort() {
@@ -982,14 +787,8 @@ public int getBroadcastPort() {
}
/*
- * Get event dispatcher.
- * @return event dispatcher.
- *
- public final EventDispatcher getEventDispatcher() {
- return eventDispatcher;
- }*/
-
- /* (non-Javadoc)
+ * (non-Javadoc)
+ *
* @see org.epics.pvaccess.client.ClientContext#dispose()
*/
public void dispose() {
@@ -1000,37 +799,36 @@ public void dispose() {
}
}
- // ************************************************************************** //
-
/**
* Broadcast transport.
+ *
* @return broadcast transport.
*/
- //public UDPTransport getBroadcastTransport() {
public BlockingUDPTransport getBroadcastTransport() {
return broadcastTransport;
}
/**
* Broadcast transport.
+ *
* @return broadcast transport.
*/
-// public UDPTransport getSearchTransport() {
public BlockingUDPTransport getSearchTransport() {
return searchTransport;
}
/**
* Get local multicast address (group).
+ *
* @return the address.
*/
- public InetSocketAddress getLocalMulticastAddress()
- {
+ public InetSocketAddress getLocalMulticastAddress() {
return localBroadcastAddress;
}
-
+
/**
* Get PVA transport (virtual circuit) registry.
+ *
* @return PVA transport (virtual circuit) registry.
*/
public TransportRegistry getTransportRegistry() {
@@ -1039,6 +837,7 @@ public TransportRegistry getTransportRegistry() {
/**
* Get timer.
+ *
* @return timer.
*/
public Timer getTimer() {
@@ -1052,22 +851,19 @@ public Mapnull if disabled.
- *
- public LeaderFollowersThreadPool getLeaderFollowersThreadPool() {
- return leaderFollowersThreadPool;
- }*/
-
/**
- * Called each time new server is detected.
+ * Get LF thread pool.
+ *
+ * @return LF thread pool, can be null if disabled.
+ *
+ * public LeaderFollowersThreadPool getLeaderFollowersThreadPool() {
+ * return leaderFollowersThreadPool; }
+ */
+
+ /**
+ * Called each time new server is detected.
*/
- public void newServerDetected()
- {
+ public void newServerDetected() {
if (channelSearchManager != null)
channelSearchManager.newServerDetected();
}
-
+
/**
- * Get, or create if necessary, transport of given server address.
- * Note that this method might block (creating TCP connection, verifying it).
- * @param serverAddress required transport address
- * @param priority process priority.
+ * Get, or create if necessary, transport of given server address. Note that
+ * this method might block (creating TCP connection, verifying it).
+ *
+ * @param serverAddress
+ * required transport address
+ * @param priority
+ * process priority.
* @return transport for given address
*/
- Transport getTransport(TransportClient client, InetSocketAddress serverAddress, byte minorRevision, short priority)
- {
- try
- {
+ Transport getTransport(TransportClient client, InetSocketAddress serverAddress, byte minorRevision,
+ short priority) {
+ try {
return connector.connect(client, clientResponseHandler, serverAddress, minorRevision, priority);
- }
- catch (ConnectionException cex)
- {
+ } catch (ConnectionException cex) {
logger.log(Level.SEVERE, "Failed to create transport for: " + serverAddress, cex);
}
-
+
return null;
}
-
+
/**
* Generate Client channel ID (CID).
- * @return Client channel ID (CID).
- */
- private int generateCID()
- {
- synchronized (channelsByCID)
- {
- // search first free (theoretically possible loop of death)
- while (getChannel(++lastCID) != null);
- // reserve CID
- channelsByCID.put(lastCID, null);
- return lastCID;
- }
+ *
+ * @return Client channel ID (CID).
+ */
+ private int generateCID() {
+ // reserve CID
+ channelsByCID.put(lastCID, null);
+ return lastCID;
}
/**
* Free generated channel ID (CID).
*/
- private void freeCID(int cid)
- {
- synchronized (channelsByCID)
- {
- channelsByCID.remove(cid);
- }
+ private void freeCID(int cid) {
+ channelsByCID.remove(cid);
+
}
/**
* Searches for a response request with given channel IOID.
- * @param ioid I/O ID.
+ *
+ * @param ioid
+ * I/O ID.
* @return request response with given I/O ID.
*/
- public ResponseRequest getResponseRequest(int ioid)
- {
- synchronized (pendingResponseRequests)
- {
- return (ResponseRequest)pendingResponseRequests.get(ioid);
- }
+ public ResponseRequest getResponseRequest(int ioid) {
+
+ return (ResponseRequest) pendingResponseRequests.get(ioid);
}
/**
* Register response request.
- * @param request request to register.
+ *
+ * @param request
+ * request to register.
* @return request ID (IOID).
*/
- public int registerResponseRequest(ResponseRequest request)
- {
- synchronized (pendingResponseRequests)
- {
- int ioid = generateIOID();
- pendingResponseRequests.put(ioid, request);
- return ioid;
- }
+ public int registerResponseRequest(ResponseRequest request) {
+
+ int ioid = generateIOID();
+ pendingResponseRequests.put(ioid, request);
+ return ioid;
+
}
/**
* Unregister response request.
- * @param request request to unregister.
+ *
+ * @param request
+ * request to unregister.
* @return removed object, can be null
*/
- public ResponseRequest unregisterResponseRequest(ResponseRequest request)
- {
- synchronized (pendingResponseRequests)
- {
- return (ResponseRequest)pendingResponseRequests.remove(request.getIOID());
- }
+ public ResponseRequest unregisterResponseRequest(ResponseRequest request) {
+ return (ResponseRequest) pendingResponseRequests.remove(request.getIOID());
}
/**
* Generate IOID.
- * @return IOID.
- */
- private int generateIOID()
- {
- synchronized (pendingResponseRequests)
- {
- // search first free (theoretically possible loop of death)
- while (pendingResponseRequests.get(++lastIOID) != null || lastIOID == PVAConstants.PVA_INVALID_IOID);
- // reserve IOID
- pendingResponseRequests.put(lastIOID, null);
- return lastIOID;
- }
+ *
+ * @return IOID.
+ */
+ private int generateIOID() {
+
+ // search first free (theoretically possible loop of death)
+ while (pendingResponseRequests.get(++lastIOID) != null || lastIOID == PVAConstants.PVA_INVALID_IOID)
+ ;
+ // reserve IOID
+ pendingResponseRequests.put(lastIOID, null);
+ return lastIOID;
}
/**
* Get (and if necessary create) beacon handler.
- * @param protocol protocol used.
- * @param responseFrom remote source address of received beacon.
+ *
+ * @param protocol
+ * protocol used.
+ * @param responseFrom
+ * remote source address of received beacon.
* @return beacon handler for particular server.
*/
- public BeaconHandler getBeaconHandler(String protocol, InetSocketAddress responseFrom)
- {
+ public BeaconHandler getBeaconHandler(String protocol, InetSocketAddress responseFrom) {
// TODO for now we monitor only TCP responses
if (!protocol.equals(ProtocolType.tcp.name()))
return null;
-
+
synchronized (beaconHandlers) {
- MapThis package provides support for services that are implemented as an RPC (Remote Procedure Call). PVAccess provideds two flavors of RPC: putProcessGet @@ -102,25 +102,25 @@
The rest of this document describes the following:
The client is implemented via the following interfaces and factory:
interface ServiceClientRequester extends Requester{
@@ -196,10 +196,10 @@ Client
-
+
Server
-
+
The service is implemented via the following interfaces and factory:
//RPCServer defined in org.epics.ca.server.impl.local
@@ -259,10 +259,10 @@ Server
The project provides examples in package (org.epics.pvService.example). This section describes ExampleClient and ExampleServiceFactory, which are the client @@ -402,7 +402,7 @@
Note that both records are created by extending org.epics.pvService.service. This is defined in pvService.xml.structure.service.xml:
diff --git a/pvAccessJava/src/org/epics/pvaccess/impl/remote/IntrospectionRegistry.java b/pvAccessJava/src/org/epics/pvaccess/impl/remote/IntrospectionRegistry.java index ea5acb4e3..dd2bf338f 100644 --- a/pvAccessJava/src/org/epics/pvaccess/impl/remote/IntrospectionRegistry.java +++ b/pvAccessJava/src/org/epics/pvaccess/impl/remote/IntrospectionRegistry.java @@ -15,16 +15,17 @@ package org.epics.pvaccess.impl.remote; import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; import org.epics.pvaccess.PVFactory; -import org.epics.pvaccess.util.ShortHashMap; +import org.epics.pvaccess.util.BooleanHolder; import org.epics.pvdata.pv.DeserializableControl; import org.epics.pvdata.pv.Field; import org.epics.pvdata.pv.FieldCreate; import org.epics.pvdata.pv.SerializableControl; import org.epics.pvdata.pv.Type; -import org.omg.CORBA.BooleanHolder; -import org.omg.CORBA.ShortHolder; + /** @@ -35,7 +36,8 @@ */ public final class IntrospectionRegistry { - protected ShortHashMap registry = new ShortHashMap(); + protected Mapnull if none found.
*/
- public Transport get(String type, InetSocketAddress address, short priority)
- {
+ public Transport get(String type, InetSocketAddress address, short priority) {
// TODO support type
- synchronized (transports) {
- IntHashMap priorities = transports.get(address);
- if (priorities != null)
- return (Transport)priorities.get(priority);
- else
- return null;
- }
+ Mapnull if none found.
*/
- public Transport[] get(String type, InetSocketAddress address)
- {
+ public Transport[] get(String type, InetSocketAddress address) {
// TODO support type
- synchronized (transports) {
- IntHashMap priorities = transports.get(address);
- if (priorities != null)
- {
- // TODO optimize
- Transport[] ts = new Transport[priorities.size()];
- priorities.toArray(ts);
- return ts;
- }
- else
- return null;
- }
+ Mapnull if none found.
*/
- public Transport remove(Transport transport)
- {
+ public Transport remove(Transport transport) {
// TODO support type
- //final String type = transport.getType();
final short priority = transport.getPriority();
final InetSocketAddress address = transport.getRemoteAddress();
- synchronized (transports) {
- IntHashMap priorities = transports.get(address);
- if (priorities != null) {
- transport = (Transport)priorities.remove(priority);
- if (priorities.size() == 0)
- transports.remove(address);
- if (transport != null)
- allTransports.remove(transport);
- return transport;
- }
- else
- return null;
- }
+
+ Mapnull if there is no request with such ID.
- */
- public Destroyable getRequest(int id)
- {
- synchronized (requests) {
- return (Destroyable)requests.get(id);
- }
- }
-
- public Destroyable[] getRequests()
- {
- synchronized (requests) {
- Destroyable[] reqs = new Destroyable[requests.size()];
- requests.toArray(reqs);
- return reqs;
- }
+ /**
+ * Register request
+ *
+ * @param id
+ * request ID.
+ * @param request
+ * request to be registered.
+ */
+ public void registerRequest(int id, Destroyable request) {
+ if (request == null)
+ throw new IllegalArgumentException("request == null");
+
+ requests.put(id, request);
+ }
+
+ /**
+ * Unregister request.
+ *
+ * @param id
+ * request ID.
+ */
+ public void unregisterRequest(int id) {
+
+ requests.remove(id);
+
+ }
+
+ /**
+ * Get request by its ID.
+ *
+ * @param id
+ * request ID.
+ * @return request with given ID, null if there is no request with
+ * such ID.
+ */
+ public Destroyable getRequest(int id) {
+
+ return (Destroyable) requests.get(id);
+
}
- /**
- * Destroy all registered requests.
- */
- protected void destroyAllRequests()
- {
- int[] keys;
- synchronized (requests) {
-
- // resource allocation optimization
- if (requests.size() == 0)
- return;
-
- keys = requests.keysArray();
- for (int i = 0; i < keys.length; i++) {
- final Destroyable cr = (Destroyable)requests.remove(keys[i]);
- cr.destroy();
- }
+ public Destroyable[] getRequests() {
+
+ Destroyable[] reqs = new Destroyable[requests.size()];
+ requests.values().toArray(reqs);
+ return reqs;
+
+ }
+
+ /**
+ * Destroy all registered requests.
+ */
+ protected void destroyAllRequests() {
+ Integer[] keys;
+
+ // resource allocation optimization
+ if (requests.size() == 0)
+ return;
+
+ keys = new Integer[requests.keySet().size()];
+ requests.keySet().toArray(keys);
+ for (int i = 0; i < keys.length; i++) {
+ final Destroyable cr = (Destroyable) requests.remove(keys[i]);
+ cr.destroy();
}
-
- }
- /* (non-Javadoc)
+ }
+
+ /*
+ * (non-Javadoc)
+ *
* @see org.epics.pvaccess.server.impl.remote.ServerChannel#destroy()
- */
- public synchronized void destroy()
- {
+ */
+ public synchronized void destroy() {
if (destroyed)
return;
destroyed = true;
-
+
// destroy all requests
destroyAllRequests();
- try
- {
+ try {
channelSecuritySession.close();
} catch (Throwable th) {
// guard from bad plug-on
// TODO
th.printStackTrace();
}
-
+
// TODO make impl that does shares channels (and does ref counting)!!!
// try catch?
channel.destroy();
}
- /**
- * Prints detailed information about the process variable to the standard output stream.
- * @throws IllegalStateException if the context has been destroyed.
- */
- public void printInfo() throws IllegalStateException
- {
- printInfo(System.out);
- }
-
- /**
- * Prints detailed information about the process variable to the specified output
- * stream.
- * @param out the output stream.
- * @throws IllegalStateException if the context has been destroyed.
- */
- public void printInfo(PrintStream out)
- {
- out.println("CLASS : " + getClass().getName());
- out.println("CHANNEL : " + channel);
- //out.println("RIGHTS : " + AccessRights.getEnumSet(getAccessRights()));
- }
+ /**
+ * Prints detailed information about the process variable to the standard output
+ * stream.
+ *
+ * @throws IllegalStateException
+ * if the context has been destroyed.
+ */
+ public void printInfo() throws IllegalStateException {
+ printInfo(System.out);
+ }
+ /**
+ * Prints detailed information about the process variable to the specified
+ * output stream.
+ *
+ * @param out
+ * the output stream.
+ * @throws IllegalStateException
+ * if the context has been destroyed.
+ */
+ public void printInfo(PrintStream out) {
+ out.println("CLASS : " + getClass().getName());
+ out.println("CHANNEL : " + channel);
+ }
}
-
-
diff --git a/pvAccessJava/src/org/epics/pvaccess/server/impl/remote/tcp/BlockingServerTCPTransport.java b/pvAccessJava/src/org/epics/pvaccess/server/impl/remote/tcp/BlockingServerTCPTransport.java
index 8a9c7597c..8dcf1f0e4 100644
--- a/pvAccessJava/src/org/epics/pvaccess/server/impl/remote/tcp/BlockingServerTCPTransport.java
+++ b/pvAccessJava/src/org/epics/pvaccess/server/impl/remote/tcp/BlockingServerTCPTransport.java
@@ -20,6 +20,8 @@
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
@@ -39,7 +41,6 @@
import org.epics.pvaccess.plugins.SecurityPlugin;
import org.epics.pvaccess.plugins.SecurityPlugin.SecurityPluginControl;
import org.epics.pvaccess.plugins.SecurityPlugin.SecuritySession;
-import org.epics.pvaccess.util.IntHashMap;
import org.epics.pvdata.factory.StatusFactory;
import org.epics.pvdata.misc.SerializeHelper;
import org.epics.pvdata.pv.PVField;
@@ -48,45 +49,50 @@
/**
* Server TCP transport implementation.
+ *
* @author Matej Sekoranja
* @version $Id$
*/
public class BlockingServerTCPTransport extends BlockingTCPTransport
- implements ChannelHostingTransport, TransportSender, SecurityPluginControl {
+ implements ChannelHostingTransport, TransportSender, SecurityPluginControl {
/**
- * Last SID cache.
+ * Last SID cache.
*/
private AtomicInteger lastChannelSID = new AtomicInteger(0);
/**
* Channel table (SID -> channel mapping).
*/
- private IntHashMap channels;
+ private Mapnull otherwise
*/
- public ServerChannel getChannel(int sid)
- {
- synchronized (channels) {
- return (ServerChannel)channels.get(sid);
- }
+ public ServerChannel getChannel(int sid) {
+
+ return channels.get(sid);
+
}
@Override
- public ServerChannel[] getChannels()
- {
- synchronized (channels) {
- ServerChannel[] sca = new ServerChannel[channels.size()];
- channels.toArray(sca);
- return sca;
- }
+ public ServerChannel[] getChannels() {
+
+ ServerChannel[] sca = new ServerChannel[channels.size()];
+ channels.values().toArray(sca);
+ return sca;
+
}
/**
* Get channel count.
+ *
* @return channel count.
*/
- public int getChannelCount()
- {
- synchronized (channels) {
- return channels.size();
- }
+ public int getChannelCount() {
+ return channels.size();
+
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.epics.pvaccess.impl.remote.TransportSender#lock()
*/
@Override
@@ -217,7 +204,9 @@ public void lock() {
// noop
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.epics.pvaccess.impl.remote.TransportSender#unlock()
*/
@Override
@@ -227,119 +216,122 @@ public void unlock() {
// always called from the same thread, therefore no sync needed
private boolean verifyOrVerified = false;
-
+
/**
- * PVA connection validation request.
- * A server sends a validate connection message when it receives a new connection.
- * The message indicates that the server is ready to receive requests; the client must
- * not send any messages on the connection until it has received the validate connection message
- * from the server. No reply to the message is expected by the server.
- * The purpose of the validate connection message is two-fold:
- * It informs the client of the protocol version supported by the server.
- * It prevents the client from writing a request message to its local transport
- * buffers until after the server has acknowledged that it can actually process the
- * request. This avoids a race condition caused by the server's TCP/IP stack
- * accepting connections in its backlog while the server is in the process of shutting down:
- * if the client were to send a request in this situation, the request
- * would be lost but the client could not safely re-issue the request because that
- * might violate at-most-once semantics.
- * The validate connection message guarantees that a server is not in the middle
- * of shutting down when the server's TCP/IP stack accepts an incoming connection
- * and so avoids the race condition.
- * @see org.epics.pvaccess.impl.remote.TransportSender#send(java.nio.ByteBuffer, org.epics.pvaccess.impl.remote.TransportSendControl)
+ * PVA connection validation request. A server sends a validate connection
+ * message when it receives a new connection. The message indicates that the
+ * server is ready to receive requests; the client must not send any messages on
+ * the connection until it has received the validate connection message from the
+ * server. No reply to the message is expected by the server. The purpose of the
+ * validate connection message is two-fold: It informs the client of the
+ * protocol version supported by the server. It prevents the client from writing
+ * a request message to its local transport buffers until after the server has
+ * acknowledged that it can actually process the request. This avoids a race
+ * condition caused by the server's TCP/IP stack accepting connections in its
+ * backlog while the server is in the process of shutting down: if the client
+ * were to send a request in this situation, the request would be lost but the
+ * client could not safely re-issue the request because that might violate
+ * at-most-once semantics. The validate connection message guarantees that a
+ * server is not in the middle of shutting down when the server's TCP/IP stack
+ * accepts an incoming connection and so avoids the race condition.
+ *
+ * @see org.epics.pvaccess.impl.remote.TransportSender#send(java.nio.ByteBuffer,
+ * org.epics.pvaccess.impl.remote.TransportSendControl)
*/
@Override
public void send(ByteBuffer buffer, TransportSendControl control) {
- if (!verifyOrVerified)
- {
+ if (!verifyOrVerified) {
verifyOrVerified = true;
-
+
//
- // set byte order control message
+ // set byte order control message
//
-
+
ensureBuffer(PVAConstants.PVA_MESSAGE_HEADER_SIZE);
sendBuffer.put(PVAConstants.PVA_MAGIC);
sendBuffer.put(PVAConstants.PVA_VERSION);
- sendBuffer.put((byte)0xc1); // control + server + big endian
- sendBuffer.put((byte)2); // set byte order
- sendBuffer.putInt(0);
-
-
+ sendBuffer.put((byte) 0xc1); // control + server + big endian
+ sendBuffer.put((byte) 2); // set byte order
+ sendBuffer.putInt(0);
+
//
// send verification message
//
-
- control.startMessage((byte)1, 4+2);
-
+
+ control.startMessage((byte) 1, 4 + 2);
+
// receive buffer size
buffer.putInt(getReceiveBufferSize());
-
+
// server introspection registry max size
// TODO
buffer.putShort(Short.MAX_VALUE);
-
+
// list of authNZ plugin names
Mapfalse.
+ */
+ public BooleanHolder() {
+ }
+
+ /**
+ * Instantiates an object of this class.
+ * @param value The initial value.
+ */
+ public BooleanHolder(boolean value) {
+ this.value = value;
+ }
+}
diff --git a/pvAccessJava/src/org/epics/pvaccess/util/IntHashMap.java b/pvAccessJava/src/org/epics/pvaccess/util/IntHashMap.java
deleted file mode 100644
index 29a5d501c..000000000
--- a/pvAccessJava/src/org/epics/pvaccess/util/IntHashMap.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (c) 2004 by Cosylab
- *
- * The full license specifying the redistribution, modification, usage and other
- * rights and obligations is included with the distribution of this project in
- * the file "LICENSE-CAJ". If the license is not included visit Cosylab web site,
- * A hash map that uses primitive ints for the key instead of objects. Also Entry objects are reusable.
- * NOTE: this implementatio is not synced, client has to care of that. - * - *This implemenation is based on original java implementation.
- * @author Matej Sekoranja - * @version $Id$ - * @see java.util.HashMap - */ -public class IntHashMap { - - /** - * The hash table data. - */ - private transient Entry table[]; - - /** - * The total number of entries in the hash table. - */ - private transient int count; - - /** - * The table is rehashed when its size exceeds this threshold. (The - * value of this field is (int)(capacity * loadFactor).) - * - * @serial - */ - private int threshold; - - /** - * The load factor for the hashtable. - * - * @serial - */ - private float loadFactor; - - /** - * Entry object pool. - * - */ - private transient EntryObjectPool pool; - - /** - *Innerclass that acts as a datastructure to create a new entry in the - * table.
- */ - private static class Entry { - int hash; - int key; - Object value; - Entry next; - - /** - *Create a new entry with the given values.
- * - * @param hash The code used to hash the object with - * @param key The key used to enter this in the table - * @param value The value for this key - * @param next A reference to the next entry in the table - */ - protected Entry(int hash, int key, Object value, Entry next) { - initialize(hash, key, value, next); - } - - /** - *Set given values.
- * - * @param hash The code used to hash the object with - * @param key The key used to enter this in the table - * @param value The value for this key - * @param next A reference to the next entry in the table - */ - public void initialize(int hash, int key, Object value, Entry next) { - this.hash = hash; - this.key = key; - this.value = value; - this.next = next; - } - - } - - /** - *Object pool implemenation for Entry class.
- */ - // TODO timed clean-up - private static class EntryObjectPool { - - /** - * Pool of reusable objects. - */ - private ArrayListEntry object from the object pool.
- *
- * @param hash The code used to hash the object with
- * @param key The key used to enter this in the table
- * @param value The value for this key
- * @param next A reference to the next entry in the table
- * @return Entry instance.
- */
- public Entry getEntry(int hash, int key, Object value, Entry next) {
- if (lastPos == -1) {
- return new Entry(hash, key, value, next);
- }
- else {
- Entry entry = pool.remove(lastPos--);
- entry.initialize(hash, key, value, next);
- return entry;
- }
- }
-
- /**
- * Put (return) Entry object to the object pool.
- * @param entry entry to put.
- */
- public void putEntry(Entry entry) {
- // NOTE: be sure that entry.value and entry.next are null
- pool.add(entry);
- lastPos++;
- }
- }
-
- /**
- * Constructs a new, empty hashtable with a default capacity and load
- * factor, which is 20 and 0.75 respectively.
Constructs a new, empty hashtable with the specified initial capacity
- * and default load factor, which is 0.75.
Constructs a new, empty hashtable with the specified initial - * capacity and the specified load factor.
- * - * @param initialCapacity the initial capacity of the hashtable. - * @param loadFactor the load factor of the hashtable. - * @throws IllegalArgumentException if the initial capacity is less - * than zero, or if the load factor is nonpositive. - */ - public IntHashMap(int initialCapacity, float loadFactor) { - super(); - if (initialCapacity < 0) { - throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); - } - if (loadFactor <= 0) { - throw new IllegalArgumentException("Illegal Load: " + loadFactor); - } - if (initialCapacity == 0) { - initialCapacity = 1; - } - - this.loadFactor = loadFactor; - table = new Entry[initialCapacity]; - threshold = (int) (initialCapacity * loadFactor); - - pool = new EntryObjectPool(initialCapacity); - } - - /** - *Returns the number of keys in this hashtable.
- * - * @return the number of keys in this hashtable. - */ - public int size() { - return count; - } - - /** - *Tests if this hashtable maps no keys to values.
- * - * @returntrue if this hashtable maps no keys to values;
- * false otherwise.
- */
- public boolean isEmpty() {
- return count == 0;
- }
-
- /**
- * Tests if some key maps into the specified value in this hashtable.
- * This operation is more expensive than the containsKey
- * method.
Note that this method is identical in functionality to containsValue, - * (which is part of the Map interface in the collections framework).
- * - * @param value a value to search for. - * @returntrue if and only if some key maps to the
- * value argument in this hashtable as
- * determined by the equals method;
- * false otherwise.
- * @throws NullPointerException if the value is null.
- * @see #containsKey(int)
- * @see #containsValue(Object)
- * @see java.util.Map
- */
- public boolean contains(Object value) {
- if (value == null) {
- throw new NullPointerException();
- }
-
- Entry tab[] = table;
- for (int i = tab.length; i-- > 0;) {
- for (Entry e = tab[i]; e != null; e = e.next) {
- if (e.value.equals(value)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Tests if some key maps into the specified value in this hashtable.
- * This operation is more expensive than the containsKey
- * method.
Note that this method is identical in functionality to containsValue, - * (which is part of the Map interface in the collections framework).
- * - * This method also returns key (usingkey as aka by-reference parameter);
- * key is only valid if method returns true.
- *
- * @param value a value to search for.
- * @param key will contain key fo an object, if the method returs true.
- * @return true if and only if some key maps to the
- * value argument in this hashtable as
- * determined by the equals method;
- * false otherwise.
- * @throws NullPointerException if the value is null.
- * @see #containsKey(int)
- * @see #containsValue(Object)
- * @see java.util.Map
- */
- public boolean contains(Object value, IntHolder key) {
- if (value == null) {
- throw new NullPointerException();
- }
-
- Entry tab[] = table;
- for (int i = tab.length; i-- > 0;) {
- for (Entry e = tab[i]; e != null; e = e.next) {
- if (e.value.equals(value)) {
- key.value = e.key;
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns true if this HashMap maps one or more keys
- * to this value.
Note that this method is identical in functionality to contains - * (which predates the Map interface).
- * - * @param value value whose presence in this HashMap is to be tested. - * @return booleantrue if the value is contained
- * @see java.util.Map
- * @since JDK1.2
- */
- public boolean containsValue(Object value) {
- return contains(value);
- }
-
- /**
- * Tests if the specified object is a key in this hashtable.
- * - * @param key possible key. - * @returntrue if and only if the specified object is a
- * key in this hashtable, as determined by the equals
- * method; false otherwise.
- * @see #contains(Object)
- */
- public boolean containsKey(int key) {
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index]; e != null; e = e.next) {
- if (e.hash == hash) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the value to which the specified key is mapped in this map.
- * - * @param key a key in the hashtable. - * @return the value to which the key is mapped in this hashtable; - *null if the key is not mapped to any value in
- * this hashtable.
- * @see #put(int, Object)
- */
- public Object get(int key) {
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index]; e != null; e = e.next) {
- if (e.hash == hash) {
- return e.value;
- }
- }
- return null;
- }
-
- /**
- * Increases the capacity of and internally reorganizes this - * hashtable, in order to accommodate and access its entries more - * efficiently.
- * - *This method is called automatically when the number of keys - * in the hashtable exceeds this hashtable's capacity and load - * factor.
- */ - protected void rehash() { - int oldCapacity = table.length; - Entry oldMap[] = table; - - int newCapacity = oldCapacity * 2 + 1; - Entry newMap[] = new Entry[newCapacity]; - - threshold = (int) (newCapacity * loadFactor); - table = newMap; - - for (int i = oldCapacity; i-- > 0;) { - for (Entry old = oldMap[i]; old != null;) { - Entry e = old; - old = old.next; - - int index = (e.hash & 0x7FFFFFFF) % newCapacity; - e.next = newMap[index]; - newMap[index] = e; - } - } - } - - /** - *Maps the specified key to the specified
- * value in this hashtable. The key cannot be
- * null.
The value can be retrieved by calling the get method
- * with a key that is equal to the original key.
null if it did not have one.
- * @throws NullPointerException if the key is null.
- * @see #get(int)
- */
- public Object put(int key, Object value) {
- // Makes sure the key is not already in the hashtable.
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index]; e != null; e = e.next) {
- if (e.hash == hash) {
- Object old = e.value;
- e.value = value;
- return old;
- }
- }
-
- if (count >= threshold) {
- // Rehash the table if the threshold is exceeded
- rehash();
-
- tab = table;
- index = (hash & 0x7FFFFFFF) % tab.length;
- }
-
- // Creates the new entry.
- //Entry e = new Entry(hash, key, value, tab[index]);
- Entry e = pool.getEntry(hash, key, value, tab[index]);
- tab[index] = e;
- count++;
- return null;
- }
-
- /**
- * Removes the key (and its corresponding value) from this - * hashtable.
- * - *This method does nothing if the key is not present in the - * hashtable.
- * - * @param key the key that needs to be removed. - * @return the value to which the key had been mapped in this hashtable, - * ornull if the key did not have a mapping.
- */
- public Object remove(int key) {
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
- if (e.hash == hash) {
- if (prev != null) {
- prev.next = e.next;
- } else {
- tab[index] = e.next;
- }
- count--;
- Object oldValue = e.value;
- e.value = null;
-
- e.next = null;
- pool.putEntry(e);
-
- return oldValue;
- }
- }
- return null;
- }
-
- /**
- * Clears this hashtable so that it contains no keys.
- */ - public void clear() { - Entry tab[] = table; - for (int index = tab.length; --index >= 0;) { - - Entry e = tab[index]; - if (e != null) { - e.value = null; - e.next = null; - pool.putEntry(e); - } - - tab[index] = null; - } - count = 0; - } - - /** - *Copies values to array. Note that array capacity has to be large enough.
- * @param arr array to be filled, new instance returned if given not large enough ornull.
- * @return array of values.
- */
- public Object[] toArray(Object[] arr) {
- if (arr == null || arr.length < count) {
- arr = new Object[count];
- }
-
- int pos = 0;
- Entry tab[] = table;
- for (int i = tab.length; i-- > 0;)
- for (Entry e = tab[i]; e != null; e = e.next)
- arr[pos++] = e.value;
-
- return arr;
- }
-
- /**
- * Copies keys to array.
- * @return array of keys. - */ - public int[] keysArray() { - int pos = 0; - Entry tab[] = table; - int[] keys = new int[count]; - for (int i = tab.length; i-- > 0;) - for (Entry e = tab[i]; e != null; e = e.next) - keys[pos++] = e.key; - - return keys; - } -} diff --git a/pvAccessJava/src/org/epics/pvaccess/util/ShortHashMap.java b/pvAccessJava/src/org/epics/pvaccess/util/ShortHashMap.java deleted file mode 100644 index 9addde646..000000000 --- a/pvAccessJava/src/org/epics/pvaccess/util/ShortHashMap.java +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (c) 2004 by Cosylab - * - * The full license specifying the redistribution, modification, usage and other - * rights and obligations is included with the distribution of this project in - * the file "LICENSE-CAJ". If the license is not included visit Cosylab web site, - *A hash map that uses primitive ints for the key instead of objects. Also Entry objects are reusable.
- * NOTE: this implementatio is not synced, client has to care of that. - * - *This implemenation is based on original java implementation.
- * @author Matej Sekoranja - * @version $Id$ - * @see java.util.HashMap - */ -public class ShortHashMap { - - /** - * The hash table data. - */ - private transient Entry table[]; - - /** - * The total number of entries in the hash table. - */ - private transient int count; - - /** - * The table is rehashed when its size exceeds this threshold. (The - * value of this field is (int)(capacity * loadFactor).) - * - * @serial - */ - private int threshold; - - /** - * The load factor for the hashtable. - * - * @serial - */ - private float loadFactor; - - /** - * Entry object pool. - * - */ - private transient EntryObjectPool pool; - - /** - *Innerclass that acts as a datastructure to create a new entry in the - * table.
- */ - private static class Entry { - int hash; - short key; - Object value; - Entry next; - - /** - *Create a new entry with the given values.
- * - * @param hash The code used to hash the object with - * @param key The key used to enter this in the table - * @param value The value for this key - * @param next A reference to the next entry in the table - */ - protected Entry(int hash, short key, Object value, Entry next) { - initialize(hash, key, value, next); - } - - /** - *Set given values.
- * - * @param hash The code used to hash the object with - * @param key The key used to enter this in the table - * @param value The value for this key - * @param next A reference to the next entry in the table - */ - public void initialize(int hash, short key, Object value, Entry next) { - this.hash = hash; - this.key = key; - this.value = value; - this.next = next; - } - - } - - /** - *Object pool implemenation for Entry class.
- */ - // TODO timed clean-up - private static class EntryObjectPool { - - /** - * Pool of reusable objects. - */ - private ArrayListEntry object from the object pool.
- *
- * @param hash The code used to hash the object with
- * @param key The key used to enter this in the table
- * @param value The value for this key
- * @param next A reference to the next entry in the table
- * @return Entry instance.
- */
- public Entry getEntry(int hash, short key, Object value, Entry next) {
- if (lastPos == -1) {
- return new Entry(hash, key, value, next);
- }
- else {
- Entry entry = pool.remove(lastPos--);
- entry.initialize(hash, key, value, next);
- return entry;
- }
- }
-
- /**
- * Put (return) Entry object to the object pool.
- * @param entry entry to put.
- */
- public void putEntry(Entry entry) {
- // NOTE: be sure that entry.value and entry.next are null
- pool.add(entry);
- lastPos++;
- }
- }
-
- /**
- * Constructs a new, empty hashtable with a default capacity and load
- * factor, which is 20 and 0.75 respectively.
Constructs a new, empty hashtable with the specified initial capacity
- * and default load factor, which is 0.75.
Constructs a new, empty hashtable with the specified initial - * capacity and the specified load factor.
- * - * @param initialCapacity the initial capacity of the hashtable. - * @param loadFactor the load factor of the hashtable. - * @throws IllegalArgumentException if the initial capacity is less - * than zero, or if the load factor is nonpositive. - */ - public ShortHashMap(int initialCapacity, float loadFactor) { - super(); - if (initialCapacity < 0) { - throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity); - } - if (loadFactor <= 0) { - throw new IllegalArgumentException("Illegal Load: " + loadFactor); - } - if (initialCapacity == 0) { - initialCapacity = 1; - } - - this.loadFactor = loadFactor; - table = new Entry[initialCapacity]; - threshold = (int) (initialCapacity * loadFactor); - - pool = new EntryObjectPool(initialCapacity); - } - - /** - *Returns the number of keys in this hashtable.
- * - * @return the number of keys in this hashtable. - */ - public int size() { - return count; - } - - /** - *Tests if this hashtable maps no keys to values.
- * - * @returntrue if this hashtable maps no keys to values;
- * false otherwise.
- */
- public boolean isEmpty() {
- return count == 0;
- }
-
- /**
- * Tests if some key maps into the specified value in this hashtable.
- * This operation is more expensive than the containsKey
- * method.
Note that this method is identical in functionality to containsValue, - * (which is part of the Map interface in the collections framework).
- * - * @param value a value to search for. - * @returntrue if and only if some key maps to the
- * value argument in this hashtable as
- * determined by the equals method;
- * false otherwise.
- * @throws NullPointerException if the value is null.
- * @see #containsValue(Object)
- * @see java.util.Map
- */
- public boolean contains(Object value) {
- if (value == null) {
- throw new NullPointerException();
- }
-
- Entry tab[] = table;
- for (int i = tab.length; i-- > 0;) {
- for (Entry e = tab[i]; e != null; e = e.next) {
- if (e.value.equals(value)) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Tests if some key maps into the specified value in this hashtable.
- * This operation is more expensive than the containsKey
- * method.
Note that this method is identical in functionality to containsValue, - * (which is part of the Map interface in the collections framework).
- * - * This method also returns key (usingkey as aka by-reference parameter);
- * key is only valid if method returns true.
- *
- * @param value a value to search for.
- * @param key contains objet key, if the method returns true.
- * @return true if and only if some key maps to the
- * value argument in this hashtable as
- * determined by the equals method;
- * false otherwise.
- * @throws NullPointerException if the value is null.
- * @see #containsValue(Object)
- * @see java.util.Map
- */
- public boolean contains(Object value, ShortHolder key) {
- if (value == null) {
- throw new NullPointerException();
- }
-
- Entry tab[] = table;
- for (int i = tab.length; i-- > 0;) {
- for (Entry e = tab[i]; e != null; e = e.next) {
- if (e.value.equals(value)) {
- key.value = e.key;
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns true if this HashMap maps one or more keys
- * to this value.
Note that this method is identical in functionality to contains - * (which predates the Map interface).
- * - * @param value value whose presence in this HashMap is to be tested. - * @return booleantrue if the value is contained
- * @see java.util.Map
- * @since JDK1.2
- */
- public boolean containsValue(Object value) {
- return contains(value);
- }
-
- /**
- * Tests if the specified object is a key in this hashtable.
- * - * @param key possible key. - * @returntrue if and only if the specified object is a
- * key in this hashtable, as determined by the equals
- * method; false otherwise.
- * @see #contains(Object)
- */
- public boolean containsKey(short key) {
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index]; e != null; e = e.next) {
- if (e.hash == hash) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the value to which the specified key is mapped in this map.
- * - * @param key a key in the hashtable. - * @return the value to which the key is mapped in this hashtable; - *null if the key is not mapped to any value in
- * this hashtable.
- */
- public Object get(short key) {
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index]; e != null; e = e.next) {
- if (e.hash == hash) {
- return e.value;
- }
- }
- return null;
- }
-
- /**
- * Increases the capacity of and internally reorganizes this - * hashtable, in order to accommodate and access its entries more - * efficiently.
- * - *This method is called automatically when the number of keys - * in the hashtable exceeds this hashtable's capacity and load - * factor.
- */ - protected void rehash() { - int oldCapacity = table.length; - Entry oldMap[] = table; - - int newCapacity = oldCapacity * 2 + 1; - Entry newMap[] = new Entry[newCapacity]; - - threshold = (int) (newCapacity * loadFactor); - table = newMap; - - for (int i = oldCapacity; i-- > 0;) { - for (Entry old = oldMap[i]; old != null;) { - Entry e = old; - old = old.next; - - int index = (e.hash & 0x7FFFFFFF) % newCapacity; - e.next = newMap[index]; - newMap[index] = e; - } - } - } - - /** - *Maps the specified key to the specified
- * value in this hashtable. The key cannot be
- * null.
The value can be retrieved by calling the get method
- * with a key that is equal to the original key.
null if it did not have one.
- * @throws NullPointerException if the key is null.
- */
- public Object put(short key, Object value) {
- // Makes sure the key is not already in the hashtable.
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index]; e != null; e = e.next) {
- if (e.hash == hash) {
- Object old = e.value;
- e.value = value;
- return old;
- }
- }
-
- if (count >= threshold) {
- // Rehash the table if the threshold is exceeded
- rehash();
-
- tab = table;
- index = (hash & 0x7FFFFFFF) % tab.length;
- }
-
- // Creates the new entry.
- //Entry e = new Entry(hash, key, value, tab[index]);
- Entry e = pool.getEntry(hash, key, value, tab[index]);
- tab[index] = e;
- count++;
- return null;
- }
-
- /**
- * Removes the key (and its corresponding value) from this - * hashtable.
- * - *This method does nothing if the key is not present in the - * hashtable.
- * - * @param key the key that needs to be removed. - * @return the value to which the key had been mapped in this hashtable, - * ornull if the key did not have a mapping.
- */
- public Object remove(short key) {
- Entry tab[] = table;
- int hash = key;
- int index = (hash & 0x7FFFFFFF) % tab.length;
- for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
- if (e.hash == hash) {
- if (prev != null) {
- prev.next = e.next;
- } else {
- tab[index] = e.next;
- }
- count--;
- Object oldValue = e.value;
- e.value = null;
-
- e.next = null;
- pool.putEntry(e);
-
- return oldValue;
- }
- }
- return null;
- }
-
- /**
- * Clears this hashtable so that it contains no keys.
- */ - public void clear() { - Entry tab[] = table; - for (int index = tab.length; --index >= 0;) { - - Entry e = tab[index]; - if (e != null) { - e.value = null; - e.next = null; - pool.putEntry(e); - } - - tab[index] = null; - } - count = 0; - } - - /** - *Copies values to array. Note that array capacity has to be large enough.
- * @param arr array to be filled, new instance returned if given not large enough ornull.
- * @return array of values.
- */
- public Object[] toArray(Object[] arr) {
- if (arr == null || arr.length < count) {
- arr = new Object[count];
- }
-
- int pos = 0;
- Entry tab[] = table;
- for (int i = tab.length; i-- > 0;)
- for (Entry e = tab[i]; e != null; e = e.next)
- arr[pos++] = e.value;
-
- return arr;
- }
-
-}
diff --git a/pvAccessJava/test/org/epics/pvaccess/impl/remote/test/IRSerializationTest.java b/pvAccessJava/test/org/epics/pvaccess/impl/remote/test/IRSerializationTest.java
index 55be3a62f..86ee5a0dc 100644
--- a/pvAccessJava/test/org/epics/pvaccess/impl/remote/test/IRSerializationTest.java
+++ b/pvAccessJava/test/org/epics/pvaccess/impl/remote/test/IRSerializationTest.java
@@ -11,12 +11,18 @@
import org.epics.pvaccess.PVFactory;
import org.epics.pvaccess.impl.remote.IntrospectionRegistry;
+import org.epics.pvaccess.util.BooleanHolder;
+import org.epics.pvdata.factory.FieldFactory;
import org.epics.pvdata.pv.DeserializableControl;
import org.epics.pvdata.pv.Field;
import org.epics.pvdata.pv.PVField;
import org.epics.pvdata.pv.PVStructure;
+import org.epics.pvdata.pv.ScalarType;
import org.epics.pvdata.pv.SerializableControl;
+import static org.junit.Assert.*;
+
+
/**
* JUnit test for IR supported serialization.
* @author mse
@@ -105,4 +111,20 @@ public void testDecode()
System.out.println(pvField);
}
+ public void testRegisterIntrospectionInterface() {
+
+ IntrospectionRegistry introspectionRegistry =
+ new IntrospectionRegistry();
+
+ Field field1 = FieldFactory.getFieldCreate().createScalar(ScalarType.pvDouble);
+
+ BooleanHolder existing = new BooleanHolder(true);
+
+ short key = introspectionRegistry.registerIntrospectionInterface(field1, existing);
+
+ assertEquals(1, key);
+ assertFalse(existing.value);
+
+ }
+
}
diff --git a/pvDataJava/documentation/pvDataJava.html b/pvDataJava/documentation/pvDataJava.html
index 8ddbb9318..c82b61a0d 100644
--- a/pvDataJava/documentation/pvDataJava.html
+++ b/pvDataJava/documentation/pvDataJava.html
@@ -45,15 +45,15 @@ This product is made available subject to acceptance of the EPICS open source license.
-pvDataJava is a computer software package for the efficient +
pvDataJava is a computer software package for the efficient
storage, access, and communication, of structured data. It is specifically the
Java implementation of pvData, which is one part of the set of related products in the EPICS
-V4 control system programming environment:
+V4 control system programming environment:
relatedDocumentsV4.html
Field instance via cache.Field instance via cache.
interface DeserializableControl {
@@ -652,12 +652,12 @@ Serializable
Field instance via cache.Field instance via cache.
interface SerializableArray extends Serializable {
void serialize(ByteBuffer buffer, SerializableControl flusher, int offset, int count);
-}
+}
where
Field has an ID and a type. It can be converted to a string.
+ Field has an ID and a type. It can be converted to a string.
The format is the metadata format
described in the overview.FieldCreate.
+
interface Field extends Serializable {
String getID();
Type getType();
void toString(StringBuilder buf));
void toString(StringBuilder buf,int indentLevel);
String toString();
-}
+}
where
UnionArray with the specified introspection interface.UnionArray of variant union elements.Structure. There are two methods.
@@ -961,9 +961,9 @@ endNested.
interface StatusCreate {
- Status getStatusOK();
+ Status getStatusOK();
Status createStatus(StatusType type, String message, Throwable cause);
Status deserializeStatus(ByteBuffer buffer, DeserializableControl control);
}
@@ -1092,15 +1091,15 @@ Requester
where
PVField prepends the full field name
to the message and calls PVRecord.message. The default implementation
for PVRecord either displays the message on stdout or stderr or gives
@@ -1174,7 +1173,7 @@ PVStructure.PostHandler is registered it is called otherwise no action is
- taken.postPut when a field is changed. However this is not true
for a subField of a PVUnion, PVUnionArray, or PVStructureArray.
@@ -1414,7 +1413,7 @@ shareData results in the PVArray using the primitive array that is passed to
this method. This is most useful for immutable arrays. In this case the caller
-must set the PVArray to be immutable. If the PVArray is not immutable then
+must set the PVArray to be immutable. If the PVArray is not immutable then
the application is responsibility for coordinating access to the array.
This violates the principle that objects should not expose their internal data but
is important for immutable arrays. For example pvData defines
@@ -1653,12 +1652,12 @@
PVField is created reusing the Field interface. Two methods are
@@ -1736,14 +1735,14 @@ PVArrays that satisfy one of the following.
+ PVArrays that satisfy one of the following.
Create a structure.
-+FieldCreate fieldCreate = FieldFactory.getFieldCreate(); PVDataCreate pvDataCreate = PVDataFactory.getPVDataCreate(); @@ -2172,7 +2171,7 @@Standard Properties
class Control {
Control();
double getLow();
@@ -2856,8 +2855,8 @@ BitSetUtil
currently has only one method:
BitSet related to a structure.BitSet related to a structure.@@ -3157,10 +3156,10 @@timer
This provides a general purpose timer. It provides the following features not provided by
java.util.Timerandjava.util.TimerTask:-
- Priority
+- Priority
-
The java.util implementation does not allow the user to specify the priority of the timer thread. This implementation does.- TimerNode
+- TimerNode
@@ -3387,7 +3386,7 @@
A java.util.TimerTask is not reusable. Once aTimerTaskhas been canceled or a delayTimerTaskhas run, theTimerTaskcan not be reused. Instead a newTimerTaskmust be created. ATimerNodecan be reused.src/copy
It is provided with this project because the code depends only on pvData itself. -copy provides the ability to create a structure that has +
copy provides the ability to create a structure that has a copy of an arbitrary subset of the fields in an existing top level structure. In addition it allows global options and field specific options. It has two main components: createRequest and pvCopy. @@ -3410,10 +3409,10 @@
src/copy
- createRequest
- The Channel create methods in pvAccess all have an argument - PVStructure pvRequest.
+ PVStructure pvRequest.
Given an ascii string createRequest creates a PVStructure that provides a pvData representation of the information from the ascii string. - It is this structure that can be passed to the channel create methods.
+ It is this structure that can be passed to the channel create methods.
The information in a pvRequest selects an arbitrary subset of the fields in a top level structure that resides in the server. In addition options can be specified. Both global and field specific @@ -3424,7 +3423,7 @@src/copy
It provides client specific code that manages a copy of an arbitrary subset of the fields in a top level structure that resides in the provider. It also allows provider access to options specified - by the client.
+ by the client.
pvCopy also provides filter plugin support.
This is mainly used by pvAccess clients. Given a request string it creates a pvRequest structure that can be passed to the pvAccess create methods. -In turn pvAccess passes the pvRequest to a local channel provider which +In turn pvAccess passes the pvRequest to a local channel provider which then passes it to pvCopy.
The definition of the public members is:
@@ -3503,13 +3502,13 @@pvMaster to the value
of the corresponding field in copyPVStructure.
-
+
PVStructure is
+ If options were specified, the returnedPVStructure is
a structure with a set of PVString subfields that specify name,value
pairs. name is the subField name and value is the subField value.