@@ -245,140 +245,142 @@ class CAddrMan
245245 void Connected_ (const CService &addr, int64_t nTime);
246246
247247public:
248+ // serialized format:
249+ // * version byte (currently 0)
250+ // * nKey
251+ // * nNew
252+ // * nTried
253+ // * number of "new" buckets
254+ // * all nNew addrinfos in vvNew
255+ // * all nTried addrinfos in vvTried
256+ // * for each bucket:
257+ // * number of elements
258+ // * for each element: index
259+ //
260+ // Notice that vvTried, mapAddr and vVector are never encoded explicitly;
261+ // they are instead reconstructed from the other information.
262+ //
263+ // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
264+ // otherwise it is reconstructed as well.
265+ //
266+ // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
267+ // changes to the ADDRMAN_ parameters without breaking the on-disk structure.
268+ //
269+ // We don't use IMPLEMENT_SERIALIZE since the serialization and deserialization code has
270+ // very little in common.
271+ template <typename Stream>
272+ void Serialize (Stream &s, int nType, int nVersionDummy) const
273+ {
274+ LOCK (cs);
275+
276+ unsigned char nVersion = 0 ;
277+ s << nVersion;
278+ s << nKey;
279+ s << nNew;
280+ s << nTried;
281+
282+ int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
283+ s << nUBuckets;
284+ std::map<int , int > mapUnkIds;
285+ int nIds = 0 ;
286+ for (std::map<int , CAddrInfo>::const_iterator it = mapInfo.begin (); it != mapInfo.end (); it++) {
287+ if (nIds == nNew) break ; // this means nNew was wrong, oh ow
288+ mapUnkIds[(*it).first ] = nIds;
289+ const CAddrInfo &info = (*it).second ;
290+ if (info.nRefCount ) {
291+ s << info;
292+ nIds++;
293+ }
294+ }
295+ nIds = 0 ;
296+ for (std::map<int , CAddrInfo>::const_iterator it = mapInfo.begin (); it != mapInfo.end (); it++) {
297+ if (nIds == nTried) break ; // this means nTried was wrong, oh ow
298+ const CAddrInfo &info = (*it).second ;
299+ if (info.fInTried ) {
300+ s << info;
301+ nIds++;
302+ }
303+ }
304+ for (std::vector<std::set<int > >::const_iterator it = vvNew.begin (); it != vvNew.end (); it++) {
305+ const std::set<int > &vNew = (*it);
306+ int nSize = vNew.size ();
307+ s << nSize;
308+ for (std::set<int >::const_iterator it2 = vNew.begin (); it2 != vNew.end (); it2++) {
309+ int nIndex = mapUnkIds[*it2];
310+ s << nIndex;
311+ }
312+ }
313+ }
248314
249- IMPLEMENT_SERIALIZE
250- (({
251- // serialized format:
252- // * version byte (currently 0)
253- // * nKey
254- // * nNew
255- // * nTried
256- // * number of "new" buckets
257- // * all nNew addrinfos in vvNew
258- // * all nTried addrinfos in vvTried
259- // * for each bucket:
260- // * number of elements
261- // * for each element: index
262- //
263- // Notice that vvTried, mapAddr and vVector are never encoded explicitly;
264- // they are instead reconstructed from the other information.
265- //
266- // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
267- // otherwise it is reconstructed as well.
268- //
269- // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
270- // changes to the ADDRMAN_ parameters without breaking the on-disk structure.
271- {
272- LOCK (cs);
273- unsigned char nVersion = 0 ;
274- READWRITE (nVersion);
275- READWRITE (nKey);
276- READWRITE (nNew);
277- READWRITE (nTried);
278-
279- CAddrMan *am = const_cast <CAddrMan*>(this );
280- if (fWrite )
281- {
282- int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
283- READWRITE (nUBuckets);
284- std::map<int , int > mapUnkIds;
285- int nIds = 0 ;
286- for (std::map<int , CAddrInfo>::iterator it = am->mapInfo .begin (); it != am->mapInfo .end (); it++)
287- {
288- if (nIds == nNew) break ; // this means nNew was wrong, oh ow
289- mapUnkIds[(*it).first ] = nIds;
290- CAddrInfo &info = (*it).second ;
291- if (info.nRefCount )
292- {
293- READWRITE (info);
294- nIds++;
295- }
296- }
297- nIds = 0 ;
298- for (std::map<int , CAddrInfo>::iterator it = am->mapInfo .begin (); it != am->mapInfo .end (); it++)
299- {
300- if (nIds == nTried) break ; // this means nTried was wrong, oh ow
301- CAddrInfo &info = (*it).second ;
302- if (info.fInTried )
303- {
304- READWRITE (info);
305- nIds++;
306- }
307- }
308- for (std::vector<std::set<int > >::iterator it = am->vvNew .begin (); it != am->vvNew .end (); it++)
309- {
310- const std::set<int > &vNew = (*it);
311- int nSize = vNew.size ();
312- READWRITE (nSize);
313- for (std::set<int >::iterator it2 = vNew.begin (); it2 != vNew.end (); it2++)
314- {
315- int nIndex = mapUnkIds[*it2];
316- READWRITE (nIndex);
317- }
318- }
315+ template <typename Stream>
316+ void Unserialize (Stream& s, int nType, int nVersionDummy)
317+ {
318+ LOCK (cs);
319+
320+ unsigned char nVersion;
321+ s >> nVersion;
322+ s >> nKey;
323+ s >> nNew;
324+ s >> nTried;
325+
326+ int nUBuckets = 0 ;
327+ s >> nUBuckets;
328+ nIdCount = 0 ;
329+ mapInfo.clear ();
330+ mapAddr.clear ();
331+ vRandom.clear ();
332+ vvTried = std::vector<std::vector<int > >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int >(0 ));
333+ vvNew = std::vector<std::set<int > >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int >());
334+ for (int n = 0 ; n < nNew; n++) {
335+ CAddrInfo &info = mapInfo[n];
336+ s >> info;
337+ mapAddr[info] = n;
338+ info.nRandomPos = vRandom.size ();
339+ vRandom.push_back (n);
340+ if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT) {
341+ vvNew[info.GetNewBucket (nKey)].insert (n);
342+ info.nRefCount ++;
343+ }
344+ }
345+ nIdCount = nNew;
346+ int nLost = 0 ;
347+ for (int n = 0 ; n < nTried; n++) {
348+ CAddrInfo info;
349+ s >> info;
350+ std::vector<int > &vTried = vvTried[info.GetTriedBucket (nKey)];
351+ if (vTried.size () < ADDRMAN_TRIED_BUCKET_SIZE) {
352+ info.nRandomPos = vRandom.size ();
353+ info.fInTried = true ;
354+ vRandom.push_back (nIdCount);
355+ mapInfo[nIdCount] = info;
356+ mapAddr[info] = nIdCount;
357+ vTried.push_back (nIdCount);
358+ nIdCount++;
319359 } else {
320- int nUBuckets = 0 ;
321- READWRITE (nUBuckets);
322- am->nIdCount = 0 ;
323- am->mapInfo .clear ();
324- am->mapAddr .clear ();
325- am->vRandom .clear ();
326- am->vvTried = std::vector<std::vector<int > >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int >(0 ));
327- am->vvNew = std::vector<std::set<int > >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int >());
328- for (int n = 0 ; n < am->nNew ; n++)
329- {
330- CAddrInfo &info = am->mapInfo [n];
331- READWRITE (info);
332- am->mapAddr [info] = n;
333- info.nRandomPos = vRandom.size ();
334- am->vRandom .push_back (n);
335- if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
336- {
337- am->vvNew [info.GetNewBucket (am->nKey )].insert (n);
338- info.nRefCount ++;
339- }
340- }
341- am->nIdCount = am->nNew ;
342- int nLost = 0 ;
343- for (int n = 0 ; n < am->nTried ; n++)
344- {
345- CAddrInfo info;
346- READWRITE (info);
347- std::vector<int > &vTried = am->vvTried [info.GetTriedBucket (am->nKey )];
348- if (vTried.size () < ADDRMAN_TRIED_BUCKET_SIZE)
349- {
350- info.nRandomPos = vRandom.size ();
351- info.fInTried = true ;
352- am->vRandom .push_back (am->nIdCount );
353- am->mapInfo [am->nIdCount ] = info;
354- am->mapAddr [info] = am->nIdCount ;
355- vTried.push_back (am->nIdCount );
356- am->nIdCount ++;
357- } else {
358- nLost++;
359- }
360- }
361- am->nTried -= nLost;
362- for (int b = 0 ; b < nUBuckets; b++)
363- {
364- std::set<int > &vNew = am->vvNew [b];
365- int nSize = 0 ;
366- READWRITE (nSize);
367- for (int n = 0 ; n < nSize; n++)
368- {
369- int nIndex = 0 ;
370- READWRITE (nIndex);
371- CAddrInfo &info = am->mapInfo [nIndex];
372- if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
373- {
374- info.nRefCount ++;
375- vNew.insert (nIndex);
376- }
377- }
360+ nLost++;
361+ }
362+ }
363+ nTried -= nLost;
364+ for (int b = 0 ; b < nUBuckets; b++) {
365+ std::set<int > &vNew = vvNew[b];
366+ int nSize = 0 ;
367+ s >> nSize;
368+ for (int n = 0 ; n < nSize; n++) {
369+ int nIndex = 0 ;
370+ s >> nIndex;
371+ CAddrInfo &info = mapInfo[nIndex];
372+ if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS) {
373+ info.nRefCount ++;
374+ vNew.insert (nIndex);
378375 }
379376 }
380377 }
381- });)
378+ }
379+
380+ unsigned int GetSerializeSize (int nType, int nVersion) const
381+ {
382+ return (CSizeComputer (nType, nVersion) << *this ).size ();
383+ }
382384
383385 CAddrMan () : vRandom(0 ), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int >(0 )), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set<int >())
384386 {
0 commit comments