Skip to content

Commit

Permalink
Fix corrupt Winlogbeat registry occurring on power failure (#2434) (#…
Browse files Browse the repository at this point in the history
…2546)

File writes are cached and not immediately flushed to disk. So if there is a power loss prior to flushing it seems that some corruption occurs. This adds the FILE_FLAG_WRITE_THROUGH flag to the CreateFile call to ensure that writes go directly to the disk.
  • Loading branch information
andrewkroh authored and tsg committed Sep 14, 2016
1 parent 65f37f7 commit 679248b
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ https://github.com/elastic/beats/compare/v1.3.1...1.3[Check the HEAD diff]
*Filebeat*

*Winlogbeat*
- Fix corrupt registry file that occurs on power loss by disabling file write caching. {issue}2313[2313]

==== Added

Expand Down
5 changes: 2 additions & 3 deletions winlogbeat/checkpoint/checkpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func NewCheckpoint(file string, maxUpdates int, interval time.Duration) (*Checkp
// the amount of time since the last disk write reaches flushInterval.
func (c *Checkpoint) run() {
defer c.wg.Done()
defer c.persist()

flushTimer := time.NewTimer(c.flushInterval)
defer flushTimer.Stop()
Expand All @@ -127,8 +128,6 @@ loop:
c.persist()
flushTimer.Reset(c.flushInterval)
}

c.persist()
}

// Shutdown stops the checkpoint worker (which persists any state to disk as
Expand Down Expand Up @@ -185,7 +184,7 @@ func (c *Checkpoint) persist() bool {
// flush writes the current state to disk.
func (c *Checkpoint) flush() error {
tempFile := c.file + ".new"
file, err := os.Create(tempFile)
file, err := create(tempFile)
if os.IsNotExist(err) {
// Try to create directory if it does not exist.
if createDirErr := c.createDir(); createDirErr == nil {
Expand Down
9 changes: 9 additions & 0 deletions winlogbeat/checkpoint/file_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// +build !windows

package checkpoint

import "os"

func create(path string) (*os.File, error) {
return os.Create(path)
}
37 changes: 37 additions & 0 deletions winlogbeat/checkpoint/file_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package checkpoint

import (
"os"
"syscall"
)

const (
_FILE_FLAG_WRITE_THROUGH = 0x80000000
)

func create(path string) (*os.File, error) {
return createWriteThroughFile(path)
}

// createWriteThroughFile creates a file whose write operations do not go
// through any intermediary cache, they go directly to disk.
func createWriteThroughFile(path string) (*os.File, error) {
if len(path) == 0 {
return nil, syscall.ERROR_FILE_NOT_FOUND
}
pathp, err := syscall.UTF16PtrFromString(path)
if err != nil {
return nil, err
}

h, err := syscall.CreateFile(
pathp, // Path
syscall.GENERIC_READ|syscall.GENERIC_WRITE, // Access Mode
uint32(syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE), // Share Mode
nil, // Security Attributes
syscall.CREATE_ALWAYS, // Create Mode
uint32(syscall.FILE_ATTRIBUTE_NORMAL|_FILE_FLAG_WRITE_THROUGH), // Flags and Attributes
0) // Template File

return os.NewFile(uintptr(h), path), err
}

0 comments on commit 679248b

Please sign in to comment.