/** Send all XLines we know about */ void TreeSocket::SendXLines() { std::vector<std::string> types = ServerInstance->XLines->GetAllTypes(); for (std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it) { /* Expired lines are removed in XLineManager::GetAll() */ XLineLookup* lookup = ServerInstance->XLines->GetAll(*it); /* lookup cannot be NULL in this case but a check won't hurt */ if (lookup) { for (LookupIter i = lookup->begin(); i != lookup->end(); ++i) { /* Is it burstable? this is better than an explicit check for type 'K'. * We break the loop as NONE of the items in this group are worth iterating. */ if (!i->second->IsBurstable()) break; this->WriteLine(CommandAddLine::Builder(i->second)); } } } }
/** Send all XLines we know about */ void TreeSocket::SendXLines() { char data[MAXBUF]; const char* sn = ServerInstance->Config->GetSID().c_str(); std::vector<std::string> types = ServerInstance->XLines->GetAllTypes(); for (std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it) { /* Expired lines are removed in XLineManager::GetAll() */ XLineLookup* lookup = ServerInstance->XLines->GetAll(*it); /* lookup cannot be NULL in this case but a check won't hurt */ if (lookup) { for (LookupIter i = lookup->begin(); i != lookup->end(); ++i) { /* Is it burstable? this is better than an explicit check for type 'K'. * We break the loop as NONE of the items in this group are worth iterating. */ if (!i->second->IsBurstable()) break; snprintf(data,MAXBUF,":%s ADDLINE %s %s %s %lu %lu :%s",sn, it->c_str(), i->second->Displayable(), i->second->source.c_str(), (unsigned long)i->second->set_time, (unsigned long)i->second->duration, i->second->reason.c_str()); this->WriteLine(data); } } } }
/** Send G, Q, Z and E lines */ void TreeSocket::SendXLines(TreeServer* Current) { char data[MAXBUF]; std::string n = this->ServerInstance->Config->GetSID(); const char* sn = n.c_str(); std::vector<std::string> types = ServerInstance->XLines->GetAllTypes(); time_t current = ServerInstance->Time(); for (std::vector<std::string>::iterator it = types.begin(); it != types.end(); ++it) { XLineLookup* lookup = ServerInstance->XLines->GetAll(*it); if (lookup) { for (LookupIter i = lookup->begin(); i != lookup->end(); ++i) { /* Is it burstable? this is better than an explicit check for type 'K'. * We break the loop as NONE of the items in this group are worth iterating. */ if (!i->second->IsBurstable()) break; /* If it's expired, don't bother to burst it */ if (i->second->duration && current > i->second->expiry) continue; snprintf(data,MAXBUF,":%s ADDLINE %s %s %s %lu %lu :%s",sn, it->c_str(), i->second->Displayable(), i->second->source, (unsigned long)i->second->set_time, (unsigned long)i->second->duration, i->second->reason); this->WriteLine(data); } } } }
bool WriteDatabase() { /* * We need to perform an atomic write so as not to f**k things up. * So, let's write to a temporary file, flush it, then rename the file.. * Technically, that means that this can block, but I have *never* seen that. * -- w00t */ ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Opening temporary database"); std::string xlinenewdbpath = xlinedbpath + ".new"; std::ofstream stream(xlinenewdbpath.c_str()); if (!stream.is_open()) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Cannot create database! %s (%d)", strerror(errno), errno); ServerInstance->SNO->WriteToSnoMask('a', "database: cannot create new db: %s (%d)", strerror(errno), errno); return false; } ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Opened. Writing.."); /* * Now, much as I hate writing semi-unportable formats, additional * xline types may not have a conf tag, so let's just write them. * In addition, let's use a file version, so we can maintain some * semblance of backwards compatibility for reading on startup.. * -- w00t */ stream << "VERSION 1" << std::endl; // Now, let's write. std::vector<std::string> types = ServerInstance->XLines->GetAllTypes(); for (std::vector<std::string>::const_iterator it = types.begin(); it != types.end(); ++it) { XLineLookup* lookup = ServerInstance->XLines->GetAll(*it); if (!lookup) continue; // Not possible as we just obtained the list from XLineManager for (LookupIter i = lookup->begin(); i != lookup->end(); ++i) { XLine* line = i->second; stream << "LINE " << line->type << " " << line->Displayable() << " " << ServerInstance->Config->ServerName << " " << line->set_time << " " << line->duration << " " << line->reason << std::endl; } } ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Finished writing XLines. Checking for error.."); if (stream.fail()) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Cannot write to new database! %s (%d)", strerror(errno), errno); ServerInstance->SNO->WriteToSnoMask('a', "database: cannot write to new db: %s (%d)", strerror(errno), errno); return false; } stream.close(); #ifdef _WIN32 if (remove(xlinedbpath.c_str())) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Cannot remove old database! %s (%d)", strerror(errno), errno); ServerInstance->SNO->WriteToSnoMask('a', "database: cannot remove old database: %s (%d)", strerror(errno), errno); return false; } #endif // Use rename to move temporary to new db - this is guarenteed not to f**k up, even in case of a crash. if (rename(xlinenewdbpath.c_str(), xlinedbpath.c_str()) < 0) { ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Cannot move new to old database! %s (%d)", strerror(errno), errno); ServerInstance->SNO->WriteToSnoMask('a', "database: cannot replace old with new db: %s (%d)", strerror(errno), errno); return false; } return true; }