Raven Core  3.0.0
P2P Digital Currency
messagedb.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018 The Raven Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 #include "validation.h"
5 #include "messagedb.h"
6 #include "messages.h"
7 #include <boost/thread.hpp>
8 
9 static const char MESSAGE_FLAG = 'Z'; // Message
10 static const char MY_MESSAGE_CHANNEL = 'C'; // My followed Channels
11 static const char MY_SEEN_ADDRESSES = 'S'; // Addresses that have been seen on the chain
12 static const char DB_FLAG = 'D'; // Database Flags
13 
14 CMessageDB::CMessageDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "messages" / "messages", nCacheSize, fMemory, fWipe) {
15 }
16 
17 bool CMessageDB::WriteMessage(const CMessage &message)
18 {
19  return Write(std::make_pair(MESSAGE_FLAG, message.out), message);
20 }
21 
22 bool CMessageDB::ReadMessage(const COutPoint &out, CMessage &message)
23 {
24  return Read(std::make_pair(MESSAGE_FLAG, out), message);
25 }
26 
28 {
29  return Erase(std::make_pair(MESSAGE_FLAG, out));
30 }
31 
32 bool CMessageDB::LoadMessages(std::set<CMessage>& setMessages)
33 {
34  std::unique_ptr<CDBIterator> pcursor(NewIterator());
35 
36  pcursor->Seek(std::make_pair(MESSAGE_FLAG, COutPoint()));
37 
38  // Load messages
39  while (pcursor->Valid()) {
40  boost::this_thread::interruption_point();
41  std::pair<char, COutPoint> key;
42  if (pcursor->GetKey(key) && key.first == MESSAGE_FLAG) {
43  CMessage message;
44  if (pcursor->GetValue(message)) {
45  setMessages.insert(message);
46  pcursor->Next();
47  } else {
48  LogPrintf("%s: failed to read message\n", __func__);
49  pcursor->Next();
50  }
51  } else {
52  break;
53  }
54  }
55  return true;
56 }
57 
59 {
60  std::set<CMessage> setMessages;
61  std::unique_ptr<CDBIterator> pcursor(NewIterator());
62 
63  pcursor->Seek(std::make_pair(MESSAGE_FLAG, COutPoint()));
64 
65  // Load messages
66  while (pcursor->Valid()) {
67  boost::this_thread::interruption_point();
68  std::pair<char, COutPoint> key;
69  if (pcursor->GetKey(key) && key.first == MESSAGE_FLAG) {
70  CMessage message;
71  if (pcursor->GetValue(message)) {
72  setMessages.insert(message);
73  pcursor->Next();
74  } else {
75  LogPrintf("%s: failed to read message\n", __func__);
76  pcursor->Next();
77  }
78  } else {
79  break;
80  }
81  }
82 
83  count += setMessages.size();
84  for (auto message : setMessages)
85  EraseMessage(message.out);
86 
87  return true;
88 }
89 
91  try {
92 
93  for (auto messageRemove : setDirtyMessagesRemove) {
94  if (!EraseMessage(messageRemove))
95  return error("%s: failed to erase message %s", __func__, messageRemove.ToString());
96  }
97 
98  for (auto messageAdd : mapDirtyMessagesAdd) {
99  if (!WriteMessage(messageAdd.second))
100  return error("%s: failed to write message %s", __func__, messageAdd.second.ToString());
101 
102  mapDirtyMessagesOrphaned.erase(messageAdd.first);
103  }
104 
105  for (auto orphans : mapDirtyMessagesOrphaned) {
106  CMessage msg = orphans.second;
108  if (!WriteMessage(msg))
109  return error("%s: failed to write message orphan %s", __func__, msg.ToString());
110  }
111 
112  setDirtyMessagesRemove.clear();
113  mapDirtyMessagesAdd.clear();
114  mapDirtyMessagesOrphaned.clear();
115  } catch (const std::runtime_error& e) {
116  return error("%s : %s ", __func__, std::string("System error while flushing messages: ") + e.what());
117  }
118 
119  return true;
120 }
121 
122 CMessageChannelDB::CMessageChannelDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "messages" / "channels", nCacheSize, fMemory, fWipe) {
123 }
124 
125 bool CMessageChannelDB::WriteMyMessageChannel(const std::string& channelname)
126 {
127  return Write(std::make_pair(MY_MESSAGE_CHANNEL, channelname), 1);
128 }
129 
130 bool CMessageChannelDB::ReadMyMessageChannel(const std::string& channelname)
131 {
132  int i = 1;
133  return Read(std::make_pair(MY_MESSAGE_CHANNEL, channelname), i);
134 }
135 
136 bool CMessageChannelDB::EraseMyMessageChannel(const std::string& channelname)
137 {
138  return Erase(std::make_pair(MY_MESSAGE_CHANNEL, channelname));
139 }
140 
141 bool CMessageChannelDB::LoadMyMessageChannels(std::set<std::string>& setChannels)
142 {
143  setChannels.clear();
144  std::unique_ptr<CDBIterator> pcursor(NewIterator());
145 
146  pcursor->Seek(std::make_pair(MY_MESSAGE_CHANNEL, std::string()));
147 
148  // Load messages
149  while (pcursor->Valid()) {
150  boost::this_thread::interruption_point();
151  std::pair<char, std::string> key;
152  if (pcursor->GetKey(key) && key.first == MY_MESSAGE_CHANNEL) {
153  setChannels.insert(key.second);
154  pcursor->Next();
155  } else {
156  break;
157  }
158  }
159 
160  return true;
161 }
162 
163 bool CMessageDB::WriteFlag(const std::string &name, bool fValue)
164 {
165  return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
166 }
167 
168 bool CMessageDB::ReadFlag(const std::string &name, bool &fValue)
169 {
170  char ch;
171  if (!Read(std::make_pair(DB_FLAG, name), ch))
172  return false;
173  fValue = ch == '1';
174  return true;
175 }
176 
177 
178 bool CMessageChannelDB::WriteUsedAddress(const std::string& address)
179 {
180  return Write(std::make_pair(MY_SEEN_ADDRESSES, address), 1);
181 }
182 bool CMessageChannelDB::ReadUsedAddress(const std::string& address)
183 {
184  int i;
185  return Read(std::make_pair(MY_SEEN_ADDRESSES, address), i);
186 }
187 bool CMessageChannelDB::EraseUsedAddress(const std::string& address)
188 {
189  return Erase(std::make_pair(MY_SEEN_ADDRESSES, address));
190 }
191 
192 bool CMessageChannelDB::WriteFlag(const std::string &name, bool fValue)
193 {
194  return Write(std::make_pair(DB_FLAG, name), fValue ? '1' : '0');
195 }
196 
197 bool CMessageChannelDB::ReadFlag(const std::string &name, bool &fValue)
198 {
199  char ch;
200  if (!Read(std::make_pair(DB_FLAG, name), ch))
201  return false;
202  fValue = ch == '1';
203  return true;
204 }
205 
207  try {
208  LogPrintf("%s: Flushing messagechannelsdb addSize:%u, removeSize:%u, seenAddressSize:%u\n", __func__, setDirtyChannelsAdd.size(), setDirtyChannelsRemove.size(), setDirtySeenAddressAdd.size());
209 
210  for (auto channelRemove : setDirtyChannelsRemove) {
211  if (!EraseMyMessageChannel(channelRemove))
212  return error("%s: failed to erase messagechannel %s", __func__, channelRemove);
213  }
214 
215  for (auto channelAdd : setDirtyChannelsAdd) {
216  if (!WriteMyMessageChannel(channelAdd))
217  return error("%s: failed to write messagechannel %s", __func__, channelAdd);
218  }
219 
220  for (auto seenAddress : setDirtySeenAddressAdd) {
221  if (!WriteUsedAddress(seenAddress))
222  return error("%s: failed to write seenaddress %s", __func__, seenAddress);
223  }
224 
225  setDirtyChannelsRemove.clear();
226  setDirtyChannelsAdd.clear();
227  setDirtySeenAddressAdd.clear();
229  setAddressAskedForFalse.clear();
230  } catch (const std::runtime_error& e) {
231  return error("%s : %s ", __func__, std::string("System error while flushing messagechannels: ") + e.what());
232  }
233 
234  return true;
235 }
std::set< COutPoint > setDirtyMessagesRemove
Definition: messages.cpp:15
bool Flush()
Definition: messagedb.cpp:90
std::string ToString() const
Definition: messages.h:91
CMessageChannelDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: messagedb.cpp:122
bool LoadMessages(std::set< CMessage > &setMessages)
Definition: messagedb.cpp:32
bool ReadFlag(const std::string &name, bool &fValue)
Definition: messagedb.cpp:197
bool EraseMyMessageChannel(const std::string &channelname)
Definition: messagedb.cpp:136
bool ReadMyMessageChannel(const std::string &channelname)
Definition: messagedb.cpp:130
CMessageDB(size_t nCacheSize, bool fMemory=false, bool fWipe=false)
Definition: messagedb.cpp:14
bool EraseAllMessages(int &count)
Definition: messagedb.cpp:58
MessageStatus status
Definition: messages.h:76
CDBIterator * NewIterator()
Definition: dbwrapper.h:300
bool EraseUsedAddress(const std::string &address)
Definition: messagedb.cpp:187
bool ReadMessage(const COutPoint &out, CMessage &message)
Definition: messagedb.cpp:22
std::set< std::string > setDirtyChannelsRemove
Definition: messages.cpp:20
std::set< std::string > setSubscribedChannelsAskedForFalse
Definition: messages.cpp:21
#define LogPrintf(...)
Definition: util.h:149
COutPoint out
Definition: messages.h:71
bool ReadFlag(const std::string &name, bool &fValue)
Definition: messagedb.cpp:168
bool Erase(const K &key, bool fSync=false)
Definition: dbwrapper.h:279
bool EraseMessage(const COutPoint &out)
Definition: messagedb.cpp:27
bool WriteFlag(const std::string &name, bool fValue)
Definition: messagedb.cpp:192
std::set< std::string > setAddressAskedForFalse
Definition: messages.cpp:24
std::map< COutPoint, CMessage > mapDirtyMessagesOrphaned
Definition: messages.cpp:17
bool LoadMyMessageChannels(std::set< std::string > &setChannels)
Definition: messagedb.cpp:141
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:22
bool Read(const K &key, V &value) const
Definition: dbwrapper.h:226
std::map< COutPoint, CMessage > mapDirtyMessagesAdd
Definition: messages.cpp:16
bool Write(const K &key, const V &value, bool fSync=false)
Definition: dbwrapper.h:252
bool WriteMyMessageChannel(const std::string &channelname)
Definition: messagedb.cpp:125
bool error(const char *fmt, const Args &... args)
Definition: util.h:168
std::set< std::string > setDirtyChannelsAdd
Definition: messages.cpp:19
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:572
bool WriteUsedAddress(const std::string &address)
Definition: messagedb.cpp:178
bool WriteMessage(const CMessage &message)
Definition: messagedb.cpp:17
bool ReadUsedAddress(const std::string &address)
Definition: messagedb.cpp:182
bool WriteFlag(const std::string &name, bool fValue)
Definition: messagedb.cpp:163
std::set< std::string > setDirtySeenAddressAdd
Definition: messages.cpp:23