root/src/add-ons/kernel/file_systems/netfs/server/StatisticsManager.cpp
// StatisticsManager.cpp

#include "StatisticsManager.h"

#include <AutoLocker.h>
#include <HashMap.h>
#include <Message.h>

#include "DebugSupport.h"
#include "SecurityContext.h"

typedef HashMap<HashString, int32>      UserCountMap;

// ShareStatistics
class StatisticsManager::ShareStatistics {
public:
        ShareStatistics(const char* share)
                : fShare(share),
                  fUsers()
        {
        }

        ~ShareStatistics()
        {
        }

        status_t Init()
        {
                return fUsers.InitCheck();
        }

        const char* GetShare() const
        {
                return fShare.GetString();
        }

        void AddUser(const char* user)
        {
                int32 count = 0;
                if (fUsers.ContainsKey(user))
                        count = fUsers.Get(user);
                count++;
                fUsers.Put(user, count);
        }

        void RemoveUser(const char* user)
        {
                if (!fUsers.ContainsKey(user))
                        return;

                int32 count = fUsers.Get(user);
                count--;
                if (count > 0)
                        fUsers.Put(user, count);
                else
                        fUsers.Remove(user);
        }

        status_t GetStatistics(BMessage* statistics)
        {
                // add "mounted by"
                for (UserCountMap::Iterator it = fUsers.GetIterator(); it.HasNext();) {
                        HashString user(it.Next().key);
                        status_t error = statistics->AddString("mounted by",
                                user.GetString());
                        if (error != B_OK)
                                return error;
                }
                return B_OK;
        }

private:
        HashString              fShare;
        UserCountMap    fUsers;
};

// ShareStatisticsMap
struct StatisticsManager::ShareStatisticsMap
        : HashMap<HashString, StatisticsManager::ShareStatistics*> {
};


// constructor
StatisticsManager::StatisticsManager()
        : fLock("statistics manager"),
          fShareStatistics(NULL)
{
}

// destructor
StatisticsManager::~StatisticsManager()
{
        // delete the share statistics
        for (ShareStatisticsMap::Iterator it = fShareStatistics->GetIterator();
                 it.HasNext();) {
                ShareStatistics* statistics = it.Next().value;
                delete statistics;
        }

        delete fShareStatistics;
}

// Init
status_t
StatisticsManager::Init()
{
        // check lock
        if (fLock.Sem() < 0)
                return fLock.Sem();

        // create share info map
        fShareStatistics = new(std::nothrow) ShareStatisticsMap;
        if (!fShareStatistics)
                return B_NO_MEMORY;
        status_t error = fShareStatistics->InitCheck();
        if (error != B_OK)
                return error;

        return B_OK;
}

// CreateDefault
status_t
StatisticsManager::CreateDefault()
{
        if (fManager)
                return B_OK;

        fManager = new(std::nothrow) StatisticsManager;
        if (!fManager)
                return B_NO_MEMORY;
        status_t error = fManager->Init();
        if (error != B_OK) {
                DeleteDefault();
                return error;
        }

        return B_OK;
}

// DeleteDefault
void
StatisticsManager::DeleteDefault()
{
        if (fManager) {
                delete fManager;
                fManager = NULL;
        }
}

// GetDefault
StatisticsManager*
StatisticsManager::GetDefault()
{
        return fManager;
}

// UserRemoved
void
StatisticsManager::UserRemoved(User* user)
{
        // the shares the user mounted should already have been unmounted
}

// ShareRemoved
void
StatisticsManager::ShareRemoved(Share* share)
{
        if (!share)
                return;

        AutoLocker<Locker> locker(fLock);

        ShareStatistics* statistics = fShareStatistics->Remove(share->GetName());
        delete statistics;
}

// ShareMounted
void
StatisticsManager::ShareMounted(Share* share, User* user)
{
        if (!share || !user)
                return;

        AutoLocker<Locker> locker(fLock);

        // get the statistics
        ShareStatistics* statistics = fShareStatistics->Get(share->GetName());
        if (!statistics) {
                // no statistics for this share yet: create
                statistics = new(std::nothrow) ShareStatistics(share->GetName());
                if (!statistics)
                        return;

                // add to the map
                if (fShareStatistics->Put(share->GetName(), statistics) != B_OK) {
                        delete statistics;
                        return;
                }
        }

        // add the user
        statistics->AddUser(user->GetName());
}

// ShareUnmounted
void
StatisticsManager::ShareUnmounted(Share* share, User* user)
{
        if (!share || !user)
                return;

        AutoLocker<Locker> locker(fLock);

        // get the statistics
        ShareStatistics* statistics = fShareStatistics->Get(share->GetName());
        if (!statistics)
                return;

        // remove the user
        statistics->RemoveUser(user->GetName());
}

// GetUserStatistics
status_t
StatisticsManager::GetUserStatistics(User* user, BMessage* statistics)
{
        if (!user)
                return B_BAD_VALUE;

        return GetUserStatistics(user->GetName(), statistics);
}

// GetUserStatistics
status_t
StatisticsManager::GetUserStatistics(const char* user, BMessage* _statistics)
{
        if (!user || !_statistics)
                return B_BAD_VALUE;

        // nothing for now

        return B_OK;
}

// GetShareStatistics
status_t
StatisticsManager::GetShareStatistics(Share* share, BMessage* statistics)
{
        if (!share)
                return B_BAD_VALUE;

        return GetShareStatistics(share->GetName(), statistics);
}

// GetShareStatistics
status_t
StatisticsManager::GetShareStatistics(const char* share, BMessage* _statistics)
{
        if (!share || !_statistics)
                return B_BAD_VALUE;

        AutoLocker<Locker> locker(fLock);

        // get the statistics
        ShareStatistics* statistics = fShareStatistics->Get(share);
        if (!statistics)
                return B_OK;

        // get the users
        return statistics->GetStatistics(_statistics);
}


// fManager
StatisticsManager*      StatisticsManager::fManager = NULL;