//
// RemoteClusterDataImpl.java
//

/*
VisAD system for interactive analysis and visualization of numerical
data.  Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

/* Cluster Design Ideas

Everything is via RMI - no 'local' Impl

a Data object is partitioned if any Field in it has a
partitioned domain

interfaces:
  Thing
    Data
      RemoteData (extends Remote, Data, RemoteThing)
        RemoteClusterData
          RemoteClientData
            RemoteClientTuple (extends RemoteTupleIface)
            RemoteClientField (extends RemoteField)
            RemoteClientPartitionedField (extends RemoteField)
          RemoteNodeData
            RemoteNodeTuple (extends RemoteTupleIface)
            RemoteNodeField (extends RemoteField)
            RemoteNodePartitionedField (extends RemoteField)

classes:
  UnicastRemoteObject
    RemoteThingImpl
      RemoteDataImpl
        RemoteClusterDataImpl
          RemoteClientDataImpl
            RemoteClientTupleImpl
            RemoteClientFieldImpl
            RemoteClientPartitionedFieldImpl
          RemoteNodeDataImpl
            RemoteNodeTupleImpl
            RemoteNodeFieldImpl
            RemoteNodePartitionedFieldImpl


RemoteClientPartitionedFieldImpl.getDomainSet() return UnionSet
of getDomainSet() returns from each node

add TupleIface extends Data (Tuple implements TupleIface)
and RemoteTupleIface extends TupleIface

a non-partitioned Data object is local on the client
  that is, a DataImpl

a partitioned Data object is a RemoteClientDataImpl on the
cient connected to RemodeNodeDataImpl's on the nodes

NodeAgent, Serializable class sent from client to each node
gets a Thread on arrival at node, return value from send of
NodeAgent is RemoteAgentContact (and Impl)
values from NodeAgent back declared Serializable

  abstract class NodeAgent implements Serializable, Runnable
    void sendToClient(Serializable message)
      invokes RemoteClientAgent.sendToClient(message)
    RemoteAgentContactImpl getRemoteAgentContact()
  interface RemoteAgentContact extends Remote
  class RemoteAgentContactImpl implements RemoteAgentContact
  interface RemoteClientAgent extends Remote
    void sendToClient(Serializable message)
  abstract class RemoteClientAgentImpl implements RemoteClientAgent
  class DefaultNodeRendererAgent extends NodeAgent
    void run()

  interface RemoteNodeData
    RemoteAgentContact sendAgent(NodeAgent agent)

  NodeRendererJ3D(NodeAgent agent)
  NodeRendererJ3D.doTransform()
    invokes agent.sendToClient(VisADGroup branch)


see page 60 of Java Enterprise in a Nutshell
no easy way to load RMI classes - security issues


partitioned data on client has similar data trees on
client and nodes
  leaf node on client is:
    DataImpl
    Field with partitioned domain (RemoteClientPartitionedFieldImpl)
  non-leaf node on client is:
    Tuple (RemoteClientTupleImpl)
    Field with non-partitioned domain (RemoteClientFieldImpl)
  leaf tree-nodes on cluster-node is:
    Field with partitioned domain
      (RemoteNodePartitionedFieldImpl adapting FlatField)
  non-leaf tree-nodes on cluster-node is:
    Tuple (RemoteNodeTupleImpl)
    Field with non-partitioned domain (RemoteNodeFieldImpl)
    Field with partitioned domain
      (RemoteNodePartitionedFieldImpl adapting FieldImpl)

every object in data tree on client connects to objects
in data trees on nodes

may use DisplayImplJ3D on nodes for graphics, with api = TRANSFORM_ONLY
  and DisplayRenderer = NodeDisplayRendererJ3D (extends
  TransformOnlyDisplayRendererJ3D) doesn't render to screen
uses special DisplayImplJ3D constructor signature (conflict?)
  for cluster - modified version of collaborative Display

NodeRendererJ3D extends DefaultRendererJ3D, with
ShadowNode*TypeJ3D - addToGroup() etc to leave as Serializable
  note must replace 'Image image' in VisADAppearance
ClientRendererJ3D extends DefaultRendererJ3D, not even using
ShadowTypes, but assembling VisADSceneGraphs from nodes




may also need way for client to signal implicit resolution
reduction to nodes - custom DataRenderers with custon ShadowTypes
whose doTransforms resample down, then call super.doTransform()
with downsampled data


Control field in ScalarMap is marked transient and dglo9.txt
says it should be.  But can use the getSaveString() and
setSaveString() methods of Control to transmit Control states.


cluster design should include a native VisAD Data Model on
binary files, via serialization, for an implementation of
FileFlatField on nodes

also need to support FileFlatFields

*/

/*
  DisplayImpl.syncRemoteData()
    . . .
    if (!cluster) waitForTasks(); // WLH 11 April 2001

only needed for testing client and nodes in same JVM
BUT, dglo should make this waitForTasks() more precise
*/
/*
possible deadlock in ThreadPool, if all running ActionImpls
are waiting for other ActionImpls to run
*/

/* VisAD Data Model on various file formats

Data instance method for write
Data static method for read
a parameter to these methods is a file-format-specific
implementation of a FileIO interface, that is used for
low level I/O (should deal with missing data in
file-format-specific way)

other interfaces for constructing appropriate file-format-
specific structures for Tuple, Field, FlatField, Set, Real,
Text, RealTuple, CoordinateSystem, Unit, ErrorEstimate

get review from Steve on this

*/


package visad.cluster;

import visad.*;
import java.rmi.*;

/**
   RemoteClusterDataImpl is the super class for cluster
   client and node Data.

*/ public abstract class RemoteClusterDataImpl extends RemoteDataImpl implements RemoteClusterData { /** Set that defines partition of Data across cluster; values in partitionSet's domain RealTupleType are partitioned according to: jvmTable[partitionSet.valueToIndex()] */ private Set partitionSet = null; /** domain dimension of partitionSet */ private int dimension = -1; /** lookup table for RemoteClusterData objects on nodes, last entry is on client (for non-distributed data) */ private RemoteClusterData[] jvmTable = null; /** used for testing equality */ private RemoteClusterData me = null; public RemoteClusterDataImpl() throws RemoteException { super(null); // RemoteDataImpl.AdaptedData = // RemoteThingImpl.AdaptedThing = null // but adapt a ThingImpl and a RemoteThingImpl // used for over-riding RemoteThingImpl methods adaptedThingImpl = new ThingImpl(); adaptedRemoteThingImpl = new RemoteThingImpl(adaptedThingImpl); me = this; } RemoteClusterData[] getTable() { return jvmTable; } /** return RemoteClusterData for JVM where data resides; may be RemoteClusterData for client for non-partitioned data; may be null for partitioned data outside partitoning */ public RemoteClusterData getClusterData(RealTuple domain) throws RemoteException, VisADException { if (domain == null || partitionSet == null || jvmTable == null) { throw new ClusterException("null domain or setup not done"); } if (dimension != domain.getDimension()) { // return client (last entry) for non-partitoned data return jvmTable[jvmTable.length - 1]; } // "eval" partitionSet at domain // first extract values from domain double[][] vals = new double[dimension][1]; for (int i=0; i table.length) { throw new ClusterException("table.length (" + table.length +") must " + " >= ps.length + 1 (" + (ps.getLength() + 1) + ")"); } partitionSet = ps; dimension = ps.getDimension(); } else { partitionSet = null; dimension = -1; } jvmTable = table; } public Set getPartitionSet() { return partitionSet; } public boolean clusterDataEquals(RemoteClusterData cd) throws RemoteException { return (cd == me); // seems to work - but does it really? } /** parent logic, looosely copied from DataImpl */ private RemoteClusterDataImpl parent = null; public void setParent(RemoteClusterDataImpl p) { parent = p; } public void notifyReferences() throws VisADException, RemoteException { adaptedThingImpl.notifyReferences(); // recursively propogate data change to parent if (parent != null) parent.notifyReferences(); } /** over-ride methods of RemoteThingImpl, but note these are for notifyReferences(), which currently does nothing for RemoteThingImpl */ private ThingImpl adaptedThingImpl = null; // adaptedRemoteThingImpl constructed from adaptedThingImpl private RemoteThingImpl adaptedRemoteThingImpl = null; public void addReference(ThingReference r) throws VisADException { adaptedRemoteThingImpl.addReference(r); } public void removeReference(ThingReference r) throws VisADException { adaptedRemoteThingImpl.removeReference(r); } public DataImpl local() throws VisADException, RemoteException { throw new ClusterException("no local() method for cluster data"); } /* MUST OVER-RIDE methods that acccess AdaptedThing and AdaptedData from RemoteThingImpl: public void addReference(ThingReference r) throws VisADException; public void removeReference(ThingReference r) throws VisADException; from RemoteDataImpl: public DataImpl local() throws VisADException, RemoteException; public MathType getType() throws VisADException, RemoteException; public boolean isMissing() throws VisADException, RemoteException; public Data binary(Data data, int op, int sampling_mode, int error_mode) throws VisADException, RemoteException; public Data binary(Data data, int op, MathType new_type, int sampling_mode, int error_mode ) throws VisADException, RemoteException; public Data unary(int op, int sampling_mode, int error_mode) throws VisADException, RemoteException; public Data unary(int op, MathType new_type, int sampling_mode, int error_mode) throws VisADException, RemoteException; public double[][] computeRanges(RealType[] reals) throws VisADException, RemoteException; public DataShadow computeRanges(ShadowType type, int n) throws VisADException, RemoteException; public DataShadow computeRanges(ShadowType type, DataShadow shadow) throws VisADException, RemoteException; public Data adjustSamplingError(Data error, int error_mode) throws VisADException, RemoteException; public String longString() throws VisADException, RemoteException; public String longString(String pre) throws VisADException, RemoteException; END MUST OVER-RIDE */ public static void main(String[] args) throws RemoteException, VisADException { Real r = new Real(0); RemoteClientTupleImpl cd = new RemoteClientTupleImpl(new Data[] {r}); RemoteClientTupleImpl cd2 = new RemoteClientTupleImpl(new Data[] {r}); System.out.println(cd.equals(cd)); // true System.out.println(cd.equals(cd2)); // false System.out.println(cd.clusterDataEquals(cd)); // true System.out.println(cd.clusterDataEquals(cd2)); // false System.exit(0); } }

Ads help maintain this website.