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

Force dial #696

Merged
merged 6 commits into from
Feb 24, 2022
Merged

Force dial #696

merged 6 commits into from
Feb 24, 2022

Conversation

Menduist
Copy link
Contributor

This PR allows applications to dial peers even if we reached the connection limit

A new semaphore slot will be temporarily created, so the connection can never fail because of peer limitation

Alternative for #687, needed for status-im/nimbus-eth2#3346

@Menduist Menduist mentioned this pull request Feb 22, 2022
libp2p/connmanager.nim Outdated Show resolved Hide resolved
@@ -77,13 +78,14 @@ proc release*(s: AsyncSemaphore) =
trace "Releasing slot", available = s.count,
queue = s.queue.len

s.count.inc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't guarantee that count goes above 0 - should it really complete queued futures then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's how the incoming doesn't get starved: the slot "created" by a forceAcquire can be reused for incoming connections.
Of course, after a while this slot will be deleted (because more stuff will be released than acquired)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok - hm, that is a little bit more permissive than I imagined it - it's a good point about starvation though, it does give more balance in return for longer periods of "non-compliance" - let's document this in code in case it causes trouble we didn't anticipate

if s.queue.len > 0:
var fut = s.queue[0]
s.queue.delete(0)
if not fut.finished():
fut.complete()
s.count.dec
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as general hygiene, it's probably better to mutate the state before "releasing" the work that depends on the state update to have happened, even if de-facto, the work that gets released happens later

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this proc is not async, but better be clean

@@ -77,13 +78,14 @@ proc release*(s: AsyncSemaphore) =
trace "Releasing slot", available = s.count,
queue = s.queue.len

s.count.inc
if s.queue.len > 0:
var fut = s.queue[0]
s.queue.delete(0)
if not fut.finished():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code looks odd btw: why would there be finished futures in the queue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and as a follow-up, if a future is finished already, should the "next" future be completed instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A future could be cancelled
Not sure why we don't try another, I switched to a loop and every tests pass, @dryajov?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the cancelled futures remove themselves from the queue in their cancellation callback, so that should never happen..
what could happen is that the user "manually" completes the future but that's not how one uses futures in general so..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, missed that part

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we can't figure out a reason, might be a good idea to assert with a message that the future was unexpectedly completed - by extension, a loop would no longer be needed - if this happens, I get the feeling we might get an imbalance in acquires and releases which either leads to lockups or overallocation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the counter and the queue size can now diverge due to the forceAcquire contraption, we might as well have to use a loop in release.

@Menduist Menduist merged commit c09d032 into unstable Feb 24, 2022
@Menduist Menduist deleted the forcedial branch February 24, 2022 16:31
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

Successfully merging this pull request may close these issues.

3 participants