github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/modes.go (about)

     1  // Copyright 2018 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  	"fmt"
     9  	"math"
    10  	"os"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/keybase/client/go/protocol/keybase1"
    15  	"github.com/syndtr/goleveldb/leveldb/opt"
    16  )
    17  
    18  // NewInitModeFromType returns an InitMode object corresponding to the
    19  // given type.
    20  func NewInitModeFromType(t InitModeType) InitMode {
    21  	switch t {
    22  	case InitDefault:
    23  		return modeDefault{}
    24  	case InitMinimal:
    25  		return modeMinimal{}
    26  	case InitSingleOp:
    27  		return modeSingleOp{modeDefault{}}
    28  	case InitConstrained:
    29  		return modeConstrained{modeDefault{}}
    30  	case InitMemoryLimited:
    31  		return modeMemoryLimited{modeConstrained{modeDefault{}}}
    32  	case InitTestSearch:
    33  		return modeTestSearch{modeDefault{}}
    34  	case InitSingleOpWithQR:
    35  		return modeSingleOpWithQR{modeSingleOp{modeDefault{}}}
    36  	default:
    37  		panic(fmt.Sprintf("Unknown mode: %s", t))
    38  	}
    39  }
    40  
    41  const (
    42  	defaultQRPeriod      = 1 * time.Hour
    43  	defaultQRMinUnrefAge = 2 * 7 * 24 * time.Hour // 2 weeks
    44  )
    45  
    46  // Default mode:
    47  
    48  type modeDefault struct {
    49  }
    50  
    51  func (md modeDefault) Type() InitModeType {
    52  	return InitDefault
    53  }
    54  
    55  func (md modeDefault) BlockWorkers() int {
    56  	return defaultBlockRetrievalWorkerQueueSize
    57  }
    58  
    59  func (md modeDefault) PrefetchWorkers() int {
    60  	return defaultPrefetchWorkerQueueSize
    61  }
    62  
    63  func (md modeDefault) ThrottledPrefetchPeriod() time.Duration {
    64  	return defaultThrottledPrefetchPeriod
    65  }
    66  
    67  func (md modeDefault) DefaultBlockRequestAction() BlockRequestAction {
    68  	return BlockRequestWithPrefetch
    69  }
    70  
    71  func (md modeDefault) RekeyWorkers() int {
    72  	return 16
    73  }
    74  
    75  func (md modeDefault) RekeyQueueSize() int {
    76  	return 2048 // 48 KB
    77  }
    78  
    79  func (md modeDefault) IsTestMode() bool {
    80  	return false
    81  }
    82  
    83  func (md modeDefault) IsSingleOp() bool {
    84  	return false
    85  }
    86  
    87  func (md modeDefault) DirtyBlockCacheEnabled() bool {
    88  	return true
    89  }
    90  
    91  func (md modeDefault) BackgroundFlushesEnabled() bool {
    92  	return true
    93  }
    94  
    95  func (md modeDefault) MetricsEnabled() bool {
    96  	return true
    97  }
    98  
    99  func (md modeDefault) ConflictResolutionEnabled() bool {
   100  	return true
   101  }
   102  
   103  func (md modeDefault) BlockManagementEnabled() bool {
   104  	return true
   105  }
   106  
   107  func (md modeDefault) MaxBlockPtrsToManageAtOnce() int {
   108  	return -1 /* unconstrained by default */
   109  }
   110  
   111  func (md modeDefault) QuotaReclamationEnabled() bool {
   112  	return true
   113  }
   114  
   115  func (md modeDefault) QuotaReclamationPeriod() time.Duration {
   116  	return defaultQRPeriod
   117  }
   118  
   119  func (md modeDefault) QuotaReclamationMinUnrefAge() time.Duration {
   120  	return defaultQRMinUnrefAge
   121  }
   122  
   123  func (md modeDefault) QuotaReclamationMinHeadAge() time.Duration {
   124  	// How old must the most recent TLF revision be before another
   125  	// device can run QR on that TLF?  This is large, to avoid
   126  	// unnecessary conflicts on the TLF between devices.
   127  	return defaultQRMinUnrefAge + 24*time.Hour
   128  }
   129  
   130  func (md modeDefault) NodeCacheEnabled() bool {
   131  	return true
   132  }
   133  
   134  func (md modeDefault) TLFUpdatesEnabled() bool {
   135  	return true
   136  }
   137  
   138  func (md modeDefault) KBFSServiceEnabled() bool {
   139  	return true
   140  }
   141  
   142  func (md modeDefault) JournalEnabled() bool {
   143  	return true
   144  }
   145  
   146  func (md modeDefault) UnmergedTLFsEnabled() bool {
   147  	return true
   148  }
   149  
   150  func (md modeDefault) ServiceKeepaliveEnabled() bool {
   151  	return true
   152  }
   153  
   154  func (md modeDefault) TLFEditHistoryEnabled() bool {
   155  	return true
   156  }
   157  
   158  func (md modeDefault) SendEditNotificationsEnabled() bool {
   159  	return true
   160  }
   161  
   162  func (md modeDefault) ClientType() keybase1.ClientType {
   163  	return keybase1.ClientType_KBFS
   164  }
   165  
   166  func (md modeDefault) LocalHTTPServerEnabled() bool {
   167  	return true
   168  }
   169  
   170  func (md modeDefault) MaxCleanBlockCacheCapacity() uint64 {
   171  	return math.MaxUint64
   172  }
   173  
   174  func (md modeDefault) OldStorageRootCleaningEnabled() bool {
   175  	return true
   176  }
   177  
   178  func (md modeDefault) DoRefreshFavoritesOnInit() bool {
   179  	return true
   180  }
   181  
   182  func (md modeDefault) DoLogObfuscation() bool {
   183  	return true
   184  }
   185  
   186  func (md modeDefault) BlockTLFEditHistoryIntialization() bool {
   187  	return false
   188  }
   189  
   190  func (md modeDefault) InitialDelayForBackgroundWork() time.Duration {
   191  	return 0
   192  }
   193  
   194  func (md modeDefault) BackgroundWorkPeriod() time.Duration {
   195  	return 0
   196  }
   197  
   198  func (md modeDefault) IndexingEnabled() bool {
   199  	return false
   200  }
   201  
   202  func (md modeDefault) DelayInitialConnect() bool {
   203  	return false
   204  }
   205  
   206  func (md modeDefault) DbWriteBufferSize() int {
   207  	return 10 * opt.MiB // 10 MB
   208  }
   209  
   210  func (md modeDefault) DiskCacheCompactionEnabled() bool {
   211  	return true
   212  }
   213  
   214  func (md modeDefault) EditHistoryPrefetchingEnabled() bool {
   215  	return false
   216  }
   217  
   218  // Minimal mode:
   219  
   220  type modeMinimal struct {
   221  }
   222  
   223  func (mm modeMinimal) Type() InitModeType {
   224  	return InitMinimal
   225  }
   226  
   227  func (mm modeMinimal) BlockWorkers() int {
   228  	// In minimal mode, block re-embedding is not required, so we
   229  	// don't fetch the unembedded blocks..
   230  	return 0
   231  }
   232  
   233  func (mm modeMinimal) PrefetchWorkers() int {
   234  	return 0
   235  }
   236  
   237  func (mm modeMinimal) ThrottledPrefetchPeriod() time.Duration {
   238  	return 0
   239  }
   240  
   241  func (mm modeMinimal) DefaultBlockRequestAction() BlockRequestAction {
   242  	return BlockRequestSolo
   243  }
   244  
   245  func (mm modeMinimal) RekeyWorkers() int {
   246  	return 4
   247  }
   248  
   249  func (mm modeMinimal) RekeyQueueSize() int {
   250  	return 512 // 12 KB
   251  }
   252  
   253  func (mm modeMinimal) IsTestMode() bool {
   254  	return false
   255  }
   256  
   257  func (mm modeMinimal) IsSingleOp() bool {
   258  	return false
   259  }
   260  
   261  func (mm modeMinimal) DirtyBlockCacheEnabled() bool {
   262  	// No blocks will be dirtied in minimal mode, so don't bother with
   263  	// the dirty block cache.
   264  	return false
   265  }
   266  
   267  func (mm modeMinimal) BackgroundFlushesEnabled() bool {
   268  	// Don't do background flushes when in minimal mode, since there
   269  	// shouldn't be any data writes.
   270  	return false
   271  }
   272  
   273  func (mm modeMinimal) MetricsEnabled() bool {
   274  	return false
   275  }
   276  
   277  func (mm modeMinimal) ConflictResolutionEnabled() bool {
   278  	// No need to run CR if there won't be any data writes on this
   279  	// device.  (There may still be rekey writes, but we don't allow
   280  	// conflicts to happen in that case.)
   281  	return false
   282  }
   283  
   284  func (mm modeMinimal) BlockManagementEnabled() bool {
   285  	// If this device is in minimal mode and won't be doing any data
   286  	// writes, no need deal with block-level cleanup operations.
   287  	// TODO: in the future it might still be useful to have
   288  	// e.g. mobile devices doing QR.
   289  	return false
   290  }
   291  
   292  func (mm modeMinimal) MaxBlockPtrsToManageAtOnce() int {
   293  	panic("Shouldn't be called when block management is disabled")
   294  }
   295  
   296  func (mm modeMinimal) QuotaReclamationEnabled() bool {
   297  	return false
   298  }
   299  
   300  func (mm modeMinimal) QuotaReclamationPeriod() time.Duration {
   301  	return 0
   302  }
   303  
   304  func (mm modeMinimal) QuotaReclamationMinUnrefAge() time.Duration {
   305  	return 0
   306  }
   307  
   308  func (mm modeMinimal) QuotaReclamationMinHeadAge() time.Duration {
   309  	return 0
   310  }
   311  
   312  func (mm modeMinimal) NodeCacheEnabled() bool {
   313  	// If we're in minimal mode, let the node cache remain nil to
   314  	// ensure that the user doesn't try any data reads or writes.
   315  	return false
   316  }
   317  
   318  func (mm modeMinimal) TLFUpdatesEnabled() bool {
   319  	return true
   320  }
   321  
   322  func (mm modeMinimal) KBFSServiceEnabled() bool {
   323  	return false
   324  }
   325  
   326  func (mm modeMinimal) JournalEnabled() bool {
   327  	return false
   328  }
   329  
   330  func (mm modeMinimal) UnmergedTLFsEnabled() bool {
   331  	// Writes aren't allowed, so unmerged TLFs on this device
   332  	// shouldn't be possible.
   333  	return false
   334  }
   335  
   336  func (mm modeMinimal) ServiceKeepaliveEnabled() bool {
   337  	return false
   338  }
   339  
   340  func (mm modeMinimal) TLFEditHistoryEnabled() bool {
   341  	return false
   342  }
   343  
   344  func (mm modeMinimal) SendEditNotificationsEnabled() bool {
   345  	// Writes aren't allowed, so we shouldn't need to send any.
   346  	return false
   347  }
   348  
   349  func (mm modeMinimal) ClientType() keybase1.ClientType {
   350  	return keybase1.ClientType_KBFS
   351  }
   352  
   353  func (mm modeMinimal) LocalHTTPServerEnabled() bool {
   354  	return false
   355  }
   356  
   357  func (mm modeMinimal) MaxCleanBlockCacheCapacity() uint64 {
   358  	return math.MaxUint64
   359  }
   360  
   361  func (mm modeMinimal) OldStorageRootCleaningEnabled() bool {
   362  	return false
   363  }
   364  
   365  func (mm modeMinimal) DoRefreshFavoritesOnInit() bool {
   366  	return false
   367  }
   368  
   369  func (mm modeMinimal) DoLogObfuscation() bool {
   370  	return true
   371  }
   372  
   373  func (mm modeMinimal) BlockTLFEditHistoryIntialization() bool {
   374  	// Never used.
   375  	return false
   376  }
   377  
   378  func (mm modeMinimal) InitialDelayForBackgroundWork() time.Duration {
   379  	// No background work
   380  	return math.MaxInt64
   381  }
   382  
   383  func (mm modeMinimal) BackgroundWorkPeriod() time.Duration {
   384  	// No background work
   385  	return math.MaxInt64
   386  }
   387  
   388  func (mm modeMinimal) IndexingEnabled() bool {
   389  	return false
   390  }
   391  
   392  func (mm modeMinimal) DelayInitialConnect() bool {
   393  	return false
   394  }
   395  
   396  func (mm modeMinimal) DbWriteBufferSize() int {
   397  	return 1 * opt.KiB // 1 KB
   398  }
   399  
   400  func (mm modeMinimal) DiskCacheCompactionEnabled() bool {
   401  	return false
   402  }
   403  
   404  func (mm modeMinimal) EditHistoryPrefetchingEnabled() bool {
   405  	return false
   406  }
   407  
   408  // Single op mode:
   409  
   410  type modeSingleOp struct {
   411  	InitMode
   412  }
   413  
   414  func (mso modeSingleOp) Type() InitModeType {
   415  	return InitSingleOp
   416  }
   417  
   418  func (mso modeSingleOp) RekeyWorkers() int {
   419  	// Just block all rekeys and don't bother cleaning up requests
   420  	// since the process is short lived anyway.
   421  	return 0
   422  }
   423  
   424  func (mso modeSingleOp) RekeyQueueSize() int {
   425  	return 0
   426  }
   427  
   428  func (mso modeSingleOp) QuotaReclamationEnabled() bool {
   429  	return false
   430  }
   431  
   432  func (mso modeSingleOp) QuotaReclamationPeriod() time.Duration {
   433  	return 0
   434  }
   435  
   436  func (mso modeSingleOp) QuotaReclamationMinUnrefAge() time.Duration {
   437  	return 0
   438  }
   439  
   440  func (mso modeSingleOp) QuotaReclamationMinHeadAge() time.Duration {
   441  	return 0
   442  }
   443  
   444  func (mso modeSingleOp) TLFUpdatesEnabled() bool {
   445  	return false
   446  }
   447  
   448  func (mso modeSingleOp) KBFSServiceEnabled() bool {
   449  	return false
   450  }
   451  
   452  func (mso modeSingleOp) UnmergedTLFsEnabled() bool {
   453  	// There's basically no way for a TLF to start off as unmerged
   454  	// since single-ops should be using a fresh journal.
   455  	return false
   456  }
   457  
   458  func (mso modeSingleOp) TLFEditHistoryEnabled() bool {
   459  	return false
   460  }
   461  
   462  func (mso modeSingleOp) MetricsEnabled() bool {
   463  	return false
   464  }
   465  
   466  func (mso modeSingleOp) SendEditNotificationsEnabled() bool {
   467  	// We don't want git, or other single op writes, showing up in the
   468  	// notification history.
   469  	return false
   470  }
   471  
   472  func (mso modeSingleOp) ClientType() keybase1.ClientType {
   473  	return keybase1.ClientType_NONE
   474  }
   475  
   476  func (mso modeSingleOp) LocalHTTPServerEnabled() bool {
   477  	return false
   478  }
   479  
   480  func (mso modeSingleOp) OldStorageRootCleaningEnabled() bool {
   481  	return false
   482  }
   483  
   484  func (mso modeSingleOp) DoRefreshFavoritesOnInit() bool {
   485  	return false
   486  }
   487  
   488  func (mso modeSingleOp) InitialDelayForBackgroundWork() time.Duration {
   489  	// No background work
   490  	return math.MaxInt64
   491  }
   492  
   493  func (mso modeSingleOp) BackgroundWorkPeriod() time.Duration {
   494  	// No background work
   495  	return math.MaxInt64
   496  }
   497  
   498  func (mso modeSingleOp) IsSingleOp() bool {
   499  	return true
   500  }
   501  
   502  func (mso modeSingleOp) DiskCacheCompactionEnabled() bool {
   503  	return false
   504  }
   505  
   506  // Single-op mode with QR:
   507  
   508  type modeSingleOpWithQR struct {
   509  	modeSingleOp
   510  }
   511  
   512  func (msowq modeSingleOpWithQR) QuotaReclamationEnabled() bool {
   513  	return true
   514  }
   515  
   516  func (msowq modeSingleOpWithQR) QuotaReclamationPeriod() time.Duration {
   517  	// We might end up needing to make this much shorter, because it
   518  	// can take a while to get through all the revisions.  But for now
   519  	// I want to make sure it doesn't wake up too often and cause too
   520  	// much CPU.
   521  	return 1 * time.Minute
   522  }
   523  
   524  func (msowq modeSingleOpWithQR) QuotaReclamationMinUnrefAge() time.Duration {
   525  	return 1 * time.Minute
   526  }
   527  
   528  func (msowq modeSingleOpWithQR) QuotaReclamationMinHeadAge() time.Duration {
   529  	// In the case of indexing, another device will never run QR on
   530  	// the TLFs in question, but might as well set it to something...
   531  	return 2 * time.Minute
   532  }
   533  
   534  // Constrained mode:
   535  
   536  type modeConstrained struct {
   537  	InitMode
   538  }
   539  
   540  func (mc modeConstrained) Type() InitModeType {
   541  	return InitConstrained
   542  }
   543  
   544  func (mc modeConstrained) BlockWorkers() int {
   545  	return 1
   546  }
   547  
   548  func (mc modeConstrained) PrefetchWorkers() int {
   549  	return 1
   550  }
   551  
   552  func (mc modeConstrained) DefaultBlockRequestAction() BlockRequestAction {
   553  	return BlockRequestSolo
   554  }
   555  
   556  func (mc modeConstrained) RekeyWorkers() int {
   557  	return 4
   558  }
   559  
   560  func (mc modeConstrained) RekeyQueueSize() int {
   561  	return 1024 // 24 KB
   562  }
   563  
   564  func (mc modeConstrained) BackgroundFlushesEnabled() bool {
   565  	return true
   566  }
   567  
   568  func (mc modeConstrained) ConflictResolutionEnabled() bool {
   569  	return true
   570  }
   571  
   572  func (mc modeConstrained) MaxBlockPtrsToManageAtOnce() int {
   573  	return 10000
   574  }
   575  
   576  func (mc modeConstrained) QuotaReclamationEnabled() bool {
   577  	return true
   578  }
   579  
   580  func (mc modeConstrained) QuotaReclamationPeriod() time.Duration {
   581  	return defaultQRPeriod
   582  }
   583  
   584  func (mc modeConstrained) QuotaReclamationMinUnrefAge() time.Duration {
   585  	return defaultQRMinUnrefAge
   586  }
   587  
   588  func (mc modeConstrained) QuotaReclamationMinHeadAge() time.Duration {
   589  	// Don't ever run QR in constrained mode unless this device was
   590  	// the most recent writer.
   591  	return 0
   592  }
   593  
   594  func (mc modeConstrained) KBFSServiceEnabled() bool {
   595  	return false
   596  }
   597  
   598  func (mc modeConstrained) JournalEnabled() bool {
   599  	return true
   600  }
   601  
   602  func (mc modeConstrained) UnmergedTLFsEnabled() bool {
   603  	return true
   604  }
   605  
   606  func (mc modeConstrained) ServiceKeepaliveEnabled() bool {
   607  	return false
   608  }
   609  
   610  func (mc modeConstrained) TLFEditHistoryEnabled() bool {
   611  	return true
   612  }
   613  
   614  func (mc modeConstrained) SendEditNotificationsEnabled() bool {
   615  	return true
   616  }
   617  
   618  func (mc modeConstrained) LocalHTTPServerEnabled() bool {
   619  	return true
   620  }
   621  
   622  func (mc modeConstrained) BlockTLFEditHistoryIntialization() bool {
   623  	// In constrained mode, we don't want to incur this work in the
   624  	// background when it might interfere with other foreground tasks.
   625  	// Instead, make requests that depend on the edit history block
   626  	// and effectively foreground that initialization work.
   627  	return true
   628  }
   629  
   630  func (mc modeConstrained) InitialDelayForBackgroundWork() time.Duration {
   631  	return 10 * time.Second
   632  }
   633  
   634  func (mc modeConstrained) BackgroundWorkPeriod() time.Duration {
   635  	return 5 * time.Second
   636  }
   637  
   638  func (mc modeConstrained) DelayInitialConnect() bool {
   639  	return true
   640  }
   641  
   642  func (mc modeConstrained) DbWriteBufferSize() int {
   643  	return 100 * opt.KiB // 100 KB
   644  }
   645  
   646  func (mc modeConstrained) DiskCacheCompactionEnabled() bool {
   647  	return false
   648  }
   649  
   650  // Memory limited mode
   651  
   652  type modeMemoryLimited struct {
   653  	InitMode
   654  }
   655  
   656  func (mml modeMemoryLimited) Type() InitModeType {
   657  	return InitMemoryLimited
   658  }
   659  
   660  func (mml modeMemoryLimited) RekeyWorkers() int {
   661  	return 0
   662  }
   663  
   664  func (mml modeMemoryLimited) RekeyQueueSize() int {
   665  	return 0
   666  }
   667  
   668  func (mml modeMemoryLimited) ConflictResolutionEnabled() bool {
   669  	return false
   670  }
   671  
   672  func (mml modeMemoryLimited) QuotaReclamationEnabled() bool {
   673  	return false
   674  }
   675  
   676  func (mml modeMemoryLimited) UnmergedTLFsEnabled() bool {
   677  	return false
   678  }
   679  
   680  func (mml modeMemoryLimited) SendEditNotificationsEnabled() bool {
   681  	return false
   682  }
   683  
   684  func (mml modeMemoryLimited) LocalHTTPServerEnabled() bool {
   685  	return false
   686  }
   687  
   688  func (mml modeMemoryLimited) MaxCleanBlockCacheCapacity() uint64 {
   689  	return 1 * (1 << 20) // 1 MB
   690  }
   691  
   692  func (mml modeMemoryLimited) TLFEditHistoryEnabled() bool {
   693  	return false
   694  }
   695  
   696  func (mml modeMemoryLimited) DbWriteBufferSize() int {
   697  	return 1 * opt.KiB // 1 KB
   698  }
   699  
   700  type modeTestSearch struct {
   701  	InitMode
   702  }
   703  
   704  func (mts modeTestSearch) IndexingEnabled() bool {
   705  	return true
   706  }
   707  
   708  func (mts modeTestSearch) InitialDelayForBackgroundWork() time.Duration {
   709  	// Delay background work like loading the synced TLFs, until the
   710  	// indexer has registered to receive notifications about them.
   711  	return 5 * time.Second
   712  }
   713  
   714  func (mts modeTestSearch) DelayInitialConnect() bool {
   715  	return false
   716  }
   717  
   718  // Wrapper for tests.
   719  
   720  type modeTest struct {
   721  	InitMode
   722  }
   723  
   724  func (mt modeTest) IsTestMode() bool {
   725  	return true
   726  }
   727  
   728  func (mt modeTest) QuotaReclamationPeriod() time.Duration {
   729  	// No auto-reclamation during testing.
   730  	return 0
   731  }
   732  
   733  func (mt modeTest) QuotaReclamationMinUnrefAge() time.Duration {
   734  	// Smaller archival window by default during testing, for
   735  	// backwards compatibility with old tests.
   736  	return 1 * time.Minute
   737  }
   738  
   739  func (mt modeTest) QuotaReclamationMinHeadAge() time.Duration {
   740  	// No min head age during testing.
   741  	return 0
   742  }
   743  
   744  // EnvKeybaseTestObfuscateLogsForTest is "KEYBASE_TEST_OBFUSCATE_LOGS" and used
   745  // to specify if log obfuscation should be enabled for test.
   746  const EnvKeybaseTestObfuscateLogsForTest = "KEYBASE_TEST_OBFUSCATE_LOGS"
   747  
   748  func (mt modeTest) DoLogObfuscation() bool {
   749  	e := os.Getenv(EnvKeybaseTestObfuscateLogsForTest)
   750  	return e != "" && e != "0" && strings.ToLower(e) != "false"
   751  }