@@ -18,6 +18,7 @@ package rawdb
1818
1919import (
2020 "encoding/json"
21+ "time"
2122
2223 "github.com/ethereum/go-ethereum/common"
2324 "github.com/ethereum/go-ethereum/ethdb"
@@ -30,7 +31,7 @@ import (
3031func ReadDatabaseVersion (db ethdb.KeyValueReader ) * uint64 {
3132 var version uint64
3233
33- enc , _ := db .Get (databaseVerisionKey )
34+ enc , _ := db .Get (databaseVersionKey )
3435 if len (enc ) == 0 {
3536 return nil
3637 }
@@ -47,7 +48,7 @@ func WriteDatabaseVersion(db ethdb.KeyValueWriter, version uint64) {
4748 if err != nil {
4849 log .Crit ("Failed to encode database version" , "err" , err )
4950 }
50- if err = db .Put (databaseVerisionKey , enc ); err != nil {
51+ if err = db .Put (databaseVersionKey , enc ); err != nil {
5152 log .Crit ("Failed to store the database version" , "err" , err )
5253 }
5354}
@@ -79,3 +80,61 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha
7980 log .Crit ("Failed to store chain config" , "err" , err )
8081 }
8182}
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