github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/mdserver_disk.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libkbfs 6 7 import ( 8 "bytes" 9 "os" 10 "path/filepath" 11 "reflect" 12 "sync" 13 "time" 14 15 "github.com/keybase/client/go/kbfs/ioutil" 16 "github.com/keybase/client/go/kbfs/kbfsmd" 17 "github.com/keybase/client/go/kbfs/ldbutils" 18 "github.com/keybase/client/go/kbfs/tlf" 19 "github.com/keybase/client/go/logger" 20 "github.com/keybase/client/go/protocol/keybase1" 21 "github.com/pkg/errors" 22 "github.com/syndtr/goleveldb/leveldb" 23 "golang.org/x/net/context" 24 ) 25 26 type mdServerDiskShared struct { 27 dirPath string 28 29 // Protects handleDb, branchDb, tlfStorage, and 30 // truncateLockManager. After Shutdown() is called, handleDb, 31 // branchDb, tlfStorage, and truncateLockManager are nil. 32 lock sync.RWMutex // nolint 33 // Bare TLF handle -> TLF ID 34 handleDb *leveldb.DB 35 // (TLF ID, device crypt public key) -> branch ID 36 branchDb *leveldb.DB 37 tlfStorage map[tlf.ID]*mdServerTlfStorage 38 // Always use memory for the lock storage, so it gets wiped 39 // after a restart. 40 truncateLockManager *mdServerLocalTruncateLockManager 41 implicitTeamsEnabled bool // nolint 42 // In-memory only, for now. 43 merkleRoots map[keybase1.MerkleTreeID]*kbfsmd.MerkleRoot 44 45 updateManager *mdServerLocalUpdateManager 46 47 shutdownFunc func(logger.Logger) 48 } 49 50 // MDServerDisk stores all info on disk, either in levelDBs, or disk 51 // journals and flat files for the actual MDs. 52 type MDServerDisk struct { 53 config mdServerLocalConfig 54 log logger.Logger 55 56 *mdServerDiskShared 57 } 58 59 var _ mdServerLocal = (*MDServerDisk)(nil) 60 61 func newMDServerDisk(config mdServerLocalConfig, dirPath string, 62 shutdownFunc func(logger.Logger)) (*MDServerDisk, error) { 63 handlePath := filepath.Join(dirPath, "handles") 64 handleDb, err := leveldb.OpenFile(handlePath, ldbutils.LeveldbOptions(nil)) 65 if err != nil { 66 return nil, err 67 } 68 69 branchPath := filepath.Join(dirPath, "branches") 70 branchDb, err := leveldb.OpenFile(branchPath, ldbutils.LeveldbOptions(nil)) 71 if err != nil { 72 return nil, err 73 } 74 log := config.MakeLogger("MDSD") 75 truncateLockManager := newMDServerLocalTruncatedLockManager() 76 shared := mdServerDiskShared{ 77 dirPath: dirPath, 78 handleDb: handleDb, 79 branchDb: branchDb, 80 tlfStorage: make(map[tlf.ID]*mdServerTlfStorage), 81 truncateLockManager: &truncateLockManager, 82 updateManager: newMDServerLocalUpdateManager(), 83 shutdownFunc: shutdownFunc, 84 merkleRoots: make(map[keybase1.MerkleTreeID]*kbfsmd.MerkleRoot), 85 } 86 mdserv := &MDServerDisk{config, log, &shared} 87 return mdserv, nil 88 } 89 90 // NewMDServerDir constructs a new MDServerDisk that stores its data 91 // in the given directory. 92 func NewMDServerDir( 93 config mdServerLocalConfig, dirPath string) (*MDServerDisk, error) { 94 return newMDServerDisk(config, dirPath, nil) 95 } 96 97 // NewMDServerTempDir constructs a new MDServerDisk that stores its 98 // data in a temp directory which is cleaned up on shutdown. 99 func NewMDServerTempDir(config mdServerLocalConfig) (*MDServerDisk, error) { 100 tempdir, err := ioutil.TempDir(os.TempDir(), "kbfs_mdserver_tmp") 101 if err != nil { 102 return nil, err 103 } 104 return newMDServerDisk(config, tempdir, func(log logger.Logger) { 105 err := ioutil.RemoveAll(tempdir) 106 if err != nil { 107 log.Warning("error removing %s: %s", tempdir, err) 108 } 109 }) 110 } 111 112 type errMDServerDiskShutdown struct{} 113 114 func (e errMDServerDiskShutdown) Error() string { 115 return "MDServerDisk is shutdown" 116 } 117 118 func (md *MDServerDisk) checkShutdownLocked() error { 119 if md.tlfStorage == nil { 120 return errors.WithStack(errMDServerDiskShutdown{}) 121 } 122 return nil 123 } 124 125 func (md *MDServerDisk) enableImplicitTeams() { 126 md.lock.Lock() 127 defer md.lock.Unlock() 128 md.implicitTeamsEnabled = true 129 } 130 131 func (md *MDServerDisk) setKbfsMerkleRoot( 132 treeID keybase1.MerkleTreeID, root *kbfsmd.MerkleRoot) { 133 md.lock.Lock() 134 defer md.lock.Unlock() 135 md.merkleRoots[treeID] = root 136 } 137 138 func (md *MDServerDisk) getStorage(tlfID tlf.ID) (*mdServerTlfStorage, error) { 139 storage, err := func() (*mdServerTlfStorage, error) { 140 md.lock.RLock() 141 defer md.lock.RUnlock() 142 err := md.checkShutdownLocked() 143 if err != nil { 144 return nil, err 145 } 146 return md.tlfStorage[tlfID], nil 147 }() 148 149 if err != nil { 150 return nil, err 151 } 152 153 if storage != nil { 154 return storage, nil 155 } 156 157 md.lock.Lock() 158 defer md.lock.Unlock() 159 if md.tlfStorage == nil { 160 return nil, errors.WithStack(errMDServerDiskShutdown{}) 161 } 162 163 storage = md.tlfStorage[tlfID] 164 if storage != nil { 165 return storage, nil 166 } 167 168 path := filepath.Join(md.dirPath, tlfID.String()) 169 storage = makeMDServerTlfStorage( 170 tlfID, md.config.Codec(), 171 md.config.Clock(), md.config.teamMembershipChecker(), 172 md.config.MetadataVersion(), path) 173 174 md.tlfStorage[tlfID] = storage 175 return storage, nil 176 } 177 178 func (md *MDServerDisk) getHandleID(ctx context.Context, handle tlf.Handle, 179 mStatus kbfsmd.MergeStatus) (tlfID tlf.ID, created bool, err error) { 180 handleBytes, err := md.config.Codec().Encode(handle) 181 if err != nil { 182 return tlf.NullID, false, kbfsmd.ServerError{Err: err} 183 } 184 185 md.lock.Lock() 186 defer md.lock.Unlock() 187 err = md.checkShutdownLocked() 188 if err != nil { 189 return tlf.NullID, false, err 190 } 191 192 buf, err := md.handleDb.Get(handleBytes, nil) 193 if err != nil && err != leveldb.ErrNotFound { 194 return tlf.NullID, false, kbfsmd.ServerError{Err: err} 195 } 196 if err == nil { 197 var id tlf.ID 198 err := id.UnmarshalBinary(buf) 199 if err != nil { 200 return tlf.NullID, false, kbfsmd.ServerError{Err: err} 201 } 202 return id, false, nil 203 } 204 205 // Non-readers shouldn't be able to create the dir. 206 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 207 if err != nil { 208 return tlf.NullID, false, kbfsmd.ServerError{Err: err} 209 } 210 if handle.Type() == tlf.SingleTeam { 211 isReader, err := md.config.teamMembershipChecker().IsTeamReader( 212 ctx, handle.Writers[0].AsTeamOrBust(), session.UID, 213 keybase1.OfflineAvailability_NONE) 214 if err != nil { 215 return tlf.NullID, false, kbfsmd.ServerError{Err: err} 216 } else if !isReader { 217 return tlf.NullID, false, kbfsmd.ServerErrorUnauthorized{} 218 } 219 } else if !handle.IsReader(session.UID.AsUserOrTeam()) { 220 return tlf.NullID, false, kbfsmd.ServerErrorUnauthorized{} 221 } 222 223 if md.implicitTeamsEnabled { 224 return tlf.NullID, false, kbfsmd.ServerErrorClassicTLFDoesNotExist{} 225 } 226 227 // Allocate a new random ID. 228 id, err := md.config.cryptoPure().MakeRandomTlfID(handle.Type()) 229 if err != nil { 230 return tlf.NullID, false, kbfsmd.ServerError{Err: err} 231 } 232 233 err = md.handleDb.Put(handleBytes, id.Bytes(), nil) 234 if err != nil { 235 return tlf.NullID, false, kbfsmd.ServerError{Err: err} 236 } 237 return id, true, nil 238 } 239 240 // GetForHandle implements the MDServer interface for MDServerDisk. 241 func (md *MDServerDisk) GetForHandle(ctx context.Context, handle tlf.Handle, 242 mStatus kbfsmd.MergeStatus, _ *keybase1.LockID) ( 243 tlf.ID, *RootMetadataSigned, error) { 244 if err := checkContext(ctx); err != nil { 245 return tlf.NullID, nil, err 246 } 247 248 id, created, err := md.getHandleID(ctx, handle, mStatus) 249 if err != nil { 250 return tlf.NullID, nil, err 251 } 252 253 if created { 254 return id, nil, nil 255 } 256 257 rmds, err := md.GetForTLF(ctx, id, kbfsmd.NullBranchID, mStatus, nil) 258 if err != nil { 259 return tlf.NullID, nil, err 260 } 261 return id, rmds, nil 262 } 263 264 func (md *MDServerDisk) getBranchKey(ctx context.Context, id tlf.ID) ([]byte, error) { 265 buf := &bytes.Buffer{} 266 // add folder id 267 _, err := buf.Write(id.Bytes()) 268 if err != nil { 269 return nil, err 270 } 271 // add device key 272 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 273 if err != nil { 274 return nil, err 275 } 276 _, err = buf.Write(session.CryptPublicKey.KID().ToBytes()) 277 if err != nil { 278 return nil, err 279 } 280 return buf.Bytes(), nil 281 } 282 283 func (md *MDServerDisk) getBranchID(ctx context.Context, id tlf.ID) (kbfsmd.BranchID, error) { 284 branchKey, err := md.getBranchKey(ctx, id) 285 if err != nil { 286 return kbfsmd.NullBranchID, kbfsmd.ServerError{Err: err} 287 } 288 289 md.lock.RLock() 290 defer md.lock.RUnlock() 291 err = md.checkShutdownLocked() 292 if err != nil { 293 return kbfsmd.NullBranchID, err 294 } 295 296 buf, err := md.branchDb.Get(branchKey, nil) 297 if err == leveldb.ErrNotFound { 298 return kbfsmd.NullBranchID, nil 299 } 300 if err != nil { 301 return kbfsmd.NullBranchID, kbfsmd.ServerErrorBadRequest{Reason: "Invalid branch ID"} 302 } 303 var bid kbfsmd.BranchID 304 err = md.config.Codec().Decode(buf, &bid) 305 if err != nil { 306 return kbfsmd.NullBranchID, kbfsmd.ServerErrorBadRequest{Reason: "Invalid branch ID"} 307 } 308 return bid, nil 309 } 310 311 func (md *MDServerDisk) putBranchID( 312 ctx context.Context, id tlf.ID, bid kbfsmd.BranchID) error { 313 md.lock.Lock() 314 defer md.lock.Unlock() 315 err := md.checkShutdownLocked() 316 if err != nil { 317 return err 318 } 319 320 branchKey, err := md.getBranchKey(ctx, id) 321 if err != nil { 322 return kbfsmd.ServerError{Err: err} 323 } 324 buf, err := md.config.Codec().Encode(bid) 325 if err != nil { 326 return kbfsmd.ServerError{Err: err} 327 } 328 err = md.branchDb.Put(branchKey, buf, nil) 329 if err != nil { 330 return kbfsmd.ServerError{Err: err} 331 } 332 333 return nil 334 } 335 336 func (md *MDServerDisk) deleteBranchID(ctx context.Context, id tlf.ID) error { 337 md.lock.Lock() 338 defer md.lock.Unlock() 339 err := md.checkShutdownLocked() 340 if err != nil { 341 return err 342 } 343 344 branchKey, err := md.getBranchKey(ctx, id) 345 if err != nil { 346 return kbfsmd.ServerError{Err: err} 347 } 348 err = md.branchDb.Delete(branchKey, nil) 349 if err != nil { 350 return kbfsmd.ServerError{Err: err} 351 } 352 return nil 353 } 354 355 // GetForTLF implements the MDServer interface for MDServerDisk. 356 func (md *MDServerDisk) GetForTLF(ctx context.Context, id tlf.ID, 357 bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus, _ *keybase1.LockID) ( 358 *RootMetadataSigned, error) { 359 if err := checkContext(ctx); err != nil { 360 return nil, err 361 } 362 363 // Lookup the branch ID if not supplied 364 if mStatus == kbfsmd.Unmerged && bid == kbfsmd.NullBranchID { 365 var err error 366 bid, err = md.getBranchID(ctx, id) 367 if err != nil { 368 return nil, err 369 } 370 if bid == kbfsmd.NullBranchID { 371 return nil, nil 372 } 373 } 374 375 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 376 if err != nil { 377 return nil, kbfsmd.ServerError{Err: err} 378 } 379 380 tlfStorage, err := md.getStorage(id) 381 if err != nil { 382 return nil, err 383 } 384 385 return tlfStorage.getForTLF(ctx, session.UID, bid) 386 } 387 388 // GetForTLFByTime implements the MDServer interface for MDServerDisk. 389 func (md *MDServerDisk) GetForTLFByTime( 390 ctx context.Context, id tlf.ID, serverTime time.Time) ( 391 *RootMetadataSigned, error) { 392 if err := checkContext(ctx); err != nil { 393 return nil, err 394 } 395 396 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 397 if err != nil { 398 return nil, kbfsmd.ServerError{Err: err} 399 } 400 401 tlfStorage, err := md.getStorage(id) 402 if err != nil { 403 return nil, err 404 } 405 406 rmd, err := tlfStorage.getForTLF(ctx, session.UID, kbfsmd.NullBranchID) 407 if err != nil { 408 return nil, err 409 } 410 411 // Do a linear backwards search to find the RMD that comes just 412 // before or at `serverTime`. 413 for rmd.untrustedServerTimestamp.After(serverTime) { 414 nextRev := rmd.MD.RevisionNumber() - 1 415 if nextRev == kbfsmd.RevisionUninitialized { 416 return nil, errors.Errorf( 417 "No MD found for TLF %s and serverTime %s", id, serverTime) 418 } 419 mds, err := tlfStorage.getRange( 420 ctx, session.UID, kbfsmd.NullBranchID, nextRev, nextRev) 421 if err != nil { 422 return nil, err 423 } 424 if len(mds) != 1 { 425 return nil, errors.Errorf( 426 "No MD found for TLF %s and serverTime %s", id, serverTime) 427 } 428 rmd = mds[0] 429 } 430 431 return rmd, nil 432 } 433 434 // GetRange implements the MDServer interface for MDServerDisk. 435 func (md *MDServerDisk) GetRange(ctx context.Context, id tlf.ID, 436 bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus, start, stop kbfsmd.Revision, 437 _ *keybase1.LockID) ([]*RootMetadataSigned, error) { 438 if err := checkContext(ctx); err != nil { 439 return nil, err 440 } 441 442 md.log.CDebugf(ctx, "GetRange %d %d (%s)", start, stop, mStatus) 443 444 // Lookup the branch ID if not supplied 445 if mStatus == kbfsmd.Unmerged && bid == kbfsmd.NullBranchID { 446 var err error 447 bid, err = md.getBranchID(ctx, id) 448 if err != nil { 449 return nil, err 450 } 451 if bid == kbfsmd.NullBranchID { 452 return nil, nil 453 } 454 } 455 456 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 457 if err != nil { 458 return nil, kbfsmd.ServerError{Err: err} 459 } 460 461 tlfStorage, err := md.getStorage(id) 462 if err != nil { 463 return nil, err 464 } 465 466 return tlfStorage.getRange(ctx, session.UID, bid, start, stop) 467 } 468 469 // Put implements the MDServer interface for MDServerDisk. 470 func (md *MDServerDisk) Put(ctx context.Context, rmds *RootMetadataSigned, 471 extra kbfsmd.ExtraMetadata, _ *keybase1.LockContext, _ keybase1.MDPriority) error { 472 if err := checkContext(ctx); err != nil { 473 return err 474 } 475 476 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 477 if err != nil { 478 return kbfsmd.ServerError{Err: err} 479 } 480 481 tlfStorage, err := md.getStorage(rmds.MD.TlfID()) 482 if err != nil { 483 return err 484 } 485 486 recordBranchID, err := tlfStorage.put( 487 ctx, session.UID, session.VerifyingKey, rmds, extra) 488 if err != nil { 489 return err 490 } 491 492 // Record branch ID 493 if recordBranchID { 494 err = md.putBranchID(ctx, rmds.MD.TlfID(), rmds.MD.BID()) 495 if err != nil { 496 return kbfsmd.ServerError{Err: err} 497 } 498 } 499 500 mStatus := rmds.MD.MergedStatus() 501 if mStatus == kbfsmd.Merged && 502 // Don't send notifies if it's just a rekey (the real mdserver 503 // sends a "folder needs rekey" notification in this case). 504 !(rmds.MD.IsRekeySet() && rmds.MD.IsWriterMetadataCopiedSet()) { 505 md.updateManager.setHead(rmds.MD.TlfID(), md) 506 } 507 508 return nil 509 } 510 511 // Lock (does not) implement the MDServer interface for MDServerDisk. 512 func (*MDServerDisk) Lock(ctx context.Context, 513 tlfID tlf.ID, lockID keybase1.LockID) error { 514 panic("Lock called on *MDServerDisk") 515 } 516 517 // ReleaseLock (does not) implement the MDServer interface for MDServerDisk. 518 func (*MDServerDisk) ReleaseLock(ctx context.Context, 519 tlfID tlf.ID, lockID keybase1.LockID) error { 520 panic("ReleaseLock called on *MDServerDisk") 521 } 522 523 // StartImplicitTeamMigration implements the MDServer interface. 524 func (md *MDServerDisk) StartImplicitTeamMigration( 525 ctx context.Context, id tlf.ID) (err error) { 526 panic("StartImplicitTeamMigration called on *MDServerDisk") 527 } 528 529 // PruneBranch implements the MDServer interface for MDServerDisk. 530 func (md *MDServerDisk) PruneBranch(ctx context.Context, id tlf.ID, bid kbfsmd.BranchID) error { 531 if err := checkContext(ctx); err != nil { 532 return err 533 } 534 535 if bid == kbfsmd.NullBranchID { 536 return kbfsmd.ServerErrorBadRequest{Reason: "Invalid branch ID"} 537 } 538 539 currBID, err := md.getBranchID(ctx, id) 540 if err != nil { 541 return err 542 } 543 if currBID == kbfsmd.NullBranchID || bid != currBID { 544 return kbfsmd.ServerErrorBadRequest{Reason: "Invalid branch ID"} 545 } 546 547 // Don't actually delete unmerged history. This is intentional 548 // to be consistent with the mdserver behavior-- it garbage 549 // collects discarded branches in the background. 550 return md.deleteBranchID(ctx, id) 551 } 552 553 func (md *MDServerDisk) getCurrentMergedHeadRevision( 554 ctx context.Context, id tlf.ID) (rev kbfsmd.Revision, err error) { 555 head, err := md.GetForTLF(ctx, id, kbfsmd.NullBranchID, kbfsmd.Merged, nil) 556 if err != nil { 557 return 0, err 558 } 559 if head != nil { 560 rev = head.MD.RevisionNumber() 561 } 562 return 563 } 564 565 // RegisterForUpdate implements the MDServer interface for MDServerDisk. 566 func (md *MDServerDisk) RegisterForUpdate(ctx context.Context, id tlf.ID, 567 currHead kbfsmd.Revision) (<-chan error, error) { 568 if err := checkContext(ctx); err != nil { 569 return nil, err 570 } 571 572 // are we already past this revision? If so, fire observer 573 // immediately 574 currMergedHeadRev, err := md.getCurrentMergedHeadRevision(ctx, id) 575 if err != nil { 576 return nil, err 577 } 578 579 c := md.updateManager.registerForUpdate(id, currHead, currMergedHeadRev, md) 580 return c, nil 581 } 582 583 // CancelRegistration implements the MDServer interface for MDServerDisk. 584 func (md *MDServerDisk) CancelRegistration(_ context.Context, id tlf.ID) { 585 md.updateManager.cancel(id, md) 586 } 587 588 // TruncateLock implements the MDServer interface for MDServerDisk. 589 func (md *MDServerDisk) TruncateLock(ctx context.Context, id tlf.ID) ( 590 bool, error) { 591 if err := checkContext(ctx); err != nil { 592 return false, err 593 } 594 595 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 596 if err != nil { 597 return false, kbfsmd.ServerError{Err: err} 598 } 599 600 md.lock.Lock() 601 defer md.lock.Unlock() 602 err = md.checkShutdownLocked() 603 if err != nil { 604 return false, err 605 } 606 607 return md.truncateLockManager.truncateLock(session.CryptPublicKey, id) 608 } 609 610 // TruncateUnlock implements the MDServer interface for MDServerDisk. 611 func (md *MDServerDisk) TruncateUnlock(ctx context.Context, id tlf.ID) ( 612 bool, error) { 613 if err := checkContext(ctx); err != nil { 614 return false, err 615 } 616 617 session, err := md.config.currentSessionGetter().GetCurrentSession(ctx) 618 if err != nil { 619 return false, kbfsmd.ServerError{Err: err} 620 } 621 622 md.lock.Lock() 623 defer md.lock.Unlock() 624 err = md.checkShutdownLocked() 625 if err != nil { 626 return false, err 627 } 628 629 return md.truncateLockManager.truncateUnlock(session.CryptPublicKey, id) 630 } 631 632 // Shutdown implements the MDServer interface for MDServerDisk. 633 func (md *MDServerDisk) Shutdown() { 634 md.lock.Lock() 635 defer md.lock.Unlock() 636 if md.handleDb == nil { 637 return 638 } 639 640 // Make further accesses error out. 641 642 md.handleDb.Close() 643 md.handleDb = nil 644 645 md.branchDb.Close() 646 md.branchDb = nil 647 648 tlfStorage := md.tlfStorage 649 md.tlfStorage = nil 650 651 for _, s := range tlfStorage { 652 s.shutdown() 653 } 654 655 if md.shutdownFunc != nil { 656 md.shutdownFunc(md.log) 657 } 658 } 659 660 // IsConnected implements the MDServer interface for MDServerDisk. 661 func (md *MDServerDisk) IsConnected() bool { 662 return !md.isShutdown() 663 } 664 665 // RefreshAuthToken implements the MDServer interface for MDServerDisk. 666 func (md *MDServerDisk) RefreshAuthToken(ctx context.Context) {} 667 668 // This should only be used for testing with an in-memory server. 669 func (md *MDServerDisk) copy(config mdServerLocalConfig) mdServerLocal { 670 // NOTE: observers and sessionHeads are copied shallowly on 671 // purpose, so that the MD server that gets a Put will notify all 672 // observers correctly no matter where they got on the list. 673 log := config.MakeLogger("") 674 return &MDServerDisk{config, log, md.mdServerDiskShared} 675 } 676 677 // isShutdown returns whether the logical, shared MDServer instance 678 // has been shut down. 679 func (md *MDServerDisk) isShutdown() bool { 680 md.lock.RLock() 681 defer md.lock.RUnlock() 682 return md.checkShutdownLocked() != nil 683 } 684 685 // DisableRekeyUpdatesForTesting implements the MDServer interface. 686 func (md *MDServerDisk) DisableRekeyUpdatesForTesting() { 687 // Nothing to do. 688 } 689 690 // CheckForRekeys implements the MDServer interface. 691 func (md *MDServerDisk) CheckForRekeys(ctx context.Context) <-chan error { 692 // Nothing to do 693 c := make(chan error, 1) 694 c <- nil 695 return c 696 } 697 698 func (md *MDServerDisk) addNewAssertionForTest(uid keybase1.UID, 699 newAssertion keybase1.SocialAssertion) error { 700 md.lock.Lock() 701 defer md.lock.Unlock() 702 err := md.checkShutdownLocked() 703 if err != nil { 704 return err 705 } 706 707 // Iterate through all the handles, and add handles for ones 708 // containing newAssertion to now include the uid. 709 iter := md.handleDb.NewIterator(nil, nil) 710 defer iter.Release() 711 for iter.Next() { 712 handleBytes := iter.Key() 713 var handle tlf.Handle 714 err := md.config.Codec().Decode(handleBytes, &handle) 715 if err != nil { 716 return err 717 } 718 assertions := map[keybase1.SocialAssertion]keybase1.UID{ 719 newAssertion: uid, 720 } 721 newHandle := handle.ResolveAssertions(assertions) 722 if reflect.DeepEqual(handle, newHandle) { 723 continue 724 } 725 newHandleBytes, err := md.config.Codec().Encode(newHandle) 726 if err != nil { 727 return err 728 } 729 id := iter.Value() 730 if err := md.handleDb.Put(newHandleBytes, id, nil); err != nil { 731 return err 732 } 733 } 734 return iter.Error() 735 } 736 737 // GetLatestHandleForTLF implements the MDServer interface for MDServerDisk. 738 func (md *MDServerDisk) GetLatestHandleForTLF(ctx context.Context, id tlf.ID) ( 739 tlf.Handle, error) { 740 if err := checkContext(ctx); err != nil { 741 return tlf.Handle{}, err 742 } 743 744 md.lock.RLock() 745 defer md.lock.RUnlock() 746 err := md.checkShutdownLocked() 747 if err != nil { 748 return tlf.Handle{}, err 749 } 750 751 var handle tlf.Handle 752 iter := md.handleDb.NewIterator(nil, nil) 753 defer iter.Release() 754 for iter.Next() { 755 var dbID tlf.ID 756 idBytes := iter.Value() 757 err := dbID.UnmarshalBinary(idBytes) 758 if err != nil { 759 return tlf.Handle{}, err 760 } 761 if id != dbID { 762 continue 763 } 764 handleBytes := iter.Key() 765 handle = tlf.Handle{} 766 err = md.config.Codec().Decode(handleBytes, &handle) 767 if err != nil { 768 return tlf.Handle{}, err 769 } 770 } 771 return handle, nil 772 } 773 774 // OffsetFromServerTime implements the MDServer interface for 775 // MDServerDisk. 776 func (md *MDServerDisk) OffsetFromServerTime() (time.Duration, bool) { 777 return 0, true 778 } 779 780 // GetKeyBundles implements the MDServer interface for MDServerDisk. 781 func (md *MDServerDisk) GetKeyBundles(ctx context.Context, 782 tlfID tlf.ID, wkbID kbfsmd.TLFWriterKeyBundleID, rkbID kbfsmd.TLFReaderKeyBundleID) ( 783 *kbfsmd.TLFWriterKeyBundleV3, *kbfsmd.TLFReaderKeyBundleV3, error) { 784 if err := checkContext(ctx); err != nil { 785 return nil, nil, err 786 } 787 788 tlfStorage, err := md.getStorage(tlfID) 789 if err != nil { 790 return nil, nil, err 791 } 792 793 return tlfStorage.getKeyBundles(tlfID, wkbID, rkbID) 794 } 795 796 // CheckReachability implements the MDServer interface for MDServerDisk. 797 func (md *MDServerDisk) CheckReachability(ctx context.Context) {} 798 799 // FastForwardBackoff implements the MDServer interface for MDServerDisk. 800 func (md *MDServerDisk) FastForwardBackoff() {} 801 802 // FindNextMD implements the MDServer interface for MDServerDisk. 803 func (md *MDServerDisk) FindNextMD( 804 ctx context.Context, tlfID tlf.ID, rootSeqno keybase1.Seqno) ( 805 nextKbfsRoot *kbfsmd.MerkleRoot, nextMerkleNodes [][]byte, 806 nextRootSeqno keybase1.Seqno, err error) { 807 return nil, nil, 0, nil 808 } 809 810 // GetMerkleRootLatest implements the MDServer interface for MDServerDisk. 811 func (md *MDServerDisk) GetMerkleRootLatest( 812 ctx context.Context, treeID keybase1.MerkleTreeID) ( 813 root *kbfsmd.MerkleRoot, err error) { 814 md.lock.RLock() 815 defer md.lock.RUnlock() 816 return md.merkleRoots[treeID], nil 817 }