void ApiListener::SendConfigUpdate(const JsonRpcConnection::Ptr& aclient) { Endpoint::Ptr endpoint = aclient->GetEndpoint(); ASSERT(endpoint); Zone::Ptr azone = endpoint->GetZone(); Zone::Ptr lzone = Zone::GetLocalZone(); /* don't try to send config updates to our master */ if (!azone->IsChildOf(lzone)) return; Dictionary::Ptr configUpdateV1 = new Dictionary(); Dictionary::Ptr configUpdateV2 = new Dictionary(); String zonesDir = Configuration::DataDir + "/api/zones"; for (const Zone::Ptr& zone : ConfigType::GetObjectsByType<Zone>()) { String zoneDir = zonesDir + "/" + zone->GetName(); if (!zone->IsChildOf(azone) && !zone->IsGlobal()) continue; if (!Utility::PathExists(zoneDir)) continue; Log(LogInformation, "ApiListener") << "Syncing configuration files for " << (zone->IsGlobal() ? "global " : "") << "zone '" << zone->GetName() << "' to endpoint '" << endpoint->GetName() << "'."; ConfigDirInformation config = LoadConfigDir(zonesDir + "/" + zone->GetName()); configUpdateV1->Set(zone->GetName(), config.UpdateV1); configUpdateV2->Set(zone->GetName(), config.UpdateV2); } Dictionary::Ptr message = new Dictionary({ { "jsonrpc", "2.0" }, { "method", "config::Update" }, { "params", new Dictionary({ { "update", configUpdateV1 }, { "update_v2", configUpdateV2 } }) } }); aclient->SendMessage(message); }
void ApiListener::ReplayLog(const JsonRpcConnection::Ptr& client) { Endpoint::Ptr endpoint = client->GetEndpoint(); if (endpoint->GetLogDuration() == 0) { ObjectLock olock2(endpoint); endpoint->SetSyncing(false); return; } CONTEXT("Replaying log for Endpoint '" + endpoint->GetName() + "'"); int count = -1; double peer_ts = endpoint->GetLocalLogPosition(); double logpos_ts = peer_ts; bool last_sync = false; Endpoint::Ptr target_endpoint = client->GetEndpoint(); ASSERT(target_endpoint); Zone::Ptr target_zone = target_endpoint->GetZone(); if (!target_zone) { ObjectLock olock2(endpoint); endpoint->SetSyncing(false); return; } for (;;) { boost::mutex::scoped_lock lock(m_LogLock); CloseLogFile(); RotateLogFile(); if (count == -1 || count > 50000) { OpenLogFile(); lock.unlock(); } else { last_sync = true; } count = 0; std::vector<int> files; Utility::Glob(GetApiDir() + "log/*", boost::bind(&ApiListener::LogGlobHandler, boost::ref(files), _1), GlobFile); std::sort(files.begin(), files.end()); for (int ts : files) { String path = GetApiDir() + "log/" + Convert::ToString(ts); if (ts < peer_ts) continue; Log(LogNotice, "ApiListener") << "Replaying log: " << path; std::fstream *fp = new std::fstream(path.CStr(), std::fstream::in | std::fstream::binary); StdioStream::Ptr logStream = new StdioStream(fp, true); String message; StreamReadContext src; while (true) { Dictionary::Ptr pmessage; try { StreamReadStatus srs = NetString::ReadStringFromStream(logStream, &message, src); if (srs == StatusEof) break; if (srs != StatusNewItem) continue; pmessage = JsonDecode(message); } catch (const std::exception&) { Log(LogWarning, "ApiListener") << "Unexpected end-of-file for cluster log: " << path; /* Log files may be incomplete or corrupted. This is perfectly OK. */ break; } if (pmessage->Get("timestamp") <= peer_ts) continue; Dictionary::Ptr secname = pmessage->Get("secobj"); if (secname) { ConfigObject::Ptr secobj = ConfigObject::GetObject(secname->Get("type"), secname->Get("name")); if (!secobj) continue; if (!target_zone->CanAccessObject(secobj)) continue; } try { NetString::WriteStringToStream(client->GetStream(), pmessage->Get("message")); count++; } catch (const std::exception& ex) { Log(LogWarning, "ApiListener") << "Error while replaying log for endpoint '" << endpoint->GetName() << "': " << DiagnosticInformation(ex); break; } peer_ts = pmessage->Get("timestamp"); if (ts > logpos_ts + 10) { logpos_ts = ts; Dictionary::Ptr lparams = new Dictionary(); lparams->Set("log_position", logpos_ts); Dictionary::Ptr lmessage = new Dictionary(); lmessage->Set("jsonrpc", "2.0"); lmessage->Set("method", "log::SetLogPosition"); lmessage->Set("params", lparams); JsonRpc::SendMessage(client->GetStream(), lmessage); } } logStream->Close(); } if (count > 0) { Log(LogInformation, "ApiListener") << "Replayed " << count << " messages."; } Log(LogNotice, "ApiListener") << "Replayed " << count << " messages."; if (last_sync) { { ObjectLock olock2(endpoint); endpoint->SetSyncing(false); } OpenLogFile(); break; } } }