Skip to content

Commit e6da159

Browse files
committed
dump store contents when corrupted file detected
adds Dump to store interface which returns the raw contents of the store in string format if the store is empty or not readable it returns an error adds to a ut to check that dump effectively prints the contents of the store
1 parent 565a39b commit e6da159

File tree

5 files changed

+72
-23
lines changed

5 files changed

+72
-23
lines changed

network/manager.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,12 @@ func (nm *networkManager) restore(isRehydrationRequired bool) error {
204204
} else if errors.As(err, &syntaxErr) {
205205
// if null chars detected or failed to parse, state is unrecoverable; delete it
206206
logger.Error("Failed to parse corrupted state, deleting", zap.Error(err))
207+
contents, readErr := nm.store.Dump()
208+
if readErr != nil {
209+
logger.Error("Could not read corrupted state", zap.Error(readErr))
210+
} else {
211+
logger.Info("Logging state", zap.String("stateFile", contents))
212+
}
207213
nm.store.Remove()
208214
return errors.Wrap(err, "failed to parse corrupted state")
209215
} else {

store/json.go

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -70,30 +70,10 @@ func (kvs *jsonFileStore) Read(key string, value interface{}) error {
7070

7171
// Read contents from file if memory is not in sync.
7272
if !kvs.inSync {
73-
// Open and parse the file if it exists.
74-
file, err := os.Open(kvs.fileName)
73+
b, err := kvs.readBytes()
7574
if err != nil {
76-
if os.IsNotExist(err) {
77-
return ErrKeyNotFound
78-
}
7975
return err
8076
}
81-
defer file.Close()
82-
83-
b, err := io.ReadAll(file)
84-
if err != nil {
85-
return err
86-
}
87-
88-
if len(b) == 0 {
89-
if kvs.logger != nil {
90-
kvs.logger.Info("Unable to read empty file", zap.String("fileName", kvs.fileName))
91-
} else {
92-
log.Printf("Unable to read file %s, was empty", kvs.fileName)
93-
}
94-
95-
return ErrStoreEmpty
96-
}
9777

9878
// Decode to raw JSON messages.
9979
if err := json.Unmarshal(b, &kvs.data); err != nil {
@@ -265,3 +245,44 @@ func (kvs *jsonFileStore) Remove() {
265245
}
266246
kvs.Mutex.Unlock()
267247
}
248+
249+
func (kvs *jsonFileStore) Dump() (string, error) {
250+
kvs.Mutex.Lock()
251+
defer kvs.Mutex.Unlock()
252+
253+
b, err := kvs.readBytes()
254+
if err != nil {
255+
return "", err
256+
}
257+
258+
return string(b), nil
259+
}
260+
261+
func (kvs *jsonFileStore) readBytes() ([]byte, error) {
262+
// Open and parse the file if it exists.
263+
file, err := os.Open(kvs.fileName)
264+
if err != nil {
265+
if os.IsNotExist(err) {
266+
return []byte{}, ErrKeyNotFound
267+
}
268+
return []byte{}, errors.Wrap(err, "could not open file")
269+
}
270+
defer file.Close()
271+
272+
b, err := io.ReadAll(file)
273+
if err != nil {
274+
return []byte{}, errors.Wrap(err, "could not read file")
275+
}
276+
277+
if len(b) == 0 {
278+
if kvs.logger != nil {
279+
kvs.logger.Info("Unable to read empty file", zap.String("fileName", kvs.fileName))
280+
} else {
281+
log.Printf("Unable to read file %s, was empty", kvs.fileName)
282+
}
283+
284+
return []byte{}, ErrStoreEmpty
285+
}
286+
287+
return b, nil
288+
}

store/json_test.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ func TestKeyValuePairsAreWrittenAndReadCorrectly(t *testing.T) {
129129
t.Fatalf("Failed to create KeyValueStore %v\n", err)
130130
}
131131

132+
defer os.Remove(testFileName)
133+
134+
// Dump empty store.
135+
_, err = kvs.Dump()
136+
if err == nil {
137+
t.Fatal("Expected store to be empty")
138+
}
139+
132140
// Write a key value pair.
133141
err = kvs.Write(testKey1, &writtenValue)
134142
if err != nil {
@@ -153,8 +161,17 @@ func TestKeyValuePairsAreWrittenAndReadCorrectly(t *testing.T) {
153161
testKey1, readValue, testKey1, writtenValue)
154162
}
155163

156-
// Cleanup.
157-
os.Remove(testFileName)
164+
// Dump populated store.
165+
val, err := kvs.Dump()
166+
if err != nil {
167+
t.Fatalf("Failed to dump store %v", err)
168+
}
169+
val = strings.ReplaceAll(val, " ", "")
170+
val = strings.ReplaceAll(val, "\t", "")
171+
val = strings.ReplaceAll(val, "\n", "")
172+
if val != `{"key1":{"Field1":"test","Field2":42},"key2":{"Field1":"any","Field2":14}}` {
173+
t.Errorf("Dumped data not expected: %v", val)
174+
}
158175
}
159176

160177
// test case for testing newjsonfilestore idempotent

store/mockstore.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,7 @@ func (ms *mockStore) GetLockFileName() string {
7171
}
7272

7373
func (ms *mockStore) Remove() {}
74+
75+
func (ms *mockStore) Dump() (string, error) {
76+
return fmt.Sprintf("%+v", ms.data), nil
77+
}

store/store.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type KeyValueStore interface {
1818
Unlock() error
1919
GetModificationTime() (time.Time, error)
2020
Remove()
21+
Dump() (string, error)
2122
}
2223

2324
var (

0 commit comments

Comments
 (0)