Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recover a stream with the same uid #35

Open
tstenner opened this issue Sep 10, 2019 · 4 comments
Open

Recover a stream with the same uid #35

tstenner opened this issue Sep 10, 2019 · 4 comments

Comments

@tstenner
Copy link
Collaborator

Minimal non-working example:

lsl::stream_outlet outlet(lsl::stream_info("resolvetest", "from_streaminfo"));
	lsl::stream_inlet in(outlet.info());
in.open_stream(2);

At this point, the stream info has the service ports set, but not the IP address (after all, the host could have multiple IP addresses) so the recovery kicks in and searches for a stream named "resolvetest".

This fails, because the stream's uid is known so the recovery process is aborted as soon as the stream is found:

for (std::size_t k=0;k<infos.size();k++)
if (infos[k].uid() == host_info_.uid())
return; // in this case there is no need to recover (we're still fine)

Possible solutions:

  • unset the UID when constructing an inlet from a stream info
  • (re)connect to the stream anyways, not a good idea in case the between-sample interval is bigger than the watchdog interval
  • add a force_reconnect parameter to try_recover
@tstenner
Copy link
Collaborator Author

CC @chkothe as he knows most about it.

@mgrivich
Copy link
Collaborator

mgrivich commented Sep 12, 2019 via email

@chkothe
Copy link
Contributor

chkothe commented Sep 12, 2019

I agree that the inlets in their current form aren't meant to be initialized with anything other than the result of a resolve operation. But indeed some users may feel tempted to try that, so having an error that says please use the output of a resolve operation here would fix that. At the risk of sounding a bit defensive, I'd be a little uncomfortable retrofitting a patch into a core piece of the lib that we're basically sure works correctly, just so that a user has their way who's probably better off using a queue data structure instead of LSL anyway, since they're obviously moving data from one end of their own process to another. While also keeping in mind that the resolve would be a way for them to accomplish their goal. If we had a giant test battery that tests all possible ways in which these pieces could malfunction if a change of that sort overlooked a non-obvious detail, then we could probably add coverage for a lot more niche cases.

@tstenner
Copy link
Collaborator Author

That's not the way the examples work. At most, the code should throw an
error to say, "don't do that". The inlet info should be gathered from a
resolve command, not by reusing the outlet info.

In theory yes, but the inlet construction code currently goes out of its way to allow this explicitely:

// the actual endpoint is not known yet -- we need to discover it later on the fly
// check that all the necessary information for this has been fully specified
if (type_info_.name().empty() && type_info_.type().empty() && type_info_.source_id().empty())
throw std::invalid_argument("When creating an inlet with a constructed (instead of resolved) stream_info, you must assign at least the name, type or source_id of the desired stream.");
if (type_info_.channel_count() == 0)
throw std::invalid_argument("When creating an inlet with a constructed (instead of resolved) stream_info, you must assign a nonzero channel count.");
if (type_info_.channel_format() == cft_undefined)
throw std::invalid_argument("When creating an inlet with a constructed (instead of resolved) stream_info, you must assign a channel format.");

I agree that the inlets in their current form aren't meant to be initialized with anything other than the result of a resolve operation.

It would simplify the LabRecorder code a lot because then it could just create an inlet for an outlet that's going to appear some time later.

If we had a giant test battery that tests all possible ways in which these pieces could malfunction if a change of that sort overlooked a non-obvious detail, then we could probably add coverage for a lot more niche cases.

That's where this issue came up. @mgrivich started a battery of unit tests last year and I'm expanding them from time to time. Right now they run after each commit and for each PR to make sure nothing covered breaks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants