Example #1
0
		private void MakeTried(AddressInfo info, int nId)
		{
			// remove the entry from all new buckets
			for(int bucket = 0 ; bucket < ADDRMAN_NEW_BUCKET_COUNT ; bucket++)
			{
				int pos = info.GetBucketPosition(nKey, true, bucket);
				if(vvNew[bucket, pos] == nId)
				{
					vvNew[bucket, pos] = -1;
					info.nRefCount--;
				}
			}
			nNew--;

			assert(info.nRefCount == 0);

			// which tried bucket to move the entry to
			int nKBucket = info.GetTriedBucket(nKey);
			int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);

			// first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
			if(vvTried[nKBucket, nKBucketPos] != -1)
			{
				// find an item to evict
				int nIdEvict = vvTried[nKBucket, nKBucketPos];
				assert(mapInfo.ContainsKey(nIdEvict));
				AddressInfo infoOld = mapInfo[nIdEvict];

				// Remove the to-be-evicted item from the tried set.
				infoOld.fInTried = false;
				vvTried[nKBucket, nKBucketPos] = -1;
				nTried--;

				// find which new bucket it belongs to
				int nUBucket = infoOld.GetNewBucket(nKey);
				int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
				ClearNew(nUBucket, nUBucketPos);
				assert(vvNew[nUBucket, nUBucketPos] == -1);

				// Enter it into the new set again.
				infoOld.nRefCount = 1;
				vvNew[nUBucket, nUBucketPos] = nIdEvict;
				nNew++;
			}
			assert(vvTried[nKBucket, nKBucketPos] == -1);

			vvTried[nKBucket, nKBucketPos] = nId;
			nTried++;
			info.fInTried = true;
		}
Example #2
0
		public void ReadWrite(BitcoinStream stream)
		{
			lock(cs)
			{
				Check();
				if(!stream.Serializing)
					Clear();
				stream.ReadWrite(ref nVersion);
				stream.ReadWrite(ref nKeySize);
				if(!stream.Serializing && nKeySize != 32)
					throw new FormatException("Incorrect keysize in addrman deserialization");
				stream.ReadWrite(ref nKey);
				stream.ReadWrite(ref nNew);
				stream.ReadWrite(ref nTried);

				int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
				stream.ReadWrite(ref nUBuckets);
				if(nVersion != 0)
				{
					nUBuckets ^= (1 << 30);
				}
				if(!stream.Serializing)
				{
					// Deserialize entries from the new table.
					for(int n = 0 ; n < nNew ; n++)
					{
						AddressInfo info = new AddressInfo();
						info.ReadWrite(stream);
						mapInfo.Add(n, info);
						mapAddr[info.Address.Endpoint.Address] = n;
						info.nRandomPos = vRandom.Count;
						vRandom.Add(n);
						if(nVersion != 1 || nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
						{
							// In case the new table data cannot be used (nVersion unknown, or bucket count wrong),
							// immediately try to give them a reference based on their primary source address.
							int nUBucket = info.GetNewBucket(nKey);
							int nUBucketPos = info.GetBucketPosition(nKey, true, nUBucket);
							if(vvNew[nUBucket, nUBucketPos] == -1)
							{
								vvNew[nUBucket, nUBucketPos] = n;
								info.nRefCount++;
							}
						}
					}

					nIdCount = nNew;

					// Deserialize entries from the tried table.
					int nLost = 0;
					for(int n = 0 ; n < nTried ; n++)
					{
						AddressInfo info = new AddressInfo();
						info.ReadWrite(stream);
						int nKBucket = info.GetTriedBucket(nKey);
						int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
						if(vvTried[nKBucket, nKBucketPos] == -1)
						{
							info.nRandomPos = vRandom.Count;
							info.fInTried = true;
							vRandom.Add(nIdCount);
							mapInfo[nIdCount] = info;
							mapAddr[info.Address.Endpoint.Address] = nIdCount;
							vvTried[nKBucket, nKBucketPos] = nIdCount;
							nIdCount++;
						}
						else
						{
							nLost++;
						}
					}

					nTried -= nLost;

					// Deserialize positions in the new table (if possible).
					for(int bucket = 0 ; bucket < nUBuckets ; bucket++)
					{
						int nSize = 0;
						stream.ReadWrite(ref nSize);
						for(int n = 0 ; n < nSize ; n++)
						{
							int nIndex = 0;
							stream.ReadWrite(ref nIndex);
							if(nIndex >= 0 && nIndex < nNew)
							{
								AddressInfo info = mapInfo[nIndex];
								int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
								if(nVersion == 1 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket, nUBucketPos] == -1 && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
								{
									info.nRefCount++;
									vvNew[bucket, nUBucketPos] = nIndex;
								}
							}
						}
					}

					// Prune new entries with refcount 0 (as a result of collisions).
					int nLostUnk = 0;
					foreach(var kv in mapInfo.ToList())
					{
						if(kv.Value.fInTried == false && kv.Value.nRefCount == 0)
						{
							Delete(kv.Key);
							nLostUnk++;
						}
					}
				}
				else
				{
					Dictionary<int, int> mapUnkIds = new Dictionary<int, int>();
					int nIds = 0;
					foreach(var kv in mapInfo)
					{
						mapUnkIds[kv.Key] = nIds;
						AddressInfo info = kv.Value;
						if(info.nRefCount != 0)
						{
							assert(nIds != nNew); // this means nNew was wrong, oh ow
							info.ReadWrite(stream);
							nIds++;
						}
					}
					nIds = 0;
					foreach(var kv in mapInfo)
					{
						AddressInfo info = kv.Value;
						if(info.fInTried)
						{
							assert(nIds != nTried); // this means nTried was wrong, oh ow
							info.ReadWrite(stream);
							nIds++;
						}
					}

					for(int bucket = 0 ; bucket < ADDRMAN_NEW_BUCKET_COUNT ; bucket++)
					{
						int nSize = 0;
						for(int i = 0 ; i < ADDRMAN_BUCKET_SIZE ; i++)
						{
							if(vvNew[bucket, i] != -1)
								nSize++;
						}
						stream.ReadWrite(ref nSize);
						for(int i = 0 ; i < ADDRMAN_BUCKET_SIZE ; i++)
						{
							if(vvNew[bucket, i] != -1)
							{
								int nIndex = mapUnkIds[vvNew[bucket, i]];
								stream.ReadWrite(ref nIndex);
							}
						}
					}
				}
				Check();
			}
		}