| 205 | } |
| 206 | |
| 207 | void BaseIndex::Sync() |
| 208 | { |
| 209 | const CBlockIndex* pindex = m_best_block_index.load(); |
| 210 | if (!m_synced) { |
| 211 | auto last_log_time{NodeClock::now()}; |
| 212 | auto last_locator_write_time{last_log_time}; |
| 213 | while (true) { |
| 214 | if (m_interrupt) { |
| 215 | LogInfo("%s: m_interrupt set; exiting ThreadSync", GetName()); |
| 216 | |
| 217 | SetBestBlockIndex(pindex); |
| 218 | // No need to handle errors in Commit. If it fails, the error will be already be |
| 219 | // logged. The best way to recover is to continue, as index cannot be corrupted by |
| 220 | // a missed commit to disk for an advanced index state. |
| 221 | Commit(); |
| 222 | return; |
| 223 | } |
| 224 | |
| 225 | const CBlockIndex* pindex_next = WITH_LOCK(cs_main, return NextSyncBlock(pindex, m_chainstate->m_chain)); |
| 226 | // If pindex_next is null, it means pindex is the chain tip, so |
| 227 | // commit data indexed so far. |
| 228 | if (!pindex_next) { |
| 229 | SetBestBlockIndex(pindex); |
| 230 | // No need to handle errors in Commit. See rationale above. |
| 231 | Commit(); |
| 232 | |
| 233 | // If pindex is still the chain tip after committing, exit the |
| 234 | // sync loop. It is important for cs_main to be locked while |
| 235 | // setting m_synced = true, otherwise a new block could be |
| 236 | // attached while m_synced is still false, and it would not be |
| 237 | // indexed. |
| 238 | LOCK(::cs_main); |
| 239 | pindex_next = NextSyncBlock(pindex, m_chainstate->m_chain); |
| 240 | if (!pindex_next) { |
| 241 | m_synced = true; |
| 242 | break; |
| 243 | } |
| 244 | } |
| 245 | if (pindex_next->pprev != pindex && !Rewind(pindex, pindex_next->pprev)) { |
| 246 | FatalErrorf("Failed to rewind %s to a previous chain tip", GetName()); |
| 247 | return; |
| 248 | } |
| 249 | pindex = pindex_next; |
| 250 | |
| 251 | |
| 252 | if (!ProcessBlock(pindex)) return; // error logged internally |
| 253 | |
| 254 | auto current_time{NodeClock::now()}; |
| 255 | if (current_time - last_log_time >= SYNC_LOG_INTERVAL) { |
| 256 | LogInfo("Syncing %s with block chain from height %d", GetName(), pindex->nHeight); |
| 257 | last_log_time = current_time; |
| 258 | } |
| 259 | |
| 260 | if (current_time - last_locator_write_time >= SYNC_LOCATOR_WRITE_INTERVAL) { |
| 261 | SetBestBlockIndex(pindex); |
| 262 | last_locator_write_time = current_time; |
| 263 | // No need to handle errors in Commit. See rationale above. |
| 264 | Commit(); |