func newReaderContext(maxBytesPerSecond uint64, maxBlocksPerSecond uint64, speedPercent uint64) *ReaderContext { var ctx ReaderContext ctx.maxBytesPerSecond = maxBytesPerSecond ctx.maxBlocksPerSecond = maxBlocksPerSecond if maxBlocksPerSecond > 0 { ctx.ctx = rateio.NewReaderContext(maxBlocksPerSecond, speedPercent, newReadMeasurer()) } else { ctx.ctx = rateio.NewReaderContext(maxBytesPerSecond, speedPercent, &rateio.ReadMeasurer{}) } return &ctx }
func main() { flag.Parse() workingRootDir := path.Join(*subdDir, "root") objectsDir := path.Join(*subdDir, "objects") tmpDir := path.Join(*subdDir, "tmp") netbenchFilename := path.Join(*subdDir, "netbench") oldTriggersFilename := path.Join(*subdDir, "triggers.previous") if !createDirectory(workingRootDir) { os.Exit(1) } if !sanityCheck() { os.Exit(1) } if !createDirectory(objectsDir) { os.Exit(1) } if !createDirectory(tmpDir) { os.Exit(1) } if !mountTmpfs(tmpDir) { os.Exit(1) } if !unshareAndBind(workingRootDir) { os.Exit(1) } runtime.GOMAXPROCS(int(*maxThreads)) bytesPerSecond, blocksPerSecond, firstScan, ok := getCachedFsSpeed( workingRootDir, tmpDir) if !ok { os.Exit(1) } circularBuffer := logbuf.New(*logbufLines) logger := log.New(circularBuffer, "", log.LstdFlags) var configuration scanner.Configuration var err error configuration.ScanFilter, err = filter.NewFilter(constants.ScanExcludeList) if err != nil { fmt.Printf("Unable to set default scan exclusions\t%s\n", err) os.Exit(1) } configuration.FsScanContext = fsrateio.NewReaderContext(bytesPerSecond, blocksPerSecond, 0) defaultSpeed := configuration.FsScanContext.GetContext().SpeedPercent() if firstScan { configuration.FsScanContext.GetContext().SetSpeedPercent(100) } if *showStats { fmt.Println(configuration.FsScanContext) } var fsh scanner.FileSystemHistory fsChannel := scanner.StartScannerDaemon(workingRootDir, objectsDir, &configuration, logger) networkReaderContext := rateio.NewReaderContext( getCachedNetworkSpeed(netbenchFilename), constants.DefaultNetworkSpeedPercent, &rateio.ReadMeasurer{}) configuration.NetworkReaderContext = networkReaderContext rescanObjectCacheChannel := rpcd.Setup(&configuration, &fsh, objectsDir, networkReaderContext, netbenchFilename, oldTriggersFilename, logger) httpd.AddHtmlWriter(&fsh) httpd.AddHtmlWriter(&configuration) httpd.AddHtmlWriter(circularBuffer) html.RegisterHtmlWriterForPattern("/dumpFileSystem", "Scanned File System", &DumpableFileSystemHistory{&fsh}) err = httpd.StartServer(*portNum) if err != nil { fmt.Printf("Unable to create http server\t%s\n", err) os.Exit(1) } fsh.Update(nil) invalidateNextScanObjectCache := false sighupChannel := make(chan os.Signal) signal.Notify(sighupChannel, syscall.SIGHUP) sigtermChannel := make(chan os.Signal) signal.Notify(sigtermChannel, syscall.SIGTERM, syscall.SIGINT) writePidfile() for iter := 0; true; { select { case <-sighupChannel: err = syscall.Exec(os.Args[0], os.Args, os.Environ()) if err != nil { logger.Printf("Unable to Exec:%s\t%s\n", os.Args[0], err) } case <-sigtermChannel: gracefulCleanup() case fs := <-fsChannel: if *showStats { fmt.Printf("Completed cycle: %d\n", iter) } if invalidateNextScanObjectCache { fs.ScanObjectCache() invalidateNextScanObjectCache = false } fsh.Update(fs) iter++ runtime.GC() // An opportune time to take out the garbage. if *showStats { fmt.Print(fsh) fmt.Print(fsh.FileSystem()) memstats.WriteMemoryStats(os.Stdout) fmt.Println() } if firstScan { configuration.FsScanContext.GetContext().SetSpeedPercent( defaultSpeed) firstScan = false if *showStats { fmt.Println(configuration.FsScanContext) } } case <-rescanObjectCacheChannel: invalidateNextScanObjectCache = true fsh.UpdateObjectCacheOnly() } } }
func (t *rpcType) doFetch(request sub.FetchRequest) error { defer t.clearFetchInProgress() objectServer := objectclient.NewObjectClient(request.ServerAddress) defer objectServer.Close() benchmark := false linkSpeed, haveLinkSpeed := netspeed.GetSpeedToAddress( request.ServerAddress) if haveLinkSpeed { t.logFetch(request, linkSpeed) } else { if t.networkReaderContext.MaximumSpeed() < 1 { benchmark = enoughBytesForBenchmark(objectServer, request) if benchmark { objectServer.SetExclusiveGetObjects(true) t.logger.Printf("Fetch(%s) %d objects and benchmark speed\n", request.ServerAddress, len(request.Hashes)) } else { t.logFetch(request, 0) } } else { t.logFetch(request, t.networkReaderContext.MaximumSpeed()) } } objectsReader, err := objectServer.GetObjects(request.Hashes) if err != nil { t.logger.Printf("Error getting object reader: %s\n", err.Error()) return err } defer objectsReader.Close() var totalLength uint64 defer t.rescanObjectCacheFunction() timeStart := time.Now() for _, hash := range request.Hashes { length, reader, err := objectsReader.NextObject() if err != nil { t.logger.Println(err) return err } r := io.Reader(reader) if haveLinkSpeed { if linkSpeed > 0 { r = rateio.NewReaderContext(linkSpeed, uint64(t.networkReaderContext.SpeedPercent()), &rateio.ReadMeasurer{}).NewReader(reader) } } else if !benchmark { r = t.networkReaderContext.NewReader(reader) } err = readOne(t.objectsDir, hash, length, r) reader.Close() if err != nil { t.logger.Println(err) return err } totalLength += length } duration := time.Since(timeStart) speed := uint64(float64(totalLength) / duration.Seconds()) if benchmark { file, err := os.Create(t.netbenchFilename) if err == nil { fmt.Fprintf(file, "%d\n", speed) file.Close() } t.networkReaderContext.InitialiseMaximumSpeed(speed) } t.logger.Printf("Fetch() complete. Read: %s in %s (%s/s)\n", format.FormatBytes(totalLength), format.Duration(duration), format.FormatBytes(speed)) return nil }
func main() { flag.Parse() tricorder.RegisterFlags() subdDirPathname := path.Join(*rootDir, *subdDir) workingRootDir := path.Join(subdDirPathname, "root") objectsDir := path.Join(workingRootDir, *subdDir, "objects") tmpDir := path.Join(subdDirPathname, "tmp") netbenchFilename := path.Join(subdDirPathname, "netbench") oldTriggersFilename := path.Join(subdDirPathname, "triggers.previous") if !createDirectory(workingRootDir) { os.Exit(1) } if !sanityCheck() { os.Exit(1) } if !createDirectory(tmpDir) { os.Exit(1) } if !mountTmpfs(tmpDir) { os.Exit(1) } if !unshareAndBind(workingRootDir) { os.Exit(1) } if !createDirectory(objectsDir) { os.Exit(1) } runtime.GOMAXPROCS(int(*maxThreads)) circularBuffer := logbuf.New() logger := log.New(circularBuffer, "", log.LstdFlags) if err := setupserver.SetupTls(); err != nil { logger.Println(err) circularBuffer.Flush() if !*permitInsecureMode { os.Exit(1) } } bytesPerSecond, blocksPerSecond, firstScan, ok := getCachedFsSpeed( workingRootDir, tmpDir) if !ok { os.Exit(1) } publishFsSpeed(bytesPerSecond, blocksPerSecond) var configuration scanner.Configuration var err error configuration.ScanFilter, err = filter.New(scanExcludeList) if err != nil { fmt.Fprintf(os.Stderr, "Unable to set default scan exclusions: %s\n", err) os.Exit(1) } configuration.FsScanContext = fsrateio.NewReaderContext(bytesPerSecond, blocksPerSecond, *defaultScanSpeedPercent) defaultSpeed := configuration.FsScanContext.GetContext().SpeedPercent() if firstScan { configuration.FsScanContext.GetContext().SetSpeedPercent(100) } if *showStats { fmt.Println(configuration.FsScanContext) } var fsh scanner.FileSystemHistory mainFunc := func(fsChannel <-chan *scanner.FileSystem, disableScanner func(disableScanner bool)) { networkReaderContext := rateio.NewReaderContext( getCachedNetworkSpeed(netbenchFilename), *defaultNetworkSpeedPercent, &rateio.ReadMeasurer{}) configuration.NetworkReaderContext = networkReaderContext invalidateNextScanObjectCache := false rpcdHtmlWriter := rpcd.Setup(&configuration, &fsh, objectsDir, workingRootDir, networkReaderContext, netbenchFilename, oldTriggersFilename, disableScanner, func() { invalidateNextScanObjectCache = true fsh.UpdateObjectCacheOnly() }, logger) configMetricsDir, err := tricorder.RegisterDirectory("/config") if err != nil { fmt.Fprintf(os.Stderr, "Unable to create /config metrics directory: %s\n", err) os.Exit(1) } configuration.RegisterMetrics(configMetricsDir) if err != nil { fmt.Fprintf(os.Stderr, "Unable to create config metrics: %s\n", err) os.Exit(1) } httpd.AddHtmlWriter(rpcdHtmlWriter) httpd.AddHtmlWriter(&fsh) httpd.AddHtmlWriter(&configuration) httpd.AddHtmlWriter(circularBuffer) html.RegisterHtmlWriterForPattern("/dumpFileSystem", "Scanned File System", &DumpableFileSystemHistory{&fsh}) if err = httpd.StartServer(*portNum); err != nil { fmt.Fprintf(os.Stderr, "Unable to create http server: %s\n", err) os.Exit(1) } fsh.Update(nil) sighupChannel := make(chan os.Signal) signal.Notify(sighupChannel, syscall.SIGHUP) sigtermChannel := make(chan os.Signal) signal.Notify(sigtermChannel, syscall.SIGTERM, syscall.SIGINT) writePidfile() for iter := 0; true; { select { case <-sighupChannel: logger.Printf("Caught SIGHUP: re-execing with: %v\n", os.Args) circularBuffer.Flush() err = syscall.Exec(os.Args[0], os.Args, os.Environ()) if err != nil { logger.Printf("Unable to Exec:%s: %s\n", os.Args[0], err) } case <-sigtermChannel: logger.Printf("Caught SIGTERM: performing graceful cleanup\n") circularBuffer.Flush() gracefulCleanup() case fs := <-fsChannel: if *showStats { fmt.Printf("Completed cycle: %d\n", iter) } if invalidateNextScanObjectCache { fs.ScanObjectCache() invalidateNextScanObjectCache = false } fsh.Update(fs) iter++ runtime.GC() // An opportune time to take out the garbage. if *showStats { fmt.Print(fsh) fmt.Print(fsh.FileSystem()) memstats.WriteMemoryStats(os.Stdout) fmt.Println() } if firstScan { configuration.FsScanContext.GetContext().SetSpeedPercent( defaultSpeed) firstScan = false if *showStats { fmt.Println(configuration.FsScanContext) } } } } } scanner.StartScanning(workingRootDir, objectsDir, &configuration, logger, mainFunc) }