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

Support BIT and BYTE options in the BITCOUNT command #2087

Merged
merged 15 commits into from
Feb 7, 2024

Conversation

kay011
Copy link
Contributor

@kay011 kay011 commented Feb 1, 2024

For #2006, This PR enables the BITCOUNT command to support bit and byte options, but the go-redis library does not seem to support this option yet, so only the cpp unit tests are added, and the correctness is verified locally through redis-cli.

@PragmaTwice PragmaTwice linked an issue Feb 1, 2024 that may be closed by this pull request
2 tasks
@PragmaTwice
Copy link
Member

but the go-redis library does not seem to support this option yet

You can use rdb.Do in go-redis to send any command and options to kvrocks. We don't need go-redis to support anything.

@PragmaTwice PragmaTwice changed the title Feature add bitcount option Support BIT and BYTE option in the BITCOUNT command Feb 1, 2024
@PragmaTwice PragmaTwice changed the title Support BIT and BYTE option in the BITCOUNT command Support BIT and BYTE options in the BITCOUNT command Feb 1, 2024
@jihuayu
Copy link
Member

jihuayu commented Feb 1, 2024

It looks like clang-tidy run failed. You need to fix it before merging.
https://github.com/apache/kvrocks/actions/runs/7744539810/job/21124606184?pr=2087#step:8:1406

Copy link
Member

@jihuayu jihuayu left a comment

Choose a reason for hiding this comment

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

We need to clarify whether the "start" variable in the function is calculated in bits or bytes.
Others LGTM.

src/commands/cmd_bit.cc Outdated Show resolved Hide resolved
src/commands/cmd_bit.cc Show resolved Hide resolved
src/types/redis_bitmap.cc Outdated Show resolved Hide resolved
src/types/redis_bitmap_string.h Outdated Show resolved Hide resolved
src/types/redis_bitmap_string.cc Outdated Show resolved Hide resolved
src/types/redis_bitmap_string.cc Outdated Show resolved Hide resolved
@kay011
Copy link
Contributor Author

kay011 commented Feb 4, 2024

@jihuayu Thank you for review carefully, I will fix it when I am free ~

Comment on lines 83 to 84
std::string str = "hello";
string_->Set(key_, str);
Copy link
Member

Choose a reason for hiding this comment

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

we can avoid hackings for str = "hello", just set specific bits. Setting a string would be hacking

#2075 This patch unify their behaviors

Copy link
Member

@mapleFU mapleFU left a comment

Choose a reason for hiding this comment

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

LGTM except some nits and testings

@mapleFU
Copy link
Member

mapleFU commented Feb 5, 2024

Others LGTM except #2087 (comment)

}
}
int64_t bytes = 0;
if (stop_in_segment >= start_in_segment) {
Copy link
Member

Choose a reason for hiding this comment

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

This might visit undefined memory, which could introduce bug

@mapleFU
Copy link
Member

mapleFU commented Feb 6, 2024

@kay011 I found adding the test would find Bitmap has a bug here(BitmapString is ok). I've a fixing for that. Would you mind fix it yourself or let me fix that?

@kay011
Copy link
Contributor Author

kay011 commented Feb 6, 2024

@kay011 I found adding the test would find Bitmap has a bug here(BitmapString is ok). I've a fixing for that. Would you mind fix it yourself or let me fix that?

you can fix it and I will merge it. I think maybe the origin BITCOUNT which used BYTE index also has this bug

@mapleFU
Copy link
Member

mapleFU commented Feb 6, 2024

I think maybe the origin BITCOUNT which used BYTE index also has this bug

Yeah

tests/cppunit/types/bitmap_test.cc Show resolved Hide resolved
Comment on lines 265 to 286
int64_t start_in_segment = 0; // start_index int 1024 bytes segment
auto stop_in_segment = static_cast<int64_t>(pin_value.size() - 1); // stop_index int 1024 bytes segment
if (i == start_index) {
start_in_segment = u_start % kBitmapSegmentBytes;
if (is_bit_index && start_in_segment <= stop_in_segment && first_byte_neg_mask != 0) {
uint8_t first_mask_byte =
kBitSwapTable[static_cast<uint8_t>(pin_value[start_in_segment])] & first_byte_neg_mask;
mask_cnt += BitmapString::RawPopcount(&first_mask_byte, 1);
}
}
if (i == stop_index) {
stop_in_segment = u_stop % kBitmapSegmentBytes;
if (is_bit_index && start_in_segment <= stop_in_segment && last_byte_neg_mask != 0) {
uint8_t last_mask_byte = kBitSwapTable[static_cast<uint8_t>(pin_value[stop_in_segment])] & last_byte_neg_mask;
mask_cnt += BitmapString::RawPopcount(&last_mask_byte, 1);
}
}
int64_t bytes = 0;
if (stop_in_segment >= start_in_segment) {
bytes = stop_in_segment - start_in_segment + 1;
}
*cnt += BitmapString::RawPopcount(reinterpret_cast<const uint8_t *>(pin_value.data()) + start_in_segment, bytes);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
int64_t start_in_segment = 0; // start_index int 1024 bytes segment
auto stop_in_segment = static_cast<int64_t>(pin_value.size() - 1); // stop_index int 1024 bytes segment
if (i == start_index) {
start_in_segment = u_start % kBitmapSegmentBytes;
if (is_bit_index && start_in_segment <= stop_in_segment && first_byte_neg_mask != 0) {
uint8_t first_mask_byte =
kBitSwapTable[static_cast<uint8_t>(pin_value[start_in_segment])] & first_byte_neg_mask;
mask_cnt += BitmapString::RawPopcount(&first_mask_byte, 1);
}
}
if (i == stop_index) {
stop_in_segment = u_stop % kBitmapSegmentBytes;
if (is_bit_index && start_in_segment <= stop_in_segment && last_byte_neg_mask != 0) {
uint8_t last_mask_byte = kBitSwapTable[static_cast<uint8_t>(pin_value[stop_in_segment])] & last_byte_neg_mask;
mask_cnt += BitmapString::RawPopcount(&last_mask_byte, 1);
}
}
int64_t bytes = 0;
if (stop_in_segment >= start_in_segment) {
bytes = stop_in_segment - start_in_segment + 1;
}
*cnt += BitmapString::RawPopcount(reinterpret_cast<const uint8_t *>(pin_value.data()) + start_in_segment, bytes);
// Counting bits in [start_in_segment, stop_in_segment]
int64_t start_in_segment = 0; // start_index int 1024 bytes segment
auto readable_stop_in_segment = static_cast<int64_t>(pin_value.size() - 1); // stop_index int 1024 bytes segment
auto stop_in_segment = readable_stop_in_segment;
if (i == start_index) {
start_in_segment = u_start % kBitmapSegmentBytes;
if (is_bit_index && start_in_segment <= readable_stop_in_segment && first_byte_neg_mask != 0) {
uint8_t first_mask_byte =
kBitSwapTable[static_cast<uint8_t>(pin_value[start_in_segment])] & first_byte_neg_mask;
mask_cnt += BitmapString::RawPopcount(&first_mask_byte, 1);
}
}
if (i == stop_index) {
stop_in_segment = u_stop % kBitmapSegmentBytes;
if (is_bit_index && stop_in_segment <= readable_stop_in_segment && last_byte_neg_mask != 0) {
uint8_t last_mask_byte = kBitSwapTable[static_cast<uint8_t>(pin_value[stop_in_segment])] & last_byte_neg_mask;
mask_cnt += BitmapString::RawPopcount(&last_mask_byte, 1);
}
}
if (stop_in_segment >= start_in_segment && readable_stop_in_segment >= start_in_segment) {
int64_t bytes = 0;
bytes = std::min(stop_in_segment, readable_stop_in_segment) - start_in_segment + 1;
*cnt += BitmapString::RawPopcount(reinterpret_cast<const uint8_t *>(pin_value.data()) + start_in_segment, bytes);
}

@mapleFU
Copy link
Member

mapleFU commented Feb 6, 2024

@kay011 My edits are listed above

@kay011
Copy link
Contributor Author

kay011 commented Feb 6, 2024

@kay011 My edits are listed above
Got it. Let me merge it on this commit.

Copy link

sonarcloud bot commented Feb 6, 2024

Quality Gate Passed Quality Gate passed

The SonarCloud Quality Gate passed, but some issues were introduced.

13 New issues
0 Security Hotspots
89.7% Coverage on New Code
0.0% Duplication on New Code

See analysis details on SonarCloud

@mapleFU
Copy link
Member

mapleFU commented Feb 6, 2024

Will wait before Friday to waiting others review it, since I'm one of the editor.

@PragmaTwice PragmaTwice merged commit 5940b73 into apache:unstable Feb 7, 2024
30 checks passed
@jihuayu
Copy link
Member

jihuayu commented Feb 7, 2024

Thanks @kay011. BITOPS also doesn't support BIT option #1212

Do you like to have a try?

@kay011
Copy link
Contributor Author

kay011 commented Feb 7, 2024

Thanks @kay011. BITOPS also doesn't support BIT option #1212

Do you like to have a try?

@jihuayu Yeah, I am willing to do it.

JoverZhang pushed a commit to JoverZhang/kvrocks that referenced this pull request Feb 24, 2024
@jihuayu jihuayu mentioned this pull request Mar 11, 2024
2 tasks
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.

Add BIT option support for BITCOUNT command
5 participants