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

Move sub bucket #625

Closed
wants to merge 2 commits into from
Closed

Move sub bucket #625

wants to merge 2 commits into from

Conversation

Elbehery
Copy link
Member

cc @ahrtr

…nother bucket

Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
bucket_test.go Outdated
if v == nil {
t.Fatal()
}
//curDst := dstBucket.Cursor()
Copy link
Member Author

Choose a reason for hiding this comment

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

I tried to use seek() to verify the subBucket is moved correctly, but I got stuck :/

I still need to

  • check for cornet cases
  • verify that
//  1. the sub-bucket cannot be found in the source bucket;
//  2. or the key already exists in the destination bucket;
//  3. the key represents a non-bucket value.

ptal if i am on the right path, otherwise correct me please ( fail fast ) :D

Copy link
Member Author

Choose a reason for hiding this comment

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

cc @ahrtr ^^

@Elbehery Elbehery force-pushed the move_subBucket branch 4 times, most recently from 381b51e to accffe2 Compare November 28, 2023 14:05
@Elbehery
Copy link
Member Author

@ahrtr i finished the test, i covered all the possible cases iiuc :)

ptal

cc @tjungblu @fuweid @serathius

// 1. the sub-bucket cannot be found in the source bucket;
// 2. or the key already exists in the destination bucket;
// 3. the key represents a non-bucket value.
func (tx *Tx) MoveSubBucket(name []byte, src *Bucket, dst *Bucket) error {
Copy link
Member

@fuweid fuweid Nov 29, 2023

Choose a reason for hiding this comment

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

It seems tx is unused here. I think we don't need this method.

Copy link
Member

@ahrtr ahrtr Nov 29, 2023

Choose a reason for hiding this comment

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

good catch!

I was thinking to support moving top level bucket. In that case, no need to provide the source bucket, the signature & implementation will be below,

func (tx *Tx) MoveSubBucket(name []byte, src *Bucket, dst *Bucket) error {
    if src != nil {
        return src.MoveSubBucket(name, dst)
    }
    return tx.root.MoveSubBucket(name, dst)
}

Copy link
Member

Choose a reason for hiding this comment

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

@Elbehery Could you help to update it in this PR?

Copy link
Member Author

Choose a reason for hiding this comment

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

@ahrtr I am confused now

how can I specify the root bucket explicitly, it is being init by the tx

bbolt/tx.go

Line 54 in 4261e22

// Copy over the root bucket.

Copy link
Member

Choose a reason for hiding this comment

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

Yes. tx.root is root bucket.

name string
srcBucketName string
subBucketName string
subBucketKey string
Copy link
Member

Choose a reason for hiding this comment

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

Maybe we can add a case to create non-inline sub bucket here.

Copy link
Member Author

Choose a reason for hiding this comment

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

u mean to use the src bucket as root bucket ?

Copy link
Member

Choose a reason for hiding this comment

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

For the bucket, if the key or sub-bucket is small, the bucket can store those in value. It' s inline type.
If the key/value is large enough to allocate new page(s) for that, the bucket value only stores the root page id.
Just want to verify these two cases.

Yeah, since you change the tx.MoveSubBucket to support root bucket, it should add some cases to cover that.

t.Fatalf("dst bucket %s does not exist: %v", tc.dstBucketName, berrors.ErrBucketNotFound)
}

mvErr := tx.MoveSubBucket([]byte(tc.subBucketName), srcBucket, dstBucket)
Copy link
Member Author

Choose a reason for hiding this comment

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

@ahrtr @fuweid i have used it here

I think it is better to keep this method, so we can create move-bucket cmd later on, wdyt ?

Signed-off-by: Mustafa Elbehery <melbeher@redhat.com>
nil,
},
{
"subBucket not exist in root bucket",
Copy link
Member Author

Choose a reason for hiding this comment

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

@fuweid @ahrtr I added these tests to tx_text, i adapted the code to test only the case when the srcBucket is nil, since these cases are covered by bucket_test

ptal

Copy link
Member

Choose a reason for hiding this comment

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

The dst could be nil as well. Please take a look at the original PR.

subBucketExistDstBucket bool
keyNoSubBucketSrcBucket bool
keyNoSubBucketDstBucket bool
expErr error
Copy link
Member

@fuweid fuweid Dec 1, 2023

Choose a reason for hiding this comment

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

Overall, it looks good to me.

For the test case, I was thinking about that introducing slice to define the path, since it's hard to follow the code with too many bools here.

During preparing data, that test case can use srcBucketPath []string to define depth of bucket. For instance,
[x, y, z]. The bucket will be like root -> x -> y -> z. srcKeyValues [][2]string is to define key value in the srcBucketPath. If it's empty, That z doesn't contain any key values. It also applies to dst.

If there is no expected error, the root -> x -> y -> z should be not found and that z should show in dstBucketPath. And all the srcKeyValues should be stored in dstBucketPath -> z.

WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

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

i can change it, but i think the booleans are easier for a reader to understand the what & how

maybe the bool names needs to be more self explanatory

wdyt @ahrtr @serathius @tjungblu

@ahrtr
Copy link
Member

ahrtr commented Dec 3, 2023

I updated the original PR #621, Please take a look.

@ahrtr
Copy link
Member

ahrtr commented Dec 4, 2023

High level the test workflow including three steps make sense,

  • create sample database
  • move a child bucket
  • verify there is no any change for child bucket's content before and after the moving

Comments:

  • The sample database should contain multiple possibilities
    • Contain big key/value so that the overflow in page header > 1
    • Huge number of key/value so that it can't be nested bucket
    • The src or dst bucket are the root bucket
    • There are multiple layer of the child bucket.
    • negative cases
  • Make the verification more generic
    • Dump the child bucket into a separate [bbolt db] file before moving it;
    • Dump the child bucket into another separate [bbolt db] file after the moving;
    • Compare the two files.

@ahrtr ahrtr deleted the branch etcd-io:master December 12, 2023 10:26
@ahrtr ahrtr closed this Dec 12, 2023
@ahrtr
Copy link
Member

ahrtr commented Dec 12, 2023

Sorry, the PR is automatically closed after renaming the master to main. Please feel free to submit a new PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants