github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/config_local.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 "flag" 9 "os" 10 "path/filepath" 11 "strings" 12 "sync" 13 "time" 14 15 "github.com/keybase/client/go/kbfs/cache" 16 "github.com/keybase/client/go/kbfs/data" 17 "github.com/keybase/client/go/kbfs/idutil" 18 "github.com/keybase/client/go/kbfs/ioutil" 19 "github.com/keybase/client/go/kbfs/kbfscodec" 20 "github.com/keybase/client/go/kbfs/kbfscrypto" 21 "github.com/keybase/client/go/kbfs/kbfsedits" 22 "github.com/keybase/client/go/kbfs/kbfsmd" 23 "github.com/keybase/client/go/kbfs/ldbutils" 24 "github.com/keybase/client/go/kbfs/libkey" 25 "github.com/keybase/client/go/kbfs/tlf" 26 "github.com/keybase/client/go/libkb" 27 "github.com/keybase/client/go/logger" 28 "github.com/keybase/client/go/protocol/keybase1" 29 "github.com/pkg/errors" 30 metrics "github.com/rcrowley/go-metrics" 31 "github.com/shirou/gopsutil/mem" 32 "github.com/syndtr/goleveldb/leveldb" 33 "github.com/syndtr/goleveldb/leveldb/storage" 34 "golang.org/x/net/context" 35 "golang.org/x/net/trace" 36 ) 37 38 const ( 39 // Default time after setting the rekey bit before prompting for a 40 // paper key. 41 rekeyWithPromptWaitTimeDefault = 10 * time.Minute 42 // see Config doc for the purpose of DelayedCancellationGracePeriod 43 delayedCancellationGracePeriodDefault = 2 * time.Second 44 // tlfValidDurationDefault is the default for tlf validity before redoing identify. 45 tlfValidDurationDefault = 6 * time.Hour 46 // bgFlushDirOpThresholdDefault is the default for how many 47 // directory operations should be batched together in a single 48 // background flush. 49 bgFlushDirOpBatchSizeDefault = 100 50 // bgFlushPeriodDefault is the default for how long to wait for a 51 // batch to fill up before syncing a set of changes to the servers. 52 bgFlushPeriodDefault = 1 * time.Second 53 keyBundlesCacheCapacityBytes = 10 * cache.MB 54 // folder name for persisted config parameters. 55 syncedTlfConfigFolderName = "synced_tlf_config" 56 57 // By default, this will be the block type given to all blocks 58 // that aren't explicitly some other type. 59 defaultBlockTypeDefault = keybase1.BlockType_DATA 60 61 // By default, allow 10% of the free bytes on disk to be used in the disk block cache. 62 defaultDiskBlockCacheFraction = 0.10 63 64 // By default, allow 100% of the free bytes on disk to be used in the sync 65 // block cache. 66 defaultSyncBlockCacheFraction = 1.00 67 68 // By default, use v2 block encryption. 69 defaultBlockCryptVersion = kbfscrypto.EncryptionSecretboxWithKeyNonce 70 71 // How many times to retry loading the sync DB in the background 72 // if there's an error. 73 maxSyncDBLoadAttempts = 10 74 // How long to wait between load attempts. 75 syncDBLoadWaitPeriod = 10 * time.Second 76 ) 77 78 // ConfigLocal implements the Config interface using purely local 79 // server objects (no KBFS operations used RPCs). 80 type ConfigLocal struct { 81 lock sync.RWMutex 82 kbfs KBFSOps 83 keyman KeyManager 84 rep Reporter 85 kcache KeyCache 86 kbcache kbfsmd.KeyBundleCache 87 bcache data.BlockCache 88 dirtyBcache data.DirtyBlockCache 89 diskBlockCache DiskBlockCache 90 diskMDCache DiskMDCache 91 diskQuotaCache DiskQuotaCache 92 blockMetadataStore BlockMetadataStore 93 xattrStore XattrStore 94 codec kbfscodec.Codec 95 mdops MDOps 96 kops libkey.KeyOps 97 crypto Crypto 98 chat Chat 99 mdcache MDCache 100 bops BlockOps 101 mdserv MDServer 102 bserv BlockServer 103 keyserv libkey.KeyServer 104 service KeybaseService 105 bsplit data.BlockSplitter 106 notifier Notifier 107 clock Clock 108 kbpki KBPKI 109 renamer ConflictRenamer 110 userHistory *kbfsedits.UserHistory 111 registry metrics.Registry 112 loggerFn func(prefix string) logger.Logger 113 noBGFlush bool // logic opposite so the default value is the common setting 114 rwpWaitTime time.Duration 115 diskLimiter DiskLimiter 116 syncedTlfs map[tlf.ID]FolderSyncConfig // if nil, couldn't load DB 117 syncedTlfPaths map[string]bool 118 defaultBlockType keybase1.BlockType 119 kbfsService *KBFSService 120 kbCtx Context 121 rootNodeWrappers []func(Node) Node 122 tlfClearCancels map[tlf.ID]context.CancelFunc 123 vdebugSetting string 124 vlogs []*libkb.VDebugLog 125 resetForLoginTargets []ResetForLoginer 126 127 maxNameBytes uint32 128 rekeyQueue RekeyQueue 129 storageRoot string 130 diskCacheMode DiskCacheMode 131 diskBlockCacheFraction float64 132 syncBlockCacheFraction float64 133 134 traceLock sync.RWMutex 135 traceEnabled bool 136 137 delayedCancellationGracePeriod time.Duration 138 139 // allKnownConfigsForTesting is used for testing, and contains all created 140 // Config objects in this test. 141 allKnownConfigsForTesting *[]Config 142 143 // tlfValidDuration is the time TLFs are valid before redoing identification. 144 tlfValidDuration time.Duration 145 146 // bgFlushDirOpBatchSize indicates how many directory operations 147 // should be batched together in a single background flush. 148 bgFlushDirOpBatchSize int 149 150 // bgFlushPeriod indicates how long to wait for a batch to fill up 151 // before syncing a set of changes to the servers. 152 bgFlushPeriod time.Duration 153 154 // metadataVersion is the version to use when creating new metadata. 155 metadataVersion kbfsmd.MetadataVer 156 157 // blockCryptVersion is the version to use when encrypting blocks. 158 blockCryptVersion kbfscrypto.EncryptionVer 159 160 // conflictResolutionDB stores information about failed CRs 161 conflictResolutionDB *ldbutils.LevelDb 162 163 // settingsDB stores information about local KBFS settings 164 settingsDB *SettingsDB 165 166 mode InitMode 167 168 quotaUsage map[keybase1.UserOrTeamID]*EventuallyConsistentQuotaUsage 169 rekeyFSMLimiter *OngoingWorkLimiter 170 171 subscriptionManagerManager *subscriptionManagerManager 172 } 173 174 // DiskCacheMode represents the mode of initialization for the disk cache. 175 type DiskCacheMode int 176 177 var _ flag.Value = (*DiskCacheMode)(nil) 178 179 const ( 180 // DiskCacheModeOff indicates to leave off the disk cache. 181 DiskCacheModeOff DiskCacheMode = iota 182 // DiskCacheModeLocal indicates to use a local disk cache. 183 DiskCacheModeLocal 184 // DiskCacheModeRemote indicates to use a remote disk cache. 185 DiskCacheModeRemote 186 ) 187 188 // String outputs a human-readable description of this DiskBlockCacheMode. 189 func (m DiskCacheMode) String() string { 190 switch m { 191 case DiskCacheModeOff: 192 return "off" 193 case DiskCacheModeLocal: 194 return "local" 195 case DiskCacheModeRemote: 196 return "remote" 197 } 198 return "unknown" 199 } 200 201 // Set parses a string representing a disk block cache initialization mode, 202 // and outputs the mode value corresponding to that string. Defaults to 203 // DiskCacheModeOff. 204 func (m *DiskCacheMode) Set(s string) error { 205 *m = DiskCacheModeOff 206 switch strings.ToLower(strings.TrimSpace(s)) { 207 case "local": 208 *m = DiskCacheModeLocal 209 case "remote": 210 *m = DiskCacheModeRemote 211 } 212 return nil 213 } 214 215 var _ Config = (*ConfigLocal)(nil) 216 217 // getDefaultCleanBlockCacheCapacity returns the default clean block 218 // cache capacity. If we can get total RAM of the system, we cap at 219 // the smaller of <1/8 of available memory> and 220 // <MaxBlockSizeBytesDefault * DefaultBlocksInMemCache>; otherwise, 221 // fallback to latter. 222 func getDefaultCleanBlockCacheCapacity(mode InitMode) uint64 { 223 const minCapacity = 10 * uint64(data.MaxBlockSizeBytesDefault) // 5mb 224 capacity := uint64(data.MaxBlockSizeBytesDefault) * DefaultBlocksInMemCache 225 vmstat, err := mem.VirtualMemory() 226 if err == nil { 227 ramBased := vmstat.Total / 8 228 if ramBased < minCapacity { 229 ramBased = minCapacity 230 } 231 if ramBased < capacity { 232 capacity = ramBased 233 } 234 } 235 if capacity > mode.MaxCleanBlockCacheCapacity() { 236 capacity = mode.MaxCleanBlockCacheCapacity() 237 } 238 return capacity 239 } 240 241 type keyOpsConfigWrapper struct { 242 Config 243 } 244 245 func (k keyOpsConfigWrapper) KBPKI() idutil.KBPKI { 246 return k.Config.KBPKI() 247 } 248 249 // NewConfigLocal constructs a new ConfigLocal with some default 250 // components that don't depend on a logger. The caller will have to 251 // fill in the rest. 252 // 253 // TODO: Now that NewConfigLocal takes loggerFn, add more default 254 // components. 255 func NewConfigLocal(mode InitMode, 256 loggerFn func(module string) logger.Logger, 257 storageRoot string, diskCacheMode DiskCacheMode, 258 kbCtx Context) *ConfigLocal { 259 config := &ConfigLocal{ 260 loggerFn: loggerFn, 261 storageRoot: storageRoot, 262 mode: mode, 263 diskCacheMode: diskCacheMode, 264 kbCtx: kbCtx, 265 tlfClearCancels: make(map[tlf.ID]context.CancelFunc), 266 } 267 config.SetCodec(kbfscodec.NewMsgpack()) 268 if diskCacheMode == DiskCacheModeLocal { 269 // Any error is logged in the function itself. 270 _ = config.loadSyncedTlfsLocked() 271 } 272 config.SetClock(data.WallClock{}) 273 config.SetReporter(NewReporterSimple(config.Clock(), 10)) 274 config.SetConflictRenamer(WriterDeviceDateConflictRenamer{config}) 275 config.ResetCaches() 276 config.SetKeyOps(libkey.NewKeyOpsStandard(keyOpsConfigWrapper{config})) 277 config.SetRekeyQueue(NewRekeyQueueStandard(config)) 278 uhLog := config.MakeLogger("HIS") 279 config.SetUserHistory(kbfsedits.NewUserHistory( 280 uhLog, config.MakeVLogger(uhLog))) 281 282 config.maxNameBytes = data.MaxNameBytesDefault 283 config.rwpWaitTime = rekeyWithPromptWaitTimeDefault 284 285 config.delayedCancellationGracePeriod = delayedCancellationGracePeriodDefault 286 // Don't bother creating the registry if UseNilMetrics is set, or 287 // if we're in minimal mode. 288 if !metrics.UseNilMetrics && config.Mode().MetricsEnabled() { 289 registry := metrics.NewRegistry() 290 config.SetMetricsRegistry(registry) 291 } 292 293 config.tlfValidDuration = tlfValidDurationDefault 294 config.bgFlushDirOpBatchSize = bgFlushDirOpBatchSizeDefault 295 config.bgFlushPeriod = bgFlushPeriodDefault 296 config.metadataVersion = defaultClientMetadataVer 297 config.defaultBlockType = defaultBlockTypeDefault 298 config.quotaUsage = 299 make(map[keybase1.UserOrTeamID]*EventuallyConsistentQuotaUsage) 300 config.rekeyFSMLimiter = NewOngoingWorkLimiter(config.Mode().RekeyWorkers()) 301 config.diskBlockCacheFraction = defaultDiskBlockCacheFraction 302 config.syncBlockCacheFraction = defaultSyncBlockCacheFraction 303 304 config.blockCryptVersion = defaultBlockCryptVersion 305 306 config.conflictResolutionDB = openCRDB(config) 307 config.settingsDB = openSettingsDB(config) 308 309 config.subscriptionManagerManager = newSubscriptionManagerManager(config) 310 311 return config 312 } 313 314 // KBFSOps implements the Config interface for ConfigLocal. 315 func (c *ConfigLocal) KBFSOps() KBFSOps { 316 c.lock.RLock() 317 defer c.lock.RUnlock() 318 return c.kbfs 319 } 320 321 // SetKBFSOps implements the Config interface for ConfigLocal. 322 func (c *ConfigLocal) SetKBFSOps(k KBFSOps) { 323 c.lock.Lock() 324 defer c.lock.Unlock() 325 c.kbfs = k 326 } 327 328 // KBPKI implements the Config interface for ConfigLocal. 329 func (c *ConfigLocal) KBPKI() KBPKI { 330 c.lock.RLock() 331 defer c.lock.RUnlock() 332 return c.kbpki 333 } 334 335 // CurrentSessionGetter implements the Config interface for ConfigLocal. 336 func (c *ConfigLocal) CurrentSessionGetter() idutil.CurrentSessionGetter { 337 c.lock.RLock() 338 defer c.lock.RUnlock() 339 return c.kbpki 340 } 341 342 // SetKBPKI implements the Config interface for ConfigLocal. 343 func (c *ConfigLocal) SetKBPKI(k KBPKI) { 344 c.lock.Lock() 345 defer c.lock.Unlock() 346 c.kbpki = k 347 } 348 349 // KeyManager implements the Config interface for ConfigLocal. 350 func (c *ConfigLocal) KeyManager() KeyManager { 351 c.lock.RLock() 352 defer c.lock.RUnlock() 353 return c.keyman 354 } 355 356 // SetKeyManager implements the Config interface for ConfigLocal. 357 func (c *ConfigLocal) SetKeyManager(k KeyManager) { 358 c.lock.Lock() 359 defer c.lock.Unlock() 360 c.keyman = k 361 } 362 363 // KeyGetter implements the Config interface for ConfigLocal. 364 func (c *ConfigLocal) keyGetter() blockKeyGetter { 365 c.lock.RLock() 366 defer c.lock.RUnlock() 367 return c.keyman 368 } 369 370 // Reporter implements the Config interface for ConfigLocal. 371 func (c *ConfigLocal) Reporter() Reporter { 372 c.lock.RLock() 373 defer c.lock.RUnlock() 374 return c.rep 375 } 376 377 // SetReporter implements the Config interface for ConfigLocal. 378 func (c *ConfigLocal) SetReporter(r Reporter) { 379 c.lock.Lock() 380 defer c.lock.Unlock() 381 c.rep = r 382 } 383 384 // KeyCache implements the Config interface for ConfigLocal. 385 func (c *ConfigLocal) KeyCache() KeyCache { 386 c.lock.RLock() 387 defer c.lock.RUnlock() 388 return c.kcache 389 } 390 391 // SetKeyCache implements the Config interface for ConfigLocal. 392 func (c *ConfigLocal) SetKeyCache(k KeyCache) { 393 c.lock.Lock() 394 defer c.lock.Unlock() 395 c.kcache = k 396 } 397 398 // KeyBundleCache implements the Config interface for ConfigLocal. 399 func (c *ConfigLocal) KeyBundleCache() kbfsmd.KeyBundleCache { 400 c.lock.RLock() 401 defer c.lock.RUnlock() 402 return c.kbcache 403 } 404 405 // SetKeyBundleCache implements the Config interface for ConfigLocal. 406 func (c *ConfigLocal) SetKeyBundleCache(k kbfsmd.KeyBundleCache) { 407 c.lock.Lock() 408 defer c.lock.Unlock() 409 c.kbcache = k 410 } 411 412 // BlockCache implements the Config interface for ConfigLocal. 413 func (c *ConfigLocal) BlockCache() data.BlockCache { 414 c.lock.RLock() 415 defer c.lock.RUnlock() 416 return c.bcache 417 } 418 419 // SetBlockCache implements the Config interface for ConfigLocal. 420 func (c *ConfigLocal) SetBlockCache(b data.BlockCache) { 421 c.lock.Lock() 422 defer c.lock.Unlock() 423 c.bcache = b 424 } 425 426 // DirtyBlockCache implements the Config interface for ConfigLocal. 427 func (c *ConfigLocal) DirtyBlockCache() data.DirtyBlockCache { 428 c.lock.RLock() 429 defer c.lock.RUnlock() 430 return c.dirtyBcache 431 } 432 433 // SetDirtyBlockCache implements the Config interface for ConfigLocal. 434 func (c *ConfigLocal) SetDirtyBlockCache(d data.DirtyBlockCache) { 435 c.lock.Lock() 436 defer c.lock.Unlock() 437 c.dirtyBcache = d 438 } 439 440 // DiskBlockCache implements the Config interface for ConfigLocal. 441 func (c *ConfigLocal) DiskBlockCache() DiskBlockCache { 442 c.lock.RLock() 443 defer c.lock.RUnlock() 444 return c.diskBlockCache 445 } 446 447 // SetDiskBlockCacheFraction implements the Config interface for ConfigLocal. 448 func (c *ConfigLocal) SetDiskBlockCacheFraction(fraction float64) { 449 c.lock.Lock() 450 defer c.lock.Unlock() 451 c.diskBlockCacheFraction = fraction 452 } 453 454 // SetSyncBlockCacheFraction implements the Config interface for ConfigLocal. 455 func (c *ConfigLocal) SetSyncBlockCacheFraction(fraction float64) { 456 c.lock.Lock() 457 defer c.lock.Unlock() 458 c.syncBlockCacheFraction = fraction 459 } 460 461 // DiskMDCache implements the Config interface for ConfigLocal. 462 func (c *ConfigLocal) DiskMDCache() DiskMDCache { 463 c.lock.RLock() 464 defer c.lock.RUnlock() 465 return c.diskMDCache 466 } 467 468 // DiskQuotaCache implements the Config interface for ConfigLocal. 469 func (c *ConfigLocal) DiskQuotaCache() DiskQuotaCache { 470 c.lock.RLock() 471 defer c.lock.RUnlock() 472 return c.diskQuotaCache 473 } 474 475 // XattrStore implements the Config interface for ConfigLocal. 476 func (c *ConfigLocal) XattrStore() XattrStore { 477 c.lock.RLock() 478 defer c.lock.RUnlock() 479 return c.xattrStore 480 } 481 482 // DiskLimiter implements the Config interface for ConfigLocal. 483 func (c *ConfigLocal) DiskLimiter() DiskLimiter { 484 c.lock.RLock() 485 defer c.lock.RUnlock() 486 return c.diskLimiter 487 } 488 489 // Crypto implements the Config interface for ConfigLocal. 490 func (c *ConfigLocal) Crypto() Crypto { 491 c.lock.RLock() 492 defer c.lock.RUnlock() 493 return c.crypto 494 } 495 496 // Chat implements the Config interface for ConfigLocal. 497 func (c *ConfigLocal) Chat() Chat { 498 c.lock.RLock() 499 defer c.lock.RUnlock() 500 return c.chat 501 } 502 503 // Signer implements the Config interface for ConfigLocal. 504 func (c *ConfigLocal) Signer() kbfscrypto.Signer { 505 c.lock.RLock() 506 defer c.lock.RUnlock() 507 return c.crypto 508 } 509 510 // SetCrypto implements the Config interface for ConfigLocal. 511 func (c *ConfigLocal) SetCrypto(cr Crypto) { 512 c.lock.Lock() 513 defer c.lock.Unlock() 514 c.crypto = cr 515 } 516 517 // SetChat implements the Config interface for ConfigLocal. 518 func (c *ConfigLocal) SetChat(ch Chat) { 519 c.lock.Lock() 520 defer c.lock.Unlock() 521 c.chat = ch 522 } 523 524 // CryptoPure implements the Config interface for ConfigLocal. 525 func (c *ConfigLocal) cryptoPure() cryptoPure { 526 c.lock.RLock() 527 defer c.lock.RUnlock() 528 return c.crypto 529 } 530 531 // Codec implements the Config interface for ConfigLocal. 532 func (c *ConfigLocal) Codec() kbfscodec.Codec { 533 c.lock.RLock() 534 defer c.lock.RUnlock() 535 return c.codec 536 } 537 538 // SetCodec implements the Config interface for ConfigLocal. 539 func (c *ConfigLocal) SetCodec(co kbfscodec.Codec) { 540 c.lock.Lock() 541 defer c.lock.Unlock() 542 c.codec = co 543 RegisterOps(c.codec) 544 } 545 546 // MDOps implements the Config interface for ConfigLocal. 547 func (c *ConfigLocal) MDOps() MDOps { 548 c.lock.RLock() 549 defer c.lock.RUnlock() 550 return c.mdops 551 } 552 553 // SetMDOps implements the Config interface for ConfigLocal. 554 func (c *ConfigLocal) SetMDOps(m MDOps) { 555 c.lock.Lock() 556 defer c.lock.Unlock() 557 c.mdops = m 558 } 559 560 // KeyOps implements the Config interface for ConfigLocal. 561 func (c *ConfigLocal) KeyOps() libkey.KeyOps { 562 c.lock.RLock() 563 defer c.lock.RUnlock() 564 return c.kops 565 } 566 567 // SetKeyOps implements the Config interface for ConfigLocal. 568 func (c *ConfigLocal) SetKeyOps(k libkey.KeyOps) { 569 c.lock.Lock() 570 defer c.lock.Unlock() 571 c.kops = k 572 } 573 574 // MDCache implements the Config interface for ConfigLocal. 575 func (c *ConfigLocal) MDCache() MDCache { 576 c.lock.RLock() 577 defer c.lock.RUnlock() 578 return c.mdcache 579 } 580 581 // SetMDCache implements the Config interface for ConfigLocal. 582 func (c *ConfigLocal) SetMDCache(m MDCache) { 583 c.lock.Lock() 584 defer c.lock.Unlock() 585 c.mdcache = m 586 } 587 588 // BlockOps implements the Config interface for ConfigLocal. 589 func (c *ConfigLocal) BlockOps() BlockOps { 590 c.lock.RLock() 591 defer c.lock.RUnlock() 592 return c.bops 593 } 594 595 // SetBlockOps implements the Config interface for ConfigLocal. 596 func (c *ConfigLocal) SetBlockOps(b BlockOps) { 597 c.lock.Lock() 598 defer c.lock.Unlock() 599 c.bops = b 600 } 601 602 // MDServer implements the Config interface for ConfigLocal. 603 func (c *ConfigLocal) MDServer() MDServer { 604 c.lock.RLock() 605 defer c.lock.RUnlock() 606 return c.mdserv 607 } 608 609 // SetMDServer implements the Config interface for ConfigLocal. 610 func (c *ConfigLocal) SetMDServer(m MDServer) { 611 c.lock.Lock() 612 defer c.lock.Unlock() 613 c.mdserv = m 614 } 615 616 // BlockServer implements the Config interface for ConfigLocal. 617 func (c *ConfigLocal) BlockServer() BlockServer { 618 c.lock.RLock() 619 defer c.lock.RUnlock() 620 return c.bserv 621 } 622 623 // SetBlockServer implements the Config interface for ConfigLocal. 624 func (c *ConfigLocal) SetBlockServer(b BlockServer) { 625 c.lock.Lock() 626 defer c.lock.Unlock() 627 c.bserv = b 628 } 629 630 // KeyServer implements the Config interface for ConfigLocal. 631 func (c *ConfigLocal) KeyServer() libkey.KeyServer { 632 c.lock.RLock() 633 defer c.lock.RUnlock() 634 return c.keyserv 635 } 636 637 // SetKeyServer implements the Config interface for ConfigLocal. 638 func (c *ConfigLocal) SetKeyServer(k libkey.KeyServer) { 639 c.lock.Lock() 640 defer c.lock.Unlock() 641 c.keyserv = k 642 } 643 644 // KeybaseService implements the Config interface for ConfigLocal. 645 func (c *ConfigLocal) KeybaseService() KeybaseService { 646 c.lock.RLock() 647 defer c.lock.RUnlock() 648 return c.service 649 } 650 651 // SetKeybaseService implements the Config interface for ConfigLocal. 652 func (c *ConfigLocal) SetKeybaseService(k KeybaseService) { 653 c.lock.Lock() 654 defer c.lock.Unlock() 655 c.service = k 656 } 657 658 // BlockSplitter implements the Config interface for ConfigLocal. 659 func (c *ConfigLocal) BlockSplitter() data.BlockSplitter { 660 c.lock.RLock() 661 defer c.lock.RUnlock() 662 return c.bsplit 663 } 664 665 // SetBlockSplitter implements the Config interface for ConfigLocal. 666 func (c *ConfigLocal) SetBlockSplitter(b data.BlockSplitter) { 667 c.lock.Lock() 668 defer c.lock.Unlock() 669 c.bsplit = b 670 } 671 672 // Notifier implements the Config interface for ConfigLocal. 673 func (c *ConfigLocal) Notifier() Notifier { 674 c.lock.RLock() 675 defer c.lock.RUnlock() 676 return c.notifier 677 } 678 679 // SetNotifier implements the Config interface for ConfigLocal. 680 func (c *ConfigLocal) SetNotifier(n Notifier) { 681 c.lock.Lock() 682 defer c.lock.Unlock() 683 c.notifier = n 684 } 685 686 // Clock implements the Config interface for ConfigLocal. 687 func (c *ConfigLocal) Clock() Clock { 688 c.lock.RLock() 689 defer c.lock.RUnlock() 690 return c.clock 691 } 692 693 // SetClock implements the Config interface for ConfigLocal. 694 func (c *ConfigLocal) SetClock(cl Clock) { 695 c.lock.Lock() 696 defer c.lock.Unlock() 697 c.clock = cl 698 } 699 700 // ConflictRenamer implements the Config interface for ConfigLocal. 701 func (c *ConfigLocal) ConflictRenamer() ConflictRenamer { 702 c.lock.RLock() 703 defer c.lock.RUnlock() 704 return c.renamer 705 } 706 707 // SetConflictRenamer implements the Config interface for ConfigLocal. 708 func (c *ConfigLocal) SetConflictRenamer(cr ConflictRenamer) { 709 c.lock.Lock() 710 defer c.lock.Unlock() 711 c.renamer = cr 712 } 713 714 // UserHistory implements the Config interface for ConfigLocal. 715 func (c *ConfigLocal) UserHistory() *kbfsedits.UserHistory { 716 c.lock.RLock() 717 defer c.lock.RUnlock() 718 return c.userHistory 719 } 720 721 // SetUserHistory implements the Config interface for ConfigLocal. 722 func (c *ConfigLocal) SetUserHistory(uh *kbfsedits.UserHistory) { 723 c.lock.Lock() 724 defer c.lock.Unlock() 725 c.userHistory = uh 726 } 727 728 // MetadataVersion implements the Config interface for ConfigLocal. 729 func (c *ConfigLocal) MetadataVersion() kbfsmd.MetadataVer { 730 c.lock.RLock() 731 defer c.lock.RUnlock() 732 return c.metadataVersion 733 } 734 735 // SetMetadataVersion implements the Config interface for ConfigLocal. 736 func (c *ConfigLocal) SetMetadataVersion(mdVer kbfsmd.MetadataVer) { 737 c.lock.Lock() 738 defer c.lock.Unlock() 739 c.metadataVersion = mdVer 740 } 741 742 // DataVersion implements the Config interface for ConfigLocal. 743 func (c *ConfigLocal) DataVersion() data.Ver { 744 return data.IndirectDirsVer 745 } 746 747 // BlockCryptVersion implements the Config interface for ConfigLocal. 748 func (c *ConfigLocal) BlockCryptVersion() kbfscrypto.EncryptionVer { 749 c.lock.RLock() 750 defer c.lock.RUnlock() 751 return c.blockCryptVersion 752 } 753 754 // SetBlockCryptVersion implements the Config interface for ConfigLocal. 755 func (c *ConfigLocal) SetBlockCryptVersion(ver kbfscrypto.EncryptionVer) { 756 c.lock.Lock() 757 defer c.lock.Unlock() 758 c.blockCryptVersion = ver 759 } 760 761 // DefaultBlockType implements the Config interface for ConfigLocal. 762 func (c *ConfigLocal) DefaultBlockType() keybase1.BlockType { 763 c.lock.RLock() 764 defer c.lock.RUnlock() 765 return c.defaultBlockType 766 } 767 768 // SetDefaultBlockType implements the Config interface for ConfigLocal. 769 func (c *ConfigLocal) SetDefaultBlockType(blockType keybase1.BlockType) { 770 c.lock.Lock() 771 defer c.lock.Unlock() 772 c.defaultBlockType = blockType 773 } 774 775 // DoBackgroundFlushes implements the Config interface for ConfigLocal. 776 func (c *ConfigLocal) DoBackgroundFlushes() bool { 777 if !c.Mode().BackgroundFlushesEnabled() { 778 return false 779 } 780 781 c.lock.RLock() 782 defer c.lock.RUnlock() 783 return !c.noBGFlush 784 } 785 786 // SetDoBackgroundFlushes implements the Config interface for ConfigLocal. 787 func (c *ConfigLocal) SetDoBackgroundFlushes(doBGFlush bool) { 788 c.lock.Lock() 789 defer c.lock.Unlock() 790 c.noBGFlush = !doBGFlush 791 } 792 793 // RekeyWithPromptWaitTime implements the Config interface for 794 // ConfigLocal. 795 func (c *ConfigLocal) RekeyWithPromptWaitTime() time.Duration { 796 c.lock.Lock() 797 defer c.lock.Unlock() 798 return c.rwpWaitTime 799 } 800 801 // SetRekeyWithPromptWaitTime implements the Config interface for 802 // ConfigLocal. 803 func (c *ConfigLocal) SetRekeyWithPromptWaitTime(d time.Duration) { 804 c.lock.RLock() 805 defer c.lock.RUnlock() 806 c.rwpWaitTime = d 807 } 808 809 // Mode implements the Config interface for ConfigLocal. 810 func (c *ConfigLocal) Mode() InitMode { 811 c.lock.RLock() 812 defer c.lock.RUnlock() 813 return c.mode 814 } 815 816 // SetMode implements the Config interface for ConfigLocal. 817 func (c *ConfigLocal) SetMode(mode InitMode) { 818 c.lock.Lock() 819 defer c.lock.Unlock() 820 c.mode = mode 821 } 822 823 // IsTestMode implements the Config interface for ConfigLocal. 824 func (c *ConfigLocal) IsTestMode() bool { 825 c.lock.RLock() 826 defer c.lock.RUnlock() 827 return c.mode.IsTestMode() 828 } 829 830 // DelayedCancellationGracePeriod implements the Config interface for ConfigLocal. 831 func (c *ConfigLocal) DelayedCancellationGracePeriod() time.Duration { 832 return c.delayedCancellationGracePeriod 833 } 834 835 // SetDelayedCancellationGracePeriod implements the Config interface for ConfigLocal. 836 func (c *ConfigLocal) SetDelayedCancellationGracePeriod(d time.Duration) { 837 c.delayedCancellationGracePeriod = d 838 } 839 840 // ReqsBufSize implements the Config interface for ConfigLocal. 841 func (c *ConfigLocal) ReqsBufSize() int { 842 return 20 843 } 844 845 // MaxNameBytes implements the Config interface for ConfigLocal. 846 func (c *ConfigLocal) MaxNameBytes() uint32 { 847 return c.maxNameBytes 848 } 849 850 // SetStorageRoot sets the storage root directory for this config. 851 func (c *ConfigLocal) SetStorageRoot(storageRoot string) { 852 c.lock.Lock() 853 defer c.lock.Unlock() 854 c.storageRoot = storageRoot 855 } 856 857 // StorageRoot implements the Config interface for ConfigLocal. 858 func (c *ConfigLocal) StorageRoot() string { 859 c.lock.RLock() 860 defer c.lock.RUnlock() 861 return c.storageRoot 862 } 863 864 func (c *ConfigLocal) resetCachesWithoutShutdown() data.DirtyBlockCache { 865 c.lock.Lock() 866 defer c.lock.Unlock() 867 c.mdcache = NewMDCacheStandard(defaultMDCacheCapacity) 868 c.kcache = NewKeyCacheStandard(defaultMDCacheCapacity) 869 c.kbcache = kbfsmd.NewKeyBundleCacheLRU(keyBundlesCacheCapacityBytes) 870 871 log := c.MakeLogger("") 872 var capacity uint64 873 if c.bcache == nil { 874 capacity = getDefaultCleanBlockCacheCapacity(c.mode) 875 log.Debug("setting default clean block cache capacity to %d", 876 capacity) 877 } else { 878 capacity = c.bcache.GetCleanBytesCapacity() 879 log.Debug("setting clean block cache capacity based on existing value %d", 880 capacity) 881 } 882 c.bcache = data.NewBlockCacheStandard(10000, capacity) 883 884 if !c.mode.DirtyBlockCacheEnabled() { 885 return nil 886 } 887 888 oldDirtyBcache := c.dirtyBcache 889 890 // TODO: we should probably fail or re-schedule this reset if 891 // there is anything dirty in the dirty block cache. 892 893 // The minimum number of bytes we'll try to sync in parallel. 894 // This should be roughly the minimum amount of bytes we expect 895 // our worst supported connection to send within the timeout 896 // forced on us by the upper layer (19 seconds on OS X). With the 897 // current default of a single block, this minimum works out to 898 // ~1MB, so we can support a connection speed as low as ~54 KB/s. 899 minSyncBufferSize := int64(data.MaxBlockSizeBytesDefault) 900 901 // The maximum number of bytes we can try to sync at once (also limits the 902 // amount of memory used by dirty blocks). We use the same value from clean 903 // block cache capacity here. 904 maxSyncBufferSize := int64(capacity) 905 906 // Start off conservatively to avoid getting immediate timeouts on 907 // slow connections. 908 startSyncBufferSize := minSyncBufferSize 909 910 dbcLog := c.MakeLogger("DBC") 911 c.dirtyBcache = data.NewDirtyBlockCacheStandard( 912 c.clock, dbcLog, c.makeVLoggerLocked(dbcLog), 913 minSyncBufferSize, maxSyncBufferSize, startSyncBufferSize) 914 return oldDirtyBcache 915 } 916 917 // ResetCaches implements the Config interface for ConfigLocal. 918 func (c *ConfigLocal) ResetCaches() { 919 oldDirtyBcache := c.resetCachesWithoutShutdown() 920 jManager, err := GetJournalManager(c) 921 if err == nil { 922 if err := c.journalizeBcaches(jManager); err != nil { 923 if log := c.MakeLogger(""); log != nil { 924 log.CWarningf( 925 context.TODO(), 926 "Error journalizing dirty block cache: %+v", err) 927 } 928 } 929 } 930 if oldDirtyBcache != nil { 931 // Shutdown outside of the lock so it doesn't block other 932 // access to this config. 933 if err := oldDirtyBcache.Shutdown(); err != nil { 934 if log := c.MakeLogger(""); log != nil { 935 log.CWarningf( 936 context.TODO(), 937 "Error shutting down old dirty block cache: %+v", err) 938 } 939 } 940 } 941 } 942 943 // MakeLogger implements the logMaker interface for ConfigLocal. 944 func (c *ConfigLocal) MakeLogger(module string) logger.Logger { 945 // No need to lock since c.loggerFn is initialized once at 946 // construction. Also resetCachesWithoutShutdown would deadlock. 947 return c.loggerFn(module) 948 } 949 950 func (c *ConfigLocal) makeVLoggerLocked(log logger.Logger) *libkb.VDebugLog { 951 vlog := libkb.NewVDebugLog(log) 952 vlog.Configure(c.vdebugSetting) 953 c.vlogs = append(c.vlogs, vlog) 954 return vlog 955 } 956 957 // MakeVLogger implements the logMaker interface for ConfigLocal. 958 func (c *ConfigLocal) MakeVLogger(log logger.Logger) *libkb.VDebugLog { 959 c.lock.Lock() 960 defer c.lock.Unlock() 961 return c.makeVLoggerLocked(log) 962 } 963 964 // MetricsRegistry implements the Config interface for ConfigLocal. 965 func (c *ConfigLocal) MetricsRegistry() metrics.Registry { 966 return c.registry 967 } 968 969 // SetRekeyQueue implements the Config interface for ConfigLocal. 970 func (c *ConfigLocal) SetRekeyQueue(r RekeyQueue) { 971 c.rekeyQueue = r 972 } 973 974 // RekeyQueue implements the Config interface for ConfigLocal. 975 func (c *ConfigLocal) RekeyQueue() RekeyQueue { 976 return c.rekeyQueue 977 } 978 979 // SetMetricsRegistry implements the Config interface for ConfigLocal. 980 func (c *ConfigLocal) SetMetricsRegistry(r metrics.Registry) { 981 c.registry = r 982 } 983 984 // SetTraceOptions implements the Config interface for ConfigLocal. 985 func (c *ConfigLocal) SetTraceOptions(enabled bool) { 986 c.traceLock.Lock() 987 defer c.traceLock.Unlock() 988 c.traceEnabled = enabled 989 } 990 991 // MaybeStartTrace implements the Config interface for ConfigLocal. 992 func (c *ConfigLocal) MaybeStartTrace( 993 ctx context.Context, family, title string) context.Context { 994 traceEnabled := func() bool { 995 c.traceLock.RLock() 996 defer c.traceLock.RUnlock() 997 return c.traceEnabled 998 }() 999 if !traceEnabled { 1000 return ctx 1001 } 1002 1003 tr := trace.New(family, title) 1004 tr.SetMaxEvents(25) 1005 ctx = trace.NewContext(ctx, tr) 1006 return ctx 1007 } 1008 1009 // MaybeFinishTrace implements the Config interface for ConfigLocal. 1010 func (c *ConfigLocal) MaybeFinishTrace(ctx context.Context, err error) { 1011 if tr, ok := trace.FromContext(ctx); ok { 1012 if err != nil { 1013 tr.LazyPrintf("err=%+v", err) 1014 tr.SetError() 1015 } 1016 tr.Finish() 1017 } 1018 } 1019 1020 // SetTLFValidDuration implements the Config interface for ConfigLocal. 1021 func (c *ConfigLocal) SetTLFValidDuration(r time.Duration) { 1022 c.tlfValidDuration = r 1023 } 1024 1025 // TLFValidDuration implements the Config interface for ConfigLocal. 1026 func (c *ConfigLocal) TLFValidDuration() time.Duration { 1027 return c.tlfValidDuration 1028 } 1029 1030 // SetBGFlushDirOpBatchSize implements the Config interface for ConfigLocal. 1031 func (c *ConfigLocal) SetBGFlushDirOpBatchSize(s int) { 1032 c.lock.Lock() 1033 defer c.lock.Unlock() 1034 c.bgFlushDirOpBatchSize = s 1035 } 1036 1037 // BGFlushDirOpBatchSize implements the Config interface for ConfigLocal. 1038 func (c *ConfigLocal) BGFlushDirOpBatchSize() int { 1039 c.lock.RLock() 1040 defer c.lock.RUnlock() 1041 return c.bgFlushDirOpBatchSize 1042 } 1043 1044 // SetBGFlushPeriod implements the Config interface for ConfigLocal. 1045 func (c *ConfigLocal) SetBGFlushPeriod(p time.Duration) { 1046 c.lock.Lock() 1047 defer c.lock.Unlock() 1048 c.bgFlushPeriod = p 1049 } 1050 1051 // BGFlushPeriod implements the Config interface for ConfigLocal. 1052 func (c *ConfigLocal) BGFlushPeriod() time.Duration { 1053 c.lock.RLock() 1054 defer c.lock.RUnlock() 1055 return c.bgFlushPeriod 1056 } 1057 1058 // Shutdown implements the Config interface for ConfigLocal. 1059 func (c *ConfigLocal) Shutdown(ctx context.Context) error { 1060 c.RekeyQueue().Shutdown() 1061 if c.CheckStateOnShutdown() && c.allKnownConfigsForTesting != nil { 1062 // Before we do anything, wait for all archiving and 1063 // journaling to finish. 1064 for _, config := range *c.allKnownConfigsForTesting { 1065 kbfsOps, ok := config.KBFSOps().(*KBFSOpsStandard) 1066 if !ok { 1067 continue 1068 } 1069 if err := kbfsOps.shutdownEdits(ctx); err != nil { 1070 return err 1071 } 1072 for _, fbo := range kbfsOps.ops { 1073 if err := fbo.fbm.waitForArchives(ctx); err != nil { 1074 return err 1075 } 1076 if err := fbo.fbm.waitForDeletingBlocks(ctx); err != nil { 1077 return err 1078 } 1079 log := config.MakeLogger("") 1080 if err := WaitForTLFJournal(ctx, config, fbo.id(), 1081 log); err != nil { 1082 return err 1083 } 1084 // The above wait could have resulted in some MD 1085 // flushes, so now we have to wait on any archives as 1086 // well. We only need one more check for this, since 1087 // archives don't produce MDs. 1088 if err := fbo.mdFlushes.Wait(ctx); err != nil { 1089 return err 1090 } 1091 if err := fbo.fbm.waitForArchives(ctx); err != nil { 1092 return err 1093 } 1094 if err := WaitForTLFJournal(ctx, config, fbo.id(), 1095 log); err != nil { 1096 return err 1097 } 1098 } 1099 } 1100 } 1101 1102 var errorList []error 1103 err := c.KBFSOps().Shutdown(ctx) 1104 if err != nil { 1105 errorList = append(errorList, err) 1106 // Continue with shutdown regardless of err. 1107 } 1108 err = c.BlockOps().Shutdown(ctx) 1109 if err != nil { 1110 errorList = append(errorList, err) 1111 } 1112 c.MDServer().Shutdown() 1113 c.KeyServer().Shutdown() 1114 c.KeybaseService().Shutdown() 1115 c.BlockServer().Shutdown(ctx) 1116 c.Crypto().Shutdown() 1117 c.Reporter().Shutdown() 1118 dirtyBcache := c.DirtyBlockCache() 1119 if dirtyBcache != nil { 1120 err = dirtyBcache.Shutdown() 1121 } 1122 if err != nil { 1123 errorList = append(errorList, err) 1124 } 1125 dbc := c.DiskBlockCache() 1126 if dbc != nil { 1127 dbc.Shutdown(ctx) 1128 } 1129 dmc := c.DiskMDCache() 1130 if dmc != nil { 1131 dmc.Shutdown(ctx) 1132 } 1133 dqc := c.DiskQuotaCache() 1134 if dqc != nil { 1135 dqc.Shutdown(ctx) 1136 } 1137 bms := c.blockMetadataStore 1138 if bms != nil { 1139 bms.Shutdown() 1140 } 1141 if c.conflictResolutionDB != nil { 1142 if err := c.conflictResolutionDB.Close(); err != nil { 1143 errorList = append(errorList, err) 1144 } 1145 } 1146 if c.settingsDB != nil { 1147 if err := c.settingsDB.Close(); err != nil { 1148 errorList = append(errorList, err) 1149 } 1150 } 1151 kbfsServ := c.kbfsService 1152 if kbfsServ != nil { 1153 kbfsServ.Shutdown() 1154 } 1155 1156 c.subscriptionManagerManager.Shutdown(ctx) 1157 1158 if len(errorList) == 1 { 1159 return errorList[0] 1160 } else if len(errorList) > 1 { 1161 // Aggregate errors 1162 return errors.Errorf("Multiple errors on shutdown: %+v", errorList) 1163 } 1164 1165 c.lock.Lock() 1166 defer c.lock.Unlock() 1167 for _, cancel := range c.tlfClearCancels { 1168 cancel() 1169 } 1170 1171 return nil 1172 } 1173 1174 // CheckStateOnShutdown implements the Config interface for ConfigLocal. 1175 func (c *ConfigLocal) CheckStateOnShutdown() bool { 1176 if !c.IsTestMode() { 1177 return false 1178 } 1179 if md, ok := c.MDServer().(mdServerLocal); ok { 1180 return !md.isShutdown() 1181 } 1182 return false 1183 } 1184 1185 func (c *ConfigLocal) journalizeBcaches(jManager *JournalManager) error { 1186 syncCache, ok := c.DirtyBlockCache().(*data.DirtyBlockCacheStandard) 1187 if !ok { 1188 return errors.Errorf("Dirty bcache unexpectedly type %T", syncCache) 1189 } 1190 jManager.delegateDirtyBlockCache = syncCache 1191 1192 // Make a dirty block cache specifically for the journal 1193 // server. Since this doesn't rely directly on the network, 1194 // there's no need for an adaptive sync buffer size, so we 1195 // always set the min and max to the same thing. 1196 maxSyncBufferSize := int64(ForcedBranchSquashBytesThresholdDefault) 1197 log := c.MakeLogger("DBCJ") 1198 journalCache := data.NewDirtyBlockCacheStandard( 1199 c.clock, log, c.MakeVLogger(log), 1200 maxSyncBufferSize, maxSyncBufferSize, maxSyncBufferSize) 1201 c.SetDirtyBlockCache(jManager.dirtyBlockCache(journalCache)) 1202 1203 jManager.delegateBlockCache = c.BlockCache() 1204 c.SetBlockCache(jManager.blockCache()) 1205 return nil 1206 } 1207 1208 // GetQuotaUsage implements the Config interface for ConfigLocal. 1209 func (c *ConfigLocal) GetQuotaUsage( 1210 chargedTo keybase1.UserOrTeamID) *EventuallyConsistentQuotaUsage { 1211 c.lock.RLock() 1212 quota, ok := c.quotaUsage[chargedTo] 1213 if ok { 1214 c.lock.RUnlock() 1215 return quota 1216 } 1217 c.lock.RUnlock() 1218 1219 c.lock.Lock() 1220 defer c.lock.Unlock() 1221 quota, ok = c.quotaUsage[chargedTo] 1222 log := c.MakeLogger(QuotaUsageLogModule("BDL")) 1223 vlog := c.makeVLoggerLocked(log) 1224 if !ok { 1225 if chargedTo.IsTeamOrSubteam() { 1226 quota = NewEventuallyConsistentTeamQuotaUsage( 1227 c, chargedTo.AsTeamOrBust(), log, vlog) 1228 } else { 1229 quota = NewEventuallyConsistentQuotaUsage(c, log, vlog) 1230 } 1231 c.quotaUsage[chargedTo] = quota 1232 } 1233 return quota 1234 } 1235 1236 // GetPerfLog returns the performance logger for KBFS. 1237 func (c *ConfigLocal) GetPerfLog() logger.Logger { 1238 perfLog := c.kbCtx.GetPerfLog() 1239 if perfLog != nil { 1240 return perfLog 1241 } 1242 return c.MakeLogger("") 1243 } 1244 1245 // EnableDiskLimiter fills in c.diskLimiter for use in journaling and 1246 // disk caching. It returns the EventuallyConsistentQuotaUsage object 1247 // used by the disk limiter. 1248 func (c *ConfigLocal) EnableDiskLimiter(configRoot string) error { 1249 if c.diskLimiter != nil { 1250 return errors.New("c.diskLimiter is already non-nil") 1251 } 1252 1253 params := makeDefaultBackpressureDiskLimiterParams( 1254 configRoot, c.GetQuotaUsage, c.diskBlockCacheFraction, c.syncBlockCacheFraction) 1255 log := c.MakeLogger("") 1256 log.Debug("Setting disk storage byte limit to %d and file limit to %d", 1257 params.byteLimit, params.fileLimit) 1258 err := os.MkdirAll(configRoot, 0700) 1259 if err != nil { 1260 return err 1261 } 1262 1263 diskLimiter, err := newBackpressureDiskLimiter(log, params) 1264 if err != nil { 1265 return err 1266 } 1267 c.diskLimiter = diskLimiter 1268 return nil 1269 } 1270 1271 // EnableJournaling creates a JournalManager and attaches it to 1272 // this config. journalRoot must be non-empty. Errors returned are 1273 // non-fatal. 1274 func (c *ConfigLocal) EnableJournaling( 1275 ctx context.Context, journalRoot string, 1276 bws TLFJournalBackgroundWorkStatus) error { 1277 jManager, err := GetJournalManager(c) 1278 if err == nil { 1279 // Journaling shouldn't be enabled twice for the same 1280 // config. 1281 return errors.New("trying to enable journaling twice") 1282 } 1283 1284 if c.diskLimiter == nil { 1285 return errors.New("disk limiter must be enabled to enable journaling") 1286 } 1287 1288 // TODO: Sanity-check the root directory, e.g. create 1289 // it if it doesn't exist, make sure that it doesn't 1290 // point to /keybase itself, etc. 1291 log := c.MakeLogger("") 1292 branchListener := c.KBFSOps().(branchChangeListener) 1293 flushListener := c.KBFSOps().(mdFlushListener) 1294 1295 // Make sure the journal root exists. 1296 err = ioutil.MkdirAll(journalRoot, 0700) 1297 if err != nil { 1298 return err 1299 } 1300 1301 jManager = makeJournalManager(c, log, journalRoot, c.BlockCache(), 1302 c.DirtyBlockCache(), c.BlockServer(), c.MDOps(), branchListener, 1303 flushListener, bws) 1304 1305 c.SetBlockServer(jManager.blockServer()) 1306 c.SetMDOps(jManager.mdOps()) 1307 1308 bcacheErr := c.journalizeBcaches(jManager) 1309 enableErr := func() error { 1310 // If this fails, then existing journals will be 1311 // enabled when we receive the login notification. 1312 session, err := c.KBPKI().GetCurrentSession(ctx) 1313 if err != nil { 1314 return err 1315 } 1316 1317 err = jManager.EnableExistingJournals( 1318 ctx, session.UID, session.VerifyingKey, bws) 1319 if err != nil { 1320 return err 1321 } 1322 1323 wg := jManager.MakeFBOsForExistingJournals(ctx) 1324 wg.Wait() 1325 return nil 1326 }() 1327 switch { 1328 case bcacheErr != nil && enableErr != nil: 1329 return errors.Errorf( 1330 "Got errors %+v and %+v", bcacheErr, enableErr) 1331 case bcacheErr != nil: 1332 return bcacheErr 1333 case enableErr != nil: 1334 return enableErr 1335 } 1336 1337 return nil 1338 } 1339 1340 func (c *ConfigLocal) cleanSyncBlockCacheForTlfInBackgroundLocked( 1341 tlfID tlf.ID, ch chan<- error) { 1342 // Start a background goroutine deleting all the blocks from this 1343 // TLF. 1344 ctx, cancel := context.WithCancel(context.Background()) 1345 if oldCancel, ok := c.tlfClearCancels[tlfID]; ok { 1346 oldCancel() 1347 } 1348 c.tlfClearCancels[tlfID] = cancel 1349 diskBlockCache := c.diskBlockCache 1350 go func() { 1351 defer cancel() 1352 ch <- diskBlockCache.ClearAllTlfBlocks( 1353 ctx, tlfID, DiskBlockSyncCache) 1354 }() 1355 } 1356 1357 func (c *ConfigLocal) cleanSyncBlockCache() { 1358 ctx := context.Background() 1359 dbc := c.DiskBlockCache() 1360 log := c.MakeLogger("") 1361 if dbc == nil { 1362 // This could happen if there's a race with the caches being 1363 // reset multiple times in a row. Hopefully the next reset 1364 // will clean the caches properly. 1365 log.CDebugf(ctx, "No cache set; skipping sync cleaning") 1366 return 1367 } 1368 err := dbc.WaitUntilStarted(DiskBlockSyncCache) 1369 if err != nil { 1370 log.CDebugf( 1371 ctx, "Disk block cache failed to start; can't clean: %+v", err) 1372 return 1373 } 1374 1375 c.lock.Lock() 1376 defer c.lock.Unlock() 1377 1378 for i := 0; c.syncedTlfs == nil && i < maxSyncDBLoadAttempts; i++ { 1379 // Sometimes transient iOS storage permission errors prevent 1380 // us from reading the sync config DB on startup. In that 1381 // case, the `syncedTlfs` map will be nil, but we don't want 1382 // to delete all the synced blocks. 1383 log.CDebugf( 1384 ctx, "Re-loading synced TLF list for cleaning") 1385 1386 err := c.loadSyncedTlfsLocked() 1387 if err == nil { 1388 break 1389 } 1390 c.lock.Unlock() 1391 time.Sleep(syncDBLoadWaitPeriod) 1392 c.lock.Lock() 1393 } 1394 if c.syncedTlfs == nil { 1395 log.CDebugf( 1396 ctx, "Couldn't load synced TLF list for cleaning; giving up") 1397 return 1398 } 1399 1400 cacheTlfIDs, err := c.diskBlockCache.GetTlfIDs(ctx, DiskBlockSyncCache) 1401 if err != nil { 1402 log.CDebugf( 1403 ctx, "Disk block cache can't get TLF IDs; can't clean: %+v", err) 1404 return 1405 } 1406 1407 for _, id := range cacheTlfIDs { 1408 if _, ok := c.syncedTlfs[id]; ok { 1409 continue 1410 } 1411 1412 c.GetPerfLog().CDebugf(ctx, "Clearing KBFS sync blocks for TLF %s", id) 1413 c.cleanSyncBlockCacheForTlfInBackgroundLocked(id, make(chan error, 1)) 1414 } 1415 } 1416 1417 func (c *ConfigLocal) resetDiskBlockCacheLocked() error { 1418 dbc, err := newDiskBlockCacheWrapped(c, c.storageRoot, c.mode) 1419 if err != nil { 1420 return err 1421 } 1422 c.diskBlockCache = dbc 1423 if !c.mode.IsTestMode() { 1424 go c.cleanSyncBlockCache() 1425 } 1426 return nil 1427 } 1428 1429 // MakeDiskBlockCacheIfNotExists implements the Config interface for 1430 // ConfigLocal. 1431 func (c *ConfigLocal) MakeDiskBlockCacheIfNotExists() error { 1432 c.lock.Lock() 1433 defer c.lock.Unlock() 1434 if c.diskBlockCache != nil { 1435 return nil 1436 } 1437 switch c.diskCacheMode { 1438 case DiskCacheModeOff: 1439 return nil 1440 case DiskCacheModeLocal: 1441 return c.resetDiskBlockCacheLocked() 1442 case DiskCacheModeRemote: 1443 dbc, err := NewDiskBlockCacheRemote(c.kbCtx, c) 1444 if err != nil { 1445 return err 1446 } 1447 c.diskBlockCache = dbc 1448 return nil 1449 } 1450 return nil 1451 } 1452 1453 func (c *ConfigLocal) resetDiskMDCacheLocked() error { 1454 dmc, err := newDiskMDCacheLocal(c, c.storageRoot, c.mode) 1455 if err != nil { 1456 return err 1457 } 1458 if c.diskMDCache != nil { 1459 c.diskMDCache.Shutdown(context.TODO()) 1460 } 1461 c.diskMDCache = dmc 1462 return nil 1463 } 1464 1465 // MakeDiskMDCacheIfNotExists implements the Config interface for 1466 // ConfigLocal. 1467 func (c *ConfigLocal) MakeDiskMDCacheIfNotExists() error { 1468 c.lock.Lock() 1469 defer c.lock.Unlock() 1470 if c.diskMDCache != nil { 1471 return nil 1472 } 1473 return c.resetDiskMDCacheLocked() 1474 } 1475 1476 func (c *ConfigLocal) resetDiskQuotaCacheLocked() error { 1477 dqc, err := newDiskQuotaCacheLocal(c, c.storageRoot, c.mode) 1478 if err != nil { 1479 return err 1480 } 1481 if c.diskQuotaCache != nil { 1482 c.diskQuotaCache.Shutdown(context.TODO()) 1483 } 1484 c.diskQuotaCache = dqc 1485 return nil 1486 } 1487 1488 // MakeDiskQuotaCacheIfNotExists implements the Config interface for 1489 // ConfigLocal. 1490 func (c *ConfigLocal) MakeDiskQuotaCacheIfNotExists() error { 1491 c.lock.Lock() 1492 defer c.lock.Unlock() 1493 if c.diskQuotaCache != nil { 1494 return nil 1495 } 1496 return c.resetDiskQuotaCacheLocked() 1497 } 1498 1499 // MakeBlockMetadataStoreIfNotExists implements the Config interface for 1500 // ConfigLocal. If error happens, a Noop one is populated. 1501 func (c *ConfigLocal) MakeBlockMetadataStoreIfNotExists() (err error) { 1502 c.lock.Lock() 1503 defer c.lock.Unlock() 1504 defer func() { 1505 c.xattrStore = NewXattrStoreFromBlockMetadataStore(c.blockMetadataStore) 1506 }() 1507 if c.blockMetadataStore != nil { 1508 return nil 1509 } 1510 c.blockMetadataStore, err = newDiskBlockMetadataStore( 1511 c, c.mode, c.storageRoot) 1512 if err != nil { 1513 // TODO (KBFS-3659): when we can open levelDB read-only, 1514 // do that instead of returning a Noop version. 1515 c.blockMetadataStore = &NoopBlockMetadataStore{} 1516 return err 1517 } 1518 return nil 1519 } 1520 1521 func (c *ConfigLocal) openConfigLevelDB(configName string) ( 1522 *ldbutils.LevelDb, error) { 1523 dbPath := filepath.Join(c.storageRoot, configName) 1524 stor, err := storage.OpenFile(dbPath, false) 1525 if err != nil { 1526 return nil, err 1527 } 1528 return ldbutils.OpenLevelDb(stor, c.mode) 1529 } 1530 1531 func (c *ConfigLocal) loadSyncedTlfsLocked() (err error) { 1532 defer func() { 1533 ctx := context.TODO() 1534 c.MakeLogger("").CDebugf(ctx, "Loaded synced TLFs: %+v", err) 1535 if err != nil { 1536 // Should already be nil, but make it explicit just in 1537 // case, since the cleaning behavior depends on it being 1538 // nil if there has been an error. 1539 c.syncedTlfs = nil 1540 c.GetPerfLog().CDebugf( 1541 ctx, "KBFS failed to open synced TLFs database: %v", err) 1542 } else { 1543 c.GetPerfLog().CDebugf( 1544 ctx, "KBFS loaded %d synced TLFs", len(c.syncedTlfs)) 1545 } 1546 }() 1547 syncedTlfs := make(map[tlf.ID]FolderSyncConfig) 1548 syncedTlfPaths := make(map[string]bool) 1549 if c.mode.IsTestMode() { 1550 c.syncedTlfs = syncedTlfs 1551 c.syncedTlfPaths = syncedTlfPaths 1552 return nil 1553 } 1554 if c.storageRoot == "" { 1555 return errors.New("empty storageRoot specified for non-test run") 1556 } 1557 ldb, err := c.openConfigLevelDB(syncedTlfConfigFolderName) 1558 if err != nil { 1559 return err 1560 } 1561 defer ldb.Close() 1562 iter := ldb.NewIterator(nil, nil) 1563 defer iter.Release() 1564 1565 log := c.MakeLogger("") 1566 // If there are any un-parseable IDs, delete them. 1567 deleteBatch := new(leveldb.Batch) 1568 for iter.Next() { 1569 key := string(iter.Key()) 1570 tlfID, err := tlf.ParseID(key) 1571 if err != nil { 1572 log.Debug("deleting TLF %s from synced TLF list", key) 1573 deleteBatch.Delete(iter.Key()) 1574 continue 1575 } 1576 var config FolderSyncConfig 1577 val := iter.Value() 1578 if val != nil { 1579 err = c.codec.Decode(val, &config) 1580 if err != nil { 1581 return err 1582 } 1583 } else { 1584 // For backwards-compatibility, consider a nil value to 1585 // mean "enabled". 1586 config.Mode = keybase1.FolderSyncMode_ENABLED 1587 } 1588 syncedTlfs[tlfID] = config 1589 if config.TlfPath != "" { 1590 syncedTlfPaths[config.TlfPath] = true 1591 } 1592 } 1593 c.syncedTlfs = syncedTlfs 1594 c.syncedTlfPaths = syncedTlfPaths 1595 return ldb.Write(deleteBatch, nil) 1596 } 1597 1598 // GetTlfSyncState implements the syncedTlfGetterSetter interface for 1599 // ConfigLocal. 1600 func (c *ConfigLocal) GetTlfSyncState(tlfID tlf.ID) FolderSyncConfig { 1601 c.lock.RLock() 1602 defer c.lock.RUnlock() 1603 return c.syncedTlfs[tlfID] 1604 } 1605 1606 // IsSyncedTlf implements the syncedTlfGetterSetter interface for 1607 // ConfigLocal. 1608 func (c *ConfigLocal) IsSyncedTlf(tlfID tlf.ID) bool { 1609 return c.GetTlfSyncState(tlfID).Mode == keybase1.FolderSyncMode_ENABLED 1610 } 1611 1612 // IsSyncedTlfPath implements the syncedTlfGetterSetter interface for 1613 // ConfigLocal. 1614 func (c *ConfigLocal) IsSyncedTlfPath(tlfPath string) bool { 1615 c.lock.RLock() 1616 defer c.lock.RUnlock() 1617 return c.syncedTlfPaths[tlfPath] 1618 } 1619 1620 // OfflineAvailabilityForPath implements the offlineStatusGetter 1621 // interface for ConfigLocal. 1622 func (c *ConfigLocal) OfflineAvailabilityForPath( 1623 tlfPath string) keybase1.OfflineAvailability { 1624 if c.IsSyncedTlfPath(tlfPath) { 1625 return keybase1.OfflineAvailability_BEST_EFFORT 1626 } 1627 return keybase1.OfflineAvailability_NONE 1628 } 1629 1630 // OfflineAvailabilityForID implements the offlineStatusGetter 1631 // interface for ConfigLocal. 1632 func (c *ConfigLocal) OfflineAvailabilityForID( 1633 tlfID tlf.ID) keybase1.OfflineAvailability { 1634 if c.GetTlfSyncState(tlfID).Mode != keybase1.FolderSyncMode_DISABLED { 1635 return keybase1.OfflineAvailability_BEST_EFFORT 1636 } 1637 return keybase1.OfflineAvailability_NONE 1638 } 1639 1640 func (c *ConfigLocal) setTlfSyncState( 1641 ctx context.Context, tlfID tlf.ID, config FolderSyncConfig) ( 1642 <-chan error, error) { 1643 c.lock.Lock() 1644 defer c.lock.Unlock() 1645 diskCacheWrapped, ok := c.diskBlockCache.(*diskBlockCacheWrapped) 1646 if !ok { 1647 return nil, errors.Errorf( 1648 "invalid disk cache type to set TLF sync state: %T", 1649 c.diskBlockCache) 1650 } 1651 if !diskCacheWrapped.IsSyncCacheEnabled() { 1652 return nil, errors.New("sync block cache is not enabled") 1653 } 1654 1655 if !c.mode.IsTestMode() { 1656 if c.storageRoot == "" { 1657 return nil, errors.New( 1658 "empty storageRoot specified for non-test run") 1659 } 1660 ldb, err := c.openConfigLevelDB(syncedTlfConfigFolderName) 1661 if err != nil { 1662 return nil, err 1663 } 1664 defer ldb.Close() 1665 tlfBytes, err := tlfID.MarshalText() 1666 if err != nil { 1667 return nil, err 1668 } 1669 if config.Mode == keybase1.FolderSyncMode_DISABLED { 1670 err = ldb.Delete(tlfBytes, nil) 1671 } else { 1672 if cancel, ok := c.tlfClearCancels[tlfID]; ok { 1673 cancel() 1674 } 1675 var buf []byte 1676 buf, err = c.codec.Encode(&config) 1677 if err != nil { 1678 return nil, err 1679 } 1680 err = ldb.Put(tlfBytes, buf, nil) 1681 } 1682 if err != nil { 1683 return nil, err 1684 } 1685 } 1686 1687 ch := make(chan error, 1) 1688 if config.Mode == keybase1.FolderSyncMode_DISABLED { 1689 c.GetPerfLog().CDebugf( 1690 ctx, "Clearing KBFS sync blocks for disabled TLF %s", tlfID) 1691 c.cleanSyncBlockCacheForTlfInBackgroundLocked(tlfID, ch) 1692 } else { 1693 ch <- nil 1694 } 1695 1696 oldConfig := c.syncedTlfs[tlfID] 1697 if config.TlfPath != oldConfig.TlfPath { 1698 delete(c.syncedTlfPaths, oldConfig.TlfPath) 1699 } 1700 1701 c.syncedTlfs[tlfID] = config 1702 if config.TlfPath != "" { 1703 c.syncedTlfPaths[config.TlfPath] = true 1704 } 1705 return ch, nil 1706 } 1707 1708 // SetTlfSyncState implements the syncedTlfGetterSetter interface for 1709 // ConfigLocal. 1710 func (c *ConfigLocal) SetTlfSyncState( 1711 ctx context.Context, tlfID tlf.ID, config FolderSyncConfig) ( 1712 <-chan error, error) { 1713 if !c.IsTestMode() && config.Mode != keybase1.FolderSyncMode_ENABLED { 1714 // If we're disabling, or just changing the partial sync 1715 // config (which may be removing paths), we should cancel all 1716 // the previous prefetches for this TLF. For partial syncs, a 1717 // new sync will be started. 1718 err := c.BlockOps().Prefetcher().CancelTlfPrefetches(ctx, tlfID) 1719 if err != nil { 1720 return nil, err 1721 } 1722 } 1723 return c.setTlfSyncState(ctx, tlfID, config) 1724 } 1725 1726 // GetAllSyncedTlfs implements the syncedTlfGetterSetter interface for 1727 // ConfigLocal. 1728 func (c *ConfigLocal) GetAllSyncedTlfs() []tlf.ID { 1729 c.lock.RLock() 1730 defer c.lock.RUnlock() 1731 tlfs := make([]tlf.ID, 0, len(c.syncedTlfs)) 1732 for tlf, config := range c.syncedTlfs { 1733 if config.Mode != keybase1.FolderSyncMode_DISABLED { 1734 tlfs = append(tlfs, tlf) 1735 } 1736 } 1737 return tlfs 1738 } 1739 1740 // PrefetchStatus implements the Config interface for ConfigLocal. 1741 func (c *ConfigLocal) PrefetchStatus(ctx context.Context, tlfID tlf.ID, 1742 ptr data.BlockPointer) PrefetchStatus { 1743 dbc := c.DiskBlockCache() 1744 if dbc == nil { 1745 // We must be in testing mode, so check the block retrieval queue. 1746 bops, ok := c.BlockOps().(*BlockOpsStandard) 1747 if !ok { 1748 return NoPrefetch 1749 } 1750 status, err := bops.queue.getPrefetchStatus(ptr.ID) 1751 if err != nil { 1752 c.MakeLogger("").CDebugf(ctx, 1753 "Error getting prefetch status: %+v", err) 1754 return NoPrefetch 1755 } 1756 return status 1757 } 1758 1759 prefetchStatus, err := dbc.GetPrefetchStatus( 1760 ctx, tlfID, ptr.ID, DiskBlockAnyCache) 1761 if err != nil { 1762 return NoPrefetch 1763 } 1764 return prefetchStatus 1765 } 1766 1767 // GetRekeyFSMLimiter implements the Config interface for ConfigLocal. 1768 func (c *ConfigLocal) GetRekeyFSMLimiter() *OngoingWorkLimiter { 1769 return c.rekeyFSMLimiter 1770 } 1771 1772 // GetConflictResolutionDB implements the Config interface for ConfigLocal. 1773 func (c *ConfigLocal) GetConflictResolutionDB() (db *ldbutils.LevelDb) { 1774 return c.conflictResolutionDB 1775 } 1776 1777 // GetSettingsDB implements the Config interface for ConfigLocal. 1778 func (c *ConfigLocal) GetSettingsDB() (db *SettingsDB) { 1779 return c.settingsDB 1780 } 1781 1782 // SetKBFSService sets the KBFSService for this ConfigLocal. 1783 func (c *ConfigLocal) SetKBFSService(k *KBFSService) { 1784 c.lock.Lock() 1785 defer c.lock.Unlock() 1786 if c.kbfsService != nil { 1787 c.kbfsService.Shutdown() 1788 } 1789 c.kbfsService = k 1790 } 1791 1792 // RootNodeWrappers implements the Config interface for ConfigLocal. 1793 func (c *ConfigLocal) RootNodeWrappers() []func(Node) Node { 1794 c.lock.RLock() 1795 defer c.lock.RUnlock() 1796 return c.rootNodeWrappers 1797 } 1798 1799 // AddRootNodeWrapper implements the Config interface for ConfigLocal. 1800 func (c *ConfigLocal) AddRootNodeWrapper(f func(Node) Node) { 1801 c.lock.Lock() 1802 defer c.lock.Unlock() 1803 c.rootNodeWrappers = append(c.rootNodeWrappers, f) 1804 if c.kbfs != nil { 1805 c.kbfs.AddRootNodeWrapper(f) 1806 } 1807 } 1808 1809 // SetVLogLevel implements the Config interface for ConfigLocal. 1810 func (c *ConfigLocal) SetVLogLevel(levelString string) { 1811 c.lock.Lock() 1812 defer c.lock.Unlock() 1813 c.vdebugSetting = levelString 1814 for _, vlog := range c.vlogs { 1815 vlog.Configure(levelString) 1816 } 1817 } 1818 1819 // VLogLevel implements the Config interface for ConfigLocal. 1820 func (c *ConfigLocal) VLogLevel() string { 1821 c.lock.RLock() 1822 defer c.lock.RUnlock() 1823 return c.vdebugSetting 1824 } 1825 1826 // SetDiskCacheMode sets the disk cache mode for this config, after 1827 // construction. Mostly useful for tests. 1828 func (c *ConfigLocal) SetDiskCacheMode(m DiskCacheMode) { 1829 c.lock.Lock() 1830 defer c.lock.Unlock() 1831 c.diskCacheMode = m 1832 if c.diskCacheMode == DiskCacheModeLocal { 1833 // Any error is logged in the function itself. 1834 _ = c.loadSyncedTlfsLocked() 1835 } 1836 } 1837 1838 // SubscriptionManager implements the Config interface. 1839 func (c *ConfigLocal) SubscriptionManager( 1840 clientID SubscriptionManagerClientID, purgeable bool, 1841 notifier SubscriptionNotifier) SubscriptionManager { 1842 return c.subscriptionManagerManager.get(clientID, purgeable, notifier) 1843 } 1844 1845 // SubscriptionManagerPublisher implements the Config interface. 1846 func (c *ConfigLocal) SubscriptionManagerPublisher() SubscriptionManagerPublisher { 1847 return c.subscriptionManagerManager 1848 } 1849 1850 // KbEnv implements the Config interface. 1851 func (c *ConfigLocal) KbEnv() *libkb.Env { 1852 c.lock.RLock() 1853 defer c.lock.RUnlock() 1854 return c.kbCtx.GetEnv() 1855 } 1856 1857 // KbContext implements the Config interface. 1858 func (c *ConfigLocal) KbContext() Context { 1859 c.lock.RLock() 1860 defer c.lock.RUnlock() 1861 return c.kbCtx 1862 } 1863 1864 // AddResetForLoginTarget implements the Config interface. 1865 func (c *ConfigLocal) AddResetForLoginTarget(t ResetForLoginer) { 1866 c.lock.Lock() 1867 defer c.lock.Unlock() 1868 c.resetForLoginTargets = append(c.resetForLoginTargets, t) 1869 } 1870 1871 // ResetForLogin implements the Config interface. 1872 func (c *ConfigLocal) ResetForLogin(ctx context.Context, username libkb.NormalizedUsername) { 1873 targets := func() []ResetForLoginer { 1874 ret := make([]ResetForLoginer, len(c.resetForLoginTargets)) 1875 c.lock.Lock() 1876 defer c.lock.Unlock() 1877 copy(ret, c.resetForLoginTargets) 1878 return ret 1879 }() 1880 log := c.MakeLogger("") 1881 for _, target := range targets { 1882 err := target.ResetForLogin(ctx, username) 1883 if err != nil { 1884 log.Warning("target.ResetForLogin error: %v", err) 1885 } 1886 } 1887 }