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

Change enum values to be powers of two (fix #3417) #4239

Merged
merged 2 commits into from
Jun 29, 2023

Conversation

ckeshava
Copy link
Collaborator

If merged, this code will:

@ckeshava
Copy link
Collaborator Author

@nbougalis I have a question about the choice of integers inside the Condition enum. Does it necessarily have to be powers of 2? With respect to the operations in this file, it suffices to choose different integer values right?

I understand that the choice of even/odd values is important because we do bit-wise and operator.

@greg7mdp
Copy link
Contributor

They have to be powers of two if you want to be able to set and test the bits individually.

For example if you define:

enum { A=1, B=2, C=3};

and you do:

uint32_t x = C;

the value of x will be 0x3 (the two lower bits set), so you would have both (x & A) != 0 and (x & B) != 0

if you use powers of two the bits can be set and tested individually. I used to use enums like:

enum {
   A = 1 << 0,
   B = 1 << 1,
   C = 1 << 2,
   ...
   };

@ckeshava
Copy link
Collaborator Author

They have to be powers of two if you want to be able to set and test the bits individually.

For example if you define:

enum { A=1, B=2, C=3};

and you do:

uint32_t x = C;

the value of x will be 0x3 (the two lower bits set), so you would have both (x & A) != 0 and (x & B) != 0

if you use powers of two the bits can be set and tested individually. I used to use enums like:

enum {
   A = 1 << 0,
   B = 1 << 1,
   C = 1 << 2,
   ...
   };

okay got it, thanks for the explanation! I would individually check all the conditions and that is quite verbose, this is concise 👍

@greg7mdp
Copy link
Contributor

You can use a sequence 1,2,3,4,5,... if all the conditions are exclusive from one another. But if they are flags that can be set independently, then it has to be separate bits to be workable.

@ckeshava
Copy link
Collaborator Author

You can use a sequence 1,2,3,4,5,... if all the conditions are exclusive from one another. But if they are flags that can be set independently, then it has to be separate bits to be workable.

Okay, got it 👍

@intelliot intelliot changed the title Implement changes for Issue 3417 Change enum values to be powers of two (fix #3417) Mar 14, 2023
@intelliot intelliot added the Tech Debt Non-urgent improvements label Mar 14, 2023
NEEDS_CURRENT_LEDGER = 2 + NEEDS_NETWORK_CONNECTION,
NEEDS_CLOSED_LEDGER = 4 + NEEDS_NETWORK_CONNECTION,
NEEDS_CURRENT_LEDGER = 2 * NEEDS_NETWORK_CONNECTION,
NEEDS_CLOSED_LEDGER = 4 * NEEDS_NETWORK_CONNECTION,
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider this purely stylistic change:

enum Condition {
    NO_CONDITION = 0,
    NEEDS_NETWORK_CONNECTION = 1,
    NEEDS_CURRENT_LEDGER = 2,
    NEEDS_CLOSED_LEDGER = 4,
};

Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't make much difference for small enums, but I like:

enum Condition {
    NO_CONDITION             = 0,
    NEEDS_NETWORK_CONNECTION = 1<<0,
    NEEDS_CURRENT_LEDGER     = 1<<1
    NEEDS_CLOSED_LEDGER      = 1<<2,
};

@intelliot
Copy link
Collaborator

@ckeshava would you like to pick this up?

@ckeshava
Copy link
Collaborator Author

Hello,
I have completed the code changes. The unit tests are passing locally, I'm not sure why the CI tests are failing on the ubuntu machine.

@@ -39,8 +39,8 @@ namespace RPC {
enum Condition {
NO_CONDITION = 0,
NEEDS_NETWORK_CONNECTION = 1,
NEEDS_CURRENT_LEDGER = 2 + NEEDS_NETWORK_CONNECTION,
NEEDS_CLOSED_LEDGER = 4 + NEEDS_NETWORK_CONNECTION,
NEEDS_CURRENT_LEDGER = 1 << 1,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is NEEDS_NETWORK_CONNECTION not required anymore?

@@ -94,20 +94,18 @@ conditionMet(Condition condition_required, T& context)
}

if (context.app.getOPs().isAmendmentBlocked() &&
(condition_required & NEEDS_CURRENT_LEDGER ||
condition_required & NEEDS_CLOSED_LEDGER))
(condition_required != NO_CONDITION))
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not the same test as before. Is the change on purpose?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes, I agree that the conditions have changed. I made this change approximately one year ago, so I am spacing out on the details. Let me think/check and get back to you

Copy link
Collaborator

Choose a reason for hiding this comment

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

Based on the old values, I think the conditions are equivalent. Between NEEDS_CURRENT_LEDGER and NEEDS_CLOSED_LEDGER, having any of the three low bits set in condition_required would result in the expression evaluating to true, so that covers all of the != NO_CONDITION conditions. So functionally, they are equivalent.

Now whether that was the intent is a different question.

It turns out there are only two operations which have NEEDS_NETWORK_CONNECTION: ledger_cleaner and tx. I think it's fine to disallow both of them if the server is amendment blocked.

Copy link
Collaborator

@ximinez ximinez left a comment

Choose a reason for hiding this comment

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

I think this looks good, and doesn't appear to actually change any existing behavior.

@@ -94,20 +94,18 @@ conditionMet(Condition condition_required, T& context)
}

if (context.app.getOPs().isAmendmentBlocked() &&
(condition_required & NEEDS_CURRENT_LEDGER ||
condition_required & NEEDS_CLOSED_LEDGER))
(condition_required != NO_CONDITION))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Based on the old values, I think the conditions are equivalent. Between NEEDS_CURRENT_LEDGER and NEEDS_CLOSED_LEDGER, having any of the three low bits set in condition_required would result in the expression evaluating to true, so that covers all of the != NO_CONDITION conditions. So functionally, they are equivalent.

Now whether that was the intent is a different question.

It turns out there are only two operations which have NEEDS_NETWORK_CONNECTION: ledger_cleaner and tx. I think it's fine to disallow both of them if the server is amendment blocked.

@intelliot intelliot added this to the 1.12 milestone Jun 9, 2023
@intelliot
Copy link
Collaborator

(Holding this for 1.12 unless someone requests otherwise)

@intelliot
Copy link
Collaborator

This has CI failures which need to be resolved (or explained). @ckeshava or @thejohnfreeman - could you have a look?

@thejohnfreeman
Copy link
Collaborator

Please merge develop.

- Use powers of two to clearly indicate the bitmask
- Replace bitmask with explicit if-conditions to better indicate predicates
@ckeshava
Copy link
Collaborator Author

OK, I've rebased to the develop branch, thanks for the tip!

@intelliot
Copy link
Collaborator

@HowardHinnant because there have been changes pushed after your earlier approval, could you do a quick re-review?

@intelliot intelliot merged commit 1c2ae10 into XRPLF:develop Jun 29, 2023
intelliot added a commit that referenced this pull request Jun 29, 2023
intelliot added a commit that referenced this pull request Jun 30, 2023
ckeshava added a commit to ckeshava/rippled that referenced this pull request Jul 10, 2023
- Use powers of two to clearly indicate the bitmask
- Replace bitmask with explicit if-conditions to better indicate predicates

Change enum values to be powers of two (fix XRPLF#3417) XRPLF#4239

Implement the simplified condition evaluation
removes the complex bitwise and(&) operator
Implement the second proposed solution in Nik Bougalis's comment - Software does not distinguish between different Conditions (Version: 1.5) XRPLF#3417 (comment)
I have tested this code change by performing RPC calls with the commands server_info, server_state, peers and validation_info. These commands worked as expected.
ckeshava added a commit to ckeshava/rippled that referenced this pull request Sep 22, 2023
- Use powers of two to clearly indicate the bitmask
- Replace bitmask with explicit if-conditions to better indicate predicates

Change enum values to be powers of two (fix XRPLF#3417) XRPLF#4239

Implement the simplified condition evaluation
removes the complex bitwise and(&) operator
Implement the second proposed solution in Nik Bougalis's comment - Software does not distinguish between different Conditions (Version: 1.5) XRPLF#3417 (comment)
I have tested this code change by performing RPC calls with the commands server_info, server_state, peers and validation_info. These commands worked as expected.
ckeshava added a commit to ckeshava/rippled that referenced this pull request Sep 25, 2023
- Use powers of two to clearly indicate the bitmask
- Replace bitmask with explicit if-conditions to better indicate predicates

Change enum values to be powers of two (fix XRPLF#3417) XRPLF#4239

Implement the simplified condition evaluation
removes the complex bitwise and(&) operator
Implement the second proposed solution in Nik Bougalis's comment - Software does not distinguish between different Conditions (Version: 1.5) XRPLF#3417 (comment)
I have tested this code change by performing RPC calls with the commands server_info, server_state, peers and validation_info. These commands worked as expected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Tech Debt Non-urgent improvements
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

6 participants