1 #include "ace/Get_Opt.h"
2 #include "Token_Handler.h"
4 #if defined (ACE_HAS_TOKENS_LIBRARY)
6 #include "ace/Signal.h"
9 ACE_Token_Acceptor::parse_args (int argc
, ACE_TCHAR
*argv
[])
11 ACE_TRACE ("ACE_Token_Acceptor::parse_args");
13 u_short svc_port
= ACE_DEFAULT_SERVER_PORT
;
15 ACE_LOG_MSG
->open (ACE_TEXT ("Token Service"));
17 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT ("p:"), 0);
19 for (int c
; (c
= get_opt ()) != -1; )
24 svc_port
= static_cast<u_short
> (ACE_OS::atoi (get_opt
.opt_arg ()));
27 ACE_ERROR_RETURN ((LM_ERROR
,
28 ACE_TEXT ("%n:\n[-p server-port]\n"), 1),
33 this->service_addr_
.set (svc_port
);
38 ACE_Token_Acceptor::init (int argc
, ACE_TCHAR
*argv
[])
40 ACE_TRACE ("ACE_Token_Acceptor::init");
42 // Use the options hook to parse the command line arguments and set
44 this->parse_args (argc
, argv
);
46 // Set the acceptor endpoint into listen mode (use the Singleton
47 // global Reactor...).
48 if (this->open (this->service_addr_
, ACE_Reactor::instance (),
50 &this->scheduling_strategy_
,
51 ACE_TEXT ("Token Server"),
52 ACE_TEXT ("ACE token service")) == -1)
53 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%n: %p on port %d\n"),
54 ACE_TEXT ("acceptor::open failed"),
55 this->service_addr_
.get_port_number ()), -1);
57 // Ignore SIGPIPE so that each <SVC_HANDLER> can handle this on its
59 ACE_Sig_Action
sig ((ACE_SignalHandler
) SIG_IGN
, SIGPIPE
);
62 ACE_INET_Addr server_addr
;
64 if (this->acceptor ().get_local_addr (server_addr
) == -1)
66 ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("get_remote_addr")), -1);
69 ACE_TEXT ("starting up Token Server at port %d on handle %d\n"),
70 server_addr
.get_port_number (),
71 this->acceptor ().get_handle ()));
75 // The following is a "Factory" used by the ACE_Service_Config and
76 // svc.conf file to dynamically initialize the state of the Naming
79 ACE_SVC_FACTORY_DEFINE (ACE_Token_Acceptor
)
81 // Default constructor.
83 ACE_Token_Handler::ACE_Token_Handler (ACE_Thread_Manager
*tm
)
84 : ACE_Svc_Handler
<ACE_SOCK_STREAM
, ACE_NULL_SYNCH
> (tm
),
88 ACE_TRACE ("ACE_Token_Handler::ACE_Token_Handler");
91 // Create and send a reply to the client.
94 ACE_Token_Handler::send_reply (ACE_UINT32 err
)
96 ACE_TRACE ("ACE_Token_Handler::send_reply");
101 this->token_reply_
.errnum (err
);
103 len
= this->token_reply_
.encode (buf
);
105 n
= this->peer ().send (buf
, len
);
107 if (n
!= (ssize_t
) len
)
108 ACE_ERROR_RETURN ((LM_ERROR
,
109 ACE_TEXT ("%p, expected len = %d, actual len = %d\n"),
110 ACE_TEXT ("send failed"), len
, n
), -1);
115 // Acquire the token.
118 ACE_Token_Handler::acquire (ACE_Token_Proxy
*proxy
)
120 ACE_TRACE ("ACE_Token_Handler::acquire");
122 ACE_DEBUG ((LM_DEBUG
, "in acquire for client id = %s\n",
123 proxy
->client_id ()));
126 // @@ add notify in token request reply
127 if (proxy
->acquire (0, 0, ACE_Synch_Options::asynch
) == -1)
129 if (errno
!= EWOULDBLOCK
)
131 return this->send_reply (errno
);
133 // acquire would block
134 if (request_options_
[ACE_Synch_Options::USE_TIMEOUT
] == 1)
137 if ((request_options_
.timeout ().sec () == 0) &&
138 (request_options_
.timeout ().usec () == 0))
139 return this->send_reply (EWOULDBLOCK
);
142 this->timeout_id_
= this->reactor ()->schedule_timer
143 (this, (void *) proxy
, request_options_
.timeout ());
144 if (timeout_id_
== -1)
146 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p\n"),
147 ACE_TEXT ("schedule_timer")));
148 return this->send_reply (errno
);
151 // send no reply. wait until we acquire it or until the timer
156 return this->send_reply (0);
159 // Try to acquire the token. Never block.
162 ACE_Token_Handler::try_acquire (ACE_Token_Proxy
*proxy
)
164 ACE_TRACE ("ACE_Token_Handler::try_acquire");
167 ACE_DEBUG ((LM_DEBUG
, "in try_acquire for client id = %s\n",
168 proxy
->client_id ()));
171 // @@ add notify in token request reply
172 if (proxy
->tryacquire () == -1)
173 return this->send_reply (errno
);
175 return this->send_reply (0);
178 // Release the token and allow the next client that is waiting to
182 ACE_Token_Handler::release (ACE_Token_Proxy
*proxy
)
184 ACE_TRACE ("ACE_Token_Handler::release");
186 ACE_DEBUG ((LM_DEBUG
,
187 "in release for client id = %s\n",
188 proxy
->client_id ()));
191 if (proxy
->release (ACE_Synch_Options::asynch
) == -1)
193 return this->send_reply (ACE_LOG_MSG
->errnum ());
196 if (this->timeout_id_
!= 0)
198 this->reactor ()->cancel_timer (timeout_id_
);
199 this->timeout_id_
= 0;
202 return this->send_reply (0);
205 // Yield the token if any clients are waiting, otherwise keep the
209 ACE_Token_Handler::renew (ACE_Token_Proxy
*proxy
)
211 ACE_TRACE ("ACE_Token_Handler::renew");
214 ACE_DEBUG ((LM_DEBUG
, "in renew for client id = %s\n",
215 proxy
->client_id ()));
218 if (proxy
->renew (token_request_
.requeue_position (),
219 ACE_Synch_Options::asynch
) == -1)
221 int result
= ACE_LOG_MSG
->errnum ();
222 if (result
!= EWOULDBLOCK
)
224 return this->send_reply (result
);
226 // acquire would block
227 if (request_options_
[ACE_Synch_Options::USE_TIMEOUT
] == 1)
229 this->timeout_id_
= this->reactor ()->schedule_timer
230 (this, 0, request_options_
.timeout ());
231 if (timeout_id_
== -1)
233 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p\n"),
234 ACE_TEXT ("schedule_timer")));
235 return this->send_reply (ACE_LOG_MSG
->errnum ());
238 // Send no reply. wait until we acquire it or until the timer
243 // Success, we still hold the token.
244 return this->send_reply (0);
248 ACE_Token_Handler::remove (ACE_Token_Proxy
* /* proxy */)
250 ACE_TRACE ("ACE_Token_Handler::remove");
252 ACE_DEBUG ((LM_DEBUG
, "in remove for client id = %s\n",
253 proxy
->client_id ()));
257 ACE_TEXT ("sorry: ACE_Token_Handler::remove() is not implemented")));
259 return this->send_reply (ENOTSUP
);
262 // Enable clients to limit the amount of time they'll wait for a
266 ACE_Token_Handler::handle_timeout (const ACE_Time_Value
&,
269 ACE_TRACE ("ACE_Token_Handler::handle_timeout");
271 this->timeout_id_
= 0;
273 // @@ add a try acquire here!
274 // Try to acquire the token, but if we can't get it immediately
275 // then abandon the wait.
276 // if (this->try_acquire (&token_entry) == -1)
277 // return this->abandon (token_entry);
279 ACE_Token_Proxy
*proxy
= (ACE_Token_Proxy
*) tp
;
282 ACE_DEBUG ((LM_DEBUG
, "in handle_timeout for client id = %s\n",
283 proxy
->client_id ()));
286 // Remove ourselves from the waiter list.
289 this->send_reply (ETIME
);
293 // Dispatch the appropriate operation to handle the client request.
296 ACE_Token_Handler::get_proxy (void)
298 ACE_TRACE ("ACE_Token_Handler::get_proxy");
300 // See if the proxy already exists in the collection.
301 ACE_Token_Proxy
*proxy
= collection_
.is_member (token_request_
.token_name ());
303 // If not, create one.
306 proxy
= this->create_proxy ();
308 // Put the new_proxy in this client_id's collection.
309 if (collection_
.insert (*proxy
) == -1)
310 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("insert failed\n")), 0);
312 // Delete our copy (one was created in the collection).
314 proxy
= collection_
.is_member (token_request_
.token_name ());
317 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("is_member failed\n")), 0);
319 // Set the client_id (it was set to 1 since we're
321 proxy
->client_id (token_request_
.client_id ());
328 ACE_Token_Handler::create_proxy (void)
330 ACE_TRACE ("ACE_Token_Handler::create_proxy");
332 ACE_Token_Proxy
*proxy
;
334 switch (token_request_
.token_type ())
336 case ACE_Tokens::RWLOCK
:
337 if (token_request_
.proxy_type () == ACE_RW_Token::READER
)
338 ACE_NEW_RETURN (proxy
,
339 ACE_TS_RLock (token_request_
.token_name (), this),
342 ACE_NEW_RETURN (proxy
,
343 ACE_TS_WLock (token_request_
.token_name (), this),
346 case ACE_Tokens::MUTEX
:
347 ACE_NEW_RETURN (proxy
,
348 ACE_TS_Mutex (token_request_
.token_name (), this),
352 // Nonexistent token type.
357 // Check for failed new.
365 ACE_Token_Handler::dispatch (void)
367 ACE_TRACE ("ACE_Token_Handler::dispatch");
368 ACE_Token_Proxy
*proxy
= this->get_proxy ();
373 // Dispatch the appropriate request.
374 switch (this->token_request_
.operation_type ())
376 case ACE_Token_Request::ACQUIRE
:
377 return this->acquire (proxy
);
378 case ACE_Token_Request::TRY_ACQUIRE
:
379 return this->try_acquire (proxy
);
380 case ACE_Token_Request::RELEASE
:
381 return this->release (proxy
);
382 case ACE_Token_Request::RENEW
:
383 return this->renew (proxy
);
384 case ACE_Token_Request::REMOVE
:
385 return this->remove (proxy
);
387 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("invalid type = %d\n"),
388 this->token_request_
.operation_type ()), -1);
393 // Receive, frame, and decode the client's request.
394 // Note, this method should use non-blocking I/O.
397 ACE_Token_Handler::recv_request (void)
399 ACE_TRACE ("ACE_Token_Handler::recv_request");
402 // Read the first 4 bytes to get the length of the message
403 // This implementation assumes that the first 4 bytes are
404 // the length of the message.
405 n
= this->peer ().recv ((void *) &this->token_request_
,
406 sizeof (ACE_UINT32
));
413 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p got %d bytes, expected %d bytes\n"),
414 ACE_TEXT ("recv failed"), n
, sizeof (ACE_UINT32
)));
417 // We've shutdown unexpectedly, let's abandon the connection.
421 case sizeof (ACE_UINT32
):
423 // Transform the length into host byte order.
424 ssize_t length
= this->token_request_
.length ();
426 // Do a sanity check on the length of the message.
427 if (length
> (ssize_t
) sizeof this->token_request_
)
429 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("length %d too long\n"), length
));
430 return this->abandon (1);
433 // Receive the rest of the request message.
434 // @@ beware of blocking read!!!.
435 n
= this->peer ().recv ((void *) (((char *) &this->token_request_
)
436 + sizeof (ACE_UINT32
)),
437 length
- sizeof (ACE_UINT32
));
439 // Subtract off the size of the part we skipped over...
440 if (n
!= (length
- (ssize_t
) sizeof (ACE_UINT32
)))
442 ACE_ERROR ((LM_ERROR
, ACE_TEXT ("%p expected %d, got %d\n"),
443 ACE_TEXT ("invalid length"), length
, n
));
444 return this->abandon (1);
447 // Decode the request into host byte order.
448 if (this->token_request_
.decode () == -1)
451 ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("decode failed")));
452 return this->abandon (1);
456 this->token_request_
.dump ();
462 // Callback method invoked by the ACE_Reactor when
463 // events arrive from the client.
466 ACE_Token_Handler::handle_input (ACE_HANDLE
)
468 ACE_TRACE ("ACE_Token_Handler::handle_input");
471 ACE_DEBUG ((LM_DEBUG
, "****************** in handle_input\n"));
474 if (this->recv_request () == -1)
477 return this->dispatch ();
481 ACE_Token_Handler::sleep_hook (void)
483 ACE_TRACE ("ACE_Token_Handler::sleep_hook");
484 // @@ what should we do?
489 ACE_Token_Handler::token_acquired (ACE_TPQ_Entry
*)
491 ACE_TRACE ("ACE_Token_Handler::token_acquired");
493 if (this->timeout_id_
!= 0)
495 this->reactor ()->cancel_timer (this->timeout_id_
);
496 this->timeout_id_
= 0;
499 this->send_reply (0);
503 ACE_Token_Handler::abandon (int send_error
)
505 ACE_TRACE ("ACE_Token_Handler::abandon");
507 // Release ownership or remove us from the waiter list.
508 if (this->timeout_id_
!= 0)
510 this->reactor ()->cancel_timer (timeout_id_
);
511 this->timeout_id_
= 0;
514 // @@ release all tokens
515 collection_
.release ();
518 return this->send_reply (EIO
);
523 // ************************************************************
524 // ************************************************************
525 // ************************************************************
527 ACE_TS_Mutex::ACE_TS_Mutex (const ACE_TCHAR
*name
,
528 ACE_Token_Handler
*th
)
529 : ACE_Local_Mutex (name
, 0, 1), // The 1 is debug.
532 ACE_TRACE ("ACE_TS_Mutex::ACE_TS_Mutex");
535 ACE_TS_Mutex::ACE_TS_Mutex (const ACE_TS_Mutex
&m
)
536 : ACE_Local_Mutex (m
),
539 ACE_TRACE ("ACE_TS_Mutex::ACE_TS_Mutex");
540 this->open (m
.name (), m
.ignore_deadlock_
, m
.debug_
);
544 ACE_TS_Mutex::sleep_hook (void)
546 ACE_TRACE ("ACE_TS_Mutex::sleep_hook");
552 ACE_TS_Mutex::token_acquired (ACE_TPQ_Entry
*e
)
554 ACE_TRACE ("ACE_TS_Mutex::token_acquired");
555 // Notify the token handler.
556 th_
->token_acquired (e
);
561 ACE_TS_Mutex::clone (void) const
563 ACE_TRACE ("ACE_TS_Mutex::clone");
564 ACE_Token_Proxy
*temp
;
565 ACE_NEW_RETURN (temp
, ACE_TS_Mutex (*this), 0);
569 // ************************************************************
571 ACE_TS_RLock::ACE_TS_RLock (const ACE_TCHAR
*name
,
572 ACE_Token_Handler
*th
)
573 : ACE_Local_RLock (name
, 0, 1), // The 1 is debug.
576 ACE_TRACE ("ACE_TS_RLock::ACE_TS_RLock");
579 ACE_TS_RLock::ACE_TS_RLock (const ACE_TS_RLock
&r
)
580 : ACE_Local_RLock (r
),
583 ACE_TRACE ("ACE_TS_RLock::ACE_TS_RLock");
584 this->open (r
.name (), r
.ignore_deadlock_
, r
.debug_
);
588 ACE_TS_RLock::sleep_hook (void)
590 ACE_TRACE ("ACE_TS_RLock::sleep_hook");
596 ACE_TS_RLock::token_acquired (ACE_TPQ_Entry
*e
)
598 ACE_TRACE ("ACE_TS_RLock::token_acquired");
599 // Notify the token handler.
600 th_
->token_acquired (e
);
605 ACE_TS_RLock::clone (void) const
607 ACE_TRACE ("ACE_TS_RLock::clone");
608 ACE_Token_Proxy
*temp
;
610 ACE_NEW_RETURN (temp
, ACE_TS_RLock (*this), 0);
614 // ************************************************************
616 ACE_TS_WLock::ACE_TS_WLock (const ACE_TCHAR
*name
,
617 ACE_Token_Handler
*th
)
618 : ACE_Local_WLock (name
, 0, 1), // The 1 is debug.
621 ACE_TRACE ("ACE_TS_WLock::ACE_TS_WLock");
624 ACE_TS_WLock::ACE_TS_WLock (const ACE_TS_WLock
&w
)
625 : ACE_Local_WLock (w
),
628 ACE_TRACE ("ACE_TS_WLock::ACE_TS_WLock");
629 this->open (w
.name (), w
.ignore_deadlock_
, w
.debug_
);
633 ACE_TS_WLock::sleep_hook (void)
635 ACE_TRACE ("ACE_TS_WLock::sleep_hook");
641 ACE_TS_WLock::token_acquired (ACE_TPQ_Entry
*e
)
643 ACE_TRACE ("ACE_TS_WLock::token_acquired");
644 // Notify the token handler.
645 th_
->token_acquired (e
);
650 ACE_TS_WLock::clone (void) const
652 ACE_TRACE ("ACE_TS_WLock::clone");
653 ACE_Token_Proxy
*temp
;
655 ACE_NEW_RETURN (temp
, ACE_TS_WLock (*this), 0);
659 #endif /* ACE_HAS_TOKENS_LIBRARY */