diff --git a/pkg/storage/donut/disk/disk.go b/pkg/storage/donut/disk/disk.go new file mode 100644 index 000000000..33d0c3618 --- /dev/null +++ b/pkg/storage/donut/disk/disk.go @@ -0,0 +1,174 @@ +/* + * Minimalist Object Storage, (C) 2015 Minio, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impliedisk. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package disk + +import ( + "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "syscall" + + "github.com/minio/minio/pkg/iodine" +) + +type Disk struct { + path string + fsInfo map[string]string +} + +// New - instantiate new disk +func New(diskPath string) (Disk, error) { + if diskPath == "" { + return Disk{}, iodine.New(InvalidArgument{}, nil) + } + s := syscall.Statfs_t{} + err := syscall.Statfs(diskPath, &s) + if err != nil { + return Disk{}, iodine.New(err, nil) + } + st, err := os.Stat(diskPath) + if err != nil { + return Disk{}, iodine.New(err, nil) + } + if !st.IsDir() { + return Disk{}, iodine.New(syscall.ENOTDIR, nil) + } + disk := Disk{ + path: diskPath, + fsInfo: make(map[string]string), + } + if fsType := getFSType(s.Type); fsType != "UNKNOWN" { + disk.fsInfo["FSType"] = fsType + disk.fsInfo["MountPoint"] = disk.path + return disk, nil + } + return Disk{}, iodine.New(UnsupportedFilesystem{Type: strconv.FormatInt(s.Type, 10)}, + map[string]string{"Type": strconv.FormatInt(s.Type, 10)}) +} + +// GetPath - get root disk path +func (disk Disk) GetPath() string { + return disk.path +} + +// GetFSInfo - get disk filesystem and its usage information +func (disk Disk) GetFSInfo() map[string]string { + s := syscall.Statfs_t{} + err := syscall.Statfs(disk.path, &s) + if err != nil { + return nil + } + disk.fsInfo["Total"] = formatBytes(s.Bsize * int64(s.Blocks)) + disk.fsInfo["Free"] = formatBytes(s.Bsize * int64(s.Bfree)) + disk.fsInfo["TotalB"] = strconv.FormatInt(s.Bsize*int64(s.Blocks), 10) + disk.fsInfo["FreeB"] = strconv.FormatInt(s.Bsize*int64(s.Bfree), 10) + return disk.fsInfo +} + +// MakeDir - make a directory inside disk root path +func (disk Disk) MakeDir(dirname string) error { + return os.MkdirAll(filepath.Join(disk.path, dirname), 0700) +} + +// ListDir - list a directory inside disk root path, get only directories +func (disk Disk) ListDir(dirname string) ([]os.FileInfo, error) { + dir, err := os.Open(filepath.Join(disk.path, dirname)) + if err != nil { + return nil, iodine.New(err, nil) + } + contents, err := dir.Readdir(-1) + if err != nil { + return nil, iodine.New(err, nil) + } + var directories []os.FileInfo + for _, content := range contents { + // Include only directories, ignore everything else + if content.IsDir() { + directories = append(directories, content) + } + } + return directories, nil +} + +// ListFiles - list a directory inside disk root path, get only files +func (disk Disk) ListFiles(dirname string) ([]os.FileInfo, error) { + dir, err := os.Open(filepath.Join(disk.path, dirname)) + if err != nil { + return nil, iodine.New(err, nil) + } + contents, err := dir.Readdir(-1) + if err != nil { + return nil, iodine.New(err, nil) + } + var files []os.FileInfo + for _, content := range contents { + // Include only regular files, ignore everything else + if content.Mode().IsRegular() { + files = append(files, content) + } + } + return files, nil +} + +// CreateFile - create a file inside disk root path +func (disk Disk) CreateFile(filename string) (*os.File, error) { + if filename == "" { + return nil, iodine.New(InvalidArgument{}, nil) + } + filePath := filepath.Join(disk.path, filename) + // Create directories if they don't exist + if err := os.MkdirAll(filepath.Dir(filePath), 0700); err != nil { + return nil, iodine.New(err, nil) + } + dataFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return nil, iodine.New(err, nil) + } + return dataFile, nil +} + +// OpenFile - read a file inside disk root path +func (disk Disk) OpenFile(filename string) (*os.File, error) { + if filename == "" { + return nil, iodine.New(InvalidArgument{}, nil) + } + dataFile, err := os.Open(filepath.Join(disk.path, filename)) + if err != nil { + return nil, iodine.New(err, nil) + } + return dataFile, nil +} + +// formatBytes - Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B +func formatBytes(i int64) (result string) { + switch { + case i > (1024 * 1024 * 1024 * 1024): + result = fmt.Sprintf("%.02f TB", float64(i)/1024/1024/1024/1024) + case i > (1024 * 1024 * 1024): + result = fmt.Sprintf("%.02f GB", float64(i)/1024/1024/1024) + case i > (1024 * 1024): + result = fmt.Sprintf("%.02f MB", float64(i)/1024/1024) + case i > 1024: + result = fmt.Sprintf("%.02f KB", float64(i)/1024) + default: + result = fmt.Sprintf("%d B", i) + } + result = strings.Trim(result, " ") + return +} diff --git a/pkg/storage/donut/donut_disk_internal_darwin.go b/pkg/storage/donut/disk/disk_darwin.go similarity index 54% rename from pkg/storage/donut/donut_disk_internal_darwin.go rename to pkg/storage/donut/disk/disk_darwin.go index 2aa5af6a6..e5463639e 100644 --- a/pkg/storage/donut/donut_disk_internal_darwin.go +++ b/pkg/storage/donut/disk/disk_darwin.go @@ -14,33 +14,9 @@ * limitations under the License. */ -package donut +package disk -import ( - "fmt" - "strconv" - "strings" -) - -/// This file contains all the internal functions used inside Disk interface - -// formatBytes - Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B -func (d disk) formatBytes(i uint64) (result string) { - switch { - case i > (1024 * 1024 * 1024 * 1024): - result = fmt.Sprintf("%.02f TB", float64(i)/1024/1024/1024/1024) - case i > (1024 * 1024 * 1024): - result = fmt.Sprintf("%.02f GB", float64(i)/1024/1024/1024) - case i > (1024 * 1024): - result = fmt.Sprintf("%.02f MB", float64(i)/1024/1024) - case i > 1024: - result = fmt.Sprintf("%.02f KB", float64(i)/1024) - default: - result = fmt.Sprintf("%d B", i) - } - result = strings.Trim(result, " ") - return -} +import "strconv" // fsType2StrinMap - list of filesystems supported by donut var fsType2StringMap = map[string]string{ @@ -48,7 +24,7 @@ var fsType2StringMap = map[string]string{ } // getFSType - get filesystem type -func (d disk) getFSType(fsType uint32) string { +func getFSType(fsType uint32) string { fsTypeHex := strconv.FormatUint(uint64(fsType), 16) fsTypeString, ok := fsType2StringMap[fsTypeHex] if ok == false { diff --git a/pkg/storage/donut/donut_disk_internal_linux.go b/pkg/storage/donut/disk/disk_linux.go similarity index 56% rename from pkg/storage/donut/donut_disk_internal_linux.go rename to pkg/storage/donut/disk/disk_linux.go index dd1668b34..8f4e23b25 100644 --- a/pkg/storage/donut/donut_disk_internal_linux.go +++ b/pkg/storage/donut/disk/disk_linux.go @@ -14,35 +14,11 @@ * limitations under the License. */ -package donut +package disk -import ( - "fmt" - "strconv" - "strings" -) +import "strconv" -/// This file contains all the internal functions used inside Disk interface - -// formatBytes - Convert bytes to human readable string. Like a 2 MB, 64.2 KB, 52 B -func (d disk) formatBytes(i int64) (result string) { - switch { - case i > (1024 * 1024 * 1024 * 1024): - result = fmt.Sprintf("%.02f TB", float64(i)/1024/1024/1024/1024) - case i > (1024 * 1024 * 1024): - result = fmt.Sprintf("%.02f GB", float64(i)/1024/1024/1024) - case i > (1024 * 1024): - result = fmt.Sprintf("%.02f MB", float64(i)/1024/1024) - case i > 1024: - result = fmt.Sprintf("%.02f KB", float64(i)/1024) - default: - result = fmt.Sprintf("%d B", i) - } - result = strings.Trim(result, " ") - return -} - -// fsType2StrinMap - list of filesystems supported by donut +// fsType2StringMap - list of filesystems supported by donut on linux var fsType2StringMap = map[string]string{ "1021994": "TMPFS", "137d": "EXT", @@ -58,7 +34,7 @@ var fsType2StringMap = map[string]string{ } // getFSType - get filesystem type -func (d disk) getFSType(fsType int64) string { +func getFSType(fsType int64) string { fsTypeHex := strconv.FormatInt(fsType, 16) fsTypeString, ok := fsType2StringMap[fsTypeHex] if ok == false { diff --git a/pkg/storage/donut/disk/errors.go b/pkg/storage/donut/disk/errors.go new file mode 100644 index 000000000..e195a8ded --- /dev/null +++ b/pkg/storage/donut/disk/errors.go @@ -0,0 +1,17 @@ +package disk + +// InvalidArgument invalid argument +type InvalidArgument struct{} + +func (e InvalidArgument) Error() string { + return "Invalid argument" +} + +// UnsupportedFilesystem unsupported filesystem type +type UnsupportedFilesystem struct { + Type string +} + +func (e UnsupportedFilesystem) Error() string { + return "Unsupported filesystem: " + e.Type +} diff --git a/pkg/storage/donut/donut_disk_darwin.go b/pkg/storage/donut/donut_disk_darwin.go deleted file mode 100644 index bb6c7090c..000000000 --- a/pkg/storage/donut/donut_disk_darwin.go +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package donut - -import ( - "os" - "path/filepath" - "strconv" - "syscall" - - "io/ioutil" - - "github.com/minio/minio/pkg/iodine" -) - -// internal disk struct -type disk struct { - root string - order int - filesystem map[string]string -} - -// NewDisk - instantiate new disk -func NewDisk(diskPath string, diskOrder int) (Disk, error) { - if diskPath == "" || diskOrder < 0 { - return nil, iodine.New(InvalidArgument{}, nil) - } - s := syscall.Statfs_t{} - err := syscall.Statfs(diskPath, &s) - if err != nil { - return nil, iodine.New(err, nil) - } - st, err := os.Stat(diskPath) - if err != nil { - return nil, iodine.New(err, nil) - } - if !st.IsDir() { - return nil, iodine.New(syscall.ENOTDIR, nil) - } - d := disk{ - root: diskPath, - order: diskOrder, - filesystem: make(map[string]string), - } - if fsType := d.getFSType(s.Type); fsType != "UNKNOWN" { - d.filesystem["FSType"] = fsType - d.filesystem["MountPoint"] = d.root - return d, nil - } - return nil, iodine.New(UnsupportedFilesystem{ - Type: strconv.FormatInt(s.Type, 10), - }, map[string]string{"Type": strconv.FormatInt(s.Type, 10)}) -} - -// GetPath - get root disk path -func (d disk) GetPath() string { - return d.root -} - -// GetOrder - get order of disk present in graph -func (d disk) GetOrder() int { - return d.order -} - -// GetFSInfo - get disk filesystem and its usage information -func (d disk) GetFSInfo() map[string]string { - s := syscall.Statfs_t{} - err := syscall.Statfs(d.root, &s) - if err != nil { - return nil - } - d.filesystem["Total"] = d.formatBytes(uint64(s.Bsize) * s.Blocks) - d.filesystem["Free"] = d.formatBytes(uint64(s.Bsize) * s.Bfree) - return d.filesystem -} - -// MakeDir - make a directory inside disk root path -func (d disk) MakeDir(dirname string) error { - return os.MkdirAll(filepath.Join(d.root, dirname), 0700) -} - -// ListDir - list a directory inside disk root path, get only directories -func (d disk) ListDir(dirname string) ([]os.FileInfo, error) { - contents, err := ioutil.ReadDir(filepath.Join(d.root, dirname)) - if err != nil { - return nil, iodine.New(err, nil) - } - var directories []os.FileInfo - for _, content := range contents { - // Include only directories, ignore everything else - if content.IsDir() { - directories = append(directories, content) - } - } - return directories, nil -} - -// ListFiles - list a directory inside disk root path, get only files -func (d disk) ListFiles(dirname string) ([]os.FileInfo, error) { - contents, err := ioutil.ReadDir(filepath.Join(d.root, dirname)) - if err != nil { - return nil, iodine.New(err, nil) - } - var files []os.FileInfo - for _, content := range contents { - // Include only regular files, ignore everything else - if content.Mode().IsRegular() { - files = append(files, content) - } - } - return files, nil -} - -// MakeFile - create a file inside disk root path -func (d disk) MakeFile(filename string) (*os.File, error) { - if filename == "" { - return nil, iodine.New(InvalidArgument{}, nil) - } - filePath := filepath.Join(d.root, filename) - // Create directories if they don't exist - if err := os.MkdirAll(filepath.Dir(filePath), 0700); err != nil { - return nil, iodine.New(err, nil) - } - dataFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - return nil, iodine.New(err, nil) - } - return dataFile, nil -} - -// OpenFile - read a file inside disk root path -func (d disk) OpenFile(filename string) (*os.File, error) { - if filename == "" { - return nil, iodine.New(InvalidArgument{}, nil) - } - dataFile, err := os.Open(filepath.Join(d.root, filename)) - if err != nil { - return nil, iodine.New(err, nil) - } - return dataFile, nil -} diff --git a/pkg/storage/donut/donut_disk_linux.go b/pkg/storage/donut/donut_disk_linux.go deleted file mode 100644 index 0c6ee30bb..000000000 --- a/pkg/storage/donut/donut_disk_linux.go +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Minimalist Object Storage, (C) 2015 Minio, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package donut - -import ( - "os" - "path/filepath" - "strconv" - "syscall" - - "io/ioutil" - - "github.com/minio/minio/pkg/iodine" -) - -// internal disk struct -type disk struct { - root string - order int - filesystem map[string]string -} - -// NewDisk - instantiate new disk -func NewDisk(diskPath string, diskOrder int) (Disk, error) { - if diskPath == "" || diskOrder < 0 { - return nil, iodine.New(InvalidArgument{}, nil) - } - s := syscall.Statfs_t{} - err := syscall.Statfs(diskPath, &s) - if err != nil { - return nil, iodine.New(err, nil) - } - st, err := os.Stat(diskPath) - if err != nil { - return nil, iodine.New(err, nil) - } - if !st.IsDir() { - return nil, iodine.New(syscall.ENOTDIR, nil) - } - d := disk{ - root: diskPath, - order: diskOrder, - filesystem: make(map[string]string), - } - if fsType := d.getFSType(s.Type); fsType != "UNKNOWN" { - d.filesystem["FSType"] = fsType - d.filesystem["MountPoint"] = d.root - return d, nil - } - return nil, iodine.New(UnsupportedFilesystem{ - Type: strconv.FormatInt(s.Type, 10), - }, map[string]string{"Type": strconv.FormatInt(s.Type, 10)}) -} - -// GetPath - get root disk path -func (d disk) GetPath() string { - return d.root -} - -// GetOrder - get order of disk present in graph -func (d disk) GetOrder() int { - return d.order -} - -// GetFSInfo - get disk filesystem and its usage information -func (d disk) GetFSInfo() map[string]string { - s := syscall.Statfs_t{} - err := syscall.Statfs(d.root, &s) - if err != nil { - return nil - } - d.filesystem["Total"] = d.formatBytes(s.Bsize * int64(s.Blocks)) - d.filesystem["Free"] = d.formatBytes(s.Bsize * int64(s.Bfree)) - return d.filesystem -} - -// MakeDir - make a directory inside disk root path -func (d disk) MakeDir(dirname string) error { - return os.MkdirAll(filepath.Join(d.root, dirname), 0700) -} - -// ListDir - list a directory inside disk root path, get only directories -func (d disk) ListDir(dirname string) ([]os.FileInfo, error) { - contents, err := ioutil.ReadDir(filepath.Join(d.root, dirname)) - if err != nil { - return nil, iodine.New(err, nil) - } - var directories []os.FileInfo - for _, content := range contents { - // Include only directories, ignore everything else - if content.IsDir() { - directories = append(directories, content) - } - } - return directories, nil -} - -// ListFiles - list a directory inside disk root path, get only files -func (d disk) ListFiles(dirname string) ([]os.FileInfo, error) { - contents, err := ioutil.ReadDir(filepath.Join(d.root, dirname)) - if err != nil { - return nil, iodine.New(err, nil) - } - var files []os.FileInfo - for _, content := range contents { - // Include only regular files, ignore everything else - if content.Mode().IsRegular() { - files = append(files, content) - } - } - return files, nil -} - -// MakeFile - create a file inside disk root path -func (d disk) MakeFile(filename string) (*os.File, error) { - if filename == "" { - return nil, iodine.New(InvalidArgument{}, nil) - } - filePath := filepath.Join(d.root, filename) - // Create directories if they don't exist - if err := os.MkdirAll(filepath.Dir(filePath), 0700); err != nil { - return nil, iodine.New(err, nil) - } - dataFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - return nil, iodine.New(err, nil) - } - return dataFile, nil -} - -// OpenFile - read a file inside disk root path -func (d disk) OpenFile(filename string) (*os.File, error) { - if filename == "" { - return nil, iodine.New(InvalidArgument{}, nil) - } - dataFile, err := os.Open(filepath.Join(d.root, filename)) - if err != nil { - return nil, iodine.New(err, nil) - } - return dataFile, nil -}