From 10e78785cd083ca51c6b61cc05f5026f4766157f Mon Sep 17 00:00:00 2001
From: orignal <i2porignal@yandex.ru>
Date: Fri, 5 Jun 2015 15:55:21 -0400
Subject: [PATCH] additional statistics for profiling

---
 Profiling.cpp | 43 ++++++++++++++++++++++++++++---------------
 Profiling.h   | 12 +++++++++---
 2 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/Profiling.cpp b/Profiling.cpp
index 70df0e76..390a1536 100644
--- a/Profiling.cpp
+++ b/Profiling.cpp
@@ -11,8 +11,8 @@ namespace data
 {
 	RouterProfile::RouterProfile (const IdentHash& identHash):
 		m_IdentHash (identHash), m_LastUpdateTime (boost::posix_time::second_clock::local_time()),
-		m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0),
-		m_NumTunnelsNonReplied (0)
+		m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0),
+		m_NumTimesTaken (0), m_NumTimesRejected (0) 
 	{
 	}
 
@@ -33,11 +33,15 @@ namespace data
 		participation.put (PEER_PROFILE_PARTICIPATION_AGREED, m_NumTunnelsAgreed);
 		participation.put (PEER_PROFILE_PARTICIPATION_DECLINED, m_NumTunnelsDeclined);
 		participation.put (PEER_PROFILE_PARTICIPATION_NON_REPLIED, m_NumTunnelsNonReplied);
+		boost::property_tree::ptree usage;
+		usage.put (PEER_PROFILE_USAGE_TAKEN, m_NumTimesTaken);
+		usage.put (PEER_PROFILE_USAGE_REJECTED, m_NumTimesRejected);
 		// fill property tree
 		boost::property_tree::ptree pt;
 		pt.put (PEER_PROFILE_LAST_UPDATE_TIME, boost::posix_time::to_simple_string (m_LastUpdateTime));
 		pt.put_child (PEER_PROFILE_SECTION_PARTICIPATION, participation);
-		
+		pt.put_child (PEER_PROFILE_SECTION_USAGE, usage);		
+
 		// save to file
 		auto path = i2p::util::filesystem::GetDefaultDataDir() / PEER_PROFILES_DIRECTORY;
 		if (!boost::filesystem::exists (path))
@@ -102,6 +106,10 @@ namespace data
 					m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0);
 					m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0);
 					m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0);
+					// read usage
+					auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE);
+					m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0);
+					m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0);
 				}	
 				else
 					*this = RouterProfile (m_IdentHash);
@@ -128,27 +136,32 @@ namespace data
 		UpdateTime ();
 	}	
 
-	bool RouterProfile::IsLowPartcipationRate (uint32_t elapsedTime) const
+	bool RouterProfile::IsLowPartcipationRate () const
 	{
-		if (elapsedTime < 900) // if less than 15 minutes
-			return m_NumTunnelsAgreed < m_NumTunnelsDeclined; // 50% rate
-		else
-			return 3*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // 25% rate
+		return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate
 	}	
 
-	bool RouterProfile::IsLowReplyRate (uint32_t elapsedTime) const
+	bool RouterProfile::IsLowReplyRate () const
 	{
 		auto total = m_NumTunnelsAgreed + m_NumTunnelsDeclined;
-		if (elapsedTime < 300) // if less than 5 minutes
-			return m_NumTunnelsNonReplied > 5*(total + 1);
-		else
-			return !total && m_NumTunnelsNonReplied*15 > elapsedTime;
+		return m_NumTunnelsNonReplied > 10*(total + 1);
 	}	
 		
-	bool RouterProfile::IsBad () const 
+	bool RouterProfile::IsBad ()
 	{ 
 		auto elapsedTime = (GetTime () - m_LastUpdateTime).total_seconds ();
-		return IsAlwaysDeclining () || IsLowPartcipationRate (elapsedTime) || IsLowReplyRate (elapsedTime); 
+		if (elapsedTime > 1800) 
+		{
+			m_NumTunnelsNonReplied = 0; // drop non-replied after 30 minutes of inactivity
+			if (elapsedTime > 14400) // drop agreed and declined after 4 hours of inactivity 
+			{
+				m_NumTunnelsAgreed = 0;
+				m_NumTunnelsDeclined = 0;
+			}
+		}
+		auto isBad = IsAlwaysDeclining () || IsLowPartcipationRate () || IsLowReplyRate (); 
+		if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++;
+		return isBad;	
 	}
 		
 	std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash)
diff --git a/Profiling.h b/Profiling.h
index 3a5a0844..0690d6cb 100644
--- a/Profiling.h
+++ b/Profiling.h
@@ -13,11 +13,14 @@ namespace data
 	const char PEER_PROFILE_PREFIX[] = "profile-";
 	// sections
 	const char PEER_PROFILE_SECTION_PARTICIPATION[] = "participation";
+	const char PEER_PROFILE_SECTION_USAGE[] = "usage";
 	// params	
 	const char PEER_PROFILE_LAST_UPDATE_TIME[] = "lastupdatetime";
 	const char PEER_PROFILE_PARTICIPATION_AGREED[] = "agreed";
 	const char PEER_PROFILE_PARTICIPATION_DECLINED[] = "declined";
 	const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied";	
+	const char PEER_PROFILE_USAGE_TAKEN[] = "taken";
+	const char PEER_PROFILE_USAGE_REJECTED[] = "rejected";
 
 	const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days)
 	
@@ -31,7 +34,7 @@ namespace data
 			void Save ();
 			void Load ();
 
-			bool IsBad () const;
+			bool IsBad ();
 			
 			void TunnelBuildResponse (uint8_t ret);
 			void TunnelNonReplied ();
@@ -42,8 +45,8 @@ namespace data
 			void UpdateTime ();
 
 			bool IsAlwaysDeclining () const { return !m_NumTunnelsAgreed && m_NumTunnelsDeclined >= 5; };
-			bool IsLowPartcipationRate (uint32_t elapsedTime) const;
-			bool IsLowReplyRate (uint32_t elapsedTime) const;
+			bool IsLowPartcipationRate () const;
+			bool IsLowReplyRate () const;
 			
 		private:	
 
@@ -53,6 +56,9 @@ namespace data
 			uint32_t m_NumTunnelsAgreed;
 			uint32_t m_NumTunnelsDeclined;	
 			uint32_t m_NumTunnelsNonReplied;
+			// usage
+			uint32_t m_NumTimesTaken;
+			uint32_t m_NumTimesRejected;	
 	};	
 
 	std::shared_ptr<RouterProfile> GetRouterProfile (const IdentHash& identHash);