Recent Changes - Search:

edit SideBar

GDPJS

The GDP is no longer supported by the Accessors Framework. This page exists as a historical reference.


This page is about using the GDP with JavaScript

How to use the GDP Accessors with Node.

Installation

To use the shared libraries in the GDP JavaScript interface, you must have certain packages installed.

If you are working from the Accessor svn repository, then run:

  accessors/web/gdp/adm/gdp-setup.sh

If you installed the @terraswarm/gdp npm module, then run:

  node_modules/@terraswarm/gdp/adm/gdp-setup.sh

What works

As of 8/22/16

  • The following accessors work under Node and Cape Code:
  • A Cape Code model that reads from the GDP can generate a Composite Accessor that can be run in Node.
  • @terraswarm/gdp is a Node npm module that includes a client interface to the GDP,

See gdp/lang/js/README.md for how to update the module.

What is missing

  • More tests

Testing

The Node GDP accessor tests are based on CapeCode GDP Accessor tests, see CapeCode and the GDP

The CapeCode Code Generator is run on the CapeCode .xml tests to generate tests in accessors/gdp/test/auto/.

To run the tests,

  1. Download the accessors repository
  2. Install the @terraswarm/gdp module:
    ant terraswarm-gdp-update
  3. Install libraries necessary for the GDP (See Easier GDP Deployment: shared library issues)
    ./node_modules/@terraswarm/gdp/adm/gdp-setup.sh
  4. Run the tests:
    mocha   hosts/nod/test/testNodeOneAuto.js --Dauto=gdp/test/auto

See the individual files in accessors/gdp/test/auto/ for how to run the CapeCode models and how to run the generated code using Node.

Cape Code Example

A Cape Code Model that reads from a log. When it is run, it uses the Java/GDP interface and produces the following on stdout:

  TestDisplay: foo (Thread[GDPLogRead,1,main])

Double clicking on the Blue AccessorCodeGenerator icon and then clicking on the generator button generates the following CompositeAccessor:

exports.setup = function() {
    //  This composite accessor was created by Cape Code.
    //  To regenerate this composite accessor, run:
    //  java -classpath $PTII ptolemy.cg.kernel.generic.accessor.AccessorCodeGenerator -language accessor $PTII/ptolemy/actor/lib/jjs/modules/gdp/test/GDPLogRead.xml
    //  to edit the model, run:
    //  $PTII/bin/vergil -capecode $PTII/ptolemy/actor/lib/jjs/modules/gdp/test/GDPLogRead.xml

    // Ports: GDPLogRead: ptolemy/cg/adapter/generic/accessor/adapters/ptolemy/actor/TypedCompositeActor.java

    // Start: GDPLogRead: ptolemy/cg/adapter/generic/accessor/adapters/org/terraswarm/accessor/JSAccessor.java
    var GDPLogRead = this.instantiate('GDPLogRead', 'gdp/GDPLogRead.js');
    GDPLogRead.setParameter('logname', "GDPLogRead1");

    // Start: TestSpontaneous: ptolemy/cg/adapter/generic/accessor/adapters/org/terraswarm/accessor/JSAccessor.java
    var TestSpontaneous = this.instantiate('TestSpontaneous', 'test/TestSpontaneous.js');
    TestSpontaneous.setParameter('interval', 1000.0);

    // Start: TestDisplay: ptolemy/cg/adapter/generic/accessor/adapters/org/terraswarm/accessor/JSAccessor.java
    var TestDisplay = this.instantiate('TestDisplay', 'test/TestDisplay.js');

    // Start: JavaScriptRamp: ptolemy/cg/adapter/generic/accessor/adapters/ptolemy/actor/lib/jjs/JavaScript.java
    // FIXME: See instantiate() in accessors/web/{$HOSTS_COMMON}/commonHost.js
    // We probably need to do something with the bindings.
    var JavaScriptRamp = new Accessor('JavaScriptRamp', '/** Output a sequence with a given step in values.\n *\n *  @accessor test/TestRamp\n *  @param init The value produced on its first iteration.  The\n *  initial default is 0.\n *  @input trigger The trigger\n *  @output output The output\n *  @param step The amount by which the output is incremented. The\n *  default is 1.\n *  @author Christopher Brooks\n *  @version $$Id: GDPLogRead.xml 74960 2016-07-20 15:05:03Z cxh $$\n */\nexports.setup = function() {\n    // FIXME: this only supports numbers, unlike the Cape Code Ramp\n    // actor, which supports many types.\n    this.parameter(\'init\', {\'type\':\'number\', \'value\':0});\n    this.input(\'trigger\');\n    this.output(\'output\', {\'type\':\'number\'});\n    this.parameter(\'step\', {\'type\':\'number\', \'value\':1});\n};\n\nvar _lastValue = 0;\n\nexports.initialize = function() {\n    _lastValue = this.getParameter(\'init\');\n}\nexports.fire = function() {\n    _lastValue += this.getParameter(\'step\');\n    this.send(\'output\', _lastValue);\n};', null, null, null, null);
    JavaScriptRamp.container = this;
    this.containedAccessors.push(JavaScriptRamp);
    JavaScriptRamp.setParameter('init', 0);
    JavaScriptRamp.setParameter('step', 1);

    // Connections: GDPLogRead: ptolemy/cg/adapter/generic/accessor/adapters/ptolemy/actor/TypedCompositeActor.java
    this.connect(TestSpontaneous, 'output', GDPLogRead, 'trigger');
    this.connect(JavaScriptRamp, 'output', GDPLogRead, 'recno');
    this.connect(GDPLogRead, 'data', TestDisplay, 'input');
    this.connect(TestSpontaneous, 'output', JavaScriptRamp, 'trigger');
}

After clicking on generate, the dialog box contains:

// Starting ptolemy.cg.kernel.generic.accessor.AccessorCodeGenerator {.GDPLogRead.AccessorCodeGenerator} code generation.
Writing GDPLogRead.js in file:/Users/cxh/ptII/org/terraswarm/accessor/accessors/web/gdp/test/auto/ (3153 characters)
In "/Users/cxh/ptII/org/terraswarm/accessor/accessors/web/gdp/test/auto", about to execute:

        node
        ../../../{$HOSTS_NODE}/nodeHostInvoke.js
        -timeout
        6000
        gdp/test/auto/GDPLogRead
Reading accessor at: /Users/cxh/ptII/org/terraswarm/accessor/accessors/web/gdp/test/auto/GDPLogRead.js
Reading accessor at: /Users/cxh/ptII/org/terraswarm/accessor/accessors/web/gdp/GDPLogRead.js
Reading accessor at: /Users/cxh/ptII/org/terraswarm/accessor/accessors/web/test/TestSpontaneous.js
Reading accessor at: /Users/cxh/ptII/org/terraswarm/accessor/accessors/web/test/TestDisplay.js
Instantiated accessor GDPLogRead with class gdp/test/auto/GDPLogRead
GDPLogRead.initialize()
gdp.js: GDP()
gdpjs/index.js: gdp_gcl_open(GDPLogRead1, 1)
gdpjs/index.js: gdp_gcl_open(GDPLogRead1, 1): calling gdp_init_js()
gdpjs/index.js: gdp_gcl_open(GDPLogRead1, 1): calling gdp_gcl_open()
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f

gdpjs.js: gdpGclOpen gcliname: 32
854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f

GDPLogRead.initialize() done
// Code generation complete.
node_modules/gdp/gdp.js:read(1)
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f

Reading GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
 >>> recno 1, len 3, ts 2016-07-20T14:17:37.588347000Z
00000000 66 6f 6f
         f  o  o
exiting with status OK [67896525 = 0x40c04cd]
foo
node_modules/gdp/gdp.js:read(2)
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,  
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f

Reading GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
gdpjs.js: read_gcl_records(): do_multiread() or do_simpleread() is not ok
WARNING: end of file [EPLIB:generic:3]
node_modules/gdp/gdp.js:read(3)
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f

Reading GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
gdpjs.js: read_gcl_records(): do_multiread() or do_simpleread() is not ok
WARNING: end of file [EPLIB:generic:3]
node_modules/gdp/gdp.js:read(4)
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f

Reading GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
gdpjs.js: read_gcl_records(): do_multiread() or do_simpleread() is not ok
WARNING: end of file [EPLIB:generic:3]
node_modules/gdp/gdp.js:read(5)
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
gdpjs.js: gdp_parse_name_js(): GDPLogRead1,
854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f

Reading GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
gdpjs.js: read_gcl_records(): do_multiread() or do_simpleread() is not ok
WARNING: end of file [EPLIB:generic:3]
nodeHostInvoke.js: Timeout of 6000 ms. has occurred.
About to invoke wrapup().
All Done.
 

The key thing is that the line

  foo

appears

Cape Code GDP Model to Node

Below are the steps necessary to create a Composite Accessor that reads a GDP record

Install Cape Code and the GDP

  1. Download and install the development version of Ptolemy II, which includes the Cape Code configuration
    svn co https://repo.eecs.berkeley.edu/svn-anon/projects/eal/ptII/trunk ptII
    cd ptII
    export PTII=`pwd`
    ./configure
    ant
    (cd bin; make)
  2. Get access to the gdp git repository by requesting access from Eric.
  3. Download the GDP. Installing the GDP in $PTII/vendors/gdp/gdp is preferred. (Note that the setupAndRun.sh script downloads the gdp_router into the directory above the gdp/ directory, thus, if $PTII/vendors/gdp/gdp_router will be created):
    cd $PTII/vendors
    mkdir gdp
    cd gdp
    git clone https://repo.eecs.berkeley.edu/git/projects/swarmlab/gdp.git
  4. Build the GDP. see gdp/README.md for installing the prerequisites.
    cd gdp
    make

Start the GDP Daemons and initialize the log

  1. While in the gdp directory, download the gdp_router and start it by using the script. Note that you may be prompted for your git password, so run the script in the foreground and then put it in the background.
    bash-3.2$ ./test/setupAndRun.sh
    #### ./test/setupAndRun.sh: Running git pull in /Users/cxh/ptII/vendors/gdp/gdp_router
    fatal: unable to access 'https://repo.eecs.berkeley.edu/git/projects/swarmlab/gdp_router.git/': Could not resolve host: repo.eecs.berkeley.edu
    #### ./test/setupAndRun.sh: Removing /Users/cxh/ptII/vendors/gdp/gcls and then recreating it.
    #### ./test/setupAndRun.sh: Set up /Users/cxh/ptII/vendors/gdp/ep_adm_params
     To run with these settings from the command line, use:
        export EP_PARAM_PATH=/Users/cxh/ptII/vendors/gdp/ep_adm_params
    #### ./test/setupAndRun.sh: Starting gdp_router
    Command to start gdp_router (cd /Users/cxh/ptII/vendors/gdp/gdp_router; python ./src/gdp_router.py -l routerLog.txt) &
    #### ./test/setupAndRun.sh: Starting gdplogd
    Command to start gdplogd: /Users/cxh/ptII/vendors/gdp/gdp/gdplogd/gdplogd -F -N ealmac23.local &
    My GDP routing name = ealmac23.local
    #### Creating log gdp.runTests.28866
    Command to create a log: /Users/cxh/ptII/vendors/gdp/gdp/apps/gcl-create -k none -s ealmac23.local gdp.runTests.28866
    Created new GCL aI-qVnWLmvJXGldKDgDoeHOnLVWAYOBdqNIP7jHlewQ
            on log server ealmac23.local
    exiting with status OK
    ./test/setupAndRun.sh: called with no arguments, gdp daemons running:
    cxh             20795   0.1  0.1  2496032  22608 s003  S+    7:51AM   0:00.15 /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python ./src/gdp_router.py -l routerLog.txt
    cxh             20808   0.0  0.0  2445080    824 s003  S+    7:51AM   0:00.00 grep gdp
    cxh             20799   0.0  0.0  2459344   2104 s003  S+    7:51AM   0:00.01 /Users/cxh/ptII/vendors/gdp/gdp/gdplogd/gdplogd -F -N ealmac23.local
    ./test/setupAndRun.sh: Sleeping...
      C-c C-z
    [1]+  Stopped                 ./test/setupAndRun.sh
    bash-3.2$ bg
    [1]+ ./test/setupAndRun.sh &
    bash-3.2$
  2. While in the gdp/ directory, create the log named GDPLogRead1 (The log name is also used in the Cape Code model and the Composite Accessor)
    bash-3.2$ ./apps/gcl-create -k none -s `hostname` GDPLogRead1
    Created new GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
            on log server ealmac23.local
    exiting with status OK
    bash-3.2$
  3. Add a record to the log:
    # Add a record to the log: (:source lang=bash:)
    bash-3.2$ echo "foo" | ./apps/gdp-writer -a GDPLogRead1
    GDPname: hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8 (0 recs)

    Starting to read input
    Got input «foo»
    Asynchronous event type Asynchronous Status:
            recno 1, stat OK
    gdp-writer: exiting with status OK
    bash-3.2$
  4. For testing purposes, use the C-based binary to read from the log:
    bash-3.2$ ./apps/gdp-reader GDPLogRead1
    Reading GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
     >>> recno 1, len 3, ts 2016-07-19T15:12:19.949130000Z
    00000000 66 6f 6f
             f  o  o
    exiting after 1 records with status WARNING: end of file [EPLIB:generic:3]
    bash-3.2$

As an alternative, if you are running linux (tested on ubuntu), you can also use a docker setup (requires bridge-utils and docker) to have your own log-server and router. The advantage of this is that you can have multiple instances of log-servers/routers, and everything is contained in the docker images. For details, see:

Build the GDP/JavaScript interface

  1. Build the GDP/JavaScript interface:
    cd lang/js/gdpjs
    make

Install the GDP/JavaScript interface

The JavaScript interface to the GDP is located in gdp/lang/js. However, for Node to find it, we need to install the interface as a module named @terraswarm/gdp.

Modules may be installed either globally, which requires access to the root account, or locally. We install the module locally.

To refer to our module, the JavaScript file contains:

require('@terraswarm/gdp')

When node reads this line, it searches up the directory hierarchy for directories named node_modules/@terraswarm/gdp/.

To install the interface, we use the npm install command, which will create the node_modules directory.

  1. In the near term, we install the module from the source files in the gdp repo. For our purposes, we run npm install in $PTII so that when we run node in $PTII/org.terraswarm/accessor/accessors/web/gdp/test/auto, the $PTII/node_modules directory is found:
    cd $PTII
    npm install vendors/gdp/gdp/lang/js

Note that a number of packages will be installed.

The above will create $PTII/node_modules/@terraswarm/gdp/:

bash-3.2$ ls -l $PTII/node_modules/@terraswarm/gdp
total 40
-rw-r--r--   1 cxh  staff  2218 Jul  7 16:51 README.txt
drwxr-xr-x  12 cxh  staff   408 Jul 19 08:47 apps
drwxr-xr-x  10 cxh  staff   340 Jul 19 08:47 gdpjs
-rw-r--r--   1 cxh  staff  6801 Jul 17 19:40 index.js
drwxr-xr-x   6 cxh  staff   204 Jul 19 08:47 libs
-rw-r--r--   1 cxh  staff  4205 Jul 19 08:47 package.json
bash-3.2$

You may ignore messages like:

  npm WARN enoent ENOENT: no such file or directory, open '/Users/cxh/ptII/package.json'

If you want to get rid of those messages, create $PTII/package.json:

{
    "name": "mytest",
    "version": "6.6.6"
}

CapeCode

  1. Up until now, we have been using the C-based binaries. The next step is to use the Java interface to the GDP by running Cape Code and to then generate a Composite Accessor and invoke it using Node
  2. Start Cape Code:
    $PTII/bin/vergil -capecode $PTII/ptolemy/actor/lib/jjs/modules/gdp/test/GDPLogRead.xml
    1. Run the model.
      bash-3.2$ $PTII/bin/vergil -capecode $PTII/ptolemy/actor/lib/jjs/modules/gdp/test/GDPLogRead.xml
      Updating local copy of the accessors repository.
      In "/Users/cxh/ptII/org/terraswarm/accessor/accessors", about to execute:
          svn update --non-interactive --trust-server-cert --accept postpone
      Updating '.':
      svn: E175002: Unable to connect to a repository at URL 'https://repo.eecs.berkeley.edu/svn/projects/terraswarm/accessors/trunk/accessors'
      svn: E175002: OPTIONS of 'https://repo.eecs.berkeley.edu/svn/projects/terraswarm/accessors/trunk/accessors': Could not resolve hostname `repo.eecs.berkeley.edu': Host not found
      (https://repo.eecs.berkeley.edu)
      All Done
      Could not update the accessors repository. Using local version.
      GDPLogRead: GDPLogRead.initialize() (Thread[GDPLogRead,1,main])
      gdp_api.c gdp_parse_name(GDPLogRead1,)
      gdp_api.c gdp_parse_name(): about to run sha256
      gdp_api.c gdp_parse_name(): 854d1f3f2888dbbee867792720fbf3589d328443712231bb958cde82ff6ca4f
      gdp_api.c: gdp_gcl_open():
      gdp_api.c: gdp_gcl_open(): EP_STAT_ISOK(): Setting *pgcl (0x7f9a383b32b0) to 0x7f9a382a4130!
      GDPLogRead: GDPLogRead.initialize() done (Thread[GDPLogRead,1,main])
      TestDisplay: foo (Thread[GDPLogRead,1,main])
      TestDisplay: data was null? (Thread[GDPLogRead,1,main])
      TestDisplay: data was null? (Thread[GDPLogRead,1,main])
      TestDisplay: data was null? (Thread[GDPLogRead,1,main])
      TestDisplay: data was null? (Thread[GDPLogRead,1,main])
      WARNING: TestSpontaneous: Model stopped before executing actions (e.g. producing outputs) scheduled for execution at times [6.0]
      2052 ms. Memory: 460288K Free: 292845K (64%)
      Your output will vary, but the main thing is that the line
      TestDisplay: foo (Thread[GDPLogRead,1,main])
      appears. This indicates that the Cape Code model was able to read the string foo from the log.
    2. The next step is to create a Composite Accessor and run it using Node:
      1. Double on the AccessorCodeGenerator
      2. Click on Generate. org/terraswarm/accessor/accessors/web/gdp/test/auto/GDPLogRead.js will be created and executed. The output will include the following:
        gdp_api.c: gdp_gcl_open(): EP_STAT_ISOK(): Setting *pgcl (0x104819ea0) to 0x103a03dc0!
        >>> recno 1, len 3, ts 2016-07-19T15:12:19.949130000Z
        00000000 66 6f 6f
        f o o
        The above is generated by debugging in the C code. The output will also include:
        exiting with status OK [67896525 = 0x40c04cd]
        GDPLogRead.read() data:[object Object]
        GDPLogRead.read() done
        {"err":{"error_isok":true,"error_code":"0x40c04cd","error_msg":"exiting with status OK [67896525 = 0x40c04cd]"},"records":[{"recno":1,"timestamp":"2016-07-19T15:12:19.949130000Z","value":"foo"}]}
        The above is from the TestDisplay accessor. Note that the value foo appears at the end of the line.

Invoking a Composite Accessor using just node

When the Generate button was depressed, something similar to the following output should have appeared:

Writing GDPLogRead.js in file:/Users/cxh/ptII/org/terraswarm/accessor/accessors/web/gdp/test/auto/ (3156 characters)
In "/Users/cxh/ptII/org/terraswarm/accessor/accessors/web/gdp/test/auto", about to execute:

node
../../../{$HOSTS_NODE}/nodeHostInvoke.js
-timeout
6000
gdp/test/auto/GDPLogRead

  1. To run the Composite Accessor outside of Cape Code using Node:
    bash-3.2$ cd $PTII/org/terraswarm/accessor/accessors/web/gdp/test/auto/
    bash-3.2$ ls -l GDPLogRead.js
    -rw-r--r--  1 cxh  staff  3156 Jul 19 08:52 GDPLogRead.js
    bash-3.2$ node ../../../{$HOSTS_NODE}/nodeHostInvoke.js -timeout 16000 gdp/test/auto/GDPLogRead
    Reading accessor at: /Users/cxh/ptII/org/terraswarm/accessor/accessors/web/gdp/test/auto/GDPLogRead.js

    ...

    GDPLogRead.read() data:[object Object]
    GDPLogRead.read() done
    {"err":{"error_isok":true,"error_code":"0x40c04cd","error_msg":"exiting with status OK [67896525 = 0x40c04cd]"},"records":[{"recno":1,"timestamp":"2016-07-19T15:12:19.949130000Z","value":"foo"}]}

Troubleshooting

gdplogd and gdp_router

Use ps to check that the gdplogd and gdp_router daemons are working:

bash-3.2$ ps auxgww | grep gdp
cxh             20812   0.0  0.0  2453272    836 s003  S+    7:52AM   0:00.00 grep gdp
cxh             20799   0.0  0.0  2459344   2104 s003  S     7:51AM   0:00.01 /Users/cxh/ptII/vendors/gdp/gdp/gdplogd/gdplogd -F -N ealmac23.local
cxh             20795   0.0  0.1  2496032  22608 s003  S     7:51AM   0:00.15 /opt/local/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python ./src/gdp_router.py -l routerLog.txt
bash-3.2$

If they are not running, then rerun the gdp/test/setupAndRun.sh script

gdp-reader

Use the gdp-reader binary to read from the log, see above.

If you cannot open the GCL:

bash-3.2$ ./apps/gdp-reader GDPLogRead1
Reading GCL hU0fPyiI277oZ3knIPvzBYnTKEQ3EiMbuVjN6C_2yk8
[ERROR] gdp-reader: Cannot open GCL:
    ERROR: 600 no route available [Berkeley:Swarm-GDP:600]
exiting after 0 records with status ERROR: 600 no route available [Berkeley:Swarm-GDP:600]
bash-3.2$

then perhaps the GCL was not yet created, see the gcl-create step above

How the Node/JavaScript/GDP interface works

When node is run on a Composite Accessor:

(cd $PTII/org/terraswarm/accessor/accessors/web/gdp/test/auto/; node ../../../{$HOSTS_NODE}/nodeHostInvoke.js -timeout 6000 gdp/test/auto/GDPLogRead)            

The following occurs

  1. ../../../hosts/node/nodeHostInvoke.js refers to $PTII/org/terraswarm/accessor/accessors/web/hosts/node/nodeHostInvoke.js. That file reads GDPLogRead.js, which has
    exports.setup = function() {
    ...
        var GDPLogRead = this.instantiate('GDPLogRead', 'gdp/GDPLogRead.js');
  2. The accessor mechanism looks for the gdp/GDPLogRead.js 'accessor, which is found at accessors/web/gdp/GDPLogRead.js
  3. GDPLogRead.js requires a module:
    var GDP = require('gdp');
  4. The gdp module is found at accessors/web/hosts/node/node_modules/@accessors-modules/gdp/. In that directory, package.json states that gdp.js is the main file:
      "main": "gdp.js",
  5. accessors/web/hosts/node/node_modules/@accessors-modules/gdp/gdp.js loads the module that was installed:
    var gdpjs = require('@terraswarm/gdp');
  6. $PTII/node_modules/@terraswarm/gdp/package.json is loaded, and package.json states that index.jss is the main file:
      "main": "index.js",
  7. $PTII/node_modules/@terraswarm/gdp/index.js ends up requiring ./gdpjs/gdpjs.js, which is $PTII/node_modules/@terraswarm/gdp/gdpjs/gdpjs.js.
  8. $PTII/node_modules/@terraswarm/gdp/gdpjs/gdpjs.js defines a C-interface to the gdp

How to make a GDP function available in JavaScript

For testing purposes, it is easiest to edit the files in the $PTII/node_modules/@terraswarm/gdp/ directory, then update the corresponding files in $PTII/vendors/gdp/gdp/lang/js.

$PTII/node_modules/@terrswarm/gdp/gdpjs/gdpjs.js contains the interface between the C-based GDP API and JavaScript. In that file, there are interfaces to three shared libraries.

  • libep - Eric Allman's Enhanced Portability Library
  • libgdp - The Global Data Plane
  • libgdpjs - A few small functions that make it easier to access parts of libgdp that are written using C Macros

To access a C-based GDP API function from JavaScript, look for the method signature in gdpjs.js. If the function is not there, then look for it in gdp/gdp.h and add it to gdpjs.js. After the call to ffi.Library, export the function:

For example, if we want to access the GDP ep_dbg_set() function, then in gdpjs.js:

var libep = ffi.Library(GDP_DIR + '/libs/libep.3.0', {
...
    'ep_dbg_set': ['void', ['string']],
})
..
exports.ep_dbg_set = libep.ep_dbg_set;

The next step is to add the function to $PTII/node_modules/@terraswarm/gdp/index.js. In that file, gdpjs.js is required and then reexported:

var gdpjsSupport = require(LIBGDP_H_DIR + 'gdpjs.js');

exports.ep_dbg_init = gdpjsSupport.ep_dbg_init;
exports.ep_dbg_set = gdpjsSupport.ep_dbg_set;

Then, we update the gdp module to include the call. For the node host, the gdp module is defined in accessors/web/hosts/node/node_modules/@accessors-modules/gdp/gdp.js, which appears in the Ptolemy tree as $PTII/org/terraswarm/accessor/accessors/web/hosts/node/node_modules/@accessors-modules/gdp/gdp.js:

var gdpjs = require('@terraswarm/gdp');
...
exports.GDP.prototype.setDebugLevel = function (debugLevel) {
    gdpjs.ep_dbg_set(debugLevel)
}

TroubleShooting

Cannot Read Property

Problem:

Error: TypeError: Cannot read property 'setDebugLevel' of undefined

Solution: Make sure to instantiate the GDP object

    log = new GDP.GDP(logname, 2);

Not

    log = GDP.GDP(logname, 2);

See Also

Edit - History - Print - Recent Changes - Search
Page last modified on January 02, 2018, at 03:03 AM