-
Notifications
You must be signed in to change notification settings - Fork 757
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
Classlib: Lock client id while running #3275
Classlib: Lock client id while running #3275
Conversation
* added numClients var for numClients/maxLogins as gotten from scsynth * clientID is locked while server is running and notified. * moved prHandle ... methods to Server
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just some minor things.
@@ -267,6 +267,7 @@ Server { | |||
|
|||
var <name, <addr, <clientID, <userSpecifiedClientID = false; | |||
var <isLocal, <inProcess, <>sendQuit, <>remoteControlled; | |||
var numClients; // maxLogins as sent from booted scsynth |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not call it maxLogins
? Hm, I understand that clientID
and numClients
are a pair.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find that maxLogins is a only technical name, numClients is more semantic:
it is the number of clients that the server is prepared to handle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, you could read it as the number of clients the server currently has.
@@ -351,13 +353,13 @@ Server { | |||
|
|||
} | |||
|
|||
numClients { ^numClients ?? { options.maxLogins } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in such simple cases it is more efficient to write numClients ? options.maxLogins
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
this.sendDefaultGroups; | ||
tree.value(this); | ||
ServerTree.run(this); | ||
} | ||
|
||
/* id allocators */ | ||
|
||
// private, called from server notify response with next free clientID | ||
clientIDLocked { ^this.serverRunning and: this.notified } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, when you want to inline the test, you need to write this.serverRunning and: { this.notified }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, done.
@@ -410,6 +421,65 @@ Server { | |||
}; | |||
} | |||
|
|||
prHandleClientLoginInfoFromServer { |newClientID, newMaxLogins| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you perhaps move the private implementations further down? It is better to have the public interface coming first. E.g. here: https://github.com/adcxyz/supercollider/blob/8be07637fb9255c52c3a908a14d0b46b6f140e80/SCClassLibrary/Common/Control/Server.sc#L582
@@ -351,13 +353,13 @@ Server { | |||
|
|||
} | |||
|
|||
numClients { ^numClients ? options.maxLogins } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW: In my testing, a ? b
is no more and no less than a ?? { b }
(sometimes one is faster, sometimes the other is, randomly). But if a is not nil, a ? b.method
is always 20-25% slower than a ?? { b.method }
. Let's not overextend that one surprising finding from awhile ago. In the present case here, ??
is better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok! I once tested this and found the ??
to be slower in general for single instvar lookups. But, whatever, this case counts.
rename clientIDLocked to isFullyBooted for clarity.
(doWhenBooted is tested implicitly in waitForBoot)
added unit tests for waitForBoot and bootSync, and they pass. |
} | ||
|
||
/* id allocators */ | ||
|
||
// private, called from server notify response with next free clientID | ||
isFullyBooted { ^this.serverRunning and: { this.notified } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, thinking about the naming: To me it seems that server.serverRunning
should return only ever true
when it is notified.
so I'd suggest:
var <>hasBooted;
serverRunning { ^this.hasBooted and: { this.notified } }
This might mean more changes internally. But it is correct semantically. Otherwise we'll run into allocator troubles.
E.g. when you start a NodeProxy
it should warn also when the server hasn't been notified yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point - yes can try that. a bit hairy to get to work properly, but should leave booting cleaner for the next reworking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will you still add it in this PR?
s.remove; | ||
of.free; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to add a test like that:
(
var done = false, prevNodeID, nodeID = -1;
fork {
s.boot;
1000.do {
if(s.serverRunning) {
nodeID = s.nextNodeID;
};
if(prevNodeID == nodeID) {
"error".warn;
};
prevNodeID = nodeID;
0.001.wait;
}
}
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good idea, will do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Just checking, what are the pending reviews on this? IMO the fix for I see:
|
yes - I would prefer keeping 'clients' in the name. for clarity, could be maxNumClients,
yes, done.
yes.
yes. I have two more items on the optional list:
|
and one more:
|
the idea of ( |
example
|
sorry if I am slow here, but this is still not fully clear to me:
Otherwise, IF the other app wanted to boot scsynth, it would have to be local, just asking to understand it - fine to leave it alone for now! |
Let's assume sclang and scsynth run on the same machine, but sclang has no privileges to boot scsynth. Then scsynth needs to be booted by hand. If you don't set That was IIRC, the scenario. |
@adcxyz - any chance you could rebase this on 3.9 head? I didn't realize it but this now conflicts because you moved some methods from ServerStatus to Server |
After adcxyz#9 is merged, I can approve this :) then I think it will be ready for merge. |
I've been running this for a couple of weeks now -- seems to be working. I agree -- I think it's ready to merge. |
Great! Thank you so much for trying it out @jamshark70 |
will make some attempt to look at this today and tomorrow. thanks all for working on this! |
the title and top post of this PR seem to be out of date. can someone give me a complete and up to date list of the intended changes in this PR? |
See the documentation for Other than that, I think this is actually a case where the tests document the design, so look those over if you still have questions. |
geez that is a lot. thanks for the info. |
@@ -725,13 +773,9 @@ Server { | |||
^Buffer.cachedBufferAt(this, bufnum) | |||
} | |||
|
|||
// defaultGroups for all clients on this server: | |||
|
|||
allClientIDs { ^(0..options.maxLogins-1) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be properly deprecated rather than hard removal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this hasn't been part of any release, it was added in a recent PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
understood
ServerTree.add(func, s); | ||
this.bootServer(s); | ||
|
||
synth2 = Synth("default", [\freq, 330]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's try to avoid adding new noises to the test suite.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO it's up to you to change it then; there's been no agreement about that and everyone else is fine with it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the one request isn't so important, so I approve as it is now.
global.send(server, tryToLoadReconstructedDefs); | ||
if (server.hasBooted) { | ||
global.send(server, tryToLoadReconstructedDefs); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe warn if server hasn't booted.
tests are failing for me:
|
@snappizz I can't reproduce. Look into a little bit and see if you can find why the test fails. |
the failing tests happen when i run all unit tests rather than just selectively running tests. i have figured out how to reproduce them in isolation as well: boot interpreter, boot server, then run either (also feel free to hop on slack if we want to avoid expanding this nearly record-length comment section even further) |
in TestServer_GUI
in TestServer_ServerGUI
in TestVolume
Avoid using default server in test suite
current test failures:
i think the |
ServerQuit should not run when server boots
if this.serverRunning is set to false before other state variables, ServerQuit doesn't get called cleaned up some logic in serverRunning_ so that ServerQuit runs when it should (i.e. not twice at boot)
Some of the failures @snappizz points out above are fixed in #3340. Some are due to test code in TestCoreUGens that ought to be refactored. The first one, however, caught a pretty significant issue in this PR that hadn't been covered by a unit test yet - ServerQuit was running (twice) on boot, but not on quit. I have just pushed a test and corresponding fix for this, and confirmed on my machine that the entire test suite passes except for these known failures. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks to all, i think this is good to go. there are still some issues with this PR (most significantly, i would much prefer a read-only ServerStatusWatcher:serverRunning
rather than a setter with side effects) but they can safely be put off until later.
This addresses and fixes #3272.
-> maybe clientID can now be freely user-settable while off,
and we dont need userSpecifiedClientID anymore?
so the server keeps correct info about this
(as the options may be shared between servers)
moved to Server for clarity (they do change server state)