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
For review - Server code clean up #744
Conversation
Codecov Report
@@ Coverage Diff @@
## master #744 +/- ##
=======================================
Coverage 86.99% 86.99%
=======================================
Files 100 100
Lines 21772 21772
=======================================
Hits 18941 18941
Misses 2831 2831 Continue to review full report at Codecov.
|
I pulled down this PR and tried to compile after creating a fresh build folder. I see the following [gmurthy@localhost build]$ make install |
It says ganeshmurthy closed this 5 minutes ago. I just added a comment but did not close this PR. Not sure how this got closed. |
It looks like accidentally pressed the "Close and comment" button instead of the "Comment". D'Oh. Sorry |
@ganeshmurthy what OS version did you try to build on? |
@ssorj My laptop is using Fedora 30 I also used this Docker environment by changing fedora:latest to fedora:30 and I saw the same error as above |
Running Fedora 31 there's an error in libwebsockets:
|
Travis job on macOS here is similarly unhappy. |
@ganeshmurthy, would you give this another try? I was missing libwebsockets before. I think the includes are fixed now. |
src/connection.h
Outdated
qd_timer_t* timer; // Timer for initial setup | ||
pn_connection_t* pn_conn; | ||
pn_session_t* pn_sessions[QD_SSN_CLASS_COUNT]; | ||
pn_ssl_t* ssl; | ||
qd_listener_t* listener; | ||
qd_connector_t* connector; |
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.
By and large the format convention for existing code is to have the indirection operator close to the variable name and not close to the type name. Is there a reason for changing this?
Attaching the operator to the variable name helps one to reason correctly about the variable's type when multiple variables are declared on the same line.
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.
Isn't that a pointer declaration, not an indirection operator? As in, it would be an indirection operator if I were dereferencing something, but I'm not.
I have no problem flipping it, and ultimately I'll apply whatever style we decide should go in .clang-format. I always think of it as type information that belongs with the type.
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 have a problem with either way. If you apply the new style in .clang-format will doing "clang-format -i src/*.c" change the style throughout the code?
By that I mean, if we are changing the style here, we will have to do the same everywhere.
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.
"clang-format -i src/*.c would change all the .c files there, but I wouldn't make applying clang format an all-or-nothing thing. I suggest using it when developing new code or doing a cleanup.
clang-format's formatting isn't perfect in every respect. I think it's a net win, personally, but there are cases where it's not doing what you might want. Pointer declarations is one example - with the pointer star aligned to the value, the structs don't look right.
Fortunately, you can apply it as needed and you can defeat the formatting if you need to with directives in comments.
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.
Works best with either find
or git
. Something like this to reformat all, clang-format -i $(git ls-files -- *.c *.h)
and to reformat changed files, clang-format -i $(git diff --name-only upstream/master..HEAD)
. Not sure if it is possible to only reformat changed sections of individual files like this.
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.
Isn't that a pointer declaration, not an indirection operator?
It's both. int p; is an int declaration. int * p; is a pointer declaration. The difference between them is the *, the indirection operator. The operator has the same effect on declarations and on references.
It's unfortunate that the style settings don't have a way to specify the current style easily.
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.
Please don't rebase and do a forced push. This messes the branches I've created on your last testing branch. https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing |
@ChugR okay, gotcha. (I didn't anticipate anyone basing anything on this branch until it was approved.) |
This looks good now. No compile errors. Thanks. |
Re: pointer declarations: Please do this the way Chuck suggests:
This is the convention used throughout the code. Thanks, |
On the 'dont force push to your PR branch' bit.. On the flipside, for something like this I far prefer updating the single PR (even with force pushes) than opening lots of new PRs and spreading related discussion over a bunch of them. If that discussion starts off saying 'this is just wrong, lets do some other entirely different thing, fix the actual problem, rather than whatever this does', then perhaps a new PR might be more appropriate. Essentially, I think of PR branches in a repo fork as all but private unless specifically agreed otherwise with given collaborators, and basing new branches on such known-PR sources from the fork is to accept that you might need to fix up your branches when they change and thats ok (I did that yesterday for $reasons, I had to rebase, that was fine). I wouldn't by default consider them the same thing as shared repo public feature branches like the Atlassian page discusses, which is more along the lines of someone made a feature branch in the lone shared public repo where everyone works. |
@gemmellr I asked the folks on the Proton team, and it's also conventional there to rebase PR branches. I'm totally willing to put something like "-wip" in my branch name as a way of saying "don't branch off of this unless you accept the consequences". |
I dont think that is needed personally, its fairly common practice for PR branches unless agreed otherwise. GitHub even allows for maintainers to update your PR on your behalf (if you've allowed it), and I have had such force pushes done on PRs with it enabled. |
<!-- specific language governing permissions and limitations --> | ||
<!-- under the License. --> | ||
|
||
# Code conventions |
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.
Other documentation is formatted in AsciiDoc. It would be better not to introduce Markdown in addition.
semi_colon_count++; | ||
} else { | ||
// This is an unrecognized component. Log a critical | ||
// error. |
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.
clang-format did not reflow this one. It will add breaks if a comment is over column limit, but it apparently does not try to join lines. Makes sense, joining lines can easily break meaningful formatting.
src/server.c
Outdated
// Called with qd_python_lock held. | ||
// | ||
// XXX But it doesn't use the _lh convention? | ||
qd_error_t qd_register_display_name_service(qd_dispatch_t* qd, void* displaynameservice) { |
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.
Previously the doc blocks were formatted as doxygen comment blocks, while the new comments aren't. Is that a plan?
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've been pretty lax about the format of function documentation. While I like the way the doxygen format reads in the code, I've never actually generated (or used) documentation from the source.
Way back in the beginning we designed a big chunk of what is now the router as a library intended to be public. We no longer have that goal, but it may explain why some functions have more formal documentation than others.
|
||
// XXX When is config going to be null? | ||
if (config && config->inter_router_cost > 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.
Btw, this looks to me like a response to a Coverity warning. Coverity likes to send reports about NULL config ;P The Coverity results on the page usually have something they call "static trace", which is trying to answer this question...
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.
Agreed - if coverity ever encounters a path through the code where a pointer is checked for null, then it flags any use of that pointer that isn't checked for null as a possible error.
server->sasl_config_name = sasl_config_name; | ||
server->proactor = pn_proactor(); | ||
server->container = NULL; | ||
server->start_context = 0; // XXX Should be NULL? |
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.
Probably, since this is typed as a void pointer.
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 general the code avoids using NULL in favor of 0. Not arguing for or against - that's Just the Way It Is.
Probably should be consistent.
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 C++, clang-tidy
pushes towards using the (cpp only) nullptr. Not sure what cppcheck does. I guess that C linters, if any was used, would, by default, push for using NULL.
@@ -157,6 +160,7 @@ static qd_config_sasl_plugin_t *qd_find_sasl_plugin(qd_connection_manager_t *cm, | |||
return 0; | |||
} | |||
|
|||
// XXX Should this move to server.c or its own server_config.c? | |||
void qd_server_config_free(qd_server_config_t *cf) | |||
{ |
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.
Btw, I hate having to create new files. I always feel like I am polluting someone's else carefully thought out layout...
Bbtw, I thought that clang-format with the style selected would move all opening braces on the same line. Apparently not.
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've left a few style-related comments inline.
From a more structural point of view I'm a big fan of breaking stuff up into separate source files that contain one primary public object. And a corresponding header for the object's API that lives in the top level include/qpid/dispatch directory.
We also have a convention for when a subset of an objects' API is considered internal but needs to be shared across sources. This portion of the API is put into a separate header file named object_private.h that is located in the source directory at the same level as the corresponding object.c file.
So in general I agree with the way this patch breaks things up.
@@ -157,6 +160,7 @@ static qd_config_sasl_plugin_t *qd_find_sasl_plugin(qd_connection_manager_t *cm, | |||
return 0; | |||
} | |||
|
|||
// XXX Should this move to server.c or its own server_config.c? |
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 the qd_server_config_t structure is public - connection_manager and server (perhaps others) have direct access to its fields. I prefer breaking these out to their own .h and .c files.
src/connector.c
Outdated
|
||
ALLOC_DEFINE(qd_connector_t); | ||
|
||
const char* qd_connector_policy_vhost(qd_connector_t* connector) { |
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.
Our code convention puts the opening brace for functions on its own line directly under the function. All other C constructs - structs, enums, control statements - put the opening brace on the same line.
Closing braces always appear on their own line.
src/server.c
Outdated
// Called with qd_python_lock held. | ||
// | ||
// XXX But it doesn't use the _lh convention? | ||
qd_error_t qd_register_display_name_service(qd_dispatch_t* qd, void* displaynameservice) { |
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've been pretty lax about the format of function documentation. While I like the way the doxygen format reads in the code, I've never actually generated (or used) documentation from the source.
Way back in the beginning we designed a big chunk of what is now the router as a library intended to be public. We no longer have that goal, but it may explain why some functions have more formal documentation than others.
src/server.c
Outdated
if (displaynameservice) { | ||
qd->server->py_displayname_obj = displaynameservice; | ||
Py_XINCREF((PyObject *)qd->server->py_displayname_obj); | ||
Py_XINCREF((PyObject*) qd->server->py_displayname_obj); |
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.
IIUC the (unspoken) convention is to put a space between and * in casts.
A space between the closing paran on the cast and the casted object should be part of the convention going forward.
server->sasl_config_name = sasl_config_name; | ||
server->proactor = pn_proactor(); | ||
server->container = NULL; | ||
server->start_context = 0; // XXX Should be NULL? |
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 general the code avoids using NULL in favor of 0. Not arguing for or against - that's Just the Way It Is.
Probably should be consistent.
|
||
// XXX When is config going to be null? | ||
if (config && config->inter_router_cost > 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.
Agreed - if coverity ever encounters a path through the code where a pointer is checked for null, then it flags any use of that pointer that isn't checked for null as a possible error.
…g-based formatting
Thinking back to this, my take regarding reasons why this was not merged was 1} disagreement with the code formatting change (llvm formatter does not support well the current style used in dispatch), and possibly 2} that it will break outstanding work in progress. The moving of things around in this PR was actually received well, as far as I can tell from the comments. |
@mgoulish just volunteered to reformat Dispatch to something more palatable to contemporary tooling (clang-format). Thanks, Mick, much appreciated! |
…00 bec… (apache#744) * Fixes apache#637: Reduce the number of links created from 10000 to 4000 because the test is exceeding 400 seconds in CI * Python checker fixes
A cleanup of the server code.
I'll squash this before merging.
The tests have a few failures that don't appear to be related to this change, but please double check me:
https://travis-ci.org/github/apache/qpid-dispatch/builds/690365464
There are a few questions embedded in comments here. I'd appreciate some help with those.