Home | History | Annotate | Download | only in service
      1 //
      2 // CDDL HEADER START
      3 //
      4 // The contents of this file are subject to the terms of the
      5 // Common Development and Distribution License (the License).
      6 // You may not use this file except in compliance with the License.
      7 //
      8 // You can obtain a copy of the license at usr/src/CDDL.txt
      9 // or http://www.opensolaris.org/os/licensing.
     10 // See the License for the specific language governing permissions
     11 // and limitations under the License.
     12 //
     13 // When distributing Covered Code, include this CDDL HEADER in each
     14 // file and include the License file at usr/src/CDDL.txt.
     15 // If applicable, add the following below this CDDL HEADER, with the
     16 // fields enclosed by brackets [] replaced with your own identifying
     17 // information: Portions Copyright [yyyy] [name of copyright owner]
     18 //
     19 // CDDL HEADER END
     20 //
     21 
     22 //
     23 // Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     24 // Use is subject to license terms.
     25 //
     26 
     27 #ifndef _REPLICA_HANDLER_H
     28 #define	_REPLICA_HANDLER_H
     29 
     30 #pragma ident	"@(#)replica_handler.h	1.84	08/05/20 SMI"
     31 
     32 #include <sys/os.h>
     33 #include <orb/invo/common.h>
     34 #include <orb/handler/remote_handler.h>
     35 #include <repl/service/repl_service.h>
     36 #include <orb/debug/haci_debug.h>
     37 #include <orb/refs/unref_threadpool.h>
     38 #ifdef _KERNEL_ORB
     39 #include <repl/rma/hxdoor.h>
     40 #include <repl/service/ckpt_handler.h>
     41 #endif
     42 
     43 class replica_handler_kit : public remote_handler_kit {
     44 public:
     45 	replica_handler_kit();
     46 	remote_handler	*create(Xdoor *);
     47 	void	unmarshal_cancel_remainder(service &);
     48 
     49 	static replica_handler_kit &the();
     50 	static int initialize();
     51 	static void shutdown();
     52 private:
     53 	static replica_handler_kit *the_replica_handler_kit;
     54 };
     55 
     56 
     57 //
     58 // Replica handler.  Used for replicated objects.
     59 //
     60 // Handlers are associated with a repl_service which knows the state of
     61 // the service.  The interesting service states from the handler's perspective
     62 // are PRIMARY, SECONDARY and CLIENT.  The same handler is used for all states
     63 // (there is no client handler or server handler), though some
     64 // operations are only valid for certain states - the handler checks with
     65 // its repl_service before performing any of these.
     66 //
     67 class replica_handler :
     68 	public remote_handler,
     69 	public unref_task {
     70 public:
     71 	hkit_id_t			handler_id();
     72 
     73 	// Returns the handler to be used by the unref_task
     74 	virtual handler		*get_unref_handler();
     75 
     76 	// Returns the unref_task type
     77 	virtual unref_task_type_t	unref_task_type();
     78 
     79 	//
     80 	// Create a new proxy object which is used on the primary for
     81 	// local invocations.
     82 	// This should only be called by a template which knows the
     83 	// type of the proxy being created and cast to.
     84 	//
     85 	void			*create_proxy(InterfaceDescriptor *actual_type,
     86 				    InterfaceDescriptor *deep_type);
     87 
     88 	void			revoke();
     89 	void			marshal(service &, CORBA::Object_ptr);
     90 	CORBA::Object_ptr	unmarshal(service &, CORBA::TypeId,
     91 				    generic_proxy::ProxyCreator, CORBA::TypeId);
     92 
     93 	bool			is_local();
     94 	ExceptionStatus		invoke(arg_info &, ArgValue *,
     95 				    InterfaceDescriptor *, Environment &);
     96 	void			handle_incoming_call(service &);
     97 
     98 	virtual void		*narrow(CORBA::Object_ptr, CORBA::TypeId,
     99 				    generic_proxy::ProxyCreator);
    100 
    101 	virtual void		*duplicate(CORBA::Object_ptr, CORBA::TypeId);
    102 
    103 	void			release(CORBA::Object_ptr);
    104 
    105 	void			new_reference();
    106 
    107 	bool			is_user();
    108 
    109 	repl_service		*get_service();
    110 
    111 	void			set_service(repl_service *);
    112 
    113 #ifdef _KERNEL_ORB
    114 	void			*local_invoke(CORBA::TypeId,
    115 				    InterfaceDescriptor *, Environment &);
    116 	ExceptionStatus		local_invoke_done(Environment &);
    117 
    118 	// Acquires handler lock and return handler's marshal count
    119 	virtual uint_t		begin_xdoor_unref();
    120 
    121 	//  If the xdoor has been unreferenced, decides if the handler
    122 	// can be unreferenced too.
    123 	virtual void		end_xdoor_unref(bool);
    124 
    125 	// Decides if a handler on the unref_threadpool can be ureferenced.
    126 	void			deliver_unreferenced();
    127 
    128 	// Returns true when unreference can be performed at this time.
    129 	bool			last_unref();
    130 
    131 	// Returns true if a freeze_primary() is in progress
    132 	bool			freeze_in_progress(Environment *);
    133 
    134 	// Unreferenced by a checkpoint.
    135 	void			unref_by_ckpt();
    136 
    137 	// Associate an implementation object with the handler.
    138 	void			add_impl(CORBA::Object_ptr obj);
    139 	void			rem_impl();
    140 
    141 	//
    142 	// Get the service_id of the underlying hxdoor.
    143 	// This is only to be called when there is a hxdoor.
    144 	//
    145 	replica::service_num_t get_service_id();
    146 
    147 	//
    148 	// Get the xdoor_id of the underlying hxdoor.
    149 	// This is only to be called when there is a hxdoor.
    150 	//
    151 	xdoor_id get_object_id();
    152 
    153 	//
    154 	// When a queued unreferenced on the defer list
    155 	// is to be discarded, update the handler state
    156 	// to show that an unreference is not pending.
    157 	//
    158 	void			clear_unref_flag();
    159 
    160 	// Notify handler that it has become a primary.
    161 	virtual void		become_primary_event();
    162 
    163 	// Notify handler that it has become a secondary.
    164 	virtual void		become_secondary_event();
    165 
    166 	// Constructor used when creating a new object on the primary.
    167 	replica_handler(repl_service *s, CORBA::Object_ptr objp);
    168 
    169 	// server_dead returns service state.
    170 	// Returns true if the service is DOWN.
    171 	//
    172 	bool	server_dead();
    173 
    174 	//
    175 	// Identify nodes holding references
    176 	//
    177 	void	identify_nodes_holding_refs(nodeset &refset);
    178 
    179 #endif // _KERNEL_ORB
    180 
    181 	// Constructor used when unmarshaling a new client reference.
    182 	replica_handler(Xdoor *);
    183 
    184 	//
    185 	// The handler is deleted on clients when all references go away and
    186 	// on servers (primary or secondary) when the object is deleted
    187 	// (which is only legal after unreferenced is delivered).
    188 	//
    189 	~replica_handler();
    190 
    191 private:
    192 	// To access sensitive data.
    193 	void		lock();
    194 	void		unlock();
    195 	bool		lock_held();
    196 
    197 	void		incref();
    198 
    199 	// Utilities for managing the reference count in the proxies.
    200 	void	incpxref(CORBA::Object_ptr);
    201 	uint_t	decpxref(CORBA::Object_ptr);
    202 
    203 	CORBA::Object_ptr _obj();
    204 
    205 	//
    206 	// Number of proxies.  Note that all references, whether
    207 	// primary, secondary or client go through proxies.
    208 	//
    209 	uint_t		_nref;
    210 
    211 	// The replicated service associated with this handler.
    212 	repl_service	*_servicep;
    213 
    214 	// Record handler state
    215 	handler_state_t	state_;
    216 
    217 	//
    218 	// We may or may not have an implementation object associated with
    219 	// the handler.
    220 	//
    221 	// Primary - always has an implementation object.
    222 	//
    223 	// Secondary - has an implementation object,
    224 	// EXCEPT for a period where we learn about the object through a
    225 	// checkpoint message and have not yet made the appropriate call to
    226 	// convert this to a secondary reference. However, no unreference
    227 	// action will occur during this period (an assert checks this fact).
    228 	//
    229 	// Client only - does not have an implementation object,
    230 	// but does have a proxy object pointer.
    231 	//
    232 	CORBA::Object_ptr _impl_object;
    233 	CORBA::Object_ptr proxy_obj_;
    234 
    235 	os::mutex_t	_lck;
    236 
    237 	// Disallow assignments and pass by value.
    238 	replica_handler(const replica_handler &);
    239 	replica_handler & operator = (replica_handler &);
    240 };
    241 
    242 class transaction_state;
    243 class ha_transaction_id;
    244 
    245 //
    246 // trans_ctx - Common parent for all the transacton context objects.
    247 // This parent class identifies the type of the context object.
    248 // Also contains a reference to the HA transaction id object.
    249 //
    250 class trans_ctx {
    251 public:
    252 	typedef enum {
    253 		CLIENT,
    254 		PRIMARY,
    255 		SECONDARY
    256 	} context_type;
    257 
    258 	context_type get_type();
    259 
    260 	virtual ~trans_ctx();
    261 
    262 	// Get the HA transaction id object reference.
    263 	replica::transaction_id_ptr	get_trans_id();
    264 
    265 protected:
    266 	trans_ctx(context_type, replica::transaction_id_ptr);
    267 
    268 	//
    269 	// The HA transaction id object reference
    270 	//
    271 	// The client_ctx obtains this object reference.
    272 	// Only the client_ctx performs the release on this object reference.
    273 	//
    274 	// This means that no reference counting occurs when the object
    275 	// reference is held by another type of context. This means that
    276 	// we cannot destroy a client_ctx until after all other contexts
    277 	// that have this reference are destroyed. This does not follow
    278 	// recommended practice of reference counting all references,
    279 	// but it can work.
    280 	//
    281 	replica::transaction_id_ptr	trans_id_p;
    282 
    283 private:
    284 	//
    285 	// We never create an object of this type.
    286 	// This identifies the kind of child class.
    287 	//
    288 	context_type	type;
    289 };
    290 
    291 //
    292 // Client's context is the transaction id and its object.
    293 //
    294 class client_ctx
    295 	: public trans_ctx
    296 {
    297 	friend class primary_ctx;
    298 public:
    299 	client_ctx(replica_handler *);
    300 
    301 	~client_ctx();
    302 
    303 	//
    304 	// Called when beginning an invocation to set up the transaction
    305 	// id data if necessary.
    306 	//
    307 	static client_ctx	*begin(replica_handler *, Environment &);
    308 
    309 	//
    310 	// Called when the mini-transaction is completed (we got a reply or
    311 	// an exception).
    312 	//
    313 	void	completed(Environment &e);
    314 
    315 	replica_handler		*handlerp;
    316 
    317 private:
    318 	// disallow
    319 	client_ctx(const client_ctx &);
    320 	client_ctx & operator = (client_ctx &);
    321 };
    322 
    323 class orphan_thread;
    324 
    325 #ifdef _KERNEL_ORB
    326 //
    327 // The primary transaction context is passed in the environment to all
    328 // invocations on replicated objects.
    329 // We may be a client_ctx too.
    330 //
    331 class primary_ctx
    332 	: public trans_ctx
    333 {
    334 	friend class replica_handler;
    335 	friend class orphan_thread;
    336 	friend class ha_transaction_id;
    337 	friend class transaction_state;
    338 	friend class multi_ckpt_handler;
    339 	friend class ckpt_handler_client;
    340 public:
    341 	//
    342 	// Enum identifies the purpose of the primary_ctx.
    343 	//
    344 	// The following 2 values are temporary because some services
    345 	// do checkpoints on these operations even though that is
    346 	// not officially supported.
    347 	//	ADD_SECONDARY_CKPT, REMOVE_SECONDARY_CKPT
    348 	//
    349 	typedef enum {
    350 		MINI_TRANSACTION,	// invoked from a mini-transaction
    351 		PUSH_CKPT,		// invoked from push_ckpt_task
    352 		BECOME_PRIMARY_CKPT,	// invoked from become_primary
    353 		BECOME_SECONDARY_CKPT,	// invoked from become_secondary
    354 		ADD_SECONDARY_CKPT,	// invoked from add_secondary
    355 		REMOVE_SECONDARY_CKPT	// invoked from remove_secondary
    356 	} invoke_env;
    357 
    358 	// Constructors
    359 	primary_ctx(replica_handler *);
    360 	primary_ctx(replica_handler *, invoke_env, Environment &e);
    361 
    362 	~primary_ctx();
    363 
    364 	// Extract the primary_ctx from the environment.
    365 	static primary_ctx	*extract_from(Environment &e);
    366 
    367 	// Get the saved transaction state.
    368 	transaction_state	*get_saved_state();
    369 
    370 	// The following are only used by the HA framework.
    371 
    372 	//
    373 	// Whether the mini-transaction needs an add_commit. If a mini
    374 	// transaction ever did a checkpoint, we will need to send a commit.
    375 	// If the service writer did a commit, the framework will not
    376 	// send anymore commit.
    377 	//
    378 	bool	need_commit();
    379 
    380 	// Set needcommit to true.
    381 	void	needcommit_yes();
    382 
    383 	// Set needcommit to false;
    384 	void	needcommit_no();
    385 
    386 	//
    387 	// The primary context is no longer needed because of a retry.
    388 	// Clean up state and destroy the primary context.
    389 	//
    390 	void	discard_context();
    391 
    392 private:
    393 	// Helper function. Setup for the local invocation.
    394 	void	setup_local(client_ctx *c_ctxp, Environment &e);
    395 	void	add_client_ctx(Environment &e);
    396 
    397 	// Called from replica_handler.
    398 	static void	begin_local(replica_handler *, Environment &e);
    399 
    400 	void	completed_local(Environment &e);
    401 
    402 	void	begin_remote(replica::transaction_id_ptr tr_id,
    403 	    replica_handler *h, Environment &e);
    404 
    405 	void	primary_ctx::completed_remote(Environment &e);
    406 
    407 	void	get_saved_state(replica_handler *h, Environment &e);
    408 
    409 	// Only called from orphan_thread::process_orphaned().
    410 	void	begin_orphaned(replica::transaction_id_ptr trid,
    411 	    transaction_state *st);
    412 
    413 	void	completed_orphaned(Environment &e);
    414 
    415 	// True if commit is needed for this transaction
    416 	bool		needcommit;
    417 
    418 	// Indicates the environment where the primary_ctx is created.
    419 	invoke_env	env_type;
    420 
    421 	// The client_ctx. We need this info during local invocation.
    422 	client_ctx	*clnt_ctx;
    423 
    424 	//
    425 	// Any saved state for this transaction. A non-NULL value indicates
    426 	// that the current invocation is a retry operation and that
    427 	// some state was found. Note that this can be a retry even if
    428 	// the saved_state is NULL.
    429 	//
    430 	transaction_state	*saved_state;
    431 
    432 	//
    433 	// The replica_handler which is being invoked
    434 	// This is non-NULL for invocations and NULL for orphan requests
    435 	// and push checkpoints.
    436 	//
    437 	replica_handler		*handlerp;
    438 
    439 	// disallow
    440 	primary_ctx(const primary_ctx &);
    441 	primary_ctx & operator = (primary_ctx &);
    442 };
    443 
    444 //
    445 // The secondary transaction context is passed with all checkpoint invocations.
    446 //
    447 class secondary_ctx
    448 	: public trans_ctx
    449 {
    450 	friend class ckpt_handler_server;
    451 	friend class state_hash_table_t;
    452 	friend class transaction_state;
    453 public:
    454 	// Extract the secondary_ctx from the environment.
    455 	static secondary_ctx	*extract_from(Environment &e);
    456 
    457 	// Get the transaction state.
    458 	transaction_state	*get_saved_state();
    459 
    460 private:
    461 	secondary_ctx(Environment &e);
    462 	~secondary_ctx();
    463 
    464 
    465 	void	begin(replica::transaction_id_ptr tr_id);
    466 	void	completed(Environment &e);
    467 
    468 	// The transaction state that matches the trans_id.
    469 	transaction_state	*saved_state;
    470 
    471 	// The checkpoint handler this came through.
    472 	ckpt_handler_server	*handlerp;
    473 
    474 	// disallow
    475 	secondary_ctx(const secondary_ctx &);
    476 	secondary_ctx & operator = (secondary_ctx &);
    477 };
    478 #endif // _KERNEL_ORB
    479 
    480 #if defined(HACI_DBGBUFS) && !defined(NO_REPL_DBGBUF)
    481 #define	REPL_DBGBUF
    482 extern dbg_print_buf repl_dbg;
    483 #define	REPL_DBG(args) HACI_DEBUG(ENABLE_REPL_DBG, repl_dbg, args)
    484 #else
    485 #define	REPL_DBG(args)
    486 #endif
    487 
    488 #ifndef NOINLINES
    489 #include <repl/service/replica_handler_in.h>
    490 #endif  // _NOINLINES
    491 
    492 #endif	/* _REPLICA_HANDLER_H */
    493