|
|
@ -18,6 +18,7 @@ package main |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"bytes" |
|
|
|
"bytes" |
|
|
|
|
|
|
|
"errors" |
|
|
|
"io" |
|
|
|
"io" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
slashpath "path" |
|
|
|
slashpath "path" |
|
|
@ -31,14 +32,18 @@ import ( |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
|
fsMinSpacePercent = 5 |
|
|
|
fsMinSpacePercent = 5 |
|
|
|
|
|
|
|
maxAllowedIOError = 5 |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// posix - implements StorageAPI interface.
|
|
|
|
// posix - implements StorageAPI interface.
|
|
|
|
type posix struct { |
|
|
|
type posix struct { |
|
|
|
diskPath string |
|
|
|
diskPath string |
|
|
|
minFreeDisk int64 |
|
|
|
minFreeDisk int64 |
|
|
|
|
|
|
|
ioErrCount int |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var errFaultyDisk = errors.New("Faulty disk") |
|
|
|
|
|
|
|
|
|
|
|
// checkPathLength - returns error if given path name length more than 255
|
|
|
|
// checkPathLength - returns error if given path name length more than 255
|
|
|
|
func checkPathLength(pathName string) error { |
|
|
|
func checkPathLength(pathName string) error { |
|
|
|
// For MS Windows, the maximum path length is 255
|
|
|
|
// For MS Windows, the maximum path length is 255
|
|
|
@ -183,6 +188,16 @@ func (s posix) getVolDir(volume string) (string, error) { |
|
|
|
|
|
|
|
|
|
|
|
// Make a volume entry.
|
|
|
|
// Make a volume entry.
|
|
|
|
func (s posix) MakeVol(volume string) (err error) { |
|
|
|
func (s posix) MakeVol(volume string) (err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
@ -203,6 +218,16 @@ func (s posix) MakeVol(volume string) (err error) { |
|
|
|
|
|
|
|
|
|
|
|
// ListVols - list volumes.
|
|
|
|
// ListVols - list volumes.
|
|
|
|
func (s posix) ListVols() (volsInfo []VolInfo, err error) { |
|
|
|
func (s posix) ListVols() (volsInfo []VolInfo, err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return nil, errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
volsInfo, err = listVols(s.diskPath) |
|
|
|
volsInfo, err = listVols(s.diskPath) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
@ -219,6 +244,16 @@ func (s posix) ListVols() (volsInfo []VolInfo, err error) { |
|
|
|
|
|
|
|
|
|
|
|
// StatVol - get volume info.
|
|
|
|
// StatVol - get volume info.
|
|
|
|
func (s posix) StatVol(volume string) (volInfo VolInfo, err error) { |
|
|
|
func (s posix) StatVol(volume string) (volInfo VolInfo, err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return VolInfo{}, errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return VolInfo{}, err |
|
|
|
return VolInfo{}, err |
|
|
@ -248,9 +283,19 @@ func (s posix) StatVol(volume string) (volInfo VolInfo, err error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// DeleteVol - delete a volume.
|
|
|
|
// DeleteVol - delete a volume.
|
|
|
|
func (s posix) DeleteVol(volume string) error { |
|
|
|
func (s posix) DeleteVol(volume string) (err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err := checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -278,9 +323,19 @@ func (s posix) DeleteVol(volume string) error { |
|
|
|
|
|
|
|
|
|
|
|
// ListDir - return all the entries at the given directory path.
|
|
|
|
// ListDir - return all the entries at the given directory path.
|
|
|
|
// If an entry is a directory it will be returned with a trailing "/".
|
|
|
|
// If an entry is a directory it will be returned with a trailing "/".
|
|
|
|
func (s posix) ListDir(volume, dirPath string) ([]string, error) { |
|
|
|
func (s posix) ListDir(volume, dirPath string) (entries []string, err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return nil, errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err := checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -306,6 +361,16 @@ func (s posix) ListDir(volume, dirPath string) ([]string, error) { |
|
|
|
// for io.EOF. Additionally ReadFile also starts reading from an
|
|
|
|
// for io.EOF. Additionally ReadFile also starts reading from an
|
|
|
|
// offset.
|
|
|
|
// offset.
|
|
|
|
func (s posix) ReadFile(volume string, path string, offset int64, buf []byte) (n int64, err error) { |
|
|
|
func (s posix) ReadFile(volume string, path string, offset int64, buf []byte) (n int64, err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return 0, errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return 0, err |
|
|
|
return 0, err |
|
|
@ -371,6 +436,16 @@ func (s posix) ReadFile(volume string, path string, offset int64, buf []byte) (n |
|
|
|
// AppendFile - append a byte array at path, if file doesn't exist at
|
|
|
|
// AppendFile - append a byte array at path, if file doesn't exist at
|
|
|
|
// path this call explicitly creates it.
|
|
|
|
// path this call explicitly creates it.
|
|
|
|
func (s posix) AppendFile(volume, path string, buf []byte) (n int64, err error) { |
|
|
|
func (s posix) AppendFile(volume, path string, buf []byte) (n int64, err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return 0, errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return 0, err |
|
|
|
return 0, err |
|
|
@ -423,6 +498,16 @@ func (s posix) AppendFile(volume, path string, buf []byte) (n int64, err error) |
|
|
|
|
|
|
|
|
|
|
|
// StatFile - get file info.
|
|
|
|
// StatFile - get file info.
|
|
|
|
func (s posix) StatFile(volume, path string) (file FileInfo, err error) { |
|
|
|
func (s posix) StatFile(volume, path string) (file FileInfo, err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return FileInfo{}, errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return FileInfo{}, err |
|
|
|
return FileInfo{}, err |
|
|
@ -504,9 +589,19 @@ func deleteFile(basePath, deletePath string) error { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// DeleteFile - delete a file at path.
|
|
|
|
// DeleteFile - delete a file at path.
|
|
|
|
func (s posix) DeleteFile(volume, path string) error { |
|
|
|
func (s posix) DeleteFile(volume, path string) (err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err := checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -535,9 +630,19 @@ func (s posix) DeleteFile(volume, path string) error { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// RenameFile - rename source path to destination path atomically.
|
|
|
|
// RenameFile - rename source path to destination path atomically.
|
|
|
|
func (s posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) error { |
|
|
|
func (s posix) RenameFile(srcVolume, srcPath, dstVolume, dstPath string) (err error) { |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
if err == syscall.EIO { |
|
|
|
|
|
|
|
s.ioErrCount++ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if s.ioErrCount > maxAllowedIOError { |
|
|
|
|
|
|
|
return errFaultyDisk |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Validate if disk is free.
|
|
|
|
// Validate if disk is free.
|
|
|
|
if err := checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
if err = checkDiskFree(s.diskPath, s.minFreeDisk); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|