diff --git a/src/online/current_user.cpp b/src/online/current_user.cpp index 51ac435a2..6e9c57e16 100644 --- a/src/online/current_user.cpp +++ b/src/online/current_user.cpp @@ -576,8 +576,9 @@ namespace Online{ { if (now_online) { + //User came online relation_info->setOnline(true); - profile->setFriend(); + profile->setFriend(); //Do this because a user might have accepted a pending friend request. to_notify.push_back(profile->getUserName()); } } diff --git a/src/online/profile.cpp b/src/online/profile.cpp index 368fa50c3..1453af298 100644 --- a/src/online/profile.cpp +++ b/src/online/profile.cpp @@ -234,7 +234,9 @@ namespace Online{ void Profile::addFriend( const uint32_t id) { assert (m_has_fetched_friends); - //FIXME check if it's not already in there + for(int i=0; i< m_friends.size(); i++) + if(m_friends[i] == id) + return; m_friends.push_back(id); } @@ -260,4 +262,20 @@ namespace Online{ return m_achievements; } + //============================================================================= + void Profile::merge(Profile * profile) + { + assert (profile != NULL); + if(!this->m_has_fetched_friends && profile->m_has_fetched_friends) + this->m_friends = profile->m_friends; + if(!this->m_has_fetched_achievements && profile->m_has_fetched_friends) + this->m_achievements = profile->m_achievements; + if(this->m_relation_info == NULL && profile->m_relation_info != NULL) + { + this->m_relation_info = profile->m_relation_info; + profile->m_relation_info = NULL; //We don't want the destructor of the profile instance to destroy the relation info + } + delete profile; + } + } // namespace Online diff --git a/src/online/profile.hpp b/src/online/profile.hpp index a79de5d57..60f5b39b6 100644 --- a/src/online/profile.hpp +++ b/src/online/profile.hpp @@ -86,10 +86,16 @@ namespace Online{ bool m_is_current_user; uint32_t m_id; irr::core::stringw m_username; + /** information about the relation with the current user */ RelationInfo * m_relation_info; + /** Whether or not the user of this profile, is a friend of the current user */ bool m_is_friend; bool m_has_fetched_friends; + /** + * List of user id's that are friends with the user of this profile. + * In case this profile is of the current user, this list also contains any id's of users that still have a friend request pending. + * */ std::vector m_friends; bool m_has_fetched_achievements; @@ -130,15 +136,16 @@ namespace Online{ RelationInfo * getRelationInfo() { return m_relation_info; } void setRelationInfo(RelationInfo * r){ delete m_relation_info; m_relation_info = r;} - void setCacheBit() { m_cache_bit = true; } - void unsetCacheBit() { m_cache_bit = false; } + void setCacheBit(bool cache_bit) { m_cache_bit = cache_bit; } bool getCacheBit() const { return m_cache_bit; } uint32_t getID() const { return m_id; } const irr::core::stringw & getUserName() const { return m_username; } + void merge(Profile * profile); - }; // class CurrentUser + + }; // class Profile } // namespace Online diff --git a/src/online/profile_manager.cpp b/src/online/profile_manager.cpp index 226cf29b8..92edd063a 100644 --- a/src/online/profile_manager.cpp +++ b/src/online/profile_manager.cpp @@ -55,10 +55,8 @@ namespace Online{ // ============================================================================ ProfileManager::~ProfileManager() { + clearPersistent(); ProfilesMap::iterator it; - for ( it = m_profiles_persistent.begin(); it != m_profiles_persistent.end(); ++it ) { - delete it->second; - } for ( it = m_profiles_cache.begin(); it != m_profiles_cache.end(); ++it ) { delete it->second; } @@ -70,25 +68,31 @@ namespace Online{ { if(m_profiles_cache.size() == m_max_cache_size) { - profile->setCacheBit(); + profile->setCacheBit(true); ProfilesMap::iterator iter; for (iter = m_profiles_cache.begin(); iter != m_profiles_cache.end(); ++iter) { if (!iter->second->getCacheBit()) return; } - //All cache bits are one! Set then all to zero except the one currently being visited + //All cache bits are one! Set them all to zero except the one currently being visited for (iter = m_profiles_cache.begin(); iter != m_profiles_cache.end(); ++iter) { - iter->second->unsetCacheBit(); + iter->second->setCacheBit(false); } - profile->setCacheBit(); + profile->setCacheBit(true); } } // ============================================================================ - + /** Initialisation before the object is displayed. If necessary this function + * will pause the race if it is running (i.e. world exists). While only some + * of the screen can be shown during the race (via the in-game menu you + * can get the options screen and the help screens only). This is used by + * the RaceResultGUI to leave the race running (for the end animation) while + * the results are being shown. + */ void ProfileManager::directToCache(Profile * profile) { assert(profile != NULL); @@ -99,10 +103,8 @@ namespace Online{ { if (!iter->second->getCacheBit()) { - ProfilesMap::iterator toErase = iter; - ++iter; - delete toErase->second; - m_profiles_cache.erase(toErase); + delete iter->second; + m_profiles_cache.erase(iter); break; } else @@ -115,13 +117,16 @@ namespace Online{ } // ============================================================================ - + /** + * Adds a profile to the persistent map. + * If a profile with the same id is already in there, the profiles are "merged" with as goal saving as much information. + * (i.e. one profile instance could have already fetched the friends, while the other could have fetched the achievements.) + */ void ProfileManager::addPersistent(Profile * profile) { if(inPersistent(profile->getID())) { - delete m_profiles_persistent[profile->getID()]; - m_profiles_persistent[profile->getID()] = profile; + m_profiles_persistent[profile->getID()]->merge(profile); } else { @@ -129,7 +134,9 @@ namespace Online{ } } // ============================================================================ - + /** + * Removes and deletes an entry from the persistent map. + */ void ProfileManager::deleteFromPersistent(const uint32_t id) { if (inPersistent(id)) @@ -163,7 +170,7 @@ namespace Online{ addToCache(profile); } else - Log::warn("ProfileManager::removePersistent", "Tried to move profile with id %d from persistent to cache while not present", id); + Log::warn("ProfileManager::moveToCache", "Tried to move profile with id %d from persistent to cache while not present", id); } // ============================================================================ @@ -171,20 +178,11 @@ namespace Online{ void ProfileManager::addToCache(Profile * profile) { if(inPersistent(profile->getID())) - { - //FIXME should do updating of values - } + m_profiles_persistent[profile->getID()]->merge(profile); else if(cacheHit(profile->getID())) - { - //FIXME should do updating of values - delete profile; - } + m_profiles_cache[profile->getID()]->merge(profile); else - { directToCache(profile); - } - Log::info("persistent size","%d", m_profiles_persistent.size()); - Log::info("cache size","%d", m_profiles_cache.size()); } // ============================================================================ @@ -192,9 +190,7 @@ namespace Online{ bool ProfileManager::inPersistent(const uint32_t id) { if (m_profiles_persistent.find(id) != m_profiles_persistent.end()) - { return true; - } return false; } diff --git a/src/online/profile_manager.hpp b/src/online/profile_manager.hpp index 9bab8b5da..54d99a8d6 100644 --- a/src/online/profile_manager.hpp +++ b/src/online/profile_manager.hpp @@ -44,9 +44,15 @@ namespace Online{ typedef std::map ProfilesMap; + /** A map of profiles that is persistent. (i.e. no automatic removing happens) Normally used for the current user's profile and friends. */ + ProfilesMap m_profiles_persistent; + /** + * Any profiles that don't go into the persistent map, go here. + * Using a Least Recent Used caching algorithm with age bits to remove entries when the max size is reached. + **/ ProfilesMap m_profiles_cache; - ProfilesMap m_profiles_persistent; // current user and friends Profile * m_currently_visiting; + /** The max size of the m_profiles cache. */ static const unsigned int m_max_cache_size = 20; void iterateCache(Profile * profile); @@ -65,6 +71,7 @@ namespace Online{ void setVisiting(const uint32_t id); bool cacheHit(const uint32_t id); bool inPersistent(const uint32_t id); + /** \return the instance of the profile that's currently being visited */ Profile * getVisitingProfile() {return m_currently_visiting;} Profile * getProfileByID(const uint32_t id);