// Capacity queries the underlying file system for disk capacity information. func (r *RocksDB) Capacity() (roachpb.StoreCapacity, error) { fileSystemUsage := gosigar.FileSystemUsage{} dir := r.dir if dir == "" { dir = "/tmp" } if err := fileSystemUsage.Get(dir); err != nil { return roachpb.StoreCapacity{}, err } if fileSystemUsage.Total > math.MaxInt64 { return roachpb.StoreCapacity{}, fmt.Errorf("unsupported disk size %s, max supported size is %s", humanize.IBytes(fileSystemUsage.Total), humanizeutil.IBytes(math.MaxInt64)) } if fileSystemUsage.Avail > math.MaxInt64 { return roachpb.StoreCapacity{}, fmt.Errorf("unsupported disk size %s, max supported size is %s", humanize.IBytes(fileSystemUsage.Avail), humanizeutil.IBytes(math.MaxInt64)) } fsuTotal := int64(fileSystemUsage.Total) fsuAvail := int64(fileSystemUsage.Avail) // If no size limitation have been placed on the store size or if the // limitation is greater than what's available, just return the actual // totals. if r.maxSize == 0 || r.maxSize >= fsuTotal || r.dir == "" { return roachpb.StoreCapacity{ Capacity: fsuTotal, Available: fsuAvail, }, nil } // Find the total size of all the files in the r.dir and all its // subdirectories. var totalUsedBytes int64 if errOuter := filepath.Walk(r.dir, func(path string, info os.FileInfo, err error) error { if err != nil { return nil } if info.Mode().IsRegular() { totalUsedBytes += info.Size() } return nil }); errOuter != nil { return roachpb.StoreCapacity{}, errOuter } available := r.maxSize - totalUsedBytes if available > fsuAvail { available = fsuAvail } if available < 0 { available = 0 } return roachpb.StoreCapacity{ Capacity: r.maxSize, Available: available, }, nil }
func GetFileSystemStat(fs sigar.FileSystem) (*FileSystemStat, error) { stat := sigar.FileSystemUsage{} if err := stat.Get(fs.DirName); err != nil { return nil, err } filesystem := FileSystemStat{ FileSystemUsage: stat, DevName: fs.DevName, Mount: fs.DirName, } return &filesystem, nil }
func GetFileSystemList75() []string { result := []string{} volumes := []sigar.FileSystem{} if runtime.GOOS == "windows" { volumes = getWindowsDrives() } else { fslist := sigar.FileSystemList{} fslist.Get() volumes = fslist.List } for _, volume := range volumes { dirName := volume.DirName usage := sigar.FileSystemUsage{} usage.Get(dirName) if usage.UsePercent() >= 75 { result = append(result, fmt.Sprintf("%s (%s)", dirName, sigar.FormatPercent(usage.UsePercent()))) } } return result }
// InitStores initializes ctx.Engines based on ctx.Stores. func (ctx *Context) InitStores(stopper *stop.Stopper) error { // TODO(peter): The comments and docs say that CacheSize and MemtableBudget // are split evenly if there are multiple stores, but we aren't doing that // currently. for _, spec := range ctx.Stores.Specs { var sizeInBytes = spec.SizeInBytes if spec.InMemory { if spec.SizePercent > 0 { sysMem, err := GetTotalMemory() if err != nil { return fmt.Errorf("could not retrieve system memory") } sizeInBytes = int64(float64(sysMem) * spec.SizePercent / 100) } if sizeInBytes != 0 && sizeInBytes < minimumStoreSize { return fmt.Errorf("%f%% of memory is only %s bytes, which is below the minimum requirement of %s", spec.SizePercent, humanize.IBytes(uint64(sizeInBytes)), humanize.IBytes(uint64(minimumStoreSize))) } ctx.Engines = append(ctx.Engines, engine.NewInMem(spec.Attributes, uint64(sizeInBytes), stopper)) } else { if spec.SizePercent > 0 { fileSystemUsage := gosigar.FileSystemUsage{} if err := fileSystemUsage.Get(spec.Path); err != nil { return err } sizeInBytes = int64(float64(fileSystemUsage.Total) * spec.SizePercent / 100) } if sizeInBytes != 0 && sizeInBytes < minimumStoreSize { return fmt.Errorf("%f%% of %s's total free space is only %s bytes, which is below the minimum requirement of %s", spec.SizePercent, spec.Path, humanize.IBytes(uint64(sizeInBytes)), humanize.IBytes(uint64(minimumStoreSize))) } ctx.Engines = append(ctx.Engines, engine.NewRocksDB(spec.Attributes, spec.Path, ctx.CacheSize, ctx.MemtableBudget, sizeInBytes, stopper)) } } if len(ctx.Engines) == 1 { log.Infof("1 storage engine initialized") } else { log.Infof("%d storage engines initialized", len(ctx.Engines)) } return nil }
// InitStores initializes ctx.Engines based on ctx.Stores. func (ctx *Context) InitStores(stopper *stop.Stopper) error { cache := engine.NewRocksDBCache(ctx.CacheSize) defer cache.Release() for _, spec := range ctx.Stores.Specs { var sizeInBytes = spec.SizeInBytes if spec.InMemory { if spec.SizePercent > 0 { sysMem, err := GetTotalMemory() if err != nil { return fmt.Errorf("could not retrieve system memory") } sizeInBytes = int64(float64(sysMem) * spec.SizePercent / 100) } if sizeInBytes != 0 && sizeInBytes < minimumStoreSize { return fmt.Errorf("%f%% of memory is only %s bytes, which is below the minimum requirement of %s", spec.SizePercent, humanizeutil.IBytes(sizeInBytes), humanizeutil.IBytes(minimumStoreSize)) } ctx.Engines = append(ctx.Engines, engine.NewInMem(spec.Attributes, sizeInBytes, stopper)) } else { if spec.SizePercent > 0 { fileSystemUsage := gosigar.FileSystemUsage{} if err := fileSystemUsage.Get(spec.Path); err != nil { return err } sizeInBytes = int64(float64(fileSystemUsage.Total) * spec.SizePercent / 100) } if sizeInBytes != 0 && sizeInBytes < minimumStoreSize { return fmt.Errorf("%f%% of %s's total free space is only %s bytes, which is below the minimum requirement of %s", spec.SizePercent, spec.Path, humanizeutil.IBytes(sizeInBytes), humanizeutil.IBytes(minimumStoreSize)) } ctx.Engines = append(ctx.Engines, engine.NewRocksDB(spec.Attributes, spec.Path, cache, ctx.MemtableBudget, sizeInBytes, stopper)) } } if len(ctx.Engines) == 1 { log.Infof("1 storage engine initialized") } else { log.Infof("%d storage engines initialized", len(ctx.Engines)) } return nil }
func GetFileSystemStat(fs sigar.FileSystem) (*FileSystemStat, error) { stat := sigar.FileSystemUsage{} err := stat.Get(fs.DirName) if err != nil { return nil, err } filesystem := FileSystemStat{ DevName: fs.DevName, Total: stat.Total, Free: stat.Free, Avail: stat.Avail, Used: stat.Used, Files: stat.Files, FreeFiles: stat.FreeFiles, Mount: fs.DirName, } return &filesystem, nil }
func main() { fslist := gosigar.FileSystemList{} fslist.Get() fmt.Fprintf(os.Stdout, output_format, "Filesystem", "Size", "Used", "Avail", "Use%", "Mounted on") for _, fs := range fslist.List { dir_name := fs.DirName usage := gosigar.FileSystemUsage{} usage.Get(dir_name) fmt.Fprintf(os.Stdout, output_format, fs.DevName, gosigar.FormatSize(usage.Total), gosigar.FormatSize(usage.Used), gosigar.FormatSize(usage.Avail), gosigar.FormatPercent(usage.UsePercent()), dir_name) } }
// CreateEngines creates Engines based on the specs in ctx.Stores. func (cfg *Config) CreateEngines() (Engines, error) { engines := Engines(nil) defer engines.Close() if cfg.enginesCreated { return Engines{}, errors.Errorf("engines already created") } cfg.enginesCreated = true cache := engine.NewRocksDBCache(cfg.CacheSize) defer cache.Release() var physicalStores int for _, spec := range cfg.Stores.Specs { if !spec.InMemory { physicalStores++ } } openFileLimitPerStore, err := setOpenFileLimit(physicalStores) if err != nil { return Engines{}, err } skipSizeCheck := cfg.TestingKnobs.Store != nil && cfg.TestingKnobs.Store.(*storage.StoreTestingKnobs).SkipMinSizeCheck for _, spec := range cfg.Stores.Specs { var sizeInBytes = spec.SizeInBytes if spec.InMemory { if spec.SizePercent > 0 { sysMem, err := GetTotalMemory() if err != nil { return Engines{}, errors.Errorf("could not retrieve system memory") } sizeInBytes = int64(float64(sysMem) * spec.SizePercent / 100) } if sizeInBytes != 0 && !skipSizeCheck && sizeInBytes < base.MinimumStoreSize { return Engines{}, errors.Errorf("%f%% of memory is only %s bytes, which is below the minimum requirement of %s", spec.SizePercent, humanizeutil.IBytes(sizeInBytes), humanizeutil.IBytes(base.MinimumStoreSize)) } engines = append(engines, engine.NewInMem(spec.Attributes, sizeInBytes)) } else { if spec.SizePercent > 0 { fileSystemUsage := gosigar.FileSystemUsage{} if err := fileSystemUsage.Get(spec.Path); err != nil { return Engines{}, err } sizeInBytes = int64(float64(fileSystemUsage.Total) * spec.SizePercent / 100) } if sizeInBytes != 0 && !skipSizeCheck && sizeInBytes < base.MinimumStoreSize { return Engines{}, errors.Errorf("%f%% of %s's total free space is only %s bytes, which is below the minimum requirement of %s", spec.SizePercent, spec.Path, humanizeutil.IBytes(sizeInBytes), humanizeutil.IBytes(base.MinimumStoreSize)) } eng, err := engine.NewRocksDB( spec.Attributes, spec.Path, cache, sizeInBytes, openFileLimitPerStore, ) if err != nil { return Engines{}, err } engines = append(engines, eng) } } if len(engines) == 1 { log.Infof(context.TODO(), "1 storage engine initialized") } else { log.Infof(context.TODO(), "%d storage engines initialized", len(engines)) } enginesCopy := engines engines = nil return enginesCopy, nil }
// Capacity queries the underlying file system for disk capacity information. func (r *RocksDB) Capacity() (roachpb.StoreCapacity, error) { fileSystemUsage := gosigar.FileSystemUsage{} dir := r.dir if dir == "" { // This is an in-memory instance. Pretend we're empty since we // don't know better and only use this for testing. Using any // part of the actual file system here can throw off allocator // rebalancing in a hard-to-trace manner. See #7050. return roachpb.StoreCapacity{ Capacity: r.maxSize, Available: r.maxSize, }, nil } if err := fileSystemUsage.Get(dir); err != nil { return roachpb.StoreCapacity{}, err } if fileSystemUsage.Total > math.MaxInt64 { return roachpb.StoreCapacity{}, fmt.Errorf("unsupported disk size %s, max supported size is %s", humanize.IBytes(fileSystemUsage.Total), humanizeutil.IBytes(math.MaxInt64)) } if fileSystemUsage.Avail > math.MaxInt64 { return roachpb.StoreCapacity{}, fmt.Errorf("unsupported disk size %s, max supported size is %s", humanize.IBytes(fileSystemUsage.Avail), humanizeutil.IBytes(math.MaxInt64)) } fsuTotal := int64(fileSystemUsage.Total) fsuAvail := int64(fileSystemUsage.Avail) // If no size limitation have been placed on the store size or if the // limitation is greater than what's available, just return the actual // totals. if r.maxSize == 0 || r.maxSize >= fsuTotal || r.dir == "" { return roachpb.StoreCapacity{ Capacity: fsuTotal, Available: fsuAvail, }, nil } // Find the total size of all the files in the r.dir and all its // subdirectories. var totalUsedBytes int64 if errOuter := filepath.Walk(r.dir, func(path string, info os.FileInfo, err error) error { if err != nil { return nil } if info.Mode().IsRegular() { totalUsedBytes += info.Size() } return nil }); errOuter != nil { return roachpb.StoreCapacity{}, errOuter } available := r.maxSize - totalUsedBytes if available > fsuAvail { available = fsuAvail } if available < 0 { available = 0 } return roachpb.StoreCapacity{ Capacity: r.maxSize, Available: available, }, nil }
import ( "os" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" sigar "github.com/elastic/gosigar" ) var _ = Describe("SigarWindows", func() { Describe("Memory", func() { It("gets the total memory", func() { mem := sigar.Mem{} err := mem.Get() Ω(err).ShouldNot(HaveOccurred()) Ω(mem.Total).Should(BeNumerically(">", 0)) }) }) Describe("Disk", func() { It("gets the total disk space", func() { usage := sigar.FileSystemUsage{} err := usage.Get(os.TempDir()) Ω(err).ShouldNot(HaveOccurred()) Ω(usage.Total).Should(BeNumerically(">", 0)) }) }) })