1414// You should have received a copy of the GNU Affero General Public License
1515// along with this program. If not, see <https://www.gnu.org/licenses/>.
1616
17- use std:: sync:: atomic:: { AtomicUsize , Ordering as AtomicOrdering } ;
17+ use std:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering as AtomicOrdering } ;
1818use std:: sync:: { Arc , Weak } ;
19- use std:: time:: Instant ;
19+ use std:: time:: { Duration , Instant } ;
2020
2121use cio:: IoChannel ;
2222use ckey:: { Address , PlatformAddress , Public } ;
@@ -25,6 +25,7 @@ use cnetwork::NodeId;
2525use cstate:: {
2626 ActionHandler , AssetScheme , AssetSchemeAddress , OwnedAsset , OwnedAssetAddress , StateDB , TopLevelState , TopStateView ,
2727} ;
28+ use ctimer:: { TimeoutHandler , TimerApi , TimerToken } ;
2829use ctypes:: invoice:: Invoice ;
2930use ctypes:: transaction:: Transaction ;
3031use ctypes:: { BlockNumber , ShardId } ;
@@ -41,7 +42,8 @@ use super::{
4142 AccountData , AssetClient , Balance , BlockChain as BlockChainTrait , BlockChainClient , BlockChainInfo , BlockInfo ,
4243 BlockProducer , ChainInfo , ChainNotify , ClientConfig , DatabaseClient , EngineClient , EngineInfo ,
4344 Error as ClientError , ExecuteClient , ImportBlock , ImportResult , ImportSealedBlock , MiningBlockChainClient ,
44- ParcelInfo , PrepareOpenBlock , RegularKey , RegularKeyOwner , ReopenBlock , Seq , Shard , StateOrBlock , TransactionInfo ,
45+ ParcelInfo , PrepareOpenBlock , RegularKey , RegularKeyOwner , ReopenBlock , ResealTimer , Seq , Shard , StateOrBlock ,
46+ TransactionInfo ,
4547} ;
4648use crate :: block:: { ClosedBlock , IsBlock , OpenBlock , SealedBlock } ;
4749use crate :: blockchain:: {
@@ -79,6 +81,10 @@ pub struct Client {
7981 genesis_accounts : Vec < Address > ,
8082
8183 importer : Importer ,
84+
85+ reseal_timer : RwLock < Option < TimerApi > > ,
86+
87+ timer_set : AtomicBool ,
8288}
8389
8490impl Client {
@@ -121,13 +127,19 @@ impl Client {
121127 queue_parcels : AtomicUsize :: new ( 0 ) ,
122128 genesis_accounts,
123129 importer,
130+ reseal_timer : RwLock :: new ( None ) ,
131+ timer_set : AtomicBool :: new ( false ) ,
124132 } ) ;
125133
126134 // ensure buffered changes are flushed.
127135 client. db . read ( ) . flush ( ) . map_err ( ClientError :: Database ) ?;
128136 Ok ( client)
129137 }
130138
139+ pub fn register_reseal_timer ( & self , timer : TimerApi ) {
140+ self . register_timer ( timer) ;
141+ }
142+
131143 /// Returns engine reference.
132144 pub fn engine ( & self ) -> & CodeChainEngine {
133145 & * self . engine
@@ -260,6 +272,40 @@ impl Client {
260272 }
261273}
262274
275+ const RESEAL_TIMER_TOKEN : TimerToken = 0 ;
276+
277+ impl TimeoutHandler for Client {
278+ fn on_timeout ( & self , token : TimerToken ) {
279+ match token {
280+ RESEAL_TIMER_TOKEN => {
281+ self . timer_set . store ( false , AtomicOrdering :: Relaxed ) ;
282+ if !self . ready_parcels ( ) . is_empty ( ) {
283+ self . update_sealing ( ) ;
284+ }
285+ }
286+ _ => unreachable ! ( ) ,
287+ }
288+ }
289+ }
290+
291+ impl ResealTimer for Client {
292+ fn register_timer ( & self , timer : TimerApi ) {
293+ * self . reseal_timer . write ( ) = Some ( timer) ;
294+ }
295+
296+ fn set_timer ( & self , duration : Duration ) {
297+ if let Some ( reseal_timer) = self . reseal_timer . read ( ) . as_ref ( ) {
298+ reseal_timer. cancel ( RESEAL_TIMER_TOKEN ) . expect ( "Timer clear succeeds" ) ;
299+ reseal_timer. schedule_once ( duration, RESEAL_TIMER_TOKEN ) . expect ( "Timer set succeeds" ) ;
300+ self . timer_set . store ( true , AtomicOrdering :: Relaxed ) ;
301+ } ;
302+ }
303+
304+ fn is_timer_set ( & self ) -> bool {
305+ self . timer_set . load ( AtomicOrdering :: Relaxed )
306+ }
307+ }
308+
263309impl DatabaseClient for Client {
264310 fn database ( & self ) -> Arc < KeyValueDB > {
265311 Arc :: clone ( & self . db ( ) )
0 commit comments