/* $Id: msg_user_table.h,v 3.13 1999/10/22 20:50:46 v2kea318 Exp $

$Log: msg_user_table.h,v $
 * Revision 3.13  1999/10/22  20:50:46  v2kea318
 * Use the OO Thread interface for thread things.
 *
 * Revision 3.12  1999/10/14  16:41:47  v2kea318
 * Use the pseudo machine independant thread.h header to define all
 * thread related things.
 *
 * Revision 3.11  1999/08/16  17:04:23  v2kea318
 * Move the MutexRep class to a separate header file.
 *
 * Revision 3.10  1999/08/12  21:45:53  v2kea318
 * Wrote a wrapper class for the Mutex.  This wrapper will work off the
 * reference count for the Pointer<Mutex> member variable.  When this count
 * is 2 (indicating the MsgUserTable::mut and a single copy) the wrapper
 * destructor will release the mutex.  This is perhaps overkill since the
 * Mutex destructor itself will check a reference count before destroying.
 * If get_access() returned a copy of a Mutex object to a local variable,
 * then when that local copy is destroyed, the Mutex destructor would be
 * called and the mutex released.  But, this assumes there are no temporaries
 * around, since destroying any temporary would also release the mutex.
 * This is safer and more general.
 *
 * Revision 3.9  1999/08/09  15:11:28  v2kea318
 * Remove the use of the Mutex::initialize() method.  This is now private
 * in the Mutex class.
 *
 * Revision 3.8  1999/08/06  15:39:08  v2kea318
 * *** empty log message ***
 *
 * Revision 3.7  1999/08/06  15:38:25  v2kea318
 * Removed the mutex object in UserInformation.  Since the socket is no
 * longer stored here, there is no need for a mutex to control access to it.
 *
 * Revision 3.6  1999/08/06  15:29:57  v2kea318
 * Added the port number to the UserInformation structure and eliminated
 * the socket object.
 *
 * Revision 3.5  1999/07/30  21:37:18  v2kea318
 * Use the Mutex class to represent all the mutices.  Changed the
 * UserInformation::gain_socket() method to return a copy of the Mutex.
 * This makes resource management easier, since the Mutex destuctor will
 * take care of the release automatically.
 *
 * Revision 3.4  1999/07/30  20:40:50  v2kea318
 * Use Pthread.h instead of pthread.h to define threads.  This is a
 * temporary kludge because of some extraneous spaces in the standard
 * version.
 *
 * Revision 3.3  1999/07/30  20:24:09  v2kea318
 * Finished converting to G++ compliant code.
 *
 * Revision 3.2  1999/07/30  17:55:48  v2kea318
 * Reformat the header file names for Standard C++ compliance.
 *
 * Revision 3.1  1999/05/19  20:24:57  v2kea318
 * Reimplement the table using a multimap container
 * from STL.
 *
 * Revision 2.1  1999/05/11  17:15:51  v2kea318
 * Added mutex objects to the table and to each UserInformation object.
 * Table operations are implemented internally to first lock the mutex,
 * do the operations, then unlock the mutex.  The user must do this
 * for the Information block.  This new design will allow multiple threads
 * to access the table simultaneously.
 *
 * Revision 1.4  1999/05/06  19:55:12  v2kea318
 * Fixed the assignment operator for UserInformation to make sure we're
 * not assigning to ourself.
 *
 * Revision 1.3  1999/05/06  19:32:21  v2kea318
 * Changed the == operator for UserInformation objects; we don't need
 * to compare the sockets, just userid and machine.
 *
 * Revision 1.2  1999/05/06  19:19:25  v2kea318
 * Many changes to the UserInformation structure to accomidate STL lists.
 *
 * Revision 1.1  1999/05/03  18:40:07  v2kea318
 * Initial revision
 *
***************************************************************************

A class to manage a table of registered users for the msg system.  The
table will store the user's name and the machine name and port on which
the user's daemon program is running.

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

#ifndef MSG_USER_TABLE_H
#define MSG_USER_TABLE_H

#include "MutexRep.h"
#include <list>
#include <multimap.h>
#include <stdexcept>
#include <strstream>
#include "Socket.h"
#include <string>
#include "pointer.h"

class MsgUserTable {
private:
  mutable MutexRep mut;  
  MutexRep get_access() const;  // get access to the mutex.
public:  
  // define a shorthand for a pointer to a Socket.
  typedef Pointer<Socket> SocketPtr;

  // define a data structure to store information about a user.
  class UserInformation {
  public:
    string userid;         // the user ID of the user
    string machine;        // the machine the user is running on.
    int port;              // the port the daemon is running on.
    UserInformation(const string& id = string(), const string& m = string(),
		    int p = -1)
	: userid(id), machine(m), port(p) {}
    UserInformation(const UserInformation& ui) 
      : userid(ui.userid), machine(ui.machine), port(ui.port) {}
    ~UserInformation() {}
    UserInformation& operator = (const UserInformation& uin)
      {
	if (this != &uin) {
	  userid = uin.userid;
	  machine = uin.machine;
	  port = uin.port;
	}
	return *this;
      }
    bool operator == (const UserInformation& uin) const
      {
	return ((userid == uin.userid) &&
		(machine == uin.machine));
      }
    bool operator < (const UserInformation& uin) const
      {
	return (userid < uin.userid);
      }
  };

  // define a shorthand for a list of UserInformation objects.
  typedef list<UserInformation> UserInfoList;

public:
  // constructors.
  MsgUserTable() : mut(), table() {};

  // destructor.
  ~MsgUserTable();

  // register a user.  The user's machine is obtained from the socket.
  void register_user(const string& id, SocketPtr s, int p);

  // de-register a user.  Needs the user ID and machine.
  void remove(const string& id, const string& machine);

  // build a list of all registered connections for a given user ID.
  Pointer<UserInfoList> query_user(const string& id) const;
  
  // return the entire list
  Pointer<UserInfoList> all_users() const;

private:
  // implement the table as map of string keys to UserInfomation objects.
  typedef multimap<string, UserInformation, less<string> > TableType;
  TableType table;
};

#endif
