* Rewrite the on-disk gossip store, compacting it along the way * * Creates a new file, writes all the updates from the `broadcast_state`, and * then atomically swaps the files. */
| 419 | * then atomically swaps the files. |
| 420 | */ |
| 421 | bool gossip_store_compact(struct gossip_store *gs) |
| 422 | { |
| 423 | size_t count = 0, deleted = 0; |
| 424 | int fd; |
| 425 | u64 off, len = sizeof(gs->version), idx; |
| 426 | struct offmap *offmap; |
| 427 | struct gossip_hdr hdr; |
| 428 | struct offmap_iter oit; |
| 429 | struct node_map_iter nit; |
| 430 | struct offset_map *omap; |
| 431 | |
| 432 | if (gs->disable_compaction) |
| 433 | return false; |
| 434 | |
| 435 | status_debug( |
| 436 | "Compacting gossip_store with %zu entries, %zu of which are stale", |
| 437 | gs->count, gs->deleted); |
| 438 | |
| 439 | fd = open(GOSSIP_STORE_TEMP_FILENAME, O_RDWR|O_TRUNC|O_CREAT, 0600); |
| 440 | |
| 441 | if (fd < 0) { |
| 442 | status_broken( |
| 443 | "Could not open file for gossip_store compaction"); |
| 444 | goto disable; |
| 445 | } |
| 446 | |
| 447 | if (write(fd, &gs->version, sizeof(gs->version)) |
| 448 | != sizeof(gs->version)) { |
| 449 | status_broken("Writing version to store: %s", strerror(errno)); |
| 450 | goto unlink_disable; |
| 451 | } |
| 452 | |
| 453 | /* Walk old file, copy everything and remember new offsets. */ |
| 454 | offmap = tal(tmpctx, struct offmap); |
| 455 | offmap_init_sized(offmap, gs->count); |
| 456 | tal_add_destructor(offmap, destroy_offmap); |
| 457 | |
| 458 | /* Start by writing all channel announcements and updates. */ |
| 459 | off = 1; |
| 460 | while (pread(gs->fd, &hdr, sizeof(hdr), off) == sizeof(hdr)) { |
| 461 | u32 msglen, wlen; |
| 462 | int msgtype; |
| 463 | |
| 464 | msglen = (be32_to_cpu(hdr.len) & GOSSIP_STORE_LEN_MASK); |
| 465 | if (be32_to_cpu(hdr.len) & GOSSIP_STORE_LEN_DELETED_BIT) { |
| 466 | off += sizeof(hdr) + msglen; |
| 467 | deleted++; |
| 468 | continue; |
| 469 | } |
| 470 | |
| 471 | count++; |
| 472 | wlen = transfer_store_msg(gs->fd, off, fd, len, &msgtype); |
| 473 | if (wlen == 0) |
| 474 | goto unlink_disable; |
| 475 | |
| 476 | /* We track location of all these message types. */ |
| 477 | if (msgtype == WIRE_GOSSIP_STORE_PRIVATE_CHANNEL |
| 478 | || msgtype == WIRE_GOSSIP_STORE_PRIVATE_UPDATE |
no test coverage detected