mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-12-15 08:23:34 +01:00
d88fa5ebe4
* fixes windows compilation, adds signal impl for windows, adds free space usage for windows, https://github.com/VictoriaMetrics/VictoriaMetrics/issues/70 https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1036 NOTE victoria metrics database still CANNOT work under windows system, only vmagent is supported. To completly port victoria metrics, you have to fix issues with separators, parsing and posix file removall * rollback separator * Adds windows setInformation api, it must behave like unix, need to test it. changes procutil * check for invlaid param * Fixes posix delete semantic * refactored a bit * fixes openbsd build * removed windows api call * Fixes code after windows add * Update lib/procutil/signal_windows.go Co-authored-by: Aliaksandr Valialkin <valyala@gmail.com>
150 lines
4.8 KiB
Go
150 lines
4.8 KiB
Go
package fs
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"unsafe"
|
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/logger"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
var (
|
|
kernelDLL = windows.MustLoadDLL("kernel32.dll")
|
|
procLock = kernelDLL.MustFindProc("LockFileEx")
|
|
procEvent = kernelDLL.MustFindProc("CreateEventW")
|
|
procDisk = kernelDLL.MustFindProc("GetDiskFreeSpaceExW")
|
|
ntDLL = windows.MustLoadDLL("ntdll.dll")
|
|
ntSetInformationProc = ntDLL.MustFindProc("NtSetInformationFile")
|
|
)
|
|
|
|
// panic at windows, if file already open by another process.
|
|
// one of possible solutions - change files opening process with correct flags.
|
|
// https://github.com/dgraph-io/badger/issues/699
|
|
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-flushfilebuffers
|
|
func mustSyncPath(string) {
|
|
}
|
|
|
|
const (
|
|
lockfileExclusiveLock = 2
|
|
fileFlagNormal = 0x00000080
|
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_file_disposition_information_ex
|
|
fileDispositionPosixSemantics = 0x00000002
|
|
fileDispositionIgnoreReadonlyAttribute = 0x00000010
|
|
)
|
|
|
|
// createFlockFile creates flock.lock file in the directory dir
|
|
// and returns the handler to the file.
|
|
// https://github.com/juju/fslock/blob/master/fslock_windows.go
|
|
func createFlockFile(dir string) (*os.File, error) {
|
|
flockFile := dir + "/flock.lock"
|
|
name, err := windows.UTF16PtrFromString(flockFile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
handle, err := windows.CreateFile(
|
|
name,
|
|
windows.GENERIC_READ|windows.DELETE,
|
|
windows.FILE_SHARE_READ|windows.FILE_SHARE_DELETE,
|
|
nil,
|
|
windows.OPEN_ALWAYS,
|
|
windows.FILE_FLAG_OVERLAPPED|fileFlagNormal,
|
|
0)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot create lock file %q: %w", flockFile, err)
|
|
}
|
|
ol, err := newOverlapped()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot create Overlapped handler: %w", err)
|
|
}
|
|
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex
|
|
// overlapped is dropped?
|
|
r1, _, err := procLock.Call(uintptr(handle), uintptr(lockfileExclusiveLock), uintptr(0), uintptr(1), uintptr(0), uintptr(unsafe.Pointer(ol)))
|
|
if r1 == 0 {
|
|
return nil, err
|
|
}
|
|
return os.NewFile(uintptr(handle), flockFile), nil
|
|
}
|
|
|
|
// stub
|
|
func mmap(fd int, offset int64, length int) ([]byte, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// stub
|
|
func mUnmap([]byte) error {
|
|
return nil
|
|
}
|
|
|
|
func mustGetFreeSpace(path string) uint64 {
|
|
var freeBytes int64
|
|
r, _, err := procDisk.Call(uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(path))),
|
|
uintptr(unsafe.Pointer(&freeBytes)))
|
|
if r == 0 {
|
|
logger.Errorf("cannot get free space: %v", err)
|
|
return 0
|
|
}
|
|
return uint64(freeBytes)
|
|
}
|
|
|
|
// stub
|
|
func fadviseSequentialRead(f *os.File, prefetch bool) error {
|
|
return nil
|
|
}
|
|
|
|
// copied from https://github.com/juju/fslock/blob/master/fslock_windows.go
|
|
// https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-overlapped
|
|
func newOverlapped() (*windows.Overlapped, error) {
|
|
event, err := createEvent(nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &windows.Overlapped{HEvent: event}, nil
|
|
}
|
|
|
|
// copied from https://github.com/juju/fslock/blob/master/fslock_windows.go
|
|
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventa
|
|
func createEvent(sa *windows.SecurityAttributes, name *uint16) (windows.Handle, error) {
|
|
r0, _, err := procEvent.Call(uintptr(unsafe.Pointer(sa)), uintptr(1), uintptr(1), uintptr(unsafe.Pointer(name)))
|
|
handle := windows.Handle(r0)
|
|
if handle == windows.InvalidHandle {
|
|
return 0, err
|
|
}
|
|
return handle, nil
|
|
}
|
|
|
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_file_disposition_information_ex
|
|
type fileDispositionInformationEx struct {
|
|
Flags uint32
|
|
}
|
|
|
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_io_status_block
|
|
type ioStatusBlock struct {
|
|
Status, Information uintptr
|
|
}
|
|
|
|
// UpdateFileHandle - changes file deletion semantic at windows to posix-like.
|
|
func UpdateFileHandle(path string) error {
|
|
handle, err := windows.Open(path, windows.GENERIC_READ|windows.DELETE, windows.FILE_SHARE_READ|windows.FILE_SHARE_DELETE)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return setPosixDelete(handle)
|
|
}
|
|
|
|
// supported starting with Windows 10, version 1709.
|
|
// supported by NTFS only.
|
|
func setPosixDelete(handle windows.Handle) error {
|
|
var iosb ioStatusBlock
|
|
flags := fileDispositionInformationEx{
|
|
Flags: fileDispositionPosixSemantics | fileDispositionIgnoreReadonlyAttribute,
|
|
}
|
|
// class FileDispositionInformationEx, // 64
|
|
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_file_information_class
|
|
r0, _, err := ntSetInformationProc.Call(uintptr(handle), uintptr(unsafe.Pointer(&iosb)), uintptr(unsafe.Pointer(&flags)), unsafe.Sizeof(flags), uintptr(64))
|
|
if r0 == 0 {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("cannot set file disposition information: NT_STATUS: 0x%X, error: %w", r0, err)
|
|
}
|