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

Address clang-tidy warnings in db files #1405

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jonesmz
Copy link
Contributor

@jonesmz jonesmz commented Jan 25, 2024

The general approach here was:

  • Always declare variables as close to where they are defined as possible.
  • Check for pre-conditions of functions before doing work (e.g. ensure we can connect to the DB before doing a bunch of string formatting)
  • Keep the scope of mutexes as reasonably small as practical.
  • Use idiomatic C11, such as for-loops over the thing being iterated, not while() loops over constants, or variables that aren't modified.
  • Prefer if(fail){return} function-body after over `if(not fail){ function-body inside if} return;

Clang-tidy returns a clean bill of health, but while going through this file i noticed a lot of things that raise questions.

Lack of checking column counts. Lack of handling the possibility of multiple return values. Questionably handling of strings. Complete lack of checking function inputs for invalid values (e.g. nullptr).

I'm not going to fix those, my organization doesn't USE the DB drivers, so i have little interest in re-working the logic beyond addressing clang-tidy warnings for my own sanity, but i did add TODO comments for someone else to look at in the future.

Additional note: While the changes look very invasive.... they aren't.

I don't think there is a way to get github to ignore whitespace in the filediff, but if someone were to compare the commit locally, they'll see that almost all of the changes are just adjusting indentation.

} else {
ret = 0;
}
convert_string_key_to_binary(kval, key, sz / 2);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

convert_string_key_to_binary() never returned anything but 0.
Changed the function to return void to simplify logic at call-sites.

@@ -184,6 +184,7 @@ typedef uint32_t turn_time_t;
#error WRONG BYTE_ORDER SETTING
#endif

// NOLINTBEGIN(clang-diagnostic-string-compare)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Suppresses clang-tidy warning about comparing the address of constant string literals is implementation specific behavior.

@@ -45,7 +45,7 @@ static void make_connection_key(void) { (void)pthread_key_create(&connection_key
pthread_key_t connection_key;
pthread_once_t connection_key_once = PTHREAD_ONCE_INIT;

int convert_string_key_to_binary(char *keysource, hmackey_t key, size_t sz) {
void convert_string_key_to_binary(char const *keysource, hmackey_t key, size_t sz) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

convert_string_key_to_binary() never returned anything but 0.
Changed the function to return void to simplify logic at call-sites.

Also, changed input parameter to char const* to allow the optimizer to assume that the contents of keysource won't be modified.

}
#endif

return;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Eliminate clang-tidy warning about unnecessary return at end of void function.

}

static int donot_print_connection_success = 0;

static void fix_user_directory(char *dir0) {
char *dir = dir0;
while (*dir == ' ')
while (*dir == ' ') {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

all control flow should always have braces

@@ -194,15 +191,12 @@ static void init_sqlite_database(sqlite3 *sqliteconnection) {
"CREATE TABLE admin_user (name varchar(32), realm varchar(127), password varchar(127), primary key (name))",
NULL};

int i = 0;
while (statements[i]) {
for (int i = 0; statements[i] != NULL; ++i) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

initialize variables as close to where they are defined as possible.

in this case, by using a for loop instead of while loop.

sqlite3_stmt *statement = NULL;
int rc = 0;
if ((rc = sqlite3_prepare(sqliteconnection, statements[i], -1, &statement, 0)) == SQLITE_OK) {
if (sqlite3_prepare(sqliteconnection, statements[i], -1, &statement, 0) == SQLITE_OK) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

int rc is written to but never read from.

This pattern repeats throughout the whole file.

@@ -212,752 +206,799 @@ static sqlite3 *get_sqlite_connection(void) {
persistent_users_db_t *pud = get_persistent_users_db();

sqlite3 *sqliteconnection = (sqlite3 *)pthread_getspecific(connection_key);
if (!sqliteconnection) {
if (sqliteconnection != NULL) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exit early if the connection is already available.


sqlite_lock(0);
sqlite3 * const sqliteconnection = get_sqlite_connection();
if (sqliteconnection == NULL) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

exit early if the connection cant be established.

int type = sqlite3_column_type(st, 0);
if (type != SQLITE_NULL)
add_to_secrets_list(sl, (const char *)sqlite3_column_text(st, 0));
for(int stepResult = sqlite3_step(st);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Use a for loop over the result of sqlite3_step() instead of a while-loop over the non-changing ctotal (the number of columns) variable.

While the control flow wasn't necessarily... "wrong" before, this is more idomatic.

lock_realms();
rp->options.perf_options.max_bps = turn_params.max_bps;
unlock_realms();
lock_realms();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function was particularly gnarly.

Locking a mutex for a single variable, when there are 2 others to modify as well?

I don't fully know what this function is actually trying to accomplish, but it's a pretty good one for an expert to review.

@eakraly
Copy link
Collaborator

eakraly commented Jan 28, 2024

@jonesmz pls rebase on latest master to fix formatting issues

@eakraly eakraly changed the title Address clang-tidy warnings in src/apps/relay/dbdrivers/sqlite.c Address clang-tidy warnings in db files Jan 28, 2024
@eakraly
Copy link
Collaborator

eakraly commented Jan 28, 2024

I took the liberty to rename the PR to more properly reflect the extend of the change @jonesmz

@jonesmz
Copy link
Contributor Author

jonesmz commented Jan 28, 2024

@jonesmz pls rebase on latest master to fix formatting issues

Sure, will do on monday.

@jonesmz
Copy link
Contributor Author

jonesmz commented Jan 28, 2024

I took the liberty to rename the PR to more properly reflect the extend of the change @jonesmz

I did make modifications to each of the DB drivers because the function signature of that one function is being changed, but really the change is 99% for the sqlite driver.

Would it be better if i split the PR into two? One for sqlite, the other for the one function?

@eakraly
Copy link
Collaborator

eakraly commented Jan 28, 2024

I took the liberty to rename the PR to more properly reflect the extend of the change @jonesmz

I did make modifications to each of the DB drivers because the function signature of that one function is being changed, but really the change is 99% for the sqlite driver.

Would it be better if i split the PR into two? One for sqlite, the other for the one function?

It is fine doing all of it in one PR actually. Makes more sense. Just updated the name.
Thank you!

@jonesmz
Copy link
Contributor Author

jonesmz commented Jan 29, 2024

Most recent commit does a small amount of re-work for the sqlite_lock() and sqlite_unlock() functions to normalize platform specific code differences. No logic changes, just lifting ifdefs up to the global level instead of littering the functions with the differences.

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.

None yet

2 participants