| 339 | } |
| 340 | |
| 341 | void Manager::bgWriter() |
| 342 | { |
| 343 | try |
| 344 | { |
| 345 | // Signal about our startup |
| 346 | |
| 347 | m_startupSemaphore.release(); |
| 348 | |
| 349 | // Loop to replicate queued changes |
| 350 | |
| 351 | while (!m_shutdown) |
| 352 | { |
| 353 | MutexLockGuard guard(m_queueMutex, FB_FUNCTION); |
| 354 | |
| 355 | for (auto& buffer : m_queue) |
| 356 | { |
| 357 | if (buffer) |
| 358 | { |
| 359 | const auto length = (ULONG) buffer->getCount(); |
| 360 | fb_assert(length); |
| 361 | |
| 362 | if (m_changeLog) |
| 363 | m_changeLog->write(length, buffer->begin(), false); |
| 364 | |
| 365 | for (auto iter : m_replicas) |
| 366 | { |
| 367 | if (iter->status.isSuccess()) |
| 368 | iter->replicator->process(&iter->status, length, buffer->begin()); |
| 369 | } |
| 370 | |
| 371 | m_queueSize -= length; |
| 372 | releaseBuffer(buffer); |
| 373 | buffer = nullptr; |
| 374 | } |
| 375 | } |
| 376 | |
| 377 | guard.release(); |
| 378 | |
| 379 | if (m_shutdown) |
| 380 | break; |
| 381 | |
| 382 | m_signalled = false; |
| 383 | m_workingSemaphore.tryEnter(1); |
| 384 | } |
| 385 | } |
| 386 | catch (const Exception& ex) |
| 387 | { |
| 388 | iscLogException("Error in replicator thread", ex); |
| 389 | } |
| 390 | |
| 391 | // Signal about our exit |
| 392 | |
| 393 | try |
| 394 | { |
| 395 | m_cleanupSemaphore.release(); |
| 396 | } |
| 397 | catch (const Firebird::Exception& ex) |
| 398 | { |
no test coverage detected