Actor Framework Documents

cancel
Showing results for 
Search instead for 
Did you mean: 

Linked Network Actor

Linked Network Actor uses network streams to create a peer-to-peer link between two already-launched actors. This link is a short circuit of the usual Actor communication tree.  In the intended use case, the actors reside in separate application instances, such as a host application running on a desktop computer and a target application running on a real-time system.  Linked Network Actor is suitable for both continuous and intermittent connections, such as a host which periodically connects to its RT target for monitoring.

To use this class, launch the two actors you wish to link and have each of them launch a nested actor of this class.  Decide which of your actors will initiate the connection, and have it send the Connect message to its Linked Network Actor. Either actor can send the Disconnect message to break the connection.  Linked Network Actor sends an Update Status Message to its caller whenever its connection status changes.  This is an abstract message; the caller is expected to provide a concrete implementation when first launching the Linked Network Actor.

Use Transmit Network Message to send messages between the linked actors.  Create the message you wish to send, and use accessor methods to set its attributes.  Wire this message to the message input of Send Transmit Network Message.  The local Linked Network Actor will send the message to the remote Linked Network Actor, which will then forward it to its caller. Note that sending a Transmit Network Message to a Linked Network Actor that is not connected will result in an error.

The package will be installed in <user.lib>\Actors\Linked Network Actor. An example VI, Linked Network Actor Test.vi, will be installed in the folder <LabVIEW>\examples\Actors\Linked Network Actor.

This version of Linked Network Actor does not cover all use cases.  Specifically:

  1. Reply Messages will not work across the network.
  2. Self-Addressed Messages will not work across the network.
  3. When either nested actor receives the Stop message, it calls Destroy Stream Endpoint on both its writer and reader streams, with no opportunity to obtain any messages that might still be in the stream. Any such messages will be lost.
  4. Because of 3, above, Drop Msg Core.vi will not work as expected. Drop Msg Core.vi will never be called on messages that are still in the network buffer.

Future versions of this actor may address these issues.

This is an EXPERIMENTAL_FORK compatible with AF 4.0.

Edit:  Updated to version 1.01.

Edit 9/27/13:  Updated to version 1.2.

1)  This version corrects a problem that occurs if a target running a Linked Network Actor is rebooted or otherwise disrupted while the Linked Network Actor is connected to a remote Linked Network Actor.  In this situation, the remote Linked Network Actor would persist in a connected state.  The next attempt to connect to the remote Linked Network Actor would fail, and the local Linked Network Actor would stop and return a timeout error.  The attempt would, however, reset the remote Linked Network Actor, and subsequent attempts to connect would succeed.

This version changes the error handling behavior of the Linked Network Actor.  The Linked Network Actor will now report timeout errors (Error -314004) without terminating.  This allows the caller to attempt to retry the connection without having to restart the Linked Network Actor.

The LNA will also report, without terminating, if the endpoint to which you wish to connect does not exist (Error -314100), or already exists (-314101).

2)  At the request of users, we have also changed the name of the abstract message "Update Status Msg" to "LNA Connection Status Msg".  This should make the abstract message easier to find when building concrete implementations, and shoudl avoid name conflicts with future actors.

3)  Certain methods in this version of the Linked Network Actor have been given community scope.  If you wish to use this version to communicate with CompactRIO and other VxWorks targets, you must install the LabVIEW 2012 Real-Time Module f1 patch, available free from National Instruments.

4)  If you try to send a message to a remote LNA, and the transmission generates an error, the local LNA will return the transmitted message and the associated error to its caller, using the abstract message "LNA Return Message Msg."  This return message will have high priority.  This will not create an error condition locally, so the LNA will not shut down.

Update by niACS (8/24/15):  I've had a fair number of requests to create a version of the LNA that uses TCP/IP.  As I was looking into the best way to do that, I realized that I needed to change the architecture of the LNA.  I've been applying the Single Responsibility Principle to the LNA, breaking it up into protocol, message pipe management, and connection management components.  I've implemented the first two components here:

  Network Endpoint Actors

The last piece, connection management, requires different solutions depending on your problem statement.  There is definitely a role for the single connection, always available object that is the LNA.  My plan is to implement such a solution that is based on Network Endpoint Actors.  Watch this space.

Comments
Active Participant Elijah_K
Active Participant

Thanks for sharing this Allen.  I spent time this weekend trying to use this to turn my measurement system into a distributed applicaiton, where a central controller could coordinate exectuon of measurements on remote systems.  I got it working, but I have a few questions:

1) One of my use cases is to have N 'clients' connect to a single server.  To do this, the server has two LNAs - one is just always listening for a connection from a new client (call it the ServerListener), which employs a known name - the other has a unique instance for every client connection that is made (call it ClientProxy).  As soon as a new client connects to the ServerListener using the known ID it spins up a new instance of ClientProxy with a unique ID, sends that ID to the client, who immediately disconnects from ServerListener and establishes a new connection with the ClientProxy.  Is this the best way to do N:1 network communication?  Would anyone recommend a different/better approach?  One obvious limitation is that no other client can connect while ServerListener is negotiating the new connection, but the entire process occurs seemingly instantaneously, so I don't see this as a big problem.  Thoughts?

2) I got the process described above working.  To test it, I spin up N clients and have them all try to connect.  This appears to work beautifully 99% of the time.  If I hit the server with 20+ simultaneous connection requests, it will occassionally 'crash.'  I still can't figure out why, but it appears that the ServerListener LNA becomes un-stoppable even though it does execute the stop core method.  I've been pulling my hair out trying to debug this scenario, but initial digging indicates that there is a blocking dequeue in the network streams API that does not employ a timeout that appears to be stuck.   Anyway, I don't expect anyone to solve this problem for me, but here's my question: has anyone else tested a large number of simultaneous client connection requests coming in to a single LNA?  I want to make sure that I'm using this in a way that is expected and known to work.  Assuming it is, I will continue to operate under the assumptiont that it is a bug/race condition in my code.  Thoughts?

Elijah Kerry
Chief Product Manager, Software Platform
_______________________________________________
Follow my Software Engineering for LabVIEW Blog
Proven Zealot
Proven Zealot

Regarding question #1: This use case is better solved -- I *think* -- with the nested network actor. I could be wrong, but I built the other style because my instinct is that the nested network actor will turn out to be easier to manage overall for this kind of dynamic distributed case. Hasn't been tried by anyone yet -- I haven't had time to explore fully -- so please give it a whirl if you have time.

I don't have anything to add to question #2.

Member Ben_Phillips
Member

I'm confused by the way these two packages install.

1.0 installs to \LabVIEW 2012\user.lib\Actors\Linked Network Actor

1.2 installs to \LabVIEW 2012\vi.lib\NI\Actors\Linked Network Actor

They're also named differently in the package manager.

If I install just 1.2, there's a missing VI in Handle Error called "Send Error Report" when I add the library to a project. 

I'm guessing maybe that's because I have AF 4.1.1.33 main fork installed, as this document states it's compatible with AF 4.0?  I have nothing in all of LV2012 folder called 'send error report'.  It's looking in the standard vi.lib actor framework folder for it.

(apologies if this should have been a separate thread)

Member lewboi
Member

I came across these issues too....

Member davidpcl
Member

Just a quick comment to say that this is absolutely fantastic!

The last actor project I did (have done 3 in total) required the development of a bolt on TCP/IP server as the actor was developed as a windows service and that worked really well, but have been looking for a more elegant way of connecting actors together across a network as will need it for a project I have just started working on which will have actors distributed across 3 pxi racks. I did start developing my own, but this has totally nullified my requirement for doing so - up and running with minimal effort, easy to understand - simply brilliant.

On another note, part of the proposal/idea for this project has been to use various actors as sub-panels in a top level GUI - have used this method before with no issues, but has anyone attempted to decouple a GUI across a network using LNA? I'm fairly sure using LNA that it would be possible, but can also see that for the extra work that will be required it may be the case that it is easier to replicate the remote actors GUI on the top level GUI.

David Clark
CLA | CTA
CLA Design Ltd
Hampshire, England
Active Participant Elijah_K
Active Participant

For the record, I addressed both of the issues I outlined in my earlier comment - the latest version of the Measurement Utility takes full advantage of the LNA and it works beautifully and reliably!  Well done Allen!!!

Elijah Kerry
Chief Product Manager, Software Platform
_______________________________________________
Follow my Software Engineering for LabVIEW Blog
Active Participant justACS
Active Participant

HI Ben,

Use revision 1.2.  The recommendation from the LV Tools Network is for companies to insall their add-on components in a company folder in vi.lib, and 1.2 conforms to that standard.

You can find the Report Error message here:  https://decibel.ni.com/content/docs/DOC-23418.  Or just install AF 4.2, which includes that message.

Active Participant justACS
Active Participant

Thanks, David!  It's always nice to hear that my stuff is making a difference.

Yes, you can use the LNA as you have described - that was the intended use case for the LNA.  You will want to pay attention to your class couplings to avoid issues with locking your classes.  Take a look at the AF on cRIO example, here:  https://decibel.ni.com/content/docs/DOC-24187#comment-25139

Member CodePeasant
Member

Allen,The cRIO project requires LNA Update Status Msg.  After installing the LNA 1.2 the Update Status Msg class is missing.  Is Write Status Msg Msg.lvclass the replacement for Update Status Msg? Apologies, this should be on the other page's comments.  Use LNA 1.0 for cRIO example. Or change inheritence from Update Status Msg to LNA Connection Status Message like Allen tells us to do in the first place, duh me.

Member Brett_J_Anderson
Member

Working great with one issue. I have multiple network cards on the host PC and each are on different domains(192.xxx.xxx.xxx & 169.xxx.xxx.xxx). When I connect to an Actor on a remote PC the Connect.vi sends the first IP address found(using the built in function String to IP) , which is not neccessarily the one I want. This causes the remote Actor to try to create an writer endpoint to the wrong IP address. I can edit the Connect.vi to make sure it sends the correct IP address. Any other solutions or suggestions?

Active Participant CaseyLamers1 Active Participant
Active Participant

You can change the order in your network settings to have the correct one first. I believe that the default action is to send the IP address of the first active network. I came upon this problem when my wireless adapter was the first item on the list and the cRIO couldn't establish a connection to that IP when I really wanted it to use the wired adpter.

In Windows 7 you open the Network and Sharing Center. Press the Alt Key and choose Advanced Settings under the Advanced menu item. Change the order that connections are accessed by network services in the top list. ie, put the adapter you want the LNA to use at the top of the list.

Casey Lamers


Phoenix, LLC


casey.lamers@phoenixwi.com


CLA, LabVIEW Champion


Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!

Active Participant cirrusio
Active Participant

niACS - Can you imagine doing something similar with shared variables rather than network streams?

Active Participant justACS
Active Participant

I can, and it's not pretty.

Shared variables are great for what they are, but they are a poor choice for streaming commands.  Among my complaints:

1)  Fixed buffer size.  Don't get behind on reading messages, or you'll lose them.

2)  Even when I keep up, I seem to lose buffered changes anyway.

3)  Fixed message size.  Awesome until you need to send objects of variable size, like arrays or strings.

4)  You need LabVIEW DSC to do proper event-driven shared variable notifications.  Otherwise, you are reduced to polling, which is risky with shared variables.  Now, I actually like DSC, but you can't use it on every project, so that's out.

5)  They can't be secured, and they are likely to be blocked by your IT department.

I like shared variables for status updates, though I note that I'm almost the only person in Systems Engineering who feels that way.  But they are a really poor choice for non-lossy communication.  Save yourself a lot of pain and stick to network streams or TCP/IP.

Active Participant MattP
Active Participant

I'm the other guy in SEwho likes NPSVs for lossy status updates.  Except for a quick and dirty hack to get something working in five minutes (with the explicit knowledge that I'm incurring software debt I'll need to repay later to refactor them out), I never use them for anything else other than the lossy status update case.

Cheers,

Matt Pollock
National Instruments
Active Participant cirrusio
Active Participant

How interesting.  I guess I don't tend to "stream" data over a network - most of my communication is of the polling type so the lossy nature of SVs have never struck me as a hindrance (I tend to use them for irregular UI interactions and returning data at fairly slow intervals).  But, I guess I can see the possible issues, but for the life of me I have never had an instance where I thought that streaming data at high rates across a network has been necessary (other than for debugging)....

But, getting to my point regarding the LNA (and this may be a dupe another post that seems to have gone stale, but since I seem to have a wider audience...) - do you consider network streams (or for that matter tcp/ip) necessary for communicating between two different applications instances on the same target (I am thinking web services here) or might there be a tidier approach that doesn't require the use of protocols designed for moving data between machines?

Active Participant justACS
Active Participant

It's not an issue of speed, it's an issue of reliable delivery.  Even buffered, shared variables are lossy, which means you are taking a risk of losing a message at a critical time.  Yes, at the kind of speeds we associate with UI interactions, that risk is low.  But why take that chance at all, when there are better mechanisms?

Same machine interprocess is not going to be fundamentally different than distributed interprocess; the available mechanisms don't change (unless you want to do something with reflective memory or the file system).  You're looking at VI Server, web services, network streams, TCP/IP, or network shared variables.  Personally, I'd stick with network streams or TCP, because they aren't lossy.  Web services aren't lossy (and are quite good and easy to use), but they are inherently command/response.  I write a lot of actors (AF and queued message handlers), so I tend to prefer announcement-based systems.

Active Participant cirrusio
Active Participant

Yes, I understand that issue, but my systems are generally embedded and the UI usually serves to be just one giant status message anyway so it is not generally an issue.  But, that is likely another discussion.

Regarding the second paragraph - this gets more to my point.  Is the LNA overkill though for a same-machine interprocess?  Let's say you have a system running a web service through which an external client will be communicating with the target (where your Actor based system is running) - would the LNA be the best approach to handle communication between the web services and the application proper or could you envision something that might be more light weight?

Active Participant justACS
Active Participant

mtat76 wrote:


                       

Yes, I understand that issue, but my systems are generally embedded and the UI usually serves to be just one giant status message anyway so it is not generally an issue.  But, that is likely another discussion.

That's actually my primary use case for shared variables.  I hate running a bunch of status traffic through my messaging channels. But as you say, that's another discussion.

Regarding the second paragraph - this gets more to my point.  Is the LNA overkill though for a same-machine interprocess?  Let's say you have a system running a web service through which an external client will be communicating with the target (where your Actor based system is running) - would the LNA be the best approach to handle communication between the web services and the application proper or could you envision something that might be more light weight?


                   

Parsing this carefully, I have to ask this question:  Are you talking about traffic within an application that has a web service and a set of actors, or between two applications?

If the web service is a part of your application, then you can get access to your top level actor's queue, and pass messages normally.

Between applications, it depends on your traffic level.  If it's the occasional message, you can get away with setting up a web service to receive actor messages that have been flattened to string, and then unflatten pass those messages on to your system.  It's a little clumsy, but very lightweight, especially if you need the web service for some other reason (security, multiple language support, etc.).

If you don't need the web service, though, or if you anticipate a lot of user interaction, or have a lot of user subpanels connecting to different parts of the system, I'd go with a set of LNAs.

Member Ben_Phillips
Member

mtat76 wrote:


                       

Is the LNA overkill though for a same-machine interprocess? 


                   

I ended up using it to great success in just that, after evaluating other technologies that can also allow inter-process comm on the same machine.  All the other ways seemed super heavyweight or complicated.  It was good ol' networking in the end, and LNA built on top of that was ideal.  I end up spawning as many as 35 LNA pairs just communicating on 'localhost', all of which are exchanging data and status messages, and it works great.

(I admit I had my doubts about Network Streams being able to deal with all that without a collision, but I was pleasantly proven wrong.)

Once the connection is set up, it's rather lightweight in terms of the code it has to execute.  It definitely adds some code of your own to get them set up just so.  But IMO for a program where you are adding and removing N external processes that you need to communicate with, there's nothing better that I know of.

Member ngblume
Member

Hey,

simple question:

When I try to run the example, I'm encountering an Error 314004..

Given your explanation before, this seems to be timeout related.

I entered various IPs (see attachment 2), but no luck (127.0.0.1, 192.168.2.100 [my IP]).

The solution is probably rather simple, but could you point me in the right direction (just getting started with AF)...

Thanks !!

Error_LNA.PNG

Error_LNA_2.PNG

Member rik_aspinall
Member

It seems hard to debug actors when the issue involves more than one. I was wondering about using wireshark, or perhaps creating a listening only actor, to eavesdrop on all the messages an LNA generates, in order to get a who did what when type log. Has anyone done anything like this, or has insight to share?

Active Participant justACS
Active Participant

Rik, if you check out the community source version of Actor Framework, you'll find that it supports a debug mode that generates user traces you can see in the Desktop Execution Trace Toolkit.  You'll get a trace every time an actor is created or destroyed, or a message is sent or received.

You'll have to sign up for the community source project.  Go here for more information:

You activate trace generation by adding the tag "AF_Debug_Trace" to the project's list of conditional disable symbols, and setting its value to True.

Member Ludwig72
Member

Since the Reply Msg.lvclass is not working with linked network actors - how can I wait for a reply message? Is there any way to realize it?

Proven Zealot
Proven Zealot

Open up the Reply Msg class and take a look at how it works... in Send, it creates a temporary queue and adds that to the data being sent. Then it tries to Dequeue. That makes it wait until the Do.vi puts data into the queue.

You'll need to mimic that code for a network connection -- something that blocks until data is available or that you can poll until data is available. One solution would be to pick a new port number and send the port number to the remote machine, then open a second Network Stream connection on that new port and try to read from it. The remote machine would open a Network Stream to that new port and would send data back to you using that. You then close the Network Stream -- or maybe you don't if you can come up with a clever way to cache the Network Stream so you can reusue it, but that's a really hard problem to solve for various reasons, so I would just kill the stream and recreate it for the next temporary.

You will need a pool of available port numbers if you expect to have multiple linked network actors in the same system... each Reply Msg would check one out, use it, then check it back in.

In short, there's a heck of a lot of infastructure required. Are you sure you can't do your work with an asynch message? Networks are generally bad places for synchronous calls.

Member Ludwig72
Member

I am setting up a test framework with LabVIEW Realtime at the one side and TestStand at the other side. LabVIEW runs at a PXI RT system and do all the measurement and control. TestStand runs at a PC and sends all the commands over an interface throught network streams.

Simplified TestStand sends a message: "give me the actual DC voltage" and waits for its return. There are too many values to get cyclic updates for all. I have to do it over requests. The Actor Framework would be an ideal solution for it but I need the reply.

Active Participant justACS
Active Participant

Congratulations.  You have one of the three use cases we've identified for reply messages.

The shipping form of reply message is probably not useful in your case, except as an example of the technique.  Here is my suggestion for how to solve this:

Create a proxy actor that will run on the host PC, alongside TestStand.  Give this actor a method like "Get Process Value".  Get Process value takes a queue refnum as an argument.  This is the queue on which you wish to receive your reply.

Create another method for the proxy actor called, say, "Receive Process Value."  Create a regular message for this method.

Create a message for Get Process Value.  Modify the Send method of this message to create a queue to pass to Get Process Value.  After you send the message, wait for the reply to appear on that reply queue.  Be sure to destroy the queue after you receive the reply.  Create an override of the message's Drop Message method.  In that method, enqueue a dummy reply.  This ensures that you will get *something* back on the queue, even if the remote target stops for some reason.  (This is where studying our reply message will be useful, because it does all of these things.)

Have the proxy's Get Process Value method transmit a message over the linked network actor to the remote actor.  This message invokes a method that will obtain your data and then return it to your proxy via a Send Receive Process Data message.

In Receive Process Value, put the data you got from the remote actor onto the reply queue.  Send Get Process Value will then return the data to TestStand.

The easiest way to make sure the data goes to the right reply queue is to pass the reply queue along with every message - TestStand to proxy to remote and then back to proxy.  The queue refnum is just a number, so it can serve as a unique identifier, and save you the trouble of having to do a lookup.  Of course, if your proxy is only serving one request at a time, you can dispense with this, and just hold the reply queue in the proxy.

Proven Zealot
Proven Zealot

Ah. There's another approach. This will help you more.

Create "Reply Proxy.vi". Load it on your remote system but do not run it (so include a non-strict static VI ref to it in your remote system hierarchy). "Reply Proxy.vi" should have inputs needed to send the reply msg and outputs that are the results of the reply msg.

Create a global VI (or some other data storage but global VI works fine for this trick) that has an Enqueuer variable. When your Actor launches, have it store its enqueuer in the global VI.

When "Reply Proxy.vi" executes, it will read the global VI to get the enqueuer and then use its input values to send a normal Reply Msg to the actor. When it gets the reply, it just outputs those values.

TestStand or any other remote system makes a VI Server call to "Remote Proxy.vi".

Proven Zealot
Proven Zealot

Or you could do what niACS said. ;-) I didn't see his reply when typing mine.

Member Ludwig72
Member

Thank you niACS. I used your instructions and it works fine.

Member CodePeasant
Member

Is there a reason LNA Disconnect.vi does not send a disconnect message to the LNA on the other end of the network stream?  When reading the comments in LNA Actor Core.vi I get the impression it was thought of at some point.  Also, do you know if a Read Single Element from Stream.vi can be interrupted from other signals besides timeout i.e. invalid handle/filedescriptor?  Thinking like a network socket programmer...

Member CodePeasant
Member

The remote endpoint has been destroyed.  Error -314220  to answer both questions.

Contributors