@@ -115,6 +115,9 @@ pub(crate) struct CrdsDataStats {
115
115
pub ( crate ) struct CrdsStats {
116
116
pub ( crate ) pull : CrdsDataStats ,
117
117
pub ( crate ) push : CrdsDataStats ,
118
+ /// number of times a message was first received via a PullResponse
119
+ /// and that message was later received via a PushMessage
120
+ pub ( crate ) num_redundant_pull_responses : u64 ,
118
121
}
119
122
120
123
/// This structure stores some local metadata associated with the CrdsValue
@@ -127,8 +130,10 @@ pub struct VersionedCrdsValue {
127
130
pub ( crate ) local_timestamp : u64 ,
128
131
/// value hash
129
132
pub ( crate ) value_hash : Hash ,
130
- /// Number of times duplicates of this value are recevied from gossip push.
131
- num_push_dups : u8 ,
133
+ /// None -> value upserted by GossipRoute::{LocalMessage,PullRequest}
134
+ /// Some(0) -> value upserted by GossipRoute::PullResponse
135
+ /// Some(k) if k > 0 -> value upserted by GossipRoute::PushMessage w/ k - 1 push duplicates
136
+ num_push_recv : Option < u8 > ,
132
137
}
133
138
134
139
#[ derive( Clone , Copy , Default ) ]
@@ -147,14 +152,21 @@ impl Cursor {
147
152
}
148
153
149
154
impl VersionedCrdsValue {
150
- fn new ( value : CrdsValue , cursor : Cursor , local_timestamp : u64 ) -> Self {
155
+ fn new ( value : CrdsValue , cursor : Cursor , local_timestamp : u64 , route : GossipRoute ) -> Self {
151
156
let value_hash = hash ( & serialize ( & value) . unwrap ( ) ) ;
157
+ let num_push_recv = match route {
158
+ GossipRoute :: LocalMessage => None ,
159
+ GossipRoute :: PullRequest => None ,
160
+ GossipRoute :: PullResponse => Some ( 0 ) ,
161
+ GossipRoute :: PushMessage ( _) => Some ( 1 ) ,
162
+ } ;
163
+
152
164
VersionedCrdsValue {
153
165
ordinal : cursor. ordinal ( ) ,
154
166
value,
155
167
local_timestamp,
156
168
value_hash,
157
- num_push_dups : 0u8 ,
169
+ num_push_recv ,
158
170
}
159
171
}
160
172
}
@@ -222,7 +234,7 @@ impl Crds {
222
234
) -> Result < ( ) , CrdsError > {
223
235
let label = value. label ( ) ;
224
236
let pubkey = value. pubkey ( ) ;
225
- let value = VersionedCrdsValue :: new ( value, self . cursor , now) ;
237
+ let value = VersionedCrdsValue :: new ( value, self . cursor , now, route ) ;
226
238
match self . table . entry ( label) {
227
239
Entry :: Vacant ( entry) => {
228
240
self . stats . lock ( ) . unwrap ( ) . record_insert ( & value, route) ;
@@ -303,8 +315,12 @@ impl Crds {
303
315
Err ( CrdsError :: InsertFailed )
304
316
} else if matches ! ( route, GossipRoute :: PushMessage ( _) ) {
305
317
let entry = entry. get_mut ( ) ;
306
- entry. num_push_dups = entry. num_push_dups . saturating_add ( 1 ) ;
307
- Err ( CrdsError :: DuplicatePush ( entry. num_push_dups ) )
318
+ if entry. num_push_recv == Some ( 0 ) {
319
+ self . stats . lock ( ) . unwrap ( ) . num_redundant_pull_responses += 1 ;
320
+ }
321
+ let num_push_dups = entry. num_push_recv . unwrap_or_default ( ) ;
322
+ entry. num_push_recv = Some ( num_push_dups. saturating_add ( 1 ) ) ;
323
+ Err ( CrdsError :: DuplicatePush ( num_push_dups) )
308
324
} else {
309
325
Err ( CrdsError :: InsertFailed )
310
326
}
@@ -1450,8 +1466,9 @@ mod tests {
1450
1466
#[ allow( clippy:: neg_cmp_op_on_partial_ord) ]
1451
1467
fn test_equal ( ) {
1452
1468
let val = CrdsValue :: new_unsigned ( CrdsData :: LegacyContactInfo ( ContactInfo :: default ( ) ) ) ;
1453
- let v1 = VersionedCrdsValue :: new ( val. clone ( ) , Cursor :: default ( ) , 1 ) ;
1454
- let v2 = VersionedCrdsValue :: new ( val, Cursor :: default ( ) , 1 ) ;
1469
+ let v1 =
1470
+ VersionedCrdsValue :: new ( val. clone ( ) , Cursor :: default ( ) , 1 , GossipRoute :: LocalMessage ) ;
1471
+ let v2 = VersionedCrdsValue :: new ( val, Cursor :: default ( ) , 1 , GossipRoute :: LocalMessage ) ;
1455
1472
assert_eq ! ( v1, v2) ;
1456
1473
assert ! ( !( v1 != v2) ) ;
1457
1474
assert ! ( !overrides( & v1. value, & v2) ) ;
@@ -1467,6 +1484,7 @@ mod tests {
1467
1484
) ) ) ,
1468
1485
Cursor :: default ( ) ,
1469
1486
1 , // local_timestamp
1487
+ GossipRoute :: LocalMessage ,
1470
1488
) ;
1471
1489
let v2 = VersionedCrdsValue :: new (
1472
1490
{
@@ -1476,6 +1494,7 @@ mod tests {
1476
1494
} ,
1477
1495
Cursor :: default ( ) ,
1478
1496
1 , // local_timestamp
1497
+ GossipRoute :: LocalMessage ,
1479
1498
) ;
1480
1499
1481
1500
assert_eq ! ( v1. value. label( ) , v2. value. label( ) ) ;
@@ -1501,6 +1520,7 @@ mod tests {
1501
1520
) ) ) ,
1502
1521
Cursor :: default ( ) ,
1503
1522
1 , // local_timestamp
1523
+ GossipRoute :: LocalMessage ,
1504
1524
) ;
1505
1525
let v2 = VersionedCrdsValue :: new (
1506
1526
CrdsValue :: new_unsigned ( CrdsData :: LegacyContactInfo ( ContactInfo :: new_localhost (
@@ -1509,6 +1529,7 @@ mod tests {
1509
1529
) ) ) ,
1510
1530
Cursor :: default ( ) ,
1511
1531
1 , // local_timestamp
1532
+ GossipRoute :: LocalMessage ,
1512
1533
) ;
1513
1534
assert_eq ! ( v1. value. label( ) , v2. value. label( ) ) ;
1514
1535
assert ! ( overrides( & v1. value, & v2) ) ;
@@ -1527,6 +1548,7 @@ mod tests {
1527
1548
) ) ) ,
1528
1549
Cursor :: default ( ) ,
1529
1550
1 , // local_timestamp
1551
+ GossipRoute :: LocalMessage ,
1530
1552
) ;
1531
1553
let v2 = VersionedCrdsValue :: new (
1532
1554
CrdsValue :: new_unsigned ( CrdsData :: LegacyContactInfo ( ContactInfo :: new_localhost (
@@ -1535,6 +1557,7 @@ mod tests {
1535
1557
) ) ) ,
1536
1558
Cursor :: default ( ) ,
1537
1559
1 , // local_timestamp
1560
+ GossipRoute :: LocalMessage ,
1538
1561
) ;
1539
1562
assert_ne ! ( v1, v2) ;
1540
1563
assert ! ( !( v1 == v2) ) ;
0 commit comments