From 206c149f48c414255aeee00260a2efecead9a105 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sun, 12 Oct 2014 23:29:56 +0200 Subject: [PATCH 1/3] Scheduling of quiet vs. verbose config saving Rename the current ECONFIG_NEED_WRITE to ECONFIG_NEED_VERBOSE_WRITE as it always broadcasts the result for SIGUSR1, even on success. Keep ECONFIG_NEED_WRITE for cases where the config should be written without a notification of success. --- include/znc/znc.h | 3 ++- src/main.cpp | 2 +- src/znc.cpp | 10 ++++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/znc/znc.h b/include/znc/znc.h index b4f3e8de..be053042 100644 --- a/include/znc/znc.h +++ b/include/znc/znc.h @@ -40,7 +40,8 @@ public: enum ConfigState { ECONFIG_NOTHING, ECONFIG_NEED_REHASH, - ECONFIG_NEED_WRITE + ECONFIG_NEED_WRITE, + ECONFIG_NEED_VERBOSE_WRITE }; void DeleteUsers(); diff --git a/src/main.cpp b/src/main.cpp index 02fcf897..844c8a3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -146,7 +146,7 @@ static void signalHandler(int sig) { break; case SIGUSR1: CUtils::PrintMessage("Caught SIGUSR1"); - CZNC::Get().SetConfigState(CZNC::ECONFIG_NEED_WRITE); + CZNC::Get().SetConfigState(CZNC::ECONFIG_NEED_VERBOSE_WRITE); break; default: CUtils::PrintMessage("WTF? Signal handler called for a signal it doesn't know?"); diff --git a/src/znc.cpp b/src/znc.cpp index 9734c799..fdd36f42 100644 --- a/src/znc.cpp +++ b/src/znc.cpp @@ -184,7 +184,8 @@ void CZNC::Loop() { while (true) { CString sError; - switch (GetConfigState()) { + ConfigState eState = GetConfigState(); + switch (eState) { case ECONFIG_NEED_REHASH: SetConfigState(ECONFIG_NOTHING); @@ -196,12 +197,13 @@ void CZNC::Loop() { } break; case ECONFIG_NEED_WRITE: + case ECONFIG_NEED_VERBOSE_WRITE: SetConfigState(ECONFIG_NOTHING); - if (WriteConfig()) { - Broadcast("Writing the config succeeded", true); - } else { + if (!WriteConfig()) { Broadcast("Writing the config file failed", true); + } else if (eState == ECONFIG_NEED_VERBOSE_WRITE) { + Broadcast("Writing the config succeeded", true); } break; case ECONFIG_NOTHING: From c424bd7acad08677f6f6140010804ef0f66ade05 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sun, 12 Oct 2014 22:13:07 +0200 Subject: [PATCH 2/3] CChan: keep track of the state Make CChan keep track of the channel key, and schedule saving of the config file when appropriate. This is more robust than trying to do it from within the chansaver module. --- include/znc/Chan.h | 4 ++-- src/Chan.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/include/znc/Chan.h b/include/znc/Chan.h index d9f28e15..5fcd3316 100644 --- a/include/znc/Chan.h +++ b/include/znc/Chan.h @@ -110,7 +110,7 @@ public: // Setters void SetModeKnown(bool b) { m_bModeKnown = b; } void SetIsOn(bool b) { m_bIsOn = b; if (!b) { Reset(); } } - void SetKey(const CString& s) { m_sKey = s; } + void SetKey(const CString& s); void SetTopic(const CString& s) { m_sTopic = s; } void SetTopicOwner(const CString& s) { m_sTopicOwner = s; } void SetTopicDate(unsigned long u) { m_ulTopicDate = u; } @@ -118,7 +118,7 @@ public: void SetAutoClearChanBuffer(bool b); void InheritAutoClearChanBuffer(bool b); void SetDetached(bool b = true) { m_bDetached = b; } - void SetInConfig(bool b) { m_bInConfig = b; } + void SetInConfig(bool b); void SetCreationDate(unsigned long u) { m_ulCreationDate = u; } void Disable() { m_bDisabled = true; } void Enable(); diff --git a/src/Chan.cpp b/src/Chan.cpp index 5dea036e..b0e86ac4 100644 --- a/src/Chan.cpp +++ b/src/Chan.cpp @@ -19,6 +19,7 @@ #include #include #include +#include using std::set; using std::vector; @@ -364,6 +365,13 @@ void CChan::ModeChange(const CString& sModes, const CNick* pOpNick) { if (!bList) { (bAdd) ? AddMode(uMode, sArg) : RemMode(uMode); } + + // This is called when we join (ZNC requests the channel modes + // on join) *and* when someone changes the channel keys. + // We ignore channel key "*" because of some broken nets. + if (uMode == 'k' && !bNoChange && bAdd && sArg != "*") { + SetKey(sArg); + } } } } @@ -623,3 +631,21 @@ void CChan::Enable() { ResetJoinTries(); m_bDisabled = false; } + +void CChan::SetKey(const CString& s) { + if (m_sKey != s) { + m_sKey = s; + if (m_bInConfig) { + CZNC::Get().SetConfigState(CZNC::ECONFIG_NEED_WRITE); + } + } +} + +void CChan::SetInConfig(bool b) { + if (m_bInConfig != b) { + m_bInConfig = b; + if (m_bInConfig) { + CZNC::Get().SetConfigState(CZNC::ECONFIG_NEED_WRITE); + } + } +} From 1d19bac8ad46601a9833afd6b93e5af54487063b Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Sat, 11 Oct 2014 17:36:13 +0200 Subject: [PATCH 3/3] Refactor chansaver (#674) CChan now keeps track of the state. The module no longer needs to rely on incoming messages, but can just mark whether each channel should be kept in config or not. Cleanup things and use C++11 for loops while we're at it... --- modules/chansaver.cpp | 66 +++++++++++-------------------------------- 1 file changed, 16 insertions(+), 50 deletions(-) diff --git a/modules/chansaver.cpp b/modules/chansaver.cpp index ffd03f24..d0975aef 100644 --- a/modules/chansaver.cpp +++ b/modules/chansaver.cpp @@ -18,22 +18,18 @@ #include #include -using std::vector; - class CChanSaverMod : public CModule { public: MODCONSTRUCTOR(CChanSaverMod) { - m_bWriteConf = false; - switch (GetType()) { case CModInfo::GlobalModule: LoadUsers(); break; case CModInfo::UserModule: - LoadUser(*GetUser()); + LoadUser(GetUser()); break; case CModInfo::NetworkModule: - LoadNetwork(*GetNetwork()); + LoadNetwork(GetNetwork()); break; } } @@ -42,71 +38,41 @@ public: } void LoadUsers() { - std::map vUsers = CZNC::Get().GetUserMap(); - for (std::map::iterator it = vUsers.begin(); it != vUsers.end(); ++it) { - LoadUser(*it->second); + const std::map& vUsers = CZNC::Get().GetUserMap(); + for (const auto& user : vUsers) { + LoadUser(user.second); } } - void LoadUser(CUser &user) { - vector vNetworks = user.GetNetworks(); - for (vector::iterator it = vNetworks.begin(); it != vNetworks.end(); ++it) { - CIRCNetwork &network = **it; - LoadNetwork(network); + void LoadUser(CUser* pUser) { + const std::vector& vNetworks = pUser->GetNetworks(); + for (const CIRCNetwork* pNetwork : vNetworks) { + LoadNetwork(pNetwork); } } - void LoadNetwork(CIRCNetwork &network) { - const vector& vChans = network.GetChans(); - - for (vector::const_iterator it = vChans.begin(); it != vChans.end(); ++it) { - CChan &chan = **it; - + void LoadNetwork(const CIRCNetwork* pNetwork) { + const std::vector& vChans = pNetwork->GetChans(); + for (CChan* pChan : vChans) { // If that channel isn't yet in the config, // we'll have to add it... - if (!chan.InConfig()) { - chan.SetInConfig(true); - m_bWriteConf = true; + if (!pChan->InConfig()) { + pChan->SetInConfig(true); } } } - virtual EModRet OnRaw(CString& sLine) { - if (m_bWriteConf) { - CZNC::Get().WriteConfig(); - m_bWriteConf = false; - } - - return CONTINUE; - } - - virtual void OnMode2(const CNick* pOpNick, CChan& Channel, char uMode, const CString& sArg, bool bAdded, bool bNoChange) { - // This is called when we join (ZNC requests the channel modes - // on join) *and* when someone changes the channel keys. - // We ignore channel key "*" because of some broken nets. - if (uMode != 'k' || bNoChange || !bAdded || sArg == "*") - return; - - Channel.SetKey(sArg); - m_bWriteConf = true; - } - virtual void OnJoin(const CNick& Nick, CChan& Channel) { - if (Nick.GetNick() == GetNetwork()->GetIRCNick().GetNick() && !Channel.InConfig()) { + if (!Channel.InConfig() && GetNetwork()->GetIRCNick().NickEquals(Nick.GetNick())) { Channel.SetInConfig(true); - CZNC::Get().WriteConfig(); } } virtual void OnPart(const CNick& Nick, CChan& Channel, const CString& sMessage) { - if (Nick.GetNick() == GetNetwork()->GetIRCNick().GetNick() && Channel.InConfig()) { + if (Channel.InConfig() && GetNetwork()->GetIRCNick().NickEquals(Nick.GetNick())) { Channel.SetInConfig(false); - CZNC::Get().WriteConfig(); } } - -private: - bool m_bWriteConf; }; template<> void TModInfo(CModInfo& Info) {