Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
26471d57
Commit
26471d57
authored
Feb 27, 2016
by
Paul Morie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove sentinel file from atomic writer
parent
8a106999
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
13 additions
and
153 deletions
+13
-153
atomic_writer.go
pkg/volume/util/atomic_writer.go
+10
-44
atomic_writer_test.go
pkg/volume/util/atomic_writer_test.go
+3
-109
No files found.
pkg/volume/util/atomic_writer.go
View file @
26471d57
...
...
@@ -37,11 +37,7 @@ const (
)
// AtomicWriter handles atomically projecting content for a set of files into
// a target directory. AtomicWriter maintains a sentinel file named
// "..sentinel" in the target directory which is updated after new data is
// projected into the target directory, allowing consumers of the data to
// listen for updates by monitoring the sentinel file with inotify or
// fanotify.
// a target directory.
//
// Note:
//
...
...
@@ -55,6 +51,10 @@ const (
// data directory symlink are created in the writer's target dir. This scheme
// allows the files to be atomically updated by changing the target of the
// data directory symlink.
//
// Consumers of the target directory can monitor the ..data symlink using
// inotify or fanotify to receive events when the content in the volume is
// updated.
type
AtomicWriter
struct
{
targetDir
string
logContext
string
...
...
@@ -72,9 +72,8 @@ func NewAtomicWriter(targetDir, logContext string) (*AtomicWriter, error) {
}
const
(
sentinelFileName
=
"..sentinel"
dataDirName
=
"..data"
newDataDirName
=
"..data_tmp"
dataDirName
=
"..data"
newDataDirName
=
"..data_tmp"
)
// Write does an atomic projection of the given payload into the writer's target
...
...
@@ -112,10 +111,8 @@ const (
// 8. A symlink to the new timestamped directory ..data_tmp is created that will
// become the new data directory
// 9. The new data directory symlink is renamed to the data directory; rename is atomic
// 10. The sentinel file modification and access times are updated (file is created if it does not
// already exist)
// 11. Old paths are removed from the user-visible portion of the target directory
// 12. The previous timestamped directory is removed, if it exists
// 10. Old paths are removed from the user-visible portion of the target directory
// 11. The previous timestamped directory is removed, if it exists
func
(
w
*
AtomicWriter
)
Write
(
payload
map
[
string
][]
byte
)
error
{
// (1)
cleanPayload
,
err
:=
validatePayload
(
payload
)
...
...
@@ -189,18 +186,12 @@ func (w *AtomicWriter) Write(payload map[string][]byte) error {
}
// (10)
if
err
=
w
.
touchSentinelFile
();
err
!=
nil
{
glog
.
Errorf
(
"%s: error touching sentinel file: %v"
,
w
.
logContext
,
err
)
return
err
}
// (11)
if
err
=
w
.
removeUserVisiblePaths
(
pathsToRemove
);
err
!=
nil
{
glog
.
Errorf
(
"%s: error removing old visible symlinks: %v"
,
w
.
logContext
,
err
)
return
err
}
// (1
2
)
// (1
1
)
if
len
(
oldTsDir
)
>
0
{
if
err
=
os
.
RemoveAll
(
path
.
Join
(
w
.
targetDir
,
oldTsDir
));
err
!=
nil
{
glog
.
Errorf
(
"%s: error removing old data directory %s: %v"
,
w
.
logContext
,
oldTsDir
,
err
)
...
...
@@ -434,28 +425,3 @@ func (w *AtomicWriter) removeUserVisiblePaths(paths sets.String) error {
return
nil
}
// touchSentinelFile touches the sentinel file or creates it if it doesn't exist.
func
(
w
*
AtomicWriter
)
touchSentinelFile
()
error
{
sentinelFilePath
:=
path
.
Join
(
w
.
targetDir
,
sentinelFileName
)
_
,
err
:=
os
.
Stat
(
sentinelFilePath
)
if
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
file
,
err
:=
os
.
Create
(
sentinelFilePath
)
if
err
!=
nil
{
glog
.
Errorf
(
"%s: unexpected error creating sentinel file %s: %v"
,
w
.
logContext
,
sentinelFilePath
,
err
)
return
err
}
file
.
Close
()
}
else
if
err
!=
nil
{
return
err
}
ts
:=
time
.
Now
()
err
=
os
.
Chtimes
(
sentinelFilePath
,
ts
,
ts
)
if
err
!=
nil
{
glog
.
Errorf
(
"%s: error updating sentinel file mod time: %v"
,
w
.
logContext
,
err
)
return
err
}
return
nil
}
pkg/volume/util/atomic_writer_test.go
View file @
26471d57
...
...
@@ -27,7 +27,6 @@ import (
"reflect"
"strings"
"testing"
"time"
"k8s.io/kubernetes/pkg/util/sets"
utiltesting
"k8s.io/kubernetes/pkg/util/testing"
...
...
@@ -371,7 +370,6 @@ IAAAAAAAsDyZDwU=`
}
checkVolumeContents
(
targetDir
,
tc
.
name
,
tc
.
payload
,
t
)
checkSentinelFile
(
targetDir
,
t
)
}
}
...
...
@@ -547,8 +545,6 @@ func TestUpdate(t *testing.T) {
continue
}
oldTs
:=
checkSentinelFile
(
targetDir
,
t
)
err
=
writer
.
Write
(
tc
.
next
)
if
err
!=
nil
{
if
tc
.
shouldWrite
{
...
...
@@ -561,19 +557,13 @@ func TestUpdate(t *testing.T) {
}
checkVolumeContents
(
targetDir
,
tc
.
name
,
tc
.
next
,
t
)
ts
:=
checkSentinelFile
(
targetDir
,
t
)
if
!
ts
.
After
(
oldTs
)
{
t
.
Errorf
(
"Unexpected timestamp on sentinel file; expected %v to be after %v"
,
ts
,
oldTs
)
}
}
}
func
TestMultipleUpdates
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
name
string
payloads
[]
map
[
string
][]
byte
clearSentinel
bool
name
string
payloads
[]
map
[
string
][]
byte
}{
{
name
:
"update 1"
,
...
...
@@ -625,7 +615,6 @@ func TestMultipleUpdates(t *testing.T) {
"bar"
:
[]
byte
(
"bar4"
),
},
},
clearSentinel
:
true
,
},
{
name
:
"subdirectories 2"
,
...
...
@@ -710,84 +699,12 @@ func TestMultipleUpdates(t *testing.T) {
continue
}
var
oldTs
*
time
.
Time
=
nil
writer
:=
&
AtomicWriter
{
targetDir
:
targetDir
,
logContext
:
"-test-"
}
for
ii
,
payload
:=
range
tc
.
payloads
{
for
_
,
payload
:=
range
tc
.
payloads
{
writer
.
Write
(
payload
)
checkVolumeContents
(
targetDir
,
tc
.
name
,
payload
,
t
)
ts
:=
checkSentinelFile
(
targetDir
,
t
)
if
oldTs
!=
nil
&&
!
ts
.
After
(
*
oldTs
)
{
t
.
Errorf
(
"%v[%v] unexpected timestamp on sentinel file; expected %v to be after %v"
,
tc
.
name
,
ii
,
ts
,
oldTs
)
}
oldTs
=
&
ts
if
tc
.
clearSentinel
{
clearSentinelFile
(
targetDir
,
t
)
}
}
}
}
func
TestSentinelFileModTimeIncreasing
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
name
string
iterations
int
clearSentinelFile
bool
}{
{
name
:
"5 iters"
,
iterations
:
5
,
},
{
name
:
"50 iters"
,
iterations
:
50
,
},
{
name
:
"1000 iters"
,
iterations
:
1000
,
},
{
name
:
"1000 clear sentinel"
,
iterations
:
1000
,
clearSentinelFile
:
true
,
},
{
name
:
"10000 clear sentinel"
,
iterations
:
10000
,
clearSentinelFile
:
true
,
},
}
for
_
,
tc
:=
range
cases
{
targetDir
,
err
:=
utiltesting
.
MkTmpdir
(
"atomic-write"
)
if
err
!=
nil
{
t
.
Errorf
(
"%v: unexpected error creating tmp dir: %v"
,
tc
.
name
,
err
)
continue
}
var
oldTs
*
time
.
Time
=
nil
writer
:=
&
AtomicWriter
{
targetDir
:
targetDir
,
logContext
:
"-test-"
}
for
i
:=
0
;
i
<
tc
.
iterations
;
i
++
{
err
=
writer
.
touchSentinelFile
()
if
err
!=
nil
{
t
.
Errorf
(
"%v: unexpected error touching sentinel file: %v"
,
tc
.
name
,
err
)
continue
}
ts
:=
checkSentinelFile
(
targetDir
,
t
)
if
oldTs
!=
nil
&&
!
ts
.
After
(
*
oldTs
)
{
t
.
Errorf
(
"%v: unexpected timestamp on sentinel file; expected %v to be after %v"
,
tc
.
name
,
ts
,
oldTs
)
continue
}
oldTs
=
&
ts
if
tc
.
clearSentinelFile
{
clearSentinelFile
(
targetDir
,
t
)
}
}
}
}
...
...
@@ -829,26 +746,3 @@ func checkVolumeContents(targetDir, tcName string, payload map[string][]byte, t
t
.
Errorf
(
"%v: payload and observed payload do not match."
,
tcName
)
}
}
func
checkSentinelFile
(
targetDir
string
,
t
*
testing
.
T
)
time
.
Time
{
sentinelFilePath
:=
filepath
.
Join
(
targetDir
,
sentinelFileName
)
info
,
err
:=
os
.
Stat
(
sentinelFilePath
)
if
err
!=
nil
{
t
.
Errorf
(
"Couldn't stat sentinel file for dir %v: %v"
,
targetDir
,
err
)
return
time
.
Now
()
}
return
info
.
ModTime
()
}
func
clearSentinelFile
(
targetDir
string
,
t
*
testing
.
T
)
{
sentinelFilePath
:=
filepath
.
Join
(
targetDir
,
sentinelFileName
)
_
,
err
:=
os
.
Stat
(
sentinelFilePath
)
if
err
!=
nil
{
t
.
Errorf
(
"Couldn't stat sentinel file for dir %v: %v"
,
targetDir
,
err
)
}
err
=
os
.
Remove
(
sentinelFilePath
)
if
err
!=
nil
{
t
.
Errorf
(
"Error removing sentinel file: %v"
,
err
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment