@@ -1157,13 +1157,84 @@ func (c *ChannelGraph) addChannelEdge(tx kvdb.RwTx,
1157
1157
return chanIndex .Put (b .Bytes (), chanKey [:])
1158
1158
}
1159
1159
1160
- // HasChannelEdge returns true if the database knows of a channel edge with the
1160
+ func (c * ChannelGraph ) HasChannelEdge (chanID uint64 ) (bool , bool , error ) {
1161
+ var (
1162
+ exists bool
1163
+ isZombie bool
1164
+ )
1165
+
1166
+ // We'll query the cache with the shared lock held to allow multiple
1167
+ // readers to access values in the cache concurrently if they exist.
1168
+ c .cacheMu .RLock ()
1169
+ if entry , ok := c .rejectCache .get (chanID ); ok {
1170
+ c .cacheMu .RUnlock ()
1171
+ exists , isZombie = entry .flags .unpack ()
1172
+
1173
+ return exists , isZombie , nil
1174
+ }
1175
+ c .cacheMu .RUnlock ()
1176
+
1177
+ c .cacheMu .Lock ()
1178
+ defer c .cacheMu .Unlock ()
1179
+
1180
+ // The item was not found with the shared lock, so we'll acquire the
1181
+ // exclusive lock and check the cache again in case another method added
1182
+ // the entry to the cache while no lock was held.
1183
+ if entry , ok := c .rejectCache .get (chanID ); ok && entry .times != nil {
1184
+ exists , isZombie = entry .flags .unpack ()
1185
+
1186
+ return exists , isZombie , nil
1187
+ }
1188
+
1189
+ if err := kvdb .View (c .db , func (tx kvdb.RTx ) error {
1190
+ edges := tx .ReadBucket (edgeBucket )
1191
+ if edges == nil {
1192
+ return ErrGraphNoEdgesFound
1193
+ }
1194
+ edgeIndex := edges .NestedReadBucket (edgeIndexBucket )
1195
+ if edgeIndex == nil {
1196
+ return ErrGraphNoEdgesFound
1197
+ }
1198
+
1199
+ var channelID [8 ]byte
1200
+ byteOrder .PutUint64 (channelID [:], chanID )
1201
+
1202
+ // If the edge doesn't exist, then we'll also check our zombie
1203
+ // index.
1204
+ if edgeIndex .Get (channelID [:]) == nil {
1205
+ exists = false
1206
+ zombieIndex := edges .NestedReadBucket (zombieBucket )
1207
+ if zombieIndex != nil {
1208
+ isZombie , _ , _ = isZombieEdge (
1209
+ zombieIndex , chanID ,
1210
+ )
1211
+ }
1212
+
1213
+ return nil
1214
+ }
1215
+
1216
+ exists = true
1217
+ isZombie = false
1218
+
1219
+ return nil
1220
+ }, func () {}); err != nil {
1221
+ return exists , isZombie , err
1222
+ }
1223
+
1224
+ c .rejectCache .insert (chanID , rejectCacheEntry {
1225
+ flags : packRejectFlags (exists , isZombie ),
1226
+ })
1227
+
1228
+ return exists , isZombie , nil
1229
+ }
1230
+
1231
+ // HasChannelEdge1 returns true if the database knows of a channel edge with the
1161
1232
// passed channel ID, and false otherwise. If an edge with that ID is found
1162
1233
// within the graph, then two time stamps representing the last time the edge
1163
1234
// was updated for both directed edges are returned along with the boolean. If
1164
1235
// it is not found, then the zombie index is checked and its result is returned
1165
1236
// as the second boolean.
1166
- func (c * ChannelGraph ) HasChannelEdge (
1237
+ func (c * ChannelGraph ) HasChannelEdge1 (
1167
1238
chanID uint64 ) (time.Time , time.Time , bool , bool , error ) {
1168
1239
1169
1240
var (
@@ -1279,6 +1350,122 @@ func (c *ChannelGraph) HasChannelEdge(
1279
1350
return upd1Time , upd2Time , exists , isZombie , nil
1280
1351
}
1281
1352
1353
+ func (c * ChannelGraph ) HasChannelEdge2 (
1354
+ chanID uint64 ) (uint32 , uint32 , bool , bool , error ) {
1355
+
1356
+ var (
1357
+ upd1Height uint32
1358
+ upd2Height uint32
1359
+ exists bool
1360
+ isZombie bool
1361
+ )
1362
+
1363
+ // We'll query the cache with the shared lock held to allow multiple
1364
+ // readers to access values in the cache concurrently if they exist.
1365
+ c .cacheMu .RLock ()
1366
+ if entry , ok := c .rejectCache .get (chanID ); ok && entry .blocks != nil {
1367
+ c .cacheMu .RUnlock ()
1368
+ exists , isZombie = entry .flags .unpack ()
1369
+
1370
+ return entry .blocks .updBlock1 , entry .blocks .updBlock2 , exists ,
1371
+ isZombie , nil
1372
+ }
1373
+ c .cacheMu .RUnlock ()
1374
+
1375
+ c .cacheMu .Lock ()
1376
+ defer c .cacheMu .Unlock ()
1377
+
1378
+ // The item was not found with the shared lock, so we'll acquire the
1379
+ // exclusive lock and check the cache again in case another method added
1380
+ // the entry to the cache while no lock was held.
1381
+ if entry , ok := c .rejectCache .get (chanID ); ok && entry .blocks != nil {
1382
+ exists , isZombie = entry .flags .unpack ()
1383
+
1384
+ return entry .blocks .updBlock1 , entry .blocks .updBlock2 , exists ,
1385
+ isZombie , nil
1386
+ }
1387
+
1388
+ if err := kvdb .View (c .db , func (tx kvdb.RTx ) error {
1389
+ edges := tx .ReadBucket (edgeBucket )
1390
+ if edges == nil {
1391
+ return ErrGraphNoEdgesFound
1392
+ }
1393
+ edgeIndex := edges .NestedReadBucket (edgeIndexBucket )
1394
+ if edgeIndex == nil {
1395
+ return ErrGraphNoEdgesFound
1396
+ }
1397
+
1398
+ var channelID [8 ]byte
1399
+ byteOrder .PutUint64 (channelID [:], chanID )
1400
+
1401
+ // If the edge doesn't exist, then we'll also check our zombie
1402
+ // index.
1403
+ if edgeIndex .Get (channelID [:]) == nil {
1404
+ exists = false
1405
+ zombieIndex := edges .NestedReadBucket (zombieBucket )
1406
+ if zombieIndex != nil {
1407
+ isZombie , _ , _ = isZombieEdge (
1408
+ zombieIndex , chanID ,
1409
+ )
1410
+ }
1411
+
1412
+ return nil
1413
+ }
1414
+
1415
+ exists = true
1416
+ isZombie = false
1417
+
1418
+ // If the channel has been found in the graph, then retrieve
1419
+ // the edges itself so we can return the last updated
1420
+ // timestamps.
1421
+ nodes := tx .ReadBucket (nodeBucket )
1422
+ if nodes == nil {
1423
+ return ErrGraphNodeNotFound
1424
+ }
1425
+
1426
+ edge1 , edge2 , err := fetchChanEdgePolicies (
1427
+ edgeIndex , edges , channelID [:],
1428
+ )
1429
+ if err != nil {
1430
+ return err
1431
+ }
1432
+
1433
+ // As we may have only one of the edges populated, only set the
1434
+ // update time if the edge was found in the database.
1435
+ if edge1 != nil {
1436
+ e1 , ok := edge1 .(* models.ChannelEdgePolicy2 )
1437
+ if ! ok {
1438
+ return fmt .Errorf ("expected " +
1439
+ "*ChannelEdgePolicy2, got: %T" , edge1 )
1440
+ }
1441
+ upd1Height = e1 .BlockHeight .Val
1442
+ }
1443
+ if edge2 != nil {
1444
+ e2 , ok := edge2 .(* models.ChannelEdgePolicy2 )
1445
+ if ! ok {
1446
+ return fmt .Errorf ("expected " +
1447
+ "*ChannelEdgePolicy2, got: %T" , edge2 )
1448
+ }
1449
+
1450
+ upd2Height = e2 .BlockHeight .Val
1451
+ }
1452
+
1453
+ return nil
1454
+ }, func () {}); err != nil {
1455
+ return 0 , 0 , exists , isZombie , err
1456
+ }
1457
+
1458
+ c .rejectCache .insert (chanID , rejectCacheEntry {
1459
+ blocks : & updateBlocks {
1460
+ updBlock1 : upd1Height ,
1461
+ updBlock2 : upd2Height ,
1462
+ },
1463
+ flags : packRejectFlags (exists , isZombie ),
1464
+ })
1465
+
1466
+ return upd1Height , upd2Height , exists , isZombie , nil
1467
+ }
1468
+
1282
1469
// UpdateChannelEdge retrieves and update edge of the graph database. Method
1283
1470
// only reserved for updating an edge info after its already been created.
1284
1471
// In order to maintain this constraints, we return an error in the scenario
0 commit comments