summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOssama Othman <ossama-othman@users.noreply.github.com>2001-06-15 16:55:31 +0000
committerOssama Othman <ossama-othman@users.noreply.github.com>2001-06-15 16:55:31 +0000
commite7c92e7379041715206d05bfd822df80e4c8b50a (patch)
tree13750bc1f792b72fd899c453fc01d932058c5108
parentcfb1ef27ea0d516eedc67cee490d9fcfd2ac5ff9 (diff)
downloadATCD-e7c92e7379041715206d05bfd822df80e4c8b50a.tar.gz
*** empty log message ***
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_GenericFactory.cpp53
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_GenericFactory.h6
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_ObjectGroup_Map.h10
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.cpp90
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.h88
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.cpp97
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.h159
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.inl45
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_Redirect_Table.cpp180
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_Redirect_Table.h100
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.cpp21
-rw-r--r--TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.h59
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing.idl23
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.cpp53
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.h6
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ObjectGroup_Map.h10
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.cpp90
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.h88
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.cpp97
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.h159
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.inl45
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp180
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.h100
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.cpp21
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.h59
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.cpp13
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.h2
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancing/NOTES3
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancingI.cpp13
-rw-r--r--TAO/orbsvcs/orbsvcs/LoadBalancingI.h2
-rw-r--r--TAO/orbsvcs/orbsvcs/NOTES3
31 files changed, 1809 insertions, 66 deletions
diff --git a/TAO/orbsvcs/orbsvcs/LB_GenericFactory.cpp b/TAO/orbsvcs/orbsvcs/LB_GenericFactory.cpp
index 753de0ee129..4a14567477f 100644
--- a/TAO/orbsvcs/orbsvcs/LB_GenericFactory.cpp
+++ b/TAO/orbsvcs/orbsvcs/LB_GenericFactory.cpp
@@ -1,6 +1,8 @@
// -*- C++ -*-
#include "LB_GenericFactory.h"
+#include "LB_ReplicaInfo.h"
+
ACE_RCSID (LoadBalancing,
LB_GenericFactory,
@@ -141,39 +143,44 @@ TAO_LB_GenericFactory::delete_object (
if (this->object_group_map_.find (fcid, object_group) == -1)
ACE_THROW (LoadBalancing::ObjectNotFound ());
- TAO_LB_Replica_Map *replica_map = object_group->replica_map;
+ TAO_LB_ReplicaInfo_Set &replica_infos = object_group->replica_infos;
- for (TAO_LB_Replica_Map::Table::iterator i = replica_map->begin ();
- i != replica_map->end ();
- ++i)
- {
- TAO_LB_Replica_Map_Entry *replica = (*i).ext_id_;
+ {
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, object_group->lock);
+ for (TAO_LB_ReplicaInfoSetIterator i = replica_infos.begin ();
+ i != replica_infos.end ();
+ ++i)
+ {
+ TAO_LB_ReplicaInfo *replica_info = (*i).ext_id_;
- LoadBalancing::GenericFactory_ptr factory =
- replica->factory.in ();
+ LoadBalancing::GenericFactory_ptr factory =
+ replica_info->factory_info.the_factory.in ();
- if (!CORBA::is_nil (factory))
- {
- LoadBalancing::GenericFactory::FactoryCreationId
- &replica_fcid = replica->factory_creation_id;
+ // If the factory reference is not nil, then the replica
+ // was created using a GenericFactory. Make sure that
+ // factory deletes it.
+ if (!CORBA::is_nil (factory))
+ {
+ LoadBalancing::GenericFactory::FactoryCreationId
+ &replica_fcid = replica_info->factory_creation_id;
- factory->delete_object (replica_fcid.in, ACE_TRY_ENV);
- ACE_CHECK;
- }
+ factory->delete_object (replica_fcid.in (), ACE_TRY_ENV);
+ ACE_CHECK;
+ }
-
- (void) replica_map->unbind (&(*i));
+ (void) replica_info->unbind (&(*i));
- delete replica_map;
- }
+ delete replica_info;
+ }
+ }
// Now delete the ObjectGroup from the set of ObjectGroups.
this->object_group_map_.unbind (fcid);
delete object_group;
}
-
- ACE_THROW (LoadBalancing::ObjectNotFound ());
+ else
+ ACE_THROW (LoadBalancing::ObjectNotFound ());
}
void
@@ -184,7 +191,7 @@ TAO_LB_GenericFactory::populate_object_group (
for (CORBA::ULong j = 0; j < factory_infos_count; ++j)
{
// The FactoryInfo::the_location member was used when
- // determining which FactoryInfo
+ // determining which FactoryInfo
// member?
// @@ It looks like it is only used when the application
// control membership style is used. The application
@@ -270,7 +277,7 @@ TAO_LB_GenericFactory::populate_object_group (
}
// No longer need to protect the allocated Replica_Map.
- safe_replica_entry.release ();
+ safe_replica_info.release ();
}
}
diff --git a/TAO/orbsvcs/orbsvcs/LB_GenericFactory.h b/TAO/orbsvcs/orbsvcs/LB_GenericFactory.h
index 0ed484b8656..811d5974fbe 100644
--- a/TAO/orbsvcs/orbsvcs/LB_GenericFactory.h
+++ b/TAO/orbsvcs/orbsvcs/LB_GenericFactory.h
@@ -35,8 +35,12 @@ class TAO_LB_ObjectGroup_Map;
/**
* @class TAO_LB_GenericFactory
*
- * @brief
+ * @brief LoadBalancing::GenericFactory implementation used by the
+ * load balancer when creating object groups.
*
+ * This GenericFactory creates an object group reference for given set
+ * of replicas. Those replicas will be created by this GenericFactory
+ * if the "infrastructure-controlled" membership style is configured.
*/
class TAO_LB_GenericFactory
: public virtual LoadBalancing::GenericFactory
diff --git a/TAO/orbsvcs/orbsvcs/LB_ObjectGroup_Map.h b/TAO/orbsvcs/orbsvcs/LB_ObjectGroup_Map.h
index 3de656e0788..07843e8f37e 100644
--- a/TAO/orbsvcs/orbsvcs/LB_ObjectGroup_Map.h
+++ b/TAO/orbsvcs/orbsvcs/LB_ObjectGroup_Map.h
@@ -25,7 +25,7 @@
#include "ace/Hash_Map_Manager_T.h"
#include "orbsvcs/LoadBalancingC.h"
-#include "LB_Replica_Set.h"
+#include "LB_ReplicaInfo_Set.h"
/**
@@ -37,13 +37,12 @@
*/
class TAO_LB_ObjectGroup_Map
{
-
public:
/**
* @class Map_Entry
*
- * @brief Value field of the replica map.
+ * @brief Value field of the ObjectGroup map.
*
* Mapping from and to all of the following fields:
* @param object_group, @param factory_creation_id, @param factory,
@@ -57,11 +56,14 @@ public:
CORBA::String_var type_id;
/// Reference to the ObjectGroup.
- TAO_LoadBalancing::ObjectGroup_var object_group;
+ LoadBalancing::ObjectGroup_var object_group;
/// Unbounded set containing replica references and all related
/// information for each replica.
TAO_LB_ReplicaInfo_Set replica_infos;
+
+ /// Lock used to synchronize access to the ReplicaInfo set.
+ TAO_SYNCH_MUTEX lock;
};
/// FactoryCreationId hash map. A FactoryCreationId is represented
diff --git a/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.cpp b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.cpp
new file mode 100644
index 00000000000..99604af4fa7
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.cpp
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+
+#include "LB_RPMS_Monitor.h"
+
+
+ACE_RCSID (LoadBalancing,
+ LB_RPMS_Monitor,
+ "$Id$")
+
+TAO_LB_RPMS_Monitor::TAO_LB_RPMS_Monitor (void)
+{
+}
+
+void
+TAO_LB_RPMS_Monitor::init (CORBA::Environment &ACE_TRY_ENV)
+{
+ // Possibly no CORBA exceptions instantiated yet so don't attempt
+ // to throw one if allocation fails.
+
+ TAO_LB_RPMS_Monitor_Interceptor *& interceptor =
+ this->interceptor_.out ();
+
+ ACE_NEW (interceptor,
+ TAO_LB_RPMS_Monitor_Interceptor (this->object_group_.in ()));
+
+ TAO_LB_RPMS_Monitor_ORBInitializer *initializer = 0;
+ ACE_NEW (temp_initializer,
+ TAO_LB_RPMS_Monitor_ORBInitializer (this->interceptor_.in ()));
+
+ PortableInterceptor::ORBInitializer_var orb_initializer =
+ temp_initializer;
+
+ PortableInterceptor::register_orb_initializer (initializer.in (),
+ ACE_TRY_ENV);
+ ACE_CHECK;
+}
+
+LoadBalancing::LoadList *
+TAO_LB_RPMS_Monitor::current_load (CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // Construct the LoadList here instead of inside the interceptor to
+ // maximize throughput in a multithreaded server replica by
+ // preventing two allocations from being added to the critical path
+ // of the client request.
+ //
+ // This optimization won't make a difference on single-threaded
+ // server replicas.
+
+ LoadBalancing::LoadList *tmp_loads = 0;
+ ACE_NEW_THROW_EX (LoadBalancing::LoadList,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ LoadBalancing::LoadList_var loads = tmps_loads;
+
+ loads->length (1);
+
+ // The LoadId should be unique within the location this monitor
+ // resides.
+ loads[0].identifier = 0; // @todo Use a symbolic constant instead.
+
+ loads[0].value = this->interceptor_->current_load ();
+
+ return loads._retn ();
+}
+
+void
+TAO_LB_RPMS_Monitor::register_redirect (const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->interceptor_.register_redirect (type_id,
+ redirect_to,
+ ACE_TRY_ENV);
+}
+
+void
+TAO_LB_RPMS_Monitor::remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->interceptor_.remove_redirect (type_id,
+ ACE_TRY_ENV);
+}
diff --git a/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.h b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.h
new file mode 100644
index 00000000000..31f6a2705e6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor.h
@@ -0,0 +1,88 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_RPMS_Monitor.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_LB_RPMS_MONITOR_H
+#define TAO_LB_RPMS_MONITOR_H
+
+#include "ace/pre.h"
+
+#include "LoadBalancing_export.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/LoadBalancingS.h"
+
+#include "LB_RPMS_Monitor_Interceptor.h"
+
+
+/**
+ * @class TAO_LB_RPMS_Monitor
+ *
+ * @brief LoadMonitor implementation that returns monitor the number
+ * of requests per second a given location receives.
+ *
+ * Since interceptors are locality-constrained, the Load Balancer
+ * actually makes feedback and control invocations methods through
+ * this LoadMonitor exposed by this LoadMonitor. This LoadMonitor
+ * basically delegates all of its work on to its underlying
+ * ServerRequestInterceptor.
+ */
+class TAO_LoadBalancing_Export TAO_LB_RPMS_Monitor
+ : public virtual POA_LoadBalancing::LoadMonitor
+{
+public:
+
+ /// Constructor
+ TAO_LB_RPMS_Monitor (void);
+
+ /**
+ * @name LoadBalancing::LoadMonitor Methods
+ */
+ //@{
+
+ /// Return the number of requests per second arriving at the
+ /// location this load monitor resides.
+ virtual LoadBalancing::LoadList *current_load (
+ CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ())
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Force redirection of requests for targets with the given
+ /// RepositoryId to the target pointed to by the given object
+ /// reference.
+ virtual void register_redirect (
+ const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ())
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Remove the redirect for targets of the given RepositoryId.
+ virtual void remove_redirect (
+ const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ())
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ //@}
+
+private:
+
+ /// Interceptor responsible for keeping track of the number of
+ /// requests arriving per second.
+ TAO_LB_RPMS_Monitor_Interceptor_var interceptor_;
+
+};
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_RPMS_MONITOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.cpp b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.cpp
new file mode 100644
index 00000000000..c8c9d5f2af7
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.cpp
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+
+#include "LB_RPMS_Monitor_Interceptor.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_RPMS_Monitor_Interceptor,
+ "$Id$")
+
+
+#if defined (__ACE_INLINE__)
+# include "LB_RPMS_Monitor_Interceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+
+TAO_LB_RPMS_Monitor_Interceptor::TAO_LB_RPMS_Monitor_Interceptor (
+ CORBA::Object_ptr object_group)
+ : lock_ (),
+ redirect_table_ (),
+ request_count_ (0),
+ interval_start_ (ACE_OS::gettimeofday ()),
+ object_group_ ()
+{
+}
+
+char *
+TAO_LB_RPMS_Monitor_Interceptor::name (TAO_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // @todo It might be necessary to use an anonymous interceptor,
+ // i.e. an interceptor whose name is the empty string ("") in
+ // case multiple interceptors of this type are registered with
+ // an ORB.
+ return CORBA::string_dup ("TAO_LB_RPMS_Monitor_Interceptor");
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::destroy (TAO_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->redirect_table_.destroy ();
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+ TAO_ENV_ARG_DEFN;
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ ++this->request_count_;
+
+ // If required to do so by the load balancer, redirect all
+ // requests back to the target corresponding to the RepositoryId in
+ // redirect table.
+ this->redirect_table_.find_redirect (ri,
+ ACE_TRY_ENV);
+ ACE_CHECK;
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::send_other (
+ PortableInterceptor::ServerRequestInfo_ptr
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
diff --git a/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.h b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.h
new file mode 100644
index 00000000000..cb0a7ccb247
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.h
@@ -0,0 +1,159 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_RPMS_Monitor_Interceptor.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_LB_RPMS_MONITOR_INTERCEPTOR_H
+#define TAO_LB_RPMS_MONITOR_INTERCEPTOR_H
+
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#includ "ace/Sync.h"
+
+#include "tao/PortableInterceptorC.h"
+#include "tao/LocalObject.h"
+
+/**
+ * @class TAO_LB_RPMS_Monitor_Interceptor
+ *
+ * @brief ServerRequestInterceptor that provides feedback and
+ * control.
+ *
+ * This ServerRequestInterceptor is used to count the number of
+ * requests per millisecond that are arriving at the location this
+ * interceptor resides.
+ */
+class TAO_LB_RPMS_Monitor_Interceptor
+ : public virtual PortableInterceptor::ServerRequestInterceptor,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+ /// Constructor
+ TAO_LB_RPMS_Monitor (void);
+
+ /**
+ * @name Methods Required by the ServerRequestInterceptor
+ * Interface
+ *
+ * These are methods that must be implemented since they are pure
+ * virtual in the abstract base class. They are the canonical
+ * methods required for all server request interceptors.
+ */
+ //@{
+
+ virtual char * name (TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void destroy (TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// The bulk of the work this interceptor implementations performs
+ /// is in this interception point.
+ virtual void receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+ virtual void receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+ virtual void send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+ virtual void send_other (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+ //@}
+
+ /**
+ * @name Feedback and control methods.
+ *
+ * Methods that indirectly provide feedback and control to the load
+ * balancer via the load monitor.
+ */
+ //@{
+
+ /// Return the current average load (requests per second).
+ CORBA::Float current_load (void) const;
+
+ /// Force redirection of requests for targets with the given
+ /// RepositoryId to the target pointed to by the given object
+ /// reference.
+ void register_redirect (const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Remove the redirect for targets of the given RepositoryId.
+ void remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ //@}
+
+public:
+
+ /// This template is actually instantiated in
+ /// `tao/Object_Ref_Table.cpp'.
+ typedef ACE_Hash_Map_Manager_Ex<const char *, CORBA::Object_ptr, ACE_Hash<const char *>, ACE_Equal_To<const char *>, ACE_Null_Mutex> Table;
+
+private:
+
+ /// Lock that forces access request count to be modified/accessed
+ /// atomically.
+ TAO_SYNCH_MUTEX lock_;
+
+ /// Flag that if set true will cause this interceptor to redirect
+ /// all requests back to the load balancer.
+ CORBA::Boolean redirect_requests_;
+
+ /// The number of requests received at the location this interceptor
+ /// resides in the current measurement interval.
+ CORBA::ULong request_count_;
+
+ // The start of the current measurement interval.
+ ACE_Time_Value interval_start_;
+
+ /// Reference to the Load Balancer.
+ LoadBalancing::ReplicationManager_var lb_;
+
+
+
+};
+
+
+#if defined (__ACE_INLINE__)
+# include "LB_RPMS_Monitor_Interceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_RPMS_MONITOR_INTERCEPTOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.inl b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.inl
new file mode 100644
index 00000000000..4cd431f4f15
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_RPMS_Monitor_Interceptor.inl
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+
+ACE_INLINE CORBA::Float
+TAO_LB_RPMS_Monitor_Interceptor::current_load (void) const
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ ACE_Time_Value elapsed_time =
+ ACE_OS::gettimeofday () - this->interval_start_;
+
+ this->interval_start_ = ACE_OS::gettimeofday ();
+
+ CORBA::Float load =
+ ACE_static_cast (CORBA::Float,
+ this->request_count_) / elapsed_time.msec ();
+
+ this->request_count_ = 0;
+ this->interval_start_ = ACE_OS::gettimeofday ();
+
+ return load;
+}
+
+ACE_INLINE void
+TAO_LB_RPMS_Monitor_Interceptor::register_redirect (
+ const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ this->redirect_table_.register_redirect (type_id,
+ redirect_to,
+ ACE_TRY_ENV);
+}
+
+ACE_INLINE void
+TAO_LB_RPMS_Monitor_Interceptor::remove_redirect (
+ const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ this->redirect_table_.remove_redirect (type_id,
+ ACE_TRY_ENV);
+}
diff --git a/TAO/orbsvcs/orbsvcs/LB_Redirect_Table.cpp b/TAO/orbsvcs/orbsvcs/LB_Redirect_Table.cpp
new file mode 100644
index 00000000000..9a6b33d519a
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_Redirect_Table.cpp
@@ -0,0 +1,180 @@
+// -*- C++ -*-
+
+#include "LB_Redirect_Table.h"
+#include "Object.h"
+#include "Exception.h"
+#include "Environment.h"
+#include "CORBA_String.h"
+#include "debug.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_Redirect_Table,
+ "$Id$")
+
+// ****************************************************************
+
+TAO_LB_Redirect_Table::TAO_LB_Redirect_Table (void)
+ : table_ ()
+{
+}
+
+TAO_LB_Redirect_Table::~TAO_LB_Redirect_Table (void)
+{
+ // Must explicitly call destroy() in the destructor since not all
+ // applications will invoke ORB::shutdown() or ORB::destroy().
+ this->destroy ();
+}
+
+void
+TAO_LB_Redirect_Table::register_redirect (
+ const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ // The RepositoryId should never be zero since it is not possible to
+ // send a NULL string as an "in" argument.
+ if (ACE_OS_String::strlen (id) == 0)
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ if (CORBA::is_nil (obj))
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ int result = this->bind (type_id, redirect_to);
+
+ if (result == 1)
+ {
+ if (TAO_debug_level > 1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) LB_Redirect_Table::register_redirect:\n"
+ " Could not register duplicate object <%s> with "
+ "the LB_Redirect_Table\n",
+ type_id));
+
+ ACE_THROW (CORBA::INV_OBJREF ());
+ }
+
+ if (result == -1)
+ {
+ if (TAO_debug_level > 1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) LB_Redirect_Table::register_redirect:\n"
+ " Could not register redirect object <%s> with "
+ "the LB_Redirect_Table\n",
+ type_id));
+
+ ACE_THROW (CORBA::INTERNAL ());
+ }
+}
+
+void
+TAO_LB_Redirect_Table::find_redirect (
+ PortableInterceptor::ServerRequestInfo_ptr ri,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ // This could become very slow if there are many type of targets
+ // being redirected since we're doing a linear search using string
+ // comparisons.
+ //
+ // We do things this way to avoid the memory allocation that would
+ // occur if we were to just use the
+ // ServerRequestInfo::target_most_derived_interface() method. At
+ // some point, there is a threshold reached where the cost of the
+ // iteration through the redirect table is more expensive than the
+ // allocation incurred by calling
+ // ServerRequestInfo::target_most_derived_interface(). That
+ // threshold is approached as the number of redirects in the table
+ // becomes "large." For now, we optimize for the common case and
+ // assume that only a few types of targets (i.e. objects/servants
+ // with different RepositoryIds) exist at the current location.
+ //
+ // Note that if no redirects are registered, then this method
+ // basically becomes a no-op.
+
+ for (Table::iterator i = this->table_.begin ();
+ i != this->table_.end ();
+ ++i)
+ {
+ // Compare the target's RepositoryId with the registered
+ // redirects.
+ CORBA::Boolean matched =
+ ri->target_is_a ((*i).ext_id_, ACE_TRY_ENV);
+ ACE_CHECK_RETURN (0);
+
+ if (matched)
+ ACE_THROW (PortableInterceptor::ForwardRequest (
+ (*i).int_id_,
+ 0 /* non-permanent forward */));
+ }
+}
+
+int
+TAO_LB_Redirect_Table::remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ Table::ENTRY *entry = 0;
+
+ int result = this->table_.find (type_id, entry);
+
+ if (result == 0)
+ {
+ // Deallocate the external ID and obtain the ORB core pointer
+ // before unbinding the entry since the entry is deallocated
+ // during the call to unbind().
+ CORBA::string_free (ACE_const_cast (char *, entry->ext_id_));
+ CORBA::Object_ptr redirect = entry->int_id_;
+
+ result = this->table_.unbind (entry);
+
+ if (result != 0)
+ return result;
+
+ CORBA::release (redirect);
+ }
+
+ return result;
+}
+
+void
+TAO_LB_Redirect_Table::destroy (void)
+{
+ for (Table::iterator i = this->table_.begin ();
+ i != this->table_.end ();
+ ++i)
+ {
+ // Deallocate the id.
+ CORBA::string_free (ACE_const_cast (char *, (*i).ext_id_));
+
+ // Release the Object.
+ CORBA::release ((*i).int_id_);
+ }
+
+ this->table_.unbind_all ();
+}
+
+int
+TAO_LB_Redirect_Table::bind (const char *id,
+ CORBA::Object_ptr obj)
+{
+ // Make sure that the supplied Object reference is valid,
+ // i.e. not nil.
+ if (id == 0 || CORBA::is_nil (obj))
+ {
+ errno = EINVAL;
+ return -1;
+ };
+
+ CORBA::String_var type_id = CORBA::string_dup (id);
+ CORBA::Object_var redirect = CORBA::Object::_duplicate (obj);
+
+ int result = this->table_.bind (type_id.in (),
+ redirect.in ());
+
+ if (result == 0)
+ {
+ // Transfer ownership to the Object Table.
+ (void) type_id._retn ();
+ (void) redirect._retn ();
+ }
+
+ return result;
+}
diff --git a/TAO/orbsvcs/orbsvcs/LB_Redirect_Table.h b/TAO/orbsvcs/orbsvcs/LB_Redirect_Table.h
new file mode 100644
index 00000000000..0b3d6d09161
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_Redirect_Table.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_Redirect_Table.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_LB_REDIRECT_TABLE_H
+#define TAO_LB_REDIRECT_TABLE_H
+
+#include "ace/pre.h"
+
+#include "corbafwd.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Functor.h"
+
+
+/**
+ * @class TAO_LB_Redirect_Table
+ *
+ * @brief Maintain a table of "redirects" corresponding to a target
+ * with the given RepositoryId.
+ *
+ * If a table entry for the given RepositoryId exists, then the load
+ * monitor will redirect the client request to the target pointed to
+ * by the object reference in that entry.
+ *
+ * It is necessary to maintain a redirect table since the load
+ * balancer determines which object group to select a replica from by
+ * examining the target's object ID. As such a request cannot simply
+ * be forwarded back to the load balancer without knowing what its
+ * intended target (i.e. object group) is. This table keeps track of
+ * the object group reference to which a replica of a given type
+ * belongs.
+ */
+class TAO_LB_Redirect_Table
+{
+public:
+
+ typedef ACE_Hash_Map_Manager_Ex<const char *, CORBA::Object_ptr, ACE_Hash<const char *>, ACE_Equal_To<const char *>, ACE_Null_Mutex> Table;
+
+ /// Constructor
+ TAO_LB_Redirect_Table (void);
+
+ /// Destructor
+ ~TAO_LB_Redirect_Table (void);
+
+ /// Register an object reference with the table, and map the given
+ /// ID to it.
+ void register_redirect (const char * type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Remove the redirect associated with the given RepositoryId.
+ void remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Check if a redirect exists for the current target. If so, then
+ /// perform the request redirection by throwing a
+ /// PortableInterceptor::ForwardRequest exception.
+ void find_redirect (PortableInterceptor::ServerRequestInfo_ptr ri,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Reclaim the resources held by this table (deallocate strings,
+ /// release object references, etc).
+ void destroy (void);
+
+private:
+
+ /// Helper method that binds the redirect to the given RepositoryId.
+ int bind (const char *type_id, CORBA::Object_ptr redirect_to);
+
+private:
+
+ /// Prevent copying
+ ACE_UNIMPLEMENTED_FUNC (TAO_LB_Redirect_Table (const TAO_LB_Redirect_Table &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const TAO_LB_Redirect_Table &))
+
+private:
+
+ /// The implementation.
+ Table table_;
+
+};
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_REDIRECT_TABLE_H */
diff --git a/TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.cpp b/TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.cpp
new file mode 100644
index 00000000000..7b4040585b5
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+
+#include "LB_ReplicaInfo.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_ReplicaInfo,
+ "$Id$")
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class ACE_Node<TAO_LB_ReplicaInfo *>;
+template class ACE_Unbounded_Set<TAO_LB_ReplicaInfo *>;
+template class ACE_Unbounded_Set_Iterator<TAO_LB_ReplicaInfo *>;
+
+#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate ACE_Node<TAO_LB_ReplicaInfo *>
+#pragma instantiate ACE_Unbounded_Set<TAO_LB_ReplicaInfo *>
+#pragma instantiate ACE_Unbounded_Set_Iterator<TAO_LB_ReplicaInfo *>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.h b/TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.h
new file mode 100644
index 00000000000..26ba0b5f5ff
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LB_ReplicaInfo.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file LB_ReplicaInfo.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_LB_REPLICA_INFO_H
+#define TAO_LB_REPLICA_INFO_H
+
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+#include "orbsvcs/LoadBalancingC.h"
+
+#include "LB_Replica_Set.h"
+
+class TAO_LB_ReplicaInfo;
+typedef ACE_Unbounded_Set<TAO_LB_ReplicaInfo *> TAO_LB_ReplicaInfoSet;
+typedef ACE_Unbounded_Set_Iterator<TAO_LB_ReplicaInfo *> TAO_LB_ReplicaInfoSetIterator;
+
+
+/**
+ * @class TAO_LB_ReplicaInfo
+ *
+ * @brief Class that contains all replica-specific information.
+ */
+class TAO_LB_ReplicaInfo
+{
+public:
+
+ /// Reference to the replica.
+ CORBA::Object_var replica;
+
+ /// FactoryInfo used when creating the replica.
+ LoadBalancing::FactoryInfo factory_info;
+
+ /// FactoryCreationId assigned to this replica. This
+ /// FactoryCreationId_var will contain a zero pointer if the replica
+ /// was not created using a GenericFactory.
+ LoadBalancing::GenericFactory::FactoryCreationId_var factory_creation_id;
+
+};
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_REPLICA_INFO_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing.idl b/TAO/orbsvcs/orbsvcs/LoadBalancing.idl
index 70362f547ac..efac122abad 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing.idl
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing.idl
@@ -18,6 +18,7 @@
#ifndef TAO_LOADBALANCING_IDL
#define TAO_LOADBALANCING_IDL
+#include "tao/PortableInterceptor.pidl"
#include "CosNaming.idl"
#include "orb.idl"
@@ -27,7 +28,7 @@
* @class LoadBalancing
*
* @brief This module defines the interfaces and data types used in
- * TAO's Load Balancing service.
+ * TAO's Load Balancing service.
* @par
* TAO's Load Balancer manages distribution of requests to replicas of
* a given Object in an effort to ensure that the applications/hosts
@@ -52,6 +53,7 @@ module LoadBalancing
/// Specification of Common Types and Exceptions for ReplicationManager
interface GenericFactory;
interface LoadNotifier;
+ interface LoadMonitor;
typedef unsigned long long ObjectGroupId;
typedef unsigned long ObjectGroupRefVersion;
@@ -168,7 +170,7 @@ module LoadBalancing
};
/// Specification of ObjectGroupManager Interface which
- /// ReplicationManager Inherits
+ /// ReplicationManager Inherits
interface ObjectGroupManager {
ObjectGroup create_member (in ObjectGroup object_group,
in Location the_location,
@@ -251,6 +253,23 @@ module LoadBalancing
};
+ /// Interface that all load monitors must implement.
+ interface LoadMonitor
+ {
+ /// Return the current load at the location the load monitor
+ /// resides.
+ readonly attribute LoadList current_load;
+
+ /// Force redirection of requests for targets with the given
+ /// RepositoryId to the target pointed to by the given object
+ /// reference.
+ void register_redirect (in string type_id,
+ in Object redirect_to);
+
+ /// Remove the redirect for targets of the given RepositoryId.
+ void remove_redirect (in string type_id);
+ };
+
};
#pragma prefix ""
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.cpp
index 753de0ee129..4a14567477f 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.cpp
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.cpp
@@ -1,6 +1,8 @@
// -*- C++ -*-
#include "LB_GenericFactory.h"
+#include "LB_ReplicaInfo.h"
+
ACE_RCSID (LoadBalancing,
LB_GenericFactory,
@@ -141,39 +143,44 @@ TAO_LB_GenericFactory::delete_object (
if (this->object_group_map_.find (fcid, object_group) == -1)
ACE_THROW (LoadBalancing::ObjectNotFound ());
- TAO_LB_Replica_Map *replica_map = object_group->replica_map;
+ TAO_LB_ReplicaInfo_Set &replica_infos = object_group->replica_infos;
- for (TAO_LB_Replica_Map::Table::iterator i = replica_map->begin ();
- i != replica_map->end ();
- ++i)
- {
- TAO_LB_Replica_Map_Entry *replica = (*i).ext_id_;
+ {
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, object_group->lock);
+ for (TAO_LB_ReplicaInfoSetIterator i = replica_infos.begin ();
+ i != replica_infos.end ();
+ ++i)
+ {
+ TAO_LB_ReplicaInfo *replica_info = (*i).ext_id_;
- LoadBalancing::GenericFactory_ptr factory =
- replica->factory.in ();
+ LoadBalancing::GenericFactory_ptr factory =
+ replica_info->factory_info.the_factory.in ();
- if (!CORBA::is_nil (factory))
- {
- LoadBalancing::GenericFactory::FactoryCreationId
- &replica_fcid = replica->factory_creation_id;
+ // If the factory reference is not nil, then the replica
+ // was created using a GenericFactory. Make sure that
+ // factory deletes it.
+ if (!CORBA::is_nil (factory))
+ {
+ LoadBalancing::GenericFactory::FactoryCreationId
+ &replica_fcid = replica_info->factory_creation_id;
- factory->delete_object (replica_fcid.in, ACE_TRY_ENV);
- ACE_CHECK;
- }
+ factory->delete_object (replica_fcid.in (), ACE_TRY_ENV);
+ ACE_CHECK;
+ }
-
- (void) replica_map->unbind (&(*i));
+ (void) replica_info->unbind (&(*i));
- delete replica_map;
- }
+ delete replica_info;
+ }
+ }
// Now delete the ObjectGroup from the set of ObjectGroups.
this->object_group_map_.unbind (fcid);
delete object_group;
}
-
- ACE_THROW (LoadBalancing::ObjectNotFound ());
+ else
+ ACE_THROW (LoadBalancing::ObjectNotFound ());
}
void
@@ -184,7 +191,7 @@ TAO_LB_GenericFactory::populate_object_group (
for (CORBA::ULong j = 0; j < factory_infos_count; ++j)
{
// The FactoryInfo::the_location member was used when
- // determining which FactoryInfo
+ // determining which FactoryInfo
// member?
// @@ It looks like it is only used when the application
// control membership style is used. The application
@@ -270,7 +277,7 @@ TAO_LB_GenericFactory::populate_object_group (
}
// No longer need to protect the allocated Replica_Map.
- safe_replica_entry.release ();
+ safe_replica_info.release ();
}
}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.h
index 0ed484b8656..811d5974fbe 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.h
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_GenericFactory.h
@@ -35,8 +35,12 @@ class TAO_LB_ObjectGroup_Map;
/**
* @class TAO_LB_GenericFactory
*
- * @brief
+ * @brief LoadBalancing::GenericFactory implementation used by the
+ * load balancer when creating object groups.
*
+ * This GenericFactory creates an object group reference for given set
+ * of replicas. Those replicas will be created by this GenericFactory
+ * if the "infrastructure-controlled" membership style is configured.
*/
class TAO_LB_GenericFactory
: public virtual LoadBalancing::GenericFactory
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ObjectGroup_Map.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ObjectGroup_Map.h
index 3de656e0788..07843e8f37e 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ObjectGroup_Map.h
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ObjectGroup_Map.h
@@ -25,7 +25,7 @@
#include "ace/Hash_Map_Manager_T.h"
#include "orbsvcs/LoadBalancingC.h"
-#include "LB_Replica_Set.h"
+#include "LB_ReplicaInfo_Set.h"
/**
@@ -37,13 +37,12 @@
*/
class TAO_LB_ObjectGroup_Map
{
-
public:
/**
* @class Map_Entry
*
- * @brief Value field of the replica map.
+ * @brief Value field of the ObjectGroup map.
*
* Mapping from and to all of the following fields:
* @param object_group, @param factory_creation_id, @param factory,
@@ -57,11 +56,14 @@ public:
CORBA::String_var type_id;
/// Reference to the ObjectGroup.
- TAO_LoadBalancing::ObjectGroup_var object_group;
+ LoadBalancing::ObjectGroup_var object_group;
/// Unbounded set containing replica references and all related
/// information for each replica.
TAO_LB_ReplicaInfo_Set replica_infos;
+
+ /// Lock used to synchronize access to the ReplicaInfo set.
+ TAO_SYNCH_MUTEX lock;
};
/// FactoryCreationId hash map. A FactoryCreationId is represented
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.cpp
new file mode 100644
index 00000000000..99604af4fa7
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.cpp
@@ -0,0 +1,90 @@
+// -*- C++ -*-
+
+#include "LB_RPMS_Monitor.h"
+
+
+ACE_RCSID (LoadBalancing,
+ LB_RPMS_Monitor,
+ "$Id$")
+
+TAO_LB_RPMS_Monitor::TAO_LB_RPMS_Monitor (void)
+{
+}
+
+void
+TAO_LB_RPMS_Monitor::init (CORBA::Environment &ACE_TRY_ENV)
+{
+ // Possibly no CORBA exceptions instantiated yet so don't attempt
+ // to throw one if allocation fails.
+
+ TAO_LB_RPMS_Monitor_Interceptor *& interceptor =
+ this->interceptor_.out ();
+
+ ACE_NEW (interceptor,
+ TAO_LB_RPMS_Monitor_Interceptor (this->object_group_.in ()));
+
+ TAO_LB_RPMS_Monitor_ORBInitializer *initializer = 0;
+ ACE_NEW (temp_initializer,
+ TAO_LB_RPMS_Monitor_ORBInitializer (this->interceptor_.in ()));
+
+ PortableInterceptor::ORBInitializer_var orb_initializer =
+ temp_initializer;
+
+ PortableInterceptor::register_orb_initializer (initializer.in (),
+ ACE_TRY_ENV);
+ ACE_CHECK;
+}
+
+LoadBalancing::LoadList *
+TAO_LB_RPMS_Monitor::current_load (CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // Construct the LoadList here instead of inside the interceptor to
+ // maximize throughput in a multithreaded server replica by
+ // preventing two allocations from being added to the critical path
+ // of the client request.
+ //
+ // This optimization won't make a difference on single-threaded
+ // server replicas.
+
+ LoadBalancing::LoadList *tmp_loads = 0;
+ ACE_NEW_THROW_EX (LoadBalancing::LoadList,
+ CORBA::NO_MEMORY (
+ CORBA::SystemException::_tao_minor_code (
+ TAO_DEFAULT_MINOR_CODE,
+ ENOMEM),
+ CORBA::COMPLETED_NO));
+ ACE_CHECK_RETURN (0);
+
+ LoadBalancing::LoadList_var loads = tmps_loads;
+
+ loads->length (1);
+
+ // The LoadId should be unique within the location this monitor
+ // resides.
+ loads[0].identifier = 0; // @todo Use a symbolic constant instead.
+
+ loads[0].value = this->interceptor_->current_load ();
+
+ return loads._retn ();
+}
+
+void
+TAO_LB_RPMS_Monitor::register_redirect (const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->interceptor_.register_redirect (type_id,
+ redirect_to,
+ ACE_TRY_ENV);
+}
+
+void
+TAO_LB_RPMS_Monitor::remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->interceptor_.remove_redirect (type_id,
+ ACE_TRY_ENV);
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.h
new file mode 100644
index 00000000000..31f6a2705e6
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor.h
@@ -0,0 +1,88 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_RPMS_Monitor.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_LB_RPMS_MONITOR_H
+#define TAO_LB_RPMS_MONITOR_H
+
+#include "ace/pre.h"
+
+#include "LoadBalancing_export.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "orbsvcs/LoadBalancingS.h"
+
+#include "LB_RPMS_Monitor_Interceptor.h"
+
+
+/**
+ * @class TAO_LB_RPMS_Monitor
+ *
+ * @brief LoadMonitor implementation that returns monitor the number
+ * of requests per second a given location receives.
+ *
+ * Since interceptors are locality-constrained, the Load Balancer
+ * actually makes feedback and control invocations methods through
+ * this LoadMonitor exposed by this LoadMonitor. This LoadMonitor
+ * basically delegates all of its work on to its underlying
+ * ServerRequestInterceptor.
+ */
+class TAO_LoadBalancing_Export TAO_LB_RPMS_Monitor
+ : public virtual POA_LoadBalancing::LoadMonitor
+{
+public:
+
+ /// Constructor
+ TAO_LB_RPMS_Monitor (void);
+
+ /**
+ * @name LoadBalancing::LoadMonitor Methods
+ */
+ //@{
+
+ /// Return the number of requests per second arriving at the
+ /// location this load monitor resides.
+ virtual LoadBalancing::LoadList *current_load (
+ CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ())
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Force redirection of requests for targets with the given
+ /// RepositoryId to the target pointed to by the given object
+ /// reference.
+ virtual void register_redirect (
+ const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ())
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// Remove the redirect for targets of the given RepositoryId.
+ virtual void remove_redirect (
+ const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV = TAO_default_environment ())
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ //@}
+
+private:
+
+ /// Interceptor responsible for keeping track of the number of
+ /// requests arriving per second.
+ TAO_LB_RPMS_Monitor_Interceptor_var interceptor_;
+
+};
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_RPMS_MONITOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.cpp
new file mode 100644
index 00000000000..c8c9d5f2af7
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.cpp
@@ -0,0 +1,97 @@
+// -*- C++ -*-
+
+#include "LB_RPMS_Monitor_Interceptor.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_RPMS_Monitor_Interceptor,
+ "$Id$")
+
+
+#if defined (__ACE_INLINE__)
+# include "LB_RPMS_Monitor_Interceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+
+TAO_LB_RPMS_Monitor_Interceptor::TAO_LB_RPMS_Monitor_Interceptor (
+ CORBA::Object_ptr object_group)
+ : lock_ (),
+ redirect_table_ (),
+ request_count_ (0),
+ interval_start_ (ACE_OS::gettimeofday ()),
+ object_group_ ()
+{
+}
+
+char *
+TAO_LB_RPMS_Monitor_Interceptor::name (TAO_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ // @todo It might be necessary to use an anonymous interceptor,
+ // i.e. an interceptor whose name is the empty string ("") in
+ // case multiple interceptors of this type are registered with
+ // an ORB.
+ return CORBA::string_dup ("TAO_LB_RPMS_Monitor_Interceptor");
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::destroy (TAO_ENV_SINGLE_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+ this->redirect_table_.destroy ();
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+ TAO_ENV_ARG_DEFN;
+
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ ++this->request_count_;
+
+ // If required to do so by the load balancer, redirect all
+ // requests back to the target corresponding to the RepositoryId in
+ // redirect table.
+ this->redirect_table_.find_redirect (ri,
+ ACE_TRY_ENV);
+ ACE_CHECK;
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException))
+{
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
+
+void
+TAO_LB_RPMS_Monitor_Interceptor::send_other (
+ PortableInterceptor::ServerRequestInfo_ptr
+ TAO_ENV_ARG_DECL_NOT_USED)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest))
+{
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.h
new file mode 100644
index 00000000000..cb0a7ccb247
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.h
@@ -0,0 +1,159 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_RPMS_Monitor_Interceptor.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_LB_RPMS_MONITOR_INTERCEPTOR_H
+#define TAO_LB_RPMS_MONITOR_INTERCEPTOR_H
+
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+# if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+# endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#includ "ace/Sync.h"
+
+#include "tao/PortableInterceptorC.h"
+#include "tao/LocalObject.h"
+
+/**
+ * @class TAO_LB_RPMS_Monitor_Interceptor
+ *
+ * @brief ServerRequestInterceptor that provides feedback and
+ * control.
+ *
+ * This ServerRequestInterceptor is used to count the number of
+ * requests per millisecond that are arriving at the location this
+ * interceptor resides.
+ */
+class TAO_LB_RPMS_Monitor_Interceptor
+ : public virtual PortableInterceptor::ServerRequestInterceptor,
+ public virtual TAO_Local_RefCounted_Object
+{
+public:
+
+ /// Constructor
+ TAO_LB_RPMS_Monitor (void);
+
+ /**
+ * @name Methods Required by the ServerRequestInterceptor
+ * Interface
+ *
+ * These are methods that must be implemented since they are pure
+ * virtual in the abstract base class. They are the canonical
+ * methods required for all server request interceptors.
+ */
+ //@{
+
+ virtual char * name (TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void destroy (TAO_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ /// The bulk of the work this interceptor implementations performs
+ /// is in this interception point.
+ virtual void receive_request_service_contexts (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+ virtual void receive_request (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+ virtual void send_reply (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException));
+
+ virtual void send_exception (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+
+ virtual void send_other (
+ PortableInterceptor::ServerRequestInfo_ptr ri
+ TAO_ENV_ARG_DECL_WITH_DEFAULTS)
+ ACE_THROW_SPEC ((CORBA::SystemException,
+ PortableInterceptor::ForwardRequest));
+ //@}
+
+ /**
+ * @name Feedback and control methods.
+ *
+ * Methods that indirectly provide feedback and control to the load
+ * balancer via the load monitor.
+ */
+ //@{
+
+ /// Return the current average load (requests per second).
+ CORBA::Float current_load (void) const;
+
+ /// Force redirection of requests for targets with the given
+ /// RepositoryId to the target pointed to by the given object
+ /// reference.
+ void register_redirect (const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Remove the redirect for targets of the given RepositoryId.
+ void remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ //@}
+
+public:
+
+ /// This template is actually instantiated in
+ /// `tao/Object_Ref_Table.cpp'.
+ typedef ACE_Hash_Map_Manager_Ex<const char *, CORBA::Object_ptr, ACE_Hash<const char *>, ACE_Equal_To<const char *>, ACE_Null_Mutex> Table;
+
+private:
+
+ /// Lock that forces access request count to be modified/accessed
+ /// atomically.
+ TAO_SYNCH_MUTEX lock_;
+
+ /// Flag that if set true will cause this interceptor to redirect
+ /// all requests back to the load balancer.
+ CORBA::Boolean redirect_requests_;
+
+ /// The number of requests received at the location this interceptor
+ /// resides in the current measurement interval.
+ CORBA::ULong request_count_;
+
+ // The start of the current measurement interval.
+ ACE_Time_Value interval_start_;
+
+ /// Reference to the Load Balancer.
+ LoadBalancing::ReplicationManager_var lb_;
+
+
+
+};
+
+
+#if defined (__ACE_INLINE__)
+# include "LB_RPMS_Monitor_Interceptor.inl"
+#endif /* __ACE_INLINE__ */
+
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_RPMS_MONITOR_INTERCEPTOR_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.inl b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.inl
new file mode 100644
index 00000000000..4cd431f4f15
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_RPMS_Monitor_Interceptor.inl
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+
+ACE_INLINE CORBA::Float
+TAO_LB_RPMS_Monitor_Interceptor::current_load (void) const
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ ACE_Time_Value elapsed_time =
+ ACE_OS::gettimeofday () - this->interval_start_;
+
+ this->interval_start_ = ACE_OS::gettimeofday ();
+
+ CORBA::Float load =
+ ACE_static_cast (CORBA::Float,
+ this->request_count_) / elapsed_time.msec ();
+
+ this->request_count_ = 0;
+ this->interval_start_ = ACE_OS::gettimeofday ();
+
+ return load;
+}
+
+ACE_INLINE void
+TAO_LB_RPMS_Monitor_Interceptor::register_redirect (
+ const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ this->redirect_table_.register_redirect (type_id,
+ redirect_to,
+ ACE_TRY_ENV);
+}
+
+ACE_INLINE void
+TAO_LB_RPMS_Monitor_Interceptor::remove_redirect (
+ const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ ACE_GUARD (TAO_SYNCH_MUTEX, guard, this->lock_);
+
+ this->redirect_table_.remove_redirect (type_id,
+ ACE_TRY_ENV);
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp
new file mode 100644
index 00000000000..9a6b33d519a
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.cpp
@@ -0,0 +1,180 @@
+// -*- C++ -*-
+
+#include "LB_Redirect_Table.h"
+#include "Object.h"
+#include "Exception.h"
+#include "Environment.h"
+#include "CORBA_String.h"
+#include "debug.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_Redirect_Table,
+ "$Id$")
+
+// ****************************************************************
+
+TAO_LB_Redirect_Table::TAO_LB_Redirect_Table (void)
+ : table_ ()
+{
+}
+
+TAO_LB_Redirect_Table::~TAO_LB_Redirect_Table (void)
+{
+ // Must explicitly call destroy() in the destructor since not all
+ // applications will invoke ORB::shutdown() or ORB::destroy().
+ this->destroy ();
+}
+
+void
+TAO_LB_Redirect_Table::register_redirect (
+ const char *type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ // The RepositoryId should never be zero since it is not possible to
+ // send a NULL string as an "in" argument.
+ if (ACE_OS_String::strlen (id) == 0)
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ if (CORBA::is_nil (obj))
+ ACE_THROW (CORBA::BAD_PARAM ());
+
+ int result = this->bind (type_id, redirect_to);
+
+ if (result == 1)
+ {
+ if (TAO_debug_level > 1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) LB_Redirect_Table::register_redirect:\n"
+ " Could not register duplicate object <%s> with "
+ "the LB_Redirect_Table\n",
+ type_id));
+
+ ACE_THROW (CORBA::INV_OBJREF ());
+ }
+
+ if (result == -1)
+ {
+ if (TAO_debug_level > 1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) LB_Redirect_Table::register_redirect:\n"
+ " Could not register redirect object <%s> with "
+ "the LB_Redirect_Table\n",
+ type_id));
+
+ ACE_THROW (CORBA::INTERNAL ());
+ }
+}
+
+void
+TAO_LB_Redirect_Table::find_redirect (
+ PortableInterceptor::ServerRequestInfo_ptr ri,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ // This could become very slow if there are many type of targets
+ // being redirected since we're doing a linear search using string
+ // comparisons.
+ //
+ // We do things this way to avoid the memory allocation that would
+ // occur if we were to just use the
+ // ServerRequestInfo::target_most_derived_interface() method. At
+ // some point, there is a threshold reached where the cost of the
+ // iteration through the redirect table is more expensive than the
+ // allocation incurred by calling
+ // ServerRequestInfo::target_most_derived_interface(). That
+ // threshold is approached as the number of redirects in the table
+ // becomes "large." For now, we optimize for the common case and
+ // assume that only a few types of targets (i.e. objects/servants
+ // with different RepositoryIds) exist at the current location.
+ //
+ // Note that if no redirects are registered, then this method
+ // basically becomes a no-op.
+
+ for (Table::iterator i = this->table_.begin ();
+ i != this->table_.end ();
+ ++i)
+ {
+ // Compare the target's RepositoryId with the registered
+ // redirects.
+ CORBA::Boolean matched =
+ ri->target_is_a ((*i).ext_id_, ACE_TRY_ENV);
+ ACE_CHECK_RETURN (0);
+
+ if (matched)
+ ACE_THROW (PortableInterceptor::ForwardRequest (
+ (*i).int_id_,
+ 0 /* non-permanent forward */));
+ }
+}
+
+int
+TAO_LB_Redirect_Table::remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ Table::ENTRY *entry = 0;
+
+ int result = this->table_.find (type_id, entry);
+
+ if (result == 0)
+ {
+ // Deallocate the external ID and obtain the ORB core pointer
+ // before unbinding the entry since the entry is deallocated
+ // during the call to unbind().
+ CORBA::string_free (ACE_const_cast (char *, entry->ext_id_));
+ CORBA::Object_ptr redirect = entry->int_id_;
+
+ result = this->table_.unbind (entry);
+
+ if (result != 0)
+ return result;
+
+ CORBA::release (redirect);
+ }
+
+ return result;
+}
+
+void
+TAO_LB_Redirect_Table::destroy (void)
+{
+ for (Table::iterator i = this->table_.begin ();
+ i != this->table_.end ();
+ ++i)
+ {
+ // Deallocate the id.
+ CORBA::string_free (ACE_const_cast (char *, (*i).ext_id_));
+
+ // Release the Object.
+ CORBA::release ((*i).int_id_);
+ }
+
+ this->table_.unbind_all ();
+}
+
+int
+TAO_LB_Redirect_Table::bind (const char *id,
+ CORBA::Object_ptr obj)
+{
+ // Make sure that the supplied Object reference is valid,
+ // i.e. not nil.
+ if (id == 0 || CORBA::is_nil (obj))
+ {
+ errno = EINVAL;
+ return -1;
+ };
+
+ CORBA::String_var type_id = CORBA::string_dup (id);
+ CORBA::Object_var redirect = CORBA::Object::_duplicate (obj);
+
+ int result = this->table_.bind (type_id.in (),
+ redirect.in ());
+
+ if (result == 0)
+ {
+ // Transfer ownership to the Object Table.
+ (void) type_id._retn ();
+ (void) redirect._retn ();
+ }
+
+ return result;
+}
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.h
new file mode 100644
index 00000000000..0b3d6d09161
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_Redirect_Table.h
@@ -0,0 +1,100 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file LB_Redirect_Table.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=============================================================================
+
+
+#ifndef TAO_LB_REDIRECT_TABLE_H
+#define TAO_LB_REDIRECT_TABLE_H
+
+#include "ace/pre.h"
+
+#include "corbafwd.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Functor.h"
+
+
+/**
+ * @class TAO_LB_Redirect_Table
+ *
+ * @brief Maintain a table of "redirects" corresponding to a target
+ * with the given RepositoryId.
+ *
+ * If a table entry for the given RepositoryId exists, then the load
+ * monitor will redirect the client request to the target pointed to
+ * by the object reference in that entry.
+ *
+ * It is necessary to maintain a redirect table since the load
+ * balancer determines which object group to select a replica from by
+ * examining the target's object ID. As such a request cannot simply
+ * be forwarded back to the load balancer without knowing what its
+ * intended target (i.e. object group) is. This table keeps track of
+ * the object group reference to which a replica of a given type
+ * belongs.
+ */
+class TAO_LB_Redirect_Table
+{
+public:
+
+ typedef ACE_Hash_Map_Manager_Ex<const char *, CORBA::Object_ptr, ACE_Hash<const char *>, ACE_Equal_To<const char *>, ACE_Null_Mutex> Table;
+
+ /// Constructor
+ TAO_LB_Redirect_Table (void);
+
+ /// Destructor
+ ~TAO_LB_Redirect_Table (void);
+
+ /// Register an object reference with the table, and map the given
+ /// ID to it.
+ void register_redirect (const char * type_id,
+ CORBA::Object_ptr redirect_to,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Remove the redirect associated with the given RepositoryId.
+ void remove_redirect (const char *type_id,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Check if a redirect exists for the current target. If so, then
+ /// perform the request redirection by throwing a
+ /// PortableInterceptor::ForwardRequest exception.
+ void find_redirect (PortableInterceptor::ServerRequestInfo_ptr ri,
+ CORBA::Environment &ACE_TRY_ENV);
+
+ /// Reclaim the resources held by this table (deallocate strings,
+ /// release object references, etc).
+ void destroy (void);
+
+private:
+
+ /// Helper method that binds the redirect to the given RepositoryId.
+ int bind (const char *type_id, CORBA::Object_ptr redirect_to);
+
+private:
+
+ /// Prevent copying
+ ACE_UNIMPLEMENTED_FUNC (TAO_LB_Redirect_Table (const TAO_LB_Redirect_Table &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const TAO_LB_Redirect_Table &))
+
+private:
+
+ /// The implementation.
+ Table table_;
+
+};
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_REDIRECT_TABLE_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.cpp
new file mode 100644
index 00000000000..7b4040585b5
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.cpp
@@ -0,0 +1,21 @@
+// -*- C++ -*-
+
+#include "LB_ReplicaInfo.h"
+
+ACE_RCSID (LoadBalancing,
+ LB_ReplicaInfo,
+ "$Id$")
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class ACE_Node<TAO_LB_ReplicaInfo *>;
+template class ACE_Unbounded_Set<TAO_LB_ReplicaInfo *>;
+template class ACE_Unbounded_Set_Iterator<TAO_LB_ReplicaInfo *>;
+
+#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate ACE_Node<TAO_LB_ReplicaInfo *>
+#pragma instantiate ACE_Unbounded_Set<TAO_LB_ReplicaInfo *>
+#pragma instantiate ACE_Unbounded_Set_Iterator<TAO_LB_ReplicaInfo *>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.h
new file mode 100644
index 00000000000..26ba0b5f5ff
--- /dev/null
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LB_ReplicaInfo.h
@@ -0,0 +1,59 @@
+// -*- C++ -*-
+
+//=======================================================================
+/**
+ * @file LB_ReplicaInfo.h
+ *
+ * $Id$
+ *
+ * @author Ossama Othman <ossama@uci.edu>
+ */
+//=======================================================================
+
+
+#ifndef TAO_LB_REPLICA_INFO_H
+#define TAO_LB_REPLICA_INFO_H
+
+#include "ace/pre.h"
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+#include "orbsvcs/LoadBalancingC.h"
+
+#include "LB_Replica_Set.h"
+
+class TAO_LB_ReplicaInfo;
+typedef ACE_Unbounded_Set<TAO_LB_ReplicaInfo *> TAO_LB_ReplicaInfoSet;
+typedef ACE_Unbounded_Set_Iterator<TAO_LB_ReplicaInfo *> TAO_LB_ReplicaInfoSetIterator;
+
+
+/**
+ * @class TAO_LB_ReplicaInfo
+ *
+ * @brief Class that contains all replica-specific information.
+ */
+class TAO_LB_ReplicaInfo
+{
+public:
+
+ /// Reference to the replica.
+ CORBA::Object_var replica;
+
+ /// FactoryInfo used when creating the replica.
+ LoadBalancing::FactoryInfo factory_info;
+
+ /// FactoryCreationId assigned to this replica. This
+ /// FactoryCreationId_var will contain a zero pointer if the replica
+ /// was not created using a GenericFactory.
+ LoadBalancing::GenericFactory::FactoryCreationId_var factory_creation_id;
+
+};
+
+#include "ace/post.h"
+
+#endif /* TAO_LB_REPLICA_INFO_H */
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.cpp
index 3102244a876..4cba2d3c82b 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.cpp
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.cpp
@@ -36,7 +36,7 @@ TAO_LoadBalancing_ReplicationManager_i::register_load_notifier (
CORBA::Environment &ACE_TRY_ENV)
ACE_THROW_SPEC ((CORBA::SystemException))
{
- ACE_THROW (CORBA::NO_IMPLEMENT());
+ ACE_THROW (CORBA::NO_IMPLEMENT ());
}
LoadBalancing::LoadNotifier_ptr
@@ -360,6 +360,17 @@ TAO_LoadBalancing_ReplicationManager_i::delete_object (
ACE_TRY_ENV);
}
+CORBA::Object_ptr
+TAO_LoadBalancing_ReplicationManager_i::replica (
+ const PortableServer::ObjectId &oid,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ // Convert the ObjectId to the hash map key.
+ CORBA::String_var stroid = PortableServer::ObjectId_to_string (oid);
+
+ int tmp = ACE_OS::atoi (stroid.in ());
+}
+
int
TAO_LoadBalancing_ReplicationManager_i::init (
PortableServer::POA_ptr root_poa)
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.h b/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.h
index 21ea01a1ebc..129bf2ddedd 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.h
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/LoadBalancingI.h
@@ -2,7 +2,7 @@
//=============================================================================
/**
- * @file ReplicaLocator.h
+ * @file LoadBalancingI.h
*
* $Id$
*
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancing/NOTES b/TAO/orbsvcs/orbsvcs/LoadBalancing/NOTES
index 2eb4428ec19..8a45993a019 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancing/NOTES
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancing/NOTES
@@ -10,7 +10,7 @@ ReplicaLocator::pre_invoke ()
LoadAnalyzer.get_replica ( ObjectId )
{
ObjectId_Replica_Map.find (ObjectId, Location_Replica_Map);
-
+
Location_Replica_Map (select replica from it);
}
@@ -109,4 +109,3 @@ if (!CORBA::is_nil (replica_map_entry->factory_info.the_factory.in ())
delete replica_map_entry;
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
-
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancingI.cpp b/TAO/orbsvcs/orbsvcs/LoadBalancingI.cpp
index 3102244a876..4cba2d3c82b 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancingI.cpp
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancingI.cpp
@@ -36,7 +36,7 @@ TAO_LoadBalancing_ReplicationManager_i::register_load_notifier (
CORBA::Environment &ACE_TRY_ENV)
ACE_THROW_SPEC ((CORBA::SystemException))
{
- ACE_THROW (CORBA::NO_IMPLEMENT());
+ ACE_THROW (CORBA::NO_IMPLEMENT ());
}
LoadBalancing::LoadNotifier_ptr
@@ -360,6 +360,17 @@ TAO_LoadBalancing_ReplicationManager_i::delete_object (
ACE_TRY_ENV);
}
+CORBA::Object_ptr
+TAO_LoadBalancing_ReplicationManager_i::replica (
+ const PortableServer::ObjectId &oid,
+ CORBA::Environment &ACE_TRY_ENV)
+{
+ // Convert the ObjectId to the hash map key.
+ CORBA::String_var stroid = PortableServer::ObjectId_to_string (oid);
+
+ int tmp = ACE_OS::atoi (stroid.in ());
+}
+
int
TAO_LoadBalancing_ReplicationManager_i::init (
PortableServer::POA_ptr root_poa)
diff --git a/TAO/orbsvcs/orbsvcs/LoadBalancingI.h b/TAO/orbsvcs/orbsvcs/LoadBalancingI.h
index 21ea01a1ebc..129bf2ddedd 100644
--- a/TAO/orbsvcs/orbsvcs/LoadBalancingI.h
+++ b/TAO/orbsvcs/orbsvcs/LoadBalancingI.h
@@ -2,7 +2,7 @@
//=============================================================================
/**
- * @file ReplicaLocator.h
+ * @file LoadBalancingI.h
*
* $Id$
*
diff --git a/TAO/orbsvcs/orbsvcs/NOTES b/TAO/orbsvcs/orbsvcs/NOTES
index 2eb4428ec19..8a45993a019 100644
--- a/TAO/orbsvcs/orbsvcs/NOTES
+++ b/TAO/orbsvcs/orbsvcs/NOTES
@@ -10,7 +10,7 @@ ReplicaLocator::pre_invoke ()
LoadAnalyzer.get_replica ( ObjectId )
{
ObjectId_Replica_Map.find (ObjectId, Location_Replica_Map);
-
+
Location_Replica_Map (select replica from it);
}
@@ -109,4 +109,3 @@ if (!CORBA::is_nil (replica_map_entry->factory_info.the_factory.in ())
delete replica_map_entry;
// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
-