@@ -18,6 +18,7 @@ package rawdb
18
18
19
19
import (
20
20
"encoding/json"
21
+ "time"
21
22
22
23
"github.com/ethereum/go-ethereum/common"
23
24
"github.com/ethereum/go-ethereum/ethdb"
@@ -30,7 +31,7 @@ import (
30
31
func ReadDatabaseVersion (db ethdb.KeyValueReader ) * uint64 {
31
32
var version uint64
32
33
33
- enc , _ := db .Get (databaseVerisionKey )
34
+ enc , _ := db .Get (databaseVersionKey )
34
35
if len (enc ) == 0 {
35
36
return nil
36
37
}
@@ -47,7 +48,7 @@ func WriteDatabaseVersion(db ethdb.KeyValueWriter, version uint64) {
47
48
if err != nil {
48
49
log .Crit ("Failed to encode database version" , "err" , err )
49
50
}
50
- if err = db .Put (databaseVerisionKey , enc ); err != nil {
51
+ if err = db .Put (databaseVersionKey , enc ); err != nil {
51
52
log .Crit ("Failed to store the database version" , "err" , err )
52
53
}
53
54
}
@@ -79,3 +80,61 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha
79
80
log .Crit ("Failed to store chain config" , "err" , err )
80
81
}
81
82
}
83
+
84
+ // crashList is a list of unclean-shutdown-markers, for rlp-encoding to the
85
+ // database
86
+ type crashList struct {
87
+ Discarded uint64 // how many ucs have we deleted
88
+ Recent []uint64 // unix timestamps of 10 latest unclean shutdowns
89
+ }
90
+
91
+ const crashesToKeep = 10
92
+
93
+ // PushUncleanShutdownMarker appends a new unclean shutdown marker and returns
94
+ // the previous data
95
+ // - a list of timestamps
96
+ // - a count of how many old unclean-shutdowns have been discarded
97
+ func PushUncleanShutdownMarker (db ethdb.KeyValueStore ) ([]uint64 , uint64 , error ) {
98
+ var uncleanShutdowns crashList
99
+ // Read old data
100
+ if data , err := db .Get (uncleanShutdownKey ); err != nil {
101
+ log .Warn ("Error reading unclean shutdown markers" , "error" , err )
102
+ } else if err := rlp .DecodeBytes (data , & uncleanShutdowns ); err != nil {
103
+ return nil , 0 , err
104
+ }
105
+ var discarded = uncleanShutdowns .Discarded
106
+ var previous = make ([]uint64 , len (uncleanShutdowns .Recent ))
107
+ copy (previous , uncleanShutdowns .Recent )
108
+ // Add a new (but cap it)
109
+ uncleanShutdowns .Recent = append (uncleanShutdowns .Recent , uint64 (time .Now ().Unix ()))
110
+ if count := len (uncleanShutdowns .Recent ); count > crashesToKeep + 1 {
111
+ numDel := count - (crashesToKeep + 1 )
112
+ uncleanShutdowns .Recent = uncleanShutdowns .Recent [numDel :]
113
+ uncleanShutdowns .Discarded += uint64 (numDel )
114
+ }
115
+ // And save it again
116
+ data , _ := rlp .EncodeToBytes (uncleanShutdowns )
117
+ if err := db .Put (uncleanShutdownKey , data ); err != nil {
118
+ log .Warn ("Failed to write unclean-shutdown marker" , "err" , err )
119
+ return nil , 0 , err
120
+ }
121
+ return previous , discarded , nil
122
+ }
123
+
124
+ // PopUncleanShutdownMarker removes the last unclean shutdown marker
125
+ func PopUncleanShutdownMarker (db ethdb.KeyValueStore ) {
126
+ var uncleanShutdowns crashList
127
+ // Read old data
128
+ if data , err := db .Get (uncleanShutdownKey ); err != nil {
129
+ log .Warn ("Error reading unclean shutdown markers" , "error" , err )
130
+ } else if err := rlp .DecodeBytes (data , & uncleanShutdowns ); err != nil {
131
+ log .Error ("Error decoding unclean shutdown markers" , "error" , err ) // Should mos def _not_ happen
132
+ }
133
+ if l := len (uncleanShutdowns .Recent ); l > 0 {
134
+ uncleanShutdowns .Recent = uncleanShutdowns .Recent [:l - 1 ]
135
+ }
136
+ data , _ := rlp .EncodeToBytes (uncleanShutdowns )
137
+ if err := db .Put (uncleanShutdownKey , data ); err != nil {
138
+ log .Warn ("Failed to clear unclean-shutdown marker" , "err" , err )
139
+ }
140
+ }
0 commit comments