static const char* version_id =
  "$Id: msg_user_table.cc,v 3.12 1999/08/17 14:31:54 v2kea318 Exp $";

// $Log: msg_user_table.cc,v $
// Revision 3.12  1999/08/17  14:31:54  v2kea318
// *** empty log message ***
//
// Revision 3.11  1999/08/16  17:04:04  v2kea318
// *** empty log message ***
//
// Revision 3.10  1999/08/12  21:36:04  v2kea318
// Removed the rls_access() method.  This is no longer necessary given
// the new use of the get_accesss() method.
//
// Revision 3.9  1999/08/12  19:25:17  v2kea318
// Do not embed C++ (//) style comments inside C (/* */) style comments.
//
// Revision 3.8  1999/08/10  21:18:49  v2kea318
// *** empty log message ***
//
// Revision 3.7  1999/08/10  21:18:12  v2kea318
// Fix the code in the register_user method that checks for duplicate
// entries.
//
// Revision 3.6  1999/08/09  22:35:23  v2kea318
// Add a check in register_user that the user isn't already registered.  This
// is done by checking the port number.  This will prevent multiple copies of
// the same entry in the table.  Such entries could arise prior to this fix if
// a daemon process died without properly cleaning up after itself in this table,
// e.g. it died with a SIGKILL.
//
// Revision 3.5  1999/08/06  15:31:08  v2kea318
// Made the required changes to MsgUserTable::register_user and the
// UserInformation constructor for the new design of the UserInformation
// object.
//
// Revision 3.4  1999/07/30  21:35:41  v2kea318
// Use the Mutex class to represent mutices.
//
// Revision 3.3  1999/07/30  20:24:09  v2kea318
// Finished converting to G++ compliant code.
//
// Revision 3.2  1999/05/20  16:11:57  v2kea318
// Redesigned the table again, this time to use the user id alone as the
// key for the map.  This allows us to actually use the map properties for
// accessing data in the table.
//
// Revision 3.1  1999/05/19  20:25:28  v2kea318
// Reimplement the table using a multimap container
// from STL.
//
// Revision 2.1  1999/05/11  17:16:30  v2kea318
// Lock and unlock the mutex object for the list in all operations.
//
// Revision 1.3  1999/05/06  21:10:49  v2kea318
// Search the table for user id's via the STL for_each algorithm.
//
// Revision 1.2  1999/05/06  19:33:05  v2kea318
// Change the remove method to let the list do the work.
//
// Revision 1.1  1999/05/03  18:39:55  v2kea318
// Initial revision
//
//***************************************************************************

#include "msg_user_table.h"

//***************************************************************************

MsgUserTable::~MsgUserTable() 
{
  MutexRep m = get_access();

  // clear the table.
  table.clear();
}

//***************************************************************************

typedef pair<MsgUserTable::TableType::iterator, 
    MsgUserTable::TableType::iterator> IteratorPair;

//***************************************************************************

void MsgUserTable::register_user(const string& id, SocketPtr s, int p)
{
  // get the name of the machine to which the socket is connected.
  string host = s->gethostname();

  // build the user info object.
  UserInformation user(id, host, p);

  // Ensure this user isn't already registered.
  MutexRep m = get_access();
  IteratorPair range = table.equal_range(id);
  for (; range.first != range.second; range.first++)
      if (range.first->second == user && range.first->second.port == p) 
	  return;
  
  // add it to the table.
  table.insert(TableType::value_type(id, user));
}

//***************************************************************************

void MsgUserTable::remove(const string& id, const string& machine)
{
  // get control of the table.
  MutexRep m = get_access();

  // delete each entry with the specified machine
  IteratorPair range = table.equal_range(id);
  for (; range.first != range.second; range.first++) 
    if (range.first->second.machine == machine) table.erase(range.first);
}

//***************************************************************************

template <class IteratorType>
static void build_list(IteratorType low, IteratorType high,
		       Pointer<MsgUserTable::UserInfoList>& lst)
{
  for (; low != high; low++) lst->push_back(low->second);
}

template <class IteratorType>
static void build_list(pair<IteratorType, IteratorType> range,
		       Pointer<MsgUserTable::UserInfoList>& lst)
{
  build_list(range.first, range.second, lst);
}

//***************************************************************************

Pointer<MsgUserTable::UserInfoList> MsgUserTable::all_users() const
{
  // build the list.
  Pointer<MsgUserTable::UserInfoList> lst(new MsgUserTable::UserInfoList);

  // copy the contents.
  MutexRep m = get_access();
  build_list(table.begin(), table.end(), lst);

  // return the list.
  return lst;
}

//***************************************************************************

Pointer<MsgUserTable::UserInfoList>
MsgUserTable::query_user(const string& id) const
{
  // build a new list.
  Pointer<UserInfoList> userlist(new UserInfoList);

  // iterate over the table.
  MutexRep m = get_access();
  build_list(table.equal_range(id), userlist);

  // return the list.
  return userlist;
}

//***************************************************************************

MutexRep MsgUserTable::get_access() const
{
  return mut;
}

