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