@@ -77,12 +77,95 @@ static bool append_msg(int fd, const u8 *msg, u32 timestamp, u64 *len)
7777 return writev (fd , iov , ARRAY_SIZE (iov )) == sizeof (hdr ) + msglen ;
7878}
7979
80+ /* Read gossip store entries, copy non-deleted ones. This code is written
81+ * as simply and robustly as possible! */
82+ static void gossip_store_compact_offline (void )
83+ {
84+ size_t count = 0 , deleted = 0 ;
85+ int old_fd , new_fd ;
86+ struct gossip_hdr hdr ;
87+ u8 version ;
88+
89+ old_fd = open (GOSSIP_STORE_FILENAME , O_RDONLY );
90+ if (old_fd == -1 )
91+ return ;
92+ new_fd = open (GOSSIP_STORE_TEMP_FILENAME , O_RDWR |O_TRUNC |O_CREAT , 0600 );
93+ if (new_fd < 0 ) {
94+ status_broken (
95+ "Could not open file for gossip_store compaction" );
96+ goto close_old ;
97+ }
98+
99+ if (!read_all (old_fd , & version , sizeof (version ))
100+ || version != GOSSIP_STORE_VERSION ) {
101+ status_broken ("gossip_store_compact: bad version" );
102+ goto close_and_delete ;
103+ }
104+
105+ if (!write_all (new_fd , & version , sizeof (version ))) {
106+ status_broken ("gossip_store_compact_offline: writing version to store: %s" ,
107+ strerror (errno ));
108+ goto close_and_delete ;
109+ }
110+
111+ /* Read everything, write non-deleted ones to new_fd */
112+ while (read_all (old_fd , & hdr , sizeof (hdr ))) {
113+ size_t msglen ;
114+ u8 * msg ;
115+
116+ msglen = (be32_to_cpu (hdr .len ) & ~GOSSIP_STORE_LEN_DELETED_BIT );
117+ msg = tal_arr (NULL , u8 , msglen );
118+ if (!read_all (old_fd , msg , msglen )) {
119+ status_broken ("gossip_store_compact_offline: reading msg len %zu from store: %s" ,
120+ msglen , strerror (errno ));
121+ tal_free (msg );
122+ goto close_and_delete ;
123+ }
124+
125+ if (be32_to_cpu (hdr .len ) & GOSSIP_STORE_LEN_DELETED_BIT ) {
126+ deleted ++ ;
127+ tal_free (msg );
128+ continue ;
129+ }
130+
131+ if (!write_all (new_fd , & hdr , sizeof (hdr ))
132+ || !write_all (new_fd , msg , msglen )) {
133+ status_broken ("gossip_store_compact_offline: writing msg len %zu to new store: %s" ,
134+ msglen , strerror (errno ));
135+ tal_free (msg );
136+ goto close_and_delete ;
137+ }
138+ tal_free (msg );
139+ count ++ ;
140+ }
141+ if (close (new_fd ) != 0 ) {
142+ status_broken ("gossip_store_compact_offline: closing new store: %s" ,
143+ strerror (errno ));
144+ goto close_old ;
145+ }
146+ close (old_fd );
147+ if (rename (GOSSIP_STORE_TEMP_FILENAME , GOSSIP_STORE_FILENAME ) != 0 ) {
148+ status_broken ("gossip_store_compact_offline: rename failed: %s" ,
149+ strerror (errno ));
150+ }
151+ status_debug ("gossip_store_compact_offline: %zu deleted, %zu copied" ,
152+ deleted , count );
153+ return ;
154+
155+ close_and_delete :
156+ close (new_fd );
157+ close_old :
158+ close (old_fd );
159+ unlink (GOSSIP_STORE_TEMP_FILENAME );
160+ }
161+
80162struct gossip_store * gossip_store_new (struct routing_state * rstate ,
81163 struct list_head * peers )
82164{
83165 struct gossip_store * gs = tal (rstate , struct gossip_store );
84166 gs -> count = gs -> deleted = 0 ;
85167 gs -> writable = true;
168+ gossip_store_compact_offline ();
86169 gs -> fd = open (GOSSIP_STORE_FILENAME , O_RDWR |O_APPEND |O_CREAT , 0600 );
87170 gs -> rstate = rstate ;
88171 gs -> disable_compaction = false;
@@ -352,19 +435,6 @@ bool gossip_store_compact(struct gossip_store *gs)
352435 return false;
353436}
354437
355- static void gossip_store_maybe_compact (struct gossip_store * gs )
356- {
357- /* Don't compact while loading! */
358- if (!gs -> writable )
359- return ;
360- if (gs -> count < 1000 )
361- return ;
362- if (gs -> deleted < gs -> count / 4 )
363- return ;
364-
365- gossip_store_compact (gs );
366- }
367-
368438u64 gossip_store_add (struct gossip_store * gs , const u8 * gossip_msg ,
369439 u32 timestamp ,
370440 const u8 * addendum )
@@ -460,8 +530,6 @@ void gossip_store_delete(struct gossip_store *gs,
460530 if (type == WIRE_CHANNEL_ANNOUNCEMENT )
461531 delete_by_index (gs , next_index ,
462532 WIRE_GOSSIP_STORE_CHANNEL_AMOUNT );
463-
464- gossip_store_maybe_compact (gs );
465533}
466534
467535const u8 * gossip_store_get (const tal_t * ctx ,
0 commit comments