-
Notifications
You must be signed in to change notification settings - Fork 124
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
Update DisplayDriverServer and ClientDisplayDriver #1448
base: RB-10.5
Are you sure you want to change the base?
Update DisplayDriverServer and ClientDisplayDriver #1448
Conversation
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 Linas!
The general approach here seems good - it's pleasing to see that you've found a way of dropping this into the existing setup with really pretty minimal changes to the code.
I've made a bunch of inline comments with small suggestions for improvements, but nothing that changes the overall strategy. In addition to those and adding some comprehensive tests, it would be good to document the new parameters somewhere, possibly in DisplayDriverServer.h
.
Cheers...
John
if (mergeDriverData && mergeDriverData->readable()) | ||
{ | ||
const IntData *sessionIdData = parameters->member<IntData>( "sessionId", true /* throw if missing */ ); | ||
tmpParameters->writable()[ "clientPID" ] = new IntData( sessionIdData->readable() ); |
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 do we need to override the clientPID
parameter with something that is no longer the process ID of the client? I can't see how it is necessary, for two reasons :
- Since only one server-side driver actually gets created from the batch of session clients, that driver will end up with a unique
clientPID
anyway. - Gaffer no longer cares what the
clientPID
is - it now usesgaffer:renderID
to determine when two drivers are from the same render - spoofing that is going to be a separate problem, and not really one that should be dealt with here.
Maybe I missed something?
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.
No I think you're right. I'll remove references to it.
@@ -70,6 +72,8 @@ IE_CORE_DEFINERUNTIMETYPED( DisplayDriverServer ); | |||
namespace | |||
{ | |||
|
|||
std::map<int, std::pair<DisplayDriverPtr, int>> mergeMap; |
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.
We use g_
prefixes to denote global variables.
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'd also be tempted to use a little struct with named field for the driver and client count, as first
and second
become a bit meaningless when you're far away from the point the thing was defined.
bool m_mergeSession; | ||
int m_mergeId; |
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'd suggest std::optional<int>
instead of two separate members here.
{ | ||
m_displayDriver->imageClose(); | ||
} | ||
else if ( auto search = mergeMap.find(m_mergeId); search != mergeMap.end() && --mergeMap[m_mergeId].second <= 0 ) |
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 is a matter of taste perhaps, but I don't think packing an assignment, a conditional test and a mutation of another variable into if()
makes for readable code. I also think it's unnecessary.
The search should never fail, because if we have a merge session, we really must have created the map entry already. If we haven't, or we've deleted it already, that would be a bug, and we don't want a silent failure. Also having done the search with find()
, we're doing another map search, because that's what mergeMap[m_mergeId]
does internally. I'd suggest simplifying to this :
else
{
auto &m = mergeMap.at( m_mergeId ); // Throws if not found, alerting us to the bug
...
}
Alternatively, we could store the map iterator as member data, instead of m_mergeId
.
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'm not a big fan of storing the iterator.
I agree that having a loud failure would be better.
|
||
// Check if merge ID in map, if not then create display driver and session count pair with merge ID. | ||
if (const auto search = mergeMap.find(m_mergeId); search == mergeMap.end()) |
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.
As above, I'm not a fan of packing a lot of stuff into an if()
, although in this case I suppose it does limit the scope of the search
variable, which is nice.
But as above, we're doing more map searches than necessary - find()
does a search, then emplace()
does a search and then []
does a search. Since in all cases we want to end up with an entry in the map, we could just do this :
auto &m = mergeMap[m_mergeId];
if( !m.first )
{
// First driver
m.first = DisplayDriver::create(
...
}
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 don't know enough about DisplayDriverServer to know if different sessions get handled on different threads. If they do, then we need to consider thread-safety for all accesses to the mergeMap
. Do you know if this is an issue or not, or is everything on a single thread?
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.
From my understanding the server runs as in a separate thread to the rest of cortex, but handles all accepts in a single threaded manner. In which case we wouldn't have to worry about thread-safety.
// Check if merge ID in map, if not then create display driver and session count pair with merge ID. | ||
if (const auto search = mergeMap.find(m_mergeId); search == mergeMap.end()) | ||
{ | ||
const IntData *sessionClientsData = parameters->member<IntData>( "sessionClients", true /* throw if missing */ ); |
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 assume this parameter tells us how many total clients there are going to be in this session, and it is the responsibility of the person setting up the clients to set it correctly?
I did wonder if we could remove the need for this by just incrementing the client count each time we add a client to the merge. But I suppose it is possible for one very slow machine (or a farm resource allocation problem) to mean that one client doesn't even start before all the others have finished.
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.
Yes it is the responsability of the client code to set the parameter up properly.
And you're right I did think about an iterator somewhere, but it could be the case that all but one machine finishes, whilst one machine hasn't even started yet, which would cause the driver to close, and hence the catalogue image.
@@ -423,9 +437,39 @@ void DisplayDriverServer::Session::handleReadOpenParameters( const boost::system | |||
|
|||
const StringData *displayType = parameters->member<StringData>( "remoteDisplayType", true /* throw if missing */ ); | |||
|
|||
const BoolData *mergeDriverData = parameters->member<BoolData>( "mergeDriver", false); |
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 would suggest omitting the mergeDriver
parameter completely as it doesn't seem to add anything. We could just use the existence of sessionId
to enable the merging behaviour.
} | ||
else | ||
{ | ||
m_mergeId = parameters->member<IntData>( "sessionId", true /* throw if missing */ )->readable(); |
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 parameter list for displays is full of all sorts of stuff we've accumulated over the years, and it's not always clear what is used by who, and when. Perhaps we could call this displayDriverServer:mergeId
to make it clearer who consumes it, and what it means? And perhaps we could do similar with sessionClients
?
Adds option to server and client driver to allow a 'merge' driver that shares a display driver to write to.
e69edc6
to
6104274
Compare
Adds option to server and client driver to allow a 'merge' driver that shares a display driver to write to.
Create a map that is shared between server sessions that links a session id to a display driver. This allows multiple client drivers to write to the same display driver and thus the same catalogue in Gaffer.
I haven't added tests yet, but does the code look good so far?
Checklist