MoveBucket moves a sub-bucket from the source bucket to the destination bucket. Returns an error if 1. the sub-bucket cannot be found in the source bucket; 2. or the key already exists in the destination bucket; 3. or the key represents a non-bucket value; 4. the source and destination buckets are t
(key []byte, dstBucket *Bucket)
| 334 | // 3. or the key represents a non-bucket value; |
| 335 | // 4. the source and destination buckets are the same. |
| 336 | func (b *Bucket) MoveBucket(key []byte, dstBucket *Bucket) (err error) { |
| 337 | lg := b.tx.db.Logger() |
| 338 | if lg != discardLogger { |
| 339 | lg.Debugf("Moving bucket %q", key) |
| 340 | defer func() { |
| 341 | if err != nil { |
| 342 | lg.Errorf("Moving bucket %q failed: %v", key, err) |
| 343 | } else { |
| 344 | lg.Debugf("Moving bucket %q successfully", key) |
| 345 | } |
| 346 | }() |
| 347 | } |
| 348 | |
| 349 | if b.tx.db == nil || dstBucket.tx.db == nil { |
| 350 | return errors.ErrTxClosed |
| 351 | } else if !b.Writable() || !dstBucket.Writable() { |
| 352 | return errors.ErrTxNotWritable |
| 353 | } |
| 354 | |
| 355 | if b.tx.db.Path() != dstBucket.tx.db.Path() || b.tx != dstBucket.tx { |
| 356 | lg.Errorf("The source and target buckets are not in the same db file, source bucket in %s and target bucket in %s", b.tx.db.Path(), dstBucket.tx.db.Path()) |
| 357 | return errors.ErrDifferentDB |
| 358 | } |
| 359 | |
| 360 | newKey := cloneBytes(key) |
| 361 | |
| 362 | // Move cursor to correct position. |
| 363 | c := b.Cursor() |
| 364 | k, v, flags := c.seek(newKey) |
| 365 | |
| 366 | // Return an error if bucket doesn't exist or is not a bucket. |
| 367 | if !bytes.Equal(newKey, k) { |
| 368 | return errors.ErrBucketNotFound |
| 369 | } else if (flags & common.BucketLeafFlag) == 0 { |
| 370 | lg.Errorf("An incompatible key %s exists in the source bucket", newKey) |
| 371 | return errors.ErrIncompatibleValue |
| 372 | } |
| 373 | |
| 374 | // Do nothing (return true directly) if the source bucket and the |
| 375 | // destination bucket are actually the same bucket. |
| 376 | if b == dstBucket || (b.RootPage() == dstBucket.RootPage() && b.RootPage() != 0) { |
| 377 | lg.Errorf("The source bucket (%s) and the target bucket (%s) are the same bucket", b, dstBucket) |
| 378 | return errors.ErrSameBuckets |
| 379 | } |
| 380 | |
| 381 | // check whether the key already exists in the destination bucket |
| 382 | curDst := dstBucket.Cursor() |
| 383 | k, _, flags = curDst.seek(newKey) |
| 384 | |
| 385 | // Return an error if there is an existing key in the destination bucket. |
| 386 | if bytes.Equal(newKey, k) { |
| 387 | if (flags & common.BucketLeafFlag) != 0 { |
| 388 | return errors.ErrBucketExists |
| 389 | } |
| 390 | lg.Errorf("An incompatible key %s exists in the target bucket", newKey) |
| 391 | return errors.ErrIncompatibleValue |
| 392 | } |
| 393 |