github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/pfsagentd/globals.go (about) 1 // Copyright (c) 2015-2021, NVIDIA CORPORATION. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package main 5 6 import ( 7 "container/list" 8 "fmt" 9 "io" 10 "log" 11 "math" 12 "net/http" 13 "os" 14 "os/exec" 15 "sync" 16 "time" 17 18 "bazil.org/fuse" 19 20 "github.com/swiftstack/fission" 21 "github.com/swiftstack/sortedmap" 22 23 "github.com/swiftstack/ProxyFS/bucketstats" 24 "github.com/swiftstack/ProxyFS/conf" 25 "github.com/swiftstack/ProxyFS/inode" 26 "github.com/swiftstack/ProxyFS/jrpcfs" 27 "github.com/swiftstack/ProxyFS/retryrpc" 28 "github.com/swiftstack/ProxyFS/utils" 29 ) 30 31 type configStruct struct { 32 FUSEVolumeName string 33 FUSEMountPointPath string // Unless starting with '/', relative to $CWD 34 FUSEUnMountRetryDelay time.Duration 35 FUSEUnMountRetryCap uint64 36 PlugInPath string 37 PlugInEnvName string 38 PlugInEnvValue string // If "", assume it's already set as desired 39 SwiftTimeout time.Duration 40 SwiftRetryLimit uint64 41 SwiftRetryDelay time.Duration 42 SwiftRetryDelayVariance uint8 43 SwiftRetryExpBackoff float64 44 SwiftConnectionPoolSize uint64 45 FetchExtentsFromFileOffset uint64 46 FetchExtentsBeforeFileOffset uint64 47 ReadCacheLineSize uint64 // Aligned chunk of a LogSegment 48 ReadCacheLineCount uint64 49 LeaseRetryLimit uint64 50 LeaseRetryDelay time.Duration 51 LeaseRetryDelayVariance uint8 52 LeaseRetryExpBackoff float64 53 SharedLeaseLimit uint64 54 ExclusiveLeaseLimit uint64 55 ExtentMapEntryLimit uint64 56 DirtyLogSegmentLimit uint64 57 DirtyFileLimit uint64 // TODO - obsolete this 58 MaxFlushSize uint64 59 MaxFlushTime time.Duration 60 LogFilePath string // Unless starting with '/', relative to $CWD; == "" means disabled 61 LogToConsole bool 62 TraceEnabled bool 63 HTTPServerIPAddr string 64 HTTPServerTCPPort uint16 65 ReadDirPlusEnabled bool 66 XAttrEnabled bool 67 EntryDuration time.Duration 68 AttrDuration time.Duration 69 AttrBlockSize uint64 70 ReaddirMaxEntries uint64 71 FUSEMaxBackground uint16 72 FUSECongestionThreshhold uint16 73 FUSEMaxWrite uint32 74 RetryRPCDeadlineIO time.Duration 75 RetryRPCKeepAlivePeriod time.Duration 76 } 77 78 type retryDelayElementStruct struct { 79 nominal time.Duration 80 variance time.Duration 81 } 82 83 type fileInodeLeaseStateType uint32 84 85 const ( 86 fileInodeLeaseStateNone fileInodeLeaseStateType = iota 87 fileInodeLeaseStateSharedRequested 88 fileInodeLeaseStateSharedGranted 89 fileInodeLeaseStateSharedPromoting 90 fileInodeLeaseStateSharedReleasing 91 fileInodeLeaseStateExclusiveRequested 92 fileInodeLeaseStateExclusiveGranted 93 fileInodeLeaseStateExclusiveDemoting 94 fileInodeLeaseStateExclusiveReleasing 95 ) 96 97 type fileInodeLeaseRequestType uint32 98 99 const ( 100 fileInodeLeaseRequestShutdown fileInodeLeaseRequestType = iota 101 fileInodeLeaseRequestShared 102 fileInodeLeaseRequestExclusive 103 fileInodeLeaseRequestDemote 104 fileInodeLeaseRequestRelease 105 ) 106 107 // singleObjectExtentStruct is used for chunkedPutContextStruct.extentMap. 108 // 109 type singleObjectExtentStruct struct { 110 fileOffset uint64 // Key in chunkedPutContextStruct.extentMap 111 objectOffset uint64 112 length uint64 113 } 114 115 // singleObjectExtentWithLinkStruct is used to represent a ReadPlanStep. A chunkedPutContext == nil 116 // indicates a zero-filled extent rather that a read from a LogSegment not yet persisted by Swift. 117 // 118 type singleObjectExtentWithLinkStruct struct { 119 fileOffset uint64 120 objectOffset uint64 121 length uint64 122 chunkedPutContext *chunkedPutContextStruct // If == nil, implies a zero-filled extent/ReadPlanStep 123 } 124 125 // multiObjectExtentStruct is used for both the fileInodeStruct.extentMap as well 126 // as for representing a ReadPlanStep. In this latter case, an objectName == "" 127 // indicates a zero-filled extent rather than a read from a LogSegment already 128 // persisted by Swift. 129 // 130 type multiObjectExtentStruct struct { 131 fileOffset uint64 // Key in fileInodeStruct.extentMap 132 containerName string 133 objectName string // If == "", implies a zero-filled extent/ReadPlanStep 134 objectOffset uint64 135 length uint64 136 } 137 138 const ( 139 chunkedPutContextStateOpen uint8 = iota // Initial state indicating Chunked PUT is available to send a chunk 140 chunkedPutContextStateClosing // After a zero-length chunk is sent to close the Chunked PUT... awaiting http.StatusCreated 141 chunkedPutContextStateClosed // Chunked PUT received an http.StatusCreated... 142 // but we cannot yet merge it's ExtentMap updates because 143 // an as-yet un-closed Chunked PUT needs to do so first 144 chunkedPutContextExitReadPollingRate = time.Millisecond 145 ) 146 147 type chunkedPutContextStruct struct { 148 sync.WaitGroup // Used to await completion of performChunkedPut goroutine 149 containerName string // 150 objectName string // 151 extentMap sortedmap.LLRBTree // Key == singleObjectExtentStruct.fileOffset; Value == *singleObjectExtentStruct 152 buf []byte // 153 chunkedPutListElement *list.Element // FIFO Element of fileInodeStruct.chunkedPutList 154 fileInode *fileInodeStruct // 155 state uint8 // One of chunkedPutContextState{Open|Closing|Closed} 156 pos int // ObjectOffset just after last sent chunk 157 sendChan chan struct{} // Single element buffered chan to wake up *chunkedPutContextStruct.sendDaemon() 158 // will be closed to indicate a flush is requested 159 wakeChan chan struct{} // Single element buffered chan to wake up *chunkedPutContextStruct.Read() 160 // will be closed to indicate a flush is requested 161 inRead bool // Set when in Read() as a hint to Close() to help Read() cleanly exit 162 flushRequested bool // Set to remember that a flush has been requested of *chunkedPutContextStruct.Read() 163 } 164 165 type fileInodeStruct struct { 166 inode.InodeNumber 167 cachedStat *jrpcfs.StatStruct // Maintained valid/coherent with ProxyFS (possibly dirty until flushed) 168 lockWaiters *list.List // List of chan struct{} lock waiters: 169 // If == nil, no lock requests 170 // If .Len() == 0, lock grant in progress or granted but no blocked lock requests 171 // If .Len() != 0, lock grant in progress or granted and other lock requests are waiting 172 leaseState fileInodeLeaseStateType // One of fileInodeLeaseState* 173 pendingLeaseInterrupt *jrpcfs.RPCInterruptType // If non-nil, either jrpcfs.RPCInterruptTypeDemote or jrpcfs.RPCInterruptTypeRelease 174 leaseListElement *list.Element // Element on one of {unleased|shared|exclusive}FileInodeCacheLRU 175 // On globals.unleasedFileInodeCacheLRU if leaseState one of: 176 // fileInodeLeaseStateNone 177 // fileInodeLeaseStateSharedReleasing 178 // fileInodeLeaseStateExclusiveReleasing 179 // On globals.sharedLeaseFileInodeCacheLRU if leaseState one of: 180 // fileInodeLeaseStateSharedRequested 181 // fileInodeLeaseStateSharedGranted 182 // fileInodeLeaseStateExclusiveDemoting 183 // On globals.exclusiveLeaseFileInodeCacheLRU if leaseState one of: 184 // fileInodeLeaseStateSharedPromoting 185 // fileInodeLeaseStateExclusiveRequested 186 // fileInodeLeaseStateExclusiveGranted 187 extentMap sortedmap.LLRBTree // Key == multiObjectExtentStruct.fileOffset; Value == *multiObjectExtentStruct 188 chunkedPutList *list.List // FIFO List of chunkedPutContextStruct's 189 flushInProgress bool // Serializes (& singularizes) explicit Flush requests 190 chunkedPutFlushWaiterList *list.List // List of *sync.WaitGroup's for those awaiting an explicit Flush 191 // Note: These waiters cannot be holding fileInodeStruct.Lock 192 dirtyListElement *list.Element // Element on globals.fileInodeDirtyList (or nil) 193 } 194 195 type fhSetType map[uint64]struct{} 196 197 type logSegmentCacheElementStateType uint8 198 199 const ( 200 logSegmentCacheElementStateGetIssued logSegmentCacheElementStateType = iota 201 logSegmentCacheElementStateGetSuccessful 202 logSegmentCacheElementStateGetFailed // In which case it must not be in LLRBTree nor LRU 203 ) 204 205 type logSegmentCacheElementKeyStruct struct { 206 logSegmentNumber uint64 // Converted from logSegmentCacheElementStruct.objectName 207 cacheLineTag uint64 // == logSegmentCacheElementStruct.offset / globals.config.ReadCacheLineSize 208 } 209 210 type logSegmentCacheElementStruct struct { 211 sync.WaitGroup // Used by those awaiting GET result 212 state logSegmentCacheElementStateType // if logSegmentCacheElementStateGetIssued 213 containerName string 214 objectName string 215 startingOffset uint64 216 cacheLRUElement *list.Element // Element on globals.logSegmentCacheLRU 217 buf []byte 218 } 219 220 type authPlugInControlStruct struct { 221 cmd *exec.Cmd 222 stdinPipe io.WriteCloser 223 stdoutPipe io.ReadCloser 224 stderrPipe io.ReadCloser 225 stdoutChan chan []byte 226 stderrChan chan []byte 227 wg sync.WaitGroup 228 } 229 230 // metricsStruct contains Prometheus-styled field names to be output by serveGetOfMetrics(). 231 // 232 // In order to utilize Go Reflection, these field names must be capitalized (i.e. Global). 233 234 type metricsStruct struct { 235 FUSE_DoLookup_calls uint64 236 FUSE_DoForget_calls uint64 237 FUSE_DoGetAttr_calls uint64 238 FUSE_DoSetAttr_calls uint64 239 FUSE_DoReadLink_calls uint64 240 FUSE_DoSymLink_calls uint64 241 FUSE_DoMkNod_calls uint64 242 FUSE_DoMkDir_calls uint64 243 FUSE_DoUnlink_calls uint64 244 FUSE_DoRmDir_calls uint64 245 FUSE_DoRename_calls uint64 246 FUSE_DoLink_calls uint64 247 FUSE_DoOpen_calls uint64 248 FUSE_DoRead_calls uint64 249 FUSE_DoWrite_calls uint64 250 FUSE_DoStatFS_calls uint64 251 FUSE_DoRelease_calls uint64 252 FUSE_DoFSync_calls uint64 253 FUSE_DoSetXAttr_calls uint64 254 FUSE_DoGetXAttr_calls uint64 255 FUSE_DoListXAttr_calls uint64 256 FUSE_DoRemoveXAttr_calls uint64 257 FUSE_DoFlush_calls uint64 258 FUSE_DoInit_calls uint64 259 FUSE_DoOpenDir_calls uint64 260 FUSE_DoReadDir_calls uint64 261 FUSE_DoReleaseDir_calls uint64 262 FUSE_DoFSyncDir_calls uint64 263 FUSE_DoGetLK_calls uint64 264 FUSE_DoSetLK_calls uint64 265 FUSE_DoSetLKW_calls uint64 266 FUSE_DoAccess_calls uint64 267 FUSE_DoCreate_calls uint64 268 FUSE_DoInterrupt_calls uint64 269 FUSE_DoBMap_calls uint64 270 FUSE_DoDestroy_calls uint64 271 FUSE_DoPoll_calls uint64 272 FUSE_DoBatchForget_calls uint64 273 FUSE_DoFAllocate_calls uint64 274 FUSE_DoReadDirPlus_calls uint64 275 FUSE_DoRename2_calls uint64 276 FUSE_DoLSeek_calls uint64 277 278 FUSE_DoRead_bytes uint64 279 FUSE_DoWrite_bytes uint64 280 281 FUSE_DoReadDir_entries uint64 282 FUSE_DoReadDirPlus_entries uint64 283 284 FUSE_DoSetXAttr_bytes uint64 285 FUSE_DoGetXAttr_bytes uint64 286 FUSE_DoListXAttr_names uint64 287 288 FUSE_DoBatchForget_nodes uint64 289 290 ReadCacheHits uint64 291 ReadCacheMisses uint64 292 293 LogSegmentPUTs uint64 294 LogSegmentPUTReadHits uint64 295 296 LeaseRequests_Shared uint64 297 LeaseRequests_Promote uint64 298 LeaseRequests_Exclusive uint64 299 LeaseRequests_Demote uint64 300 LeaseRequests_Release uint64 301 302 LeaseInterrupts_Unmount uint64 303 LeaseInterrupts_Demote uint64 304 LeaseInterrupts_Release uint64 305 306 HTTPRequests uint64 307 HTTPRequestSubmissionFailures uint64 308 HTTPRequestResponseBodyCorruptions uint64 309 HTTPRequestRetryLimitExceededCount uint64 310 HTTPRequestsRequiringReauthorization uint64 311 HTTPRequestRetries uint64 312 HTTPRequestsInFlight uint64 313 } 314 315 type statsStruct struct { 316 FUSEDoReadBytes bucketstats.BucketLog2Round 317 FUSEDoWriteBytes bucketstats.BucketLog2Round 318 319 LogSegmentGetUsec bucketstats.BucketLog2Round 320 321 LogSegmentPutBytes bucketstats.BucketLog2Round 322 323 LeaseRequests_Shared_Usec bucketstats.BucketLog2Round 324 LeaseRequests_Promote_Usec bucketstats.BucketLog2Round 325 LeaseRequests_Exclusive_Usec bucketstats.BucketLog2Round 326 LeaseRequests_Demote_Usec bucketstats.BucketLog2Round 327 LeaseRequests_Release_Usec bucketstats.BucketLog2Round 328 } 329 330 type globalsStruct struct { 331 sync.Mutex 332 config configStruct 333 logFile *os.File // == nil if configStruct.LogFilePath == "" 334 retryRPCPublicIPAddr string 335 retryRPCPort uint16 336 retryRPCClient *retryrpc.Client 337 rootCAx509CertificatePEM []byte 338 entryValidSec uint64 339 entryValidNSec uint32 340 attrValidSec uint64 341 attrValidNSec uint32 342 httpServer *http.Server 343 httpServerWG sync.WaitGroup 344 httpClient *http.Client 345 retryDelay []retryDelayElementStruct 346 authPlugInControl *authPlugInControlStruct 347 swiftAuthWaitGroup *sync.WaitGroup // Protected by sync.Mutex of globalsStruct 348 swiftAuthToken string // Protected by swiftAuthWaitGroup 349 swiftStorageURL string // Protected by swiftAuthWaitGroup 350 mountID jrpcfs.MountIDAsString 351 rootDirInodeNumber uint64 352 fissionErrChan chan error 353 fissionVolume fission.Volume 354 fuseConn *fuse.Conn 355 jrpcLastID uint64 356 fileInodeMap map[inode.InodeNumber]*fileInodeStruct 357 fileInodeDirtyList *list.List // LRU of fileInode's with non-empty chunkedPutList 358 fileInodeDirtyLogSegmentChan chan struct{} // Limits # of in-flight LogSegment Chunked PUTs 359 unleasedFileInodeCacheLRU *list.List // Front() is oldest fileInodeStruct.leaseListElement 360 sharedLeaseFileInodeCacheLRU *list.List // Front() is oldest fileInodeStruct.leaseListElement 361 exclusiveLeaseFileInodeCacheLRU *list.List // Front() is oldest fileInodeStruct.leaseListElement 362 fhToInodeNumberMap map[uint64]uint64 // Key == FH; Value == InodeNumber 363 inodeNumberToFHMap map[uint64]fhSetType // Key == InodeNumber; Value == set of FH's 364 lastFH uint64 // Valid FH's start at 1 365 logSegmentCacheMap map[logSegmentCacheElementKeyStruct]*logSegmentCacheElementStruct 366 logSegmentCacheLRU *list.List // Front() is oldest logSegmentCacheElementStruct.cacheLRUElement 367 metrics *metricsStruct 368 stats *statsStruct 369 } 370 371 var globals globalsStruct 372 373 func initializeGlobals(confMap conf.ConfMap) { 374 var ( 375 configJSONified string 376 customTransport *http.Transport 377 defaultTransport *http.Transport 378 err error 379 fileInodeDirtyLogSegmentChanIndex uint64 380 nextRetryDelay time.Duration 381 ok bool 382 plugInEnvValueSlice []string 383 retryIndex uint64 384 ) 385 386 // Default logging related globals 387 388 globals.config.LogFilePath = "" 389 globals.config.LogToConsole = true 390 globals.logFile = nil 391 392 // Process resultant confMap 393 394 globals.config.FUSEVolumeName, err = confMap.FetchOptionValueString("Agent", "FUSEVolumeName") 395 if nil != err { 396 logFatal(err) 397 } 398 399 globals.config.FUSEMountPointPath, err = confMap.FetchOptionValueString("Agent", "FUSEMountPointPath") 400 if nil != err { 401 logFatal(err) 402 } 403 404 globals.config.FUSEUnMountRetryDelay, err = confMap.FetchOptionValueDuration("Agent", "FUSEUnMountRetryDelay") 405 if nil != err { 406 logFatal(err) 407 } 408 409 globals.config.FUSEUnMountRetryCap, err = confMap.FetchOptionValueUint64("Agent", "FUSEUnMountRetryCap") 410 if nil != err { 411 logFatal(err) 412 } 413 414 globals.config.PlugInPath, err = confMap.FetchOptionValueString("Agent", "PlugInPath") 415 if nil != err { 416 logFatal(err) 417 } 418 419 globals.config.PlugInEnvName, err = confMap.FetchOptionValueString("Agent", "PlugInEnvName") 420 if nil != err { 421 logFatal(err) 422 } 423 424 err = confMap.VerifyOptionIsMissing("Agent", "PlugInEnvValue") 425 if nil == err { 426 globals.config.PlugInEnvValue = "" 427 } else { 428 plugInEnvValueSlice, err = confMap.FetchOptionValueStringSlice("Agent", "PlugInEnvValue") 429 if nil != err { 430 logFatal(err) 431 } else { 432 switch len(plugInEnvValueSlice) { 433 case 0: 434 globals.config.PlugInEnvValue = "" 435 case 1: 436 globals.config.PlugInEnvValue = plugInEnvValueSlice[0] 437 default: 438 log.Fatalf("[Agent]PlugInEnvValue must be missing, empty, or single-valued: %#v", plugInEnvValueSlice) 439 } 440 } 441 } 442 443 globals.config.SwiftTimeout, err = confMap.FetchOptionValueDuration("Agent", "SwiftTimeout") 444 if nil != err { 445 logFatal(err) 446 } 447 448 globals.config.SwiftRetryLimit, err = confMap.FetchOptionValueUint64("Agent", "SwiftRetryLimit") 449 if nil != err { 450 logFatal(err) 451 } 452 453 globals.config.SwiftRetryDelay, err = confMap.FetchOptionValueDuration("Agent", "SwiftRetryDelay") 454 if nil != err { 455 logFatal(err) 456 } 457 458 globals.config.SwiftRetryDelayVariance, err = confMap.FetchOptionValueUint8("Agent", "SwiftRetryDelayVariance") 459 if nil != err { 460 logFatal(err) 461 } 462 if 0 == globals.config.SwiftRetryDelayVariance { 463 err = fmt.Errorf("[Agent]SwiftRetryDelayVariance must be > 0") 464 logFatal(err) 465 } 466 if 100 < globals.config.SwiftRetryDelayVariance { 467 err = fmt.Errorf("[Agent]SwiftRetryDelayVariance (%v) must be <= 100", globals.config.SwiftRetryDelayVariance) 468 logFatal(err) 469 } 470 471 globals.config.SwiftRetryExpBackoff, err = confMap.FetchOptionValueFloat64("Agent", "SwiftRetryExpBackoff") 472 if nil != err { 473 logFatal(err) 474 } 475 476 globals.config.SwiftConnectionPoolSize, err = confMap.FetchOptionValueUint64("Agent", "SwiftConnectionPoolSize") 477 if nil != err { 478 logFatal(err) 479 } 480 481 globals.config.FetchExtentsFromFileOffset, err = confMap.FetchOptionValueUint64("Agent", "FetchExtentsFromFileOffset") 482 if nil != err { 483 logFatal(err) 484 } 485 486 globals.config.FetchExtentsBeforeFileOffset, err = confMap.FetchOptionValueUint64("Agent", "FetchExtentsBeforeFileOffset") 487 if nil != err { 488 logFatal(err) 489 } 490 491 globals.config.ReadCacheLineSize, err = confMap.FetchOptionValueUint64("Agent", "ReadCacheLineSize") 492 if nil != err { 493 logFatal(err) 494 } 495 496 globals.config.ReadCacheLineCount, err = confMap.FetchOptionValueUint64("Agent", "ReadCacheLineCount") 497 if nil != err { 498 logFatal(err) 499 } 500 501 globals.config.LeaseRetryLimit, err = confMap.FetchOptionValueUint64("Agent", "LeaseRetryLimit") 502 if nil != err { 503 logFatal(err) 504 } 505 506 globals.config.LeaseRetryDelay, err = confMap.FetchOptionValueDuration("Agent", "LeaseRetryDelay") 507 if nil != err { 508 logFatal(err) 509 } 510 511 globals.config.LeaseRetryDelayVariance, err = confMap.FetchOptionValueUint8("Agent", "LeaseRetryDelayVariance") 512 if nil != err { 513 logFatal(err) 514 } 515 if 0 == globals.config.LeaseRetryDelayVariance { 516 err = fmt.Errorf("[Agent]LeaseRetryDelayVariance must be > 0") 517 logFatal(err) 518 } 519 if 100 < globals.config.LeaseRetryDelayVariance { 520 err = fmt.Errorf("[Agent]LeaseRetryDelayVariance (%v) must be <= 100", globals.config.LeaseRetryDelayVariance) 521 logFatal(err) 522 } 523 524 globals.config.LeaseRetryExpBackoff, err = confMap.FetchOptionValueFloat64("Agent", "LeaseRetryExpBackoff") 525 if nil != err { 526 logFatal(err) 527 } 528 529 globals.config.SharedLeaseLimit, err = confMap.FetchOptionValueUint64("Agent", "SharedLeaseLimit") 530 if nil != err { 531 logFatal(err) 532 } 533 534 globals.config.ExclusiveLeaseLimit, err = confMap.FetchOptionValueUint64("Agent", "ExclusiveLeaseLimit") 535 if nil != err { 536 logFatal(err) 537 } 538 539 globals.config.ExtentMapEntryLimit, err = confMap.FetchOptionValueUint64("Agent", "ExtentMapEntryLimit") 540 if nil != err { 541 logFatal(err) 542 } 543 544 globals.config.DirtyLogSegmentLimit, err = confMap.FetchOptionValueUint64("Agent", "DirtyLogSegmentLimit") 545 if nil != err { 546 logFatal(err) 547 } 548 549 globals.config.DirtyFileLimit, err = confMap.FetchOptionValueUint64("Agent", "DirtyFileLimit") 550 if nil != err { 551 logFatal(err) // TODO - obsolete this 552 } 553 554 globals.config.MaxFlushSize, err = confMap.FetchOptionValueUint64("Agent", "MaxFlushSize") 555 if nil != err { 556 logFatal(err) 557 } 558 559 globals.config.MaxFlushTime, err = confMap.FetchOptionValueDuration("Agent", "MaxFlushTime") 560 if nil != err { 561 logFatal(err) 562 } 563 564 err = confMap.VerifyOptionValueIsEmpty("Agent", "LogFilePath") 565 if nil == err { 566 globals.config.LogFilePath = "" 567 } else { 568 globals.config.LogFilePath, err = confMap.FetchOptionValueString("Agent", "LogFilePath") 569 if nil != err { 570 logFatal(err) 571 } 572 } 573 574 globals.config.LogToConsole, err = confMap.FetchOptionValueBool("Agent", "LogToConsole") 575 if nil != err { 576 logFatal(err) 577 } 578 579 globals.config.TraceEnabled, err = confMap.FetchOptionValueBool("Agent", "TraceEnabled") 580 if nil != err { 581 logFatal(err) 582 } 583 584 globals.config.HTTPServerIPAddr, err = confMap.FetchOptionValueString("Agent", "HTTPServerIPAddr") 585 if nil != err { 586 logFatal(err) 587 } 588 globals.config.HTTPServerTCPPort, err = confMap.FetchOptionValueUint16("Agent", "HTTPServerTCPPort") 589 if nil != err { 590 logFatal(err) 591 } 592 593 globals.config.AttrDuration, err = confMap.FetchOptionValueDuration("Agent", "AttrDuration") 594 if nil != err { 595 logFatal(err) 596 } 597 598 globals.config.ReadDirPlusEnabled, err = confMap.FetchOptionValueBool("Agent", "ReadDirPlusEnabled") 599 if nil != err { 600 logFatal(err) 601 } 602 603 globals.config.XAttrEnabled, err = confMap.FetchOptionValueBool("Agent", "XAttrEnabled") 604 if nil != err { 605 logFatal(err) 606 } 607 608 globals.config.EntryDuration, err = confMap.FetchOptionValueDuration("Agent", "EntryDuration") 609 if nil != err { 610 logFatal(err) 611 } 612 613 globals.config.AttrDuration, err = confMap.FetchOptionValueDuration("Agent", "AttrDuration") 614 if nil != err { 615 logFatal(err) 616 } 617 618 globals.config.AttrBlockSize, err = confMap.FetchOptionValueUint64("Agent", "AttrBlockSize") 619 if nil != err { 620 logFatal(err) 621 } 622 if (0 == globals.config.AttrBlockSize) || (math.MaxUint32 < globals.config.AttrBlockSize) { 623 logFatalf("AttrBlockSize must be non-zero and fit in a uint32") 624 } 625 626 globals.config.ReaddirMaxEntries, err = confMap.FetchOptionValueUint64("Agent", "ReaddirMaxEntries") 627 if nil != err { 628 logFatal(err) 629 } 630 631 globals.config.FUSEMaxBackground, err = confMap.FetchOptionValueUint16("Agent", "FUSEMaxBackground") 632 if nil != err { 633 logFatal(err) 634 } 635 636 globals.config.FUSECongestionThreshhold, err = confMap.FetchOptionValueUint16("Agent", "FUSECongestionThreshhold") 637 if nil != err { 638 logFatal(err) 639 } 640 641 globals.config.FUSEMaxWrite, err = confMap.FetchOptionValueUint32("Agent", "FUSEMaxWrite") 642 if nil != err { 643 logFatal(err) 644 } 645 646 globals.config.RetryRPCDeadlineIO, err = confMap.FetchOptionValueDuration("Agent", "RetryRPCDeadlineIO") 647 if nil != err { 648 logFatal(err) 649 } 650 651 globals.config.RetryRPCKeepAlivePeriod, err = confMap.FetchOptionValueDuration("Agent", "RetryRPCKeepAlivePeriod") 652 if nil != err { 653 logFatal(err) 654 } 655 656 configJSONified = utils.JSONify(globals.config, true) 657 658 logInfof("\n%s", configJSONified) 659 660 globals.entryValidSec, globals.entryValidNSec = nsToUnixTime(uint64(globals.config.EntryDuration)) 661 globals.attrValidSec, globals.attrValidNSec = nsToUnixTime(uint64(globals.config.AttrDuration)) 662 663 defaultTransport, ok = http.DefaultTransport.(*http.Transport) 664 if !ok { 665 log.Fatalf("http.DefaultTransport not a *http.Transport") 666 } 667 668 customTransport = &http.Transport{ // Up-to-date as of Golang 1.11 669 Proxy: defaultTransport.Proxy, 670 DialContext: defaultTransport.DialContext, 671 Dial: defaultTransport.Dial, 672 DialTLS: defaultTransport.DialTLS, 673 TLSClientConfig: defaultTransport.TLSClientConfig, 674 TLSHandshakeTimeout: globals.config.SwiftTimeout, 675 DisableKeepAlives: false, 676 DisableCompression: defaultTransport.DisableCompression, 677 MaxIdleConns: int(globals.config.SwiftConnectionPoolSize), 678 MaxIdleConnsPerHost: int(globals.config.SwiftConnectionPoolSize), 679 MaxConnsPerHost: int(globals.config.SwiftConnectionPoolSize), 680 IdleConnTimeout: globals.config.SwiftTimeout, 681 ResponseHeaderTimeout: globals.config.SwiftTimeout, 682 ExpectContinueTimeout: globals.config.SwiftTimeout, 683 TLSNextProto: defaultTransport.TLSNextProto, 684 ProxyConnectHeader: defaultTransport.ProxyConnectHeader, 685 MaxResponseHeaderBytes: defaultTransport.MaxResponseHeaderBytes, 686 } 687 688 globals.httpClient = &http.Client{ 689 Transport: customTransport, 690 Timeout: globals.config.SwiftTimeout, 691 } 692 693 globals.retryDelay = make([]retryDelayElementStruct, globals.config.SwiftRetryLimit) 694 695 nextRetryDelay = globals.config.SwiftRetryDelay 696 697 for retryIndex = 0; retryIndex < globals.config.SwiftRetryLimit; retryIndex++ { 698 globals.retryDelay[retryIndex].nominal = nextRetryDelay 699 globals.retryDelay[retryIndex].variance = nextRetryDelay * time.Duration(globals.config.SwiftRetryDelayVariance) / time.Duration(100) 700 nextRetryDelay = time.Duration(float64(nextRetryDelay) * globals.config.SwiftRetryExpBackoff) 701 } 702 703 globals.authPlugInControl = nil 704 705 globals.swiftAuthWaitGroup = nil 706 globals.swiftAuthToken = "" 707 globals.swiftStorageURL = "" 708 709 globals.fissionErrChan = make(chan error) 710 711 globals.jrpcLastID = 1 712 713 globals.fileInodeMap = make(map[inode.InodeNumber]*fileInodeStruct) 714 715 globals.fileInodeDirtyList = list.New() 716 717 globals.fileInodeDirtyLogSegmentChan = make(chan struct{}, globals.config.DirtyLogSegmentLimit) 718 719 for fileInodeDirtyLogSegmentChanIndex = 0; fileInodeDirtyLogSegmentChanIndex < globals.config.DirtyLogSegmentLimit; fileInodeDirtyLogSegmentChanIndex++ { 720 globals.fileInodeDirtyLogSegmentChan <- struct{}{} 721 } 722 723 globals.unleasedFileInodeCacheLRU = list.New() 724 globals.sharedLeaseFileInodeCacheLRU = list.New() 725 globals.exclusiveLeaseFileInodeCacheLRU = list.New() 726 727 globals.fhToInodeNumberMap = make(map[uint64]uint64) 728 globals.inodeNumberToFHMap = make(map[uint64]fhSetType) 729 730 globals.lastFH = 0 731 732 globals.logSegmentCacheMap = make(map[logSegmentCacheElementKeyStruct]*logSegmentCacheElementStruct) 733 globals.logSegmentCacheLRU = list.New() 734 735 globals.metrics = &metricsStruct{} 736 globals.stats = &statsStruct{} 737 738 bucketstats.Register("PFSAgent", "", globals.stats) 739 } 740 741 func uninitializeGlobals() { 742 bucketstats.UnRegister("PFSAgent", "") 743 744 globals.logFile = nil 745 globals.retryRPCPublicIPAddr = "" 746 globals.retryRPCPort = 0 747 globals.retryRPCClient = nil 748 globals.rootCAx509CertificatePEM = []byte{} 749 globals.entryValidSec = 0 750 globals.entryValidNSec = 0 751 globals.attrValidSec = 0 752 globals.attrValidNSec = 0 753 globals.httpServer = nil 754 globals.httpClient = nil 755 globals.retryDelay = nil 756 globals.authPlugInControl = nil 757 globals.swiftAuthWaitGroup = nil 758 globals.swiftAuthToken = "" 759 globals.swiftStorageURL = "" 760 globals.fissionErrChan = nil 761 globals.fissionVolume = nil 762 globals.fuseConn = nil 763 globals.jrpcLastID = 0 764 globals.fileInodeMap = nil 765 globals.fileInodeDirtyList = nil 766 globals.fileInodeDirtyLogSegmentChan = nil 767 globals.unleasedFileInodeCacheLRU = nil // TODO: Obsolete this 768 globals.sharedLeaseFileInodeCacheLRU = nil // TODO: Obsolete this 769 globals.exclusiveLeaseFileInodeCacheLRU = nil // TODO: Obsolete this 770 globals.fhToInodeNumberMap = nil 771 globals.inodeNumberToFHMap = nil 772 globals.lastFH = 0 773 globals.logSegmentCacheMap = nil 774 globals.logSegmentCacheLRU = nil 775 globals.metrics = nil 776 globals.stats = nil 777 }