github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/dir_windows.go (about) 1 // +build windows 2 3 /* 4 * Copyright 2017 Dgraph Labs, Inc. and Contributors 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 package badger 20 21 // OpenDir opens a directory in windows with write access for syncing. 22 import ( 23 "fmt" 24 "os" 25 "path/filepath" 26 "syscall" 27 28 "github.com/pingcap/errors" 29 ) 30 31 func openDir(path string) (*os.File, error) { 32 fd, err := openDirWin(path) 33 if err != nil { 34 return nil, err 35 } 36 return os.NewFile(uintptr(fd), path), nil 37 } 38 39 func openDirWin(path string) (fd syscall.Handle, err error) { 40 if len(path) == 0 { 41 return syscall.InvalidHandle, syscall.ERROR_FILE_NOT_FOUND 42 } 43 pathp, err := syscall.UTF16PtrFromString(path) 44 if err != nil { 45 return syscall.InvalidHandle, err 46 } 47 access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE) 48 sharemode := uint32(syscall.FILE_SHARE_READ | syscall.FILE_SHARE_WRITE) 49 createmode := uint32(syscall.OPEN_EXISTING) 50 fl := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS) 51 return syscall.CreateFile(pathp, access, sharemode, nil, createmode, fl, 0) 52 } 53 54 // DirectoryLockGuard holds a lock on the directory. 55 type directoryLockGuard struct { 56 path string 57 } 58 59 // AcquireDirectoryLock acquires exclusive access to a directory. 60 func acquireDirectoryLock(dirPath string, pidFileName string, readOnly bool) (*directoryLockGuard, error) { 61 if readOnly { 62 return nil, ErrWindowsNotSupported 63 } 64 65 // Convert to absolute path so that Release still works even if we do an unbalanced 66 // chdir in the meantime. 67 absLockFilePath, err := filepath.Abs(filepath.Join(dirPath, pidFileName)) 68 if err != nil { 69 return nil, errors.Wrap(err, "Cannot get absolute path for pid lock file") 70 } 71 72 f, err := os.OpenFile(absLockFilePath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) 73 if err != nil { 74 return nil, errors.Wrapf(err, 75 "Cannot create pid lock file %q. Another process is using this Badger database", 76 absLockFilePath) 77 } 78 _, err = fmt.Fprintf(f, "%d\n", os.Getpid()) 79 closeErr := f.Close() 80 if err != nil { 81 return nil, errors.Wrap(err, "Cannot write to pid lock file") 82 } 83 if closeErr != nil { 84 return nil, errors.Wrap(closeErr, "Cannot close pid lock file") 85 } 86 return &directoryLockGuard{path: absLockFilePath}, nil 87 } 88 89 // Release removes the directory lock. 90 func (g *directoryLockGuard) release() error { 91 path := g.path 92 g.path = "" 93 return os.Remove(path) 94 }