PageRenderTime 59ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/dep/acelite/ace/POSIX_Proactor.cpp

https://github.com/chucho/FaceCore
C++ | 1695 lines | 1187 code | 297 blank | 211 comment | 152 complexity | 5cf4a974d07bff6fb20d131a083a1ca3 MD5 | raw file
  1. // $Id: POSIX_Proactor.cpp 92069 2010-09-28 11:38:59Z johnnyw $
  2. #include "ace/POSIX_Proactor.h"
  3. #if defined (ACE_HAS_AIO_CALLS)
  4. #if !defined (__ACE_INLINE__)
  5. #include "ace/POSIX_Proactor.inl"
  6. #endif /* __ACE_INLINE__ */
  7. # if defined (ACE_HAS_SYS_SYSTEMINFO_H)
  8. # include /**/ <sys/systeminfo.h>
  9. # endif /* ACE_HAS_SYS_SYSTEMINFO_H */
  10. #include "ace/ACE.h"
  11. #include "ace/Flag_Manip.h"
  12. #include "ace/Task_T.h"
  13. #include "ace/Log_Msg.h"
  14. #include "ace/Object_Manager.h"
  15. #include "ace/OS_NS_sys_socket.h"
  16. #include "ace/OS_NS_signal.h"
  17. #include "ace/OS_NS_unistd.h"
  18. #if defined (sun)
  19. # include "ace/OS_NS_strings.h"
  20. #endif /* sun */
  21. // *********************************************************************
  22. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  23. /**
  24. * @class ACE_POSIX_Wakeup_Completion
  25. *
  26. * This result object is used by the <end_event_loop> of the
  27. * ACE_Proactor interface to wake up all the threads blocking
  28. * for completions.
  29. */
  30. class ACE_POSIX_Wakeup_Completion : public ACE_POSIX_Asynch_Result
  31. {
  32. public:
  33. /// Constructor.
  34. ACE_POSIX_Wakeup_Completion (const ACE_Handler::Proxy_Ptr &handler_proxy,
  35. const void *act = 0,
  36. ACE_HANDLE event = ACE_INVALID_HANDLE,
  37. int priority = 0,
  38. int signal_number = ACE_SIGRTMIN);
  39. /// Destructor.
  40. virtual ~ACE_POSIX_Wakeup_Completion (void);
  41. /// This method calls the <handler>'s <handle_wakeup> method.
  42. virtual void complete (size_t bytes_transferred = 0,
  43. int success = 1,
  44. const void *completion_key = 0,
  45. u_long error = 0);
  46. };
  47. // *********************************************************************
  48. ACE_POSIX_Proactor::ACE_POSIX_Proactor (void)
  49. : os_id_ (ACE_OS_UNDEFINED)
  50. {
  51. #if defined(sun)
  52. os_id_ = ACE_OS_SUN; // set family
  53. char Buf [32];
  54. ::memset(Buf,0,sizeof(Buf));
  55. ACE_OS::sysinfo (SI_RELEASE , Buf, sizeof(Buf)-1);
  56. if (ACE_OS::strcasecmp (Buf , "5.6") == 0)
  57. os_id_ = ACE_OS_SUN_56;
  58. else if (ACE_OS::strcasecmp (Buf , "5.7") == 0)
  59. os_id_ = ACE_OS_SUN_57;
  60. else if (ACE_OS::strcasecmp (Buf , "5.8") == 0)
  61. os_id_ = ACE_OS_SUN_58;
  62. #elif defined(HPUX)
  63. os_id_ = ACE_OS_HPUX; // set family
  64. #elif defined(__OpenBSD)
  65. os_id_ = ACE_OS_OPENBSD; // set family
  66. // do the same
  67. //#else defined (LINUX, __FreeBSD__ ...)
  68. //setup here os_id_
  69. #endif
  70. }
  71. ACE_POSIX_Proactor::~ACE_POSIX_Proactor (void)
  72. {
  73. this->close ();
  74. }
  75. int
  76. ACE_POSIX_Proactor::close (void)
  77. {
  78. return 0;
  79. }
  80. int
  81. ACE_POSIX_Proactor::register_handle (ACE_HANDLE handle,
  82. const void *completion_key)
  83. {
  84. ACE_UNUSED_ARG (handle);
  85. ACE_UNUSED_ARG (completion_key);
  86. return 0;
  87. }
  88. int
  89. ACE_POSIX_Proactor::wake_up_dispatch_threads (void)
  90. {
  91. return 0;
  92. }
  93. int
  94. ACE_POSIX_Proactor::close_dispatch_threads (int)
  95. {
  96. return 0;
  97. }
  98. size_t
  99. ACE_POSIX_Proactor::number_of_threads (void) const
  100. {
  101. // @@ Implement it.
  102. ACE_NOTSUP_RETURN (0);
  103. }
  104. void
  105. ACE_POSIX_Proactor::number_of_threads (size_t threads)
  106. {
  107. // @@ Implement it.
  108. ACE_UNUSED_ARG (threads);
  109. }
  110. ACE_HANDLE
  111. ACE_POSIX_Proactor::get_handle (void) const
  112. {
  113. return ACE_INVALID_HANDLE;
  114. }
  115. ACE_Asynch_Read_Stream_Impl *
  116. ACE_POSIX_Proactor::create_asynch_read_stream (void)
  117. {
  118. ACE_Asynch_Read_Stream_Impl *implementation = 0;
  119. ACE_NEW_RETURN (implementation,
  120. ACE_POSIX_Asynch_Read_Stream (this),
  121. 0);
  122. return implementation;
  123. }
  124. ACE_Asynch_Read_Stream_Result_Impl *
  125. ACE_POSIX_Proactor::create_asynch_read_stream_result
  126. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  127. ACE_HANDLE handle,
  128. ACE_Message_Block &message_block,
  129. size_t bytes_to_read,
  130. const void* act,
  131. ACE_HANDLE event,
  132. int priority,
  133. int signal_number)
  134. {
  135. ACE_Asynch_Read_Stream_Result_Impl *implementation;
  136. ACE_NEW_RETURN (implementation,
  137. ACE_POSIX_Asynch_Read_Stream_Result (handler_proxy,
  138. handle,
  139. message_block,
  140. bytes_to_read,
  141. act,
  142. event,
  143. priority,
  144. signal_number),
  145. 0);
  146. return implementation;
  147. }
  148. ACE_Asynch_Write_Stream_Impl *
  149. ACE_POSIX_Proactor::create_asynch_write_stream (void)
  150. {
  151. ACE_Asynch_Write_Stream_Impl *implementation = 0;
  152. ACE_NEW_RETURN (implementation,
  153. ACE_POSIX_Asynch_Write_Stream (this),
  154. 0);
  155. return implementation;
  156. }
  157. ACE_Asynch_Write_Stream_Result_Impl *
  158. ACE_POSIX_Proactor::create_asynch_write_stream_result
  159. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  160. ACE_HANDLE handle,
  161. ACE_Message_Block &message_block,
  162. size_t bytes_to_write,
  163. const void* act,
  164. ACE_HANDLE event,
  165. int priority,
  166. int signal_number)
  167. {
  168. ACE_Asynch_Write_Stream_Result_Impl *implementation;
  169. ACE_NEW_RETURN (implementation,
  170. ACE_POSIX_Asynch_Write_Stream_Result (handler_proxy,
  171. handle,
  172. message_block,
  173. bytes_to_write,
  174. act,
  175. event,
  176. priority,
  177. signal_number),
  178. 0);
  179. return implementation;
  180. }
  181. ACE_Asynch_Read_File_Impl *
  182. ACE_POSIX_Proactor::create_asynch_read_file (void)
  183. {
  184. ACE_Asynch_Read_File_Impl *implementation = 0;
  185. ACE_NEW_RETURN (implementation,
  186. ACE_POSIX_Asynch_Read_File (this),
  187. 0);
  188. return implementation;
  189. }
  190. ACE_Asynch_Read_File_Result_Impl *
  191. ACE_POSIX_Proactor::create_asynch_read_file_result
  192. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  193. ACE_HANDLE handle,
  194. ACE_Message_Block &message_block,
  195. size_t bytes_to_read,
  196. const void* act,
  197. u_long offset,
  198. u_long offset_high,
  199. ACE_HANDLE event,
  200. int priority,
  201. int signal_number)
  202. {
  203. ACE_Asynch_Read_File_Result_Impl *implementation;
  204. ACE_NEW_RETURN (implementation,
  205. ACE_POSIX_Asynch_Read_File_Result (handler_proxy,
  206. handle,
  207. message_block,
  208. bytes_to_read,
  209. act,
  210. offset,
  211. offset_high,
  212. event,
  213. priority,
  214. signal_number),
  215. 0);
  216. return implementation;
  217. }
  218. ACE_Asynch_Write_File_Impl *
  219. ACE_POSIX_Proactor::create_asynch_write_file (void)
  220. {
  221. ACE_Asynch_Write_File_Impl *implementation = 0;
  222. ACE_NEW_RETURN (implementation,
  223. ACE_POSIX_Asynch_Write_File (this),
  224. 0);
  225. return implementation;
  226. }
  227. ACE_Asynch_Write_File_Result_Impl *
  228. ACE_POSIX_Proactor::create_asynch_write_file_result
  229. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  230. ACE_HANDLE handle,
  231. ACE_Message_Block &message_block,
  232. size_t bytes_to_write,
  233. const void* act,
  234. u_long offset,
  235. u_long offset_high,
  236. ACE_HANDLE event,
  237. int priority,
  238. int signal_number)
  239. {
  240. ACE_Asynch_Write_File_Result_Impl *implementation;
  241. ACE_NEW_RETURN (implementation,
  242. ACE_POSIX_Asynch_Write_File_Result (handler_proxy,
  243. handle,
  244. message_block,
  245. bytes_to_write,
  246. act,
  247. offset,
  248. offset_high,
  249. event,
  250. priority,
  251. signal_number),
  252. 0);
  253. return implementation;
  254. }
  255. ACE_Asynch_Read_Dgram_Impl *
  256. ACE_POSIX_Proactor::create_asynch_read_dgram (void)
  257. {
  258. ACE_Asynch_Read_Dgram_Impl *implementation = 0;
  259. ACE_NEW_RETURN (implementation,
  260. ACE_POSIX_Asynch_Read_Dgram (this),
  261. 0);
  262. return implementation;
  263. }
  264. ACE_Asynch_Read_Dgram_Result_Impl *
  265. ACE_POSIX_Proactor::create_asynch_read_dgram_result
  266. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  267. ACE_HANDLE handle,
  268. ACE_Message_Block *message_block,
  269. size_t bytes_to_read,
  270. int flags,
  271. int protocol_family,
  272. const void* act,
  273. ACE_HANDLE event ,
  274. int priority ,
  275. int signal_number)
  276. {
  277. ACE_Asynch_Read_Dgram_Result_Impl *implementation=0;
  278. ACE_NEW_RETURN (implementation,
  279. ACE_POSIX_Asynch_Read_Dgram_Result(handler_proxy,
  280. handle,
  281. message_block,
  282. bytes_to_read,
  283. flags,
  284. protocol_family,
  285. act,
  286. event,
  287. priority,
  288. signal_number),
  289. 0);
  290. return implementation;
  291. }
  292. ACE_Asynch_Write_Dgram_Impl *
  293. ACE_POSIX_Proactor::create_asynch_write_dgram (void)
  294. {
  295. ACE_Asynch_Write_Dgram_Impl *implementation = 0;
  296. ACE_NEW_RETURN (implementation,
  297. ACE_POSIX_Asynch_Write_Dgram (this),
  298. 0);
  299. return implementation;
  300. }
  301. ACE_Asynch_Write_Dgram_Result_Impl *
  302. ACE_POSIX_Proactor::create_asynch_write_dgram_result
  303. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  304. ACE_HANDLE handle,
  305. ACE_Message_Block *message_block,
  306. size_t bytes_to_write,
  307. int flags,
  308. const void* act,
  309. ACE_HANDLE event,
  310. int priority ,
  311. int signal_number)
  312. {
  313. ACE_Asynch_Write_Dgram_Result_Impl *implementation=0;
  314. ACE_NEW_RETURN (implementation,
  315. ACE_POSIX_Asynch_Write_Dgram_Result(handler_proxy,
  316. handle,
  317. message_block,
  318. bytes_to_write,
  319. flags,
  320. act,
  321. event,
  322. priority,
  323. signal_number),
  324. 0);
  325. return implementation;
  326. }
  327. ACE_Asynch_Accept_Impl *
  328. ACE_POSIX_Proactor::create_asynch_accept (void)
  329. {
  330. ACE_Asynch_Accept_Impl *implementation = 0;
  331. ACE_NEW_RETURN (implementation,
  332. ACE_POSIX_Asynch_Accept (this),
  333. 0);
  334. return implementation;
  335. }
  336. ACE_Asynch_Accept_Result_Impl *
  337. ACE_POSIX_Proactor::create_asynch_accept_result
  338. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  339. ACE_HANDLE listen_handle,
  340. ACE_HANDLE accept_handle,
  341. ACE_Message_Block &message_block,
  342. size_t bytes_to_read,
  343. const void* act,
  344. ACE_HANDLE event,
  345. int priority,
  346. int signal_number)
  347. {
  348. ACE_Asynch_Accept_Result_Impl *implementation;
  349. ACE_NEW_RETURN (implementation,
  350. ACE_POSIX_Asynch_Accept_Result (handler_proxy,
  351. listen_handle,
  352. accept_handle,
  353. message_block,
  354. bytes_to_read,
  355. act,
  356. event,
  357. priority,
  358. signal_number),
  359. 0);
  360. return implementation;
  361. }
  362. ACE_Asynch_Connect_Impl *
  363. ACE_POSIX_Proactor::create_asynch_connect (void)
  364. {
  365. ACE_Asynch_Connect_Impl *implementation = 0;
  366. ACE_NEW_RETURN (implementation,
  367. ACE_POSIX_Asynch_Connect (this),
  368. 0);
  369. return implementation;
  370. }
  371. ACE_Asynch_Connect_Result_Impl *
  372. ACE_POSIX_Proactor::create_asynch_connect_result
  373. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  374. ACE_HANDLE connect_handle,
  375. const void* act,
  376. ACE_HANDLE event,
  377. int priority,
  378. int signal_number)
  379. {
  380. ACE_Asynch_Connect_Result_Impl *implementation;
  381. ACE_NEW_RETURN (implementation,
  382. ACE_POSIX_Asynch_Connect_Result (handler_proxy,
  383. connect_handle,
  384. act,
  385. event,
  386. priority,
  387. signal_number),
  388. 0);
  389. return implementation;
  390. }
  391. ACE_Asynch_Transmit_File_Impl *
  392. ACE_POSIX_Proactor::create_asynch_transmit_file (void)
  393. {
  394. ACE_Asynch_Transmit_File_Impl *implementation = 0;
  395. ACE_NEW_RETURN (implementation,
  396. ACE_POSIX_Asynch_Transmit_File (this),
  397. 0);
  398. return implementation;
  399. }
  400. ACE_Asynch_Transmit_File_Result_Impl *
  401. ACE_POSIX_Proactor::create_asynch_transmit_file_result
  402. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  403. ACE_HANDLE socket,
  404. ACE_HANDLE file,
  405. ACE_Asynch_Transmit_File::Header_And_Trailer *header_and_trailer,
  406. size_t bytes_to_write,
  407. u_long offset,
  408. u_long offset_high,
  409. size_t bytes_per_send,
  410. u_long flags,
  411. const void *act,
  412. ACE_HANDLE event,
  413. int priority,
  414. int signal_number)
  415. {
  416. ACE_Asynch_Transmit_File_Result_Impl *implementation;
  417. ACE_NEW_RETURN (implementation,
  418. ACE_POSIX_Asynch_Transmit_File_Result (handler_proxy,
  419. socket,
  420. file,
  421. header_and_trailer,
  422. bytes_to_write,
  423. offset,
  424. offset_high,
  425. bytes_per_send,
  426. flags,
  427. act,
  428. event,
  429. priority,
  430. signal_number),
  431. 0);
  432. return implementation;
  433. }
  434. ACE_Asynch_Result_Impl *
  435. ACE_POSIX_Proactor::create_asynch_timer
  436. (const ACE_Handler::Proxy_Ptr &handler_proxy,
  437. const void *act,
  438. const ACE_Time_Value &tv,
  439. ACE_HANDLE event,
  440. int priority,
  441. int signal_number)
  442. {
  443. ACE_POSIX_Asynch_Timer *implementation;
  444. ACE_NEW_RETURN (implementation,
  445. ACE_POSIX_Asynch_Timer (handler_proxy,
  446. act,
  447. tv,
  448. event,
  449. priority,
  450. signal_number),
  451. 0);
  452. return implementation;
  453. }
  454. void
  455. ACE_POSIX_Proactor::application_specific_code (ACE_POSIX_Asynch_Result *asynch_result,
  456. size_t bytes_transferred,
  457. const void */* completion_key*/,
  458. u_long error)
  459. {
  460. ACE_SEH_TRY
  461. {
  462. // Call completion hook
  463. asynch_result->complete (bytes_transferred,
  464. error ? 0 : 1,
  465. 0, // No completion key.
  466. error);
  467. }
  468. ACE_SEH_FINALLY
  469. {
  470. // This is crucial to prevent memory leaks
  471. delete asynch_result;
  472. }
  473. }
  474. int
  475. ACE_POSIX_Proactor::post_wakeup_completions (int how_many)
  476. {
  477. ACE_POSIX_Wakeup_Completion *wakeup_completion = 0;
  478. for (int ci = 0; ci < how_many; ci++)
  479. {
  480. ACE_NEW_RETURN
  481. (wakeup_completion,
  482. ACE_POSIX_Wakeup_Completion (this->wakeup_handler_.proxy ()),
  483. -1);
  484. if (this->post_completion (wakeup_completion) == -1)
  485. return -1;
  486. }
  487. return 0;
  488. }
  489. ACE_POSIX_Proactor::Proactor_Type
  490. ACE_POSIX_Proactor::get_impl_type (void)
  491. {
  492. return PROACTOR_POSIX;
  493. }
  494. /**
  495. * @class ACE_AIOCB_Notify_Pipe_Manager
  496. *
  497. * @brief This class manages the notify pipe of the AIOCB Proactor.
  498. *
  499. * This class acts as the Handler for the
  500. * <Asynch_Read> operations issued on the notify pipe. This
  501. * class is very useful in implementing <Asynch_Accept> operation
  502. * class for the <AIOCB_Proactor>. This is also useful for
  503. * implementing <post_completion> for <AIOCB_Proactor>.
  504. * <AIOCB_Proactor> class issues a <Asynch_Read> on
  505. * the pipe, using this class as the
  506. * Handler. <POSIX_Asynch_Result *>'s are sent through the
  507. * notify pipe. When <POSIX_Asynch_Result *>'s show up on the
  508. * notify pipe, the <POSIX_AIOCB_Proactor> dispatches the
  509. * completion of the <Asynch_Read_Stream> and calls the
  510. * <handle_read_stream> of this class. This class calls
  511. * <complete> on the <POSIX_Asynch_Result *> and thus calls the
  512. * application handler.
  513. * Handling the MessageBlock:
  514. * We give this message block to read the result pointer through
  515. * the notify pipe. We expect that to read 4 bytes from the
  516. * notify pipe, for each <accept> call. Before giving this
  517. * message block to another <accept>, we update <wr_ptr> and put
  518. * it in its initial position.
  519. */
  520. class ACE_AIOCB_Notify_Pipe_Manager : public ACE_Handler
  521. {
  522. public:
  523. /// Constructor. You need the posix proactor because you need to call
  524. /// <application_specific_code>
  525. ACE_AIOCB_Notify_Pipe_Manager (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor);
  526. /// Destructor.
  527. virtual ~ACE_AIOCB_Notify_Pipe_Manager (void);
  528. /// Send the result pointer through the notification pipe.
  529. int notify ();
  530. /// This is the call back method when <Asynch_Read> from the pipe is
  531. /// complete.
  532. virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
  533. private:
  534. /// The implementation proactor class.
  535. ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor_;
  536. /// Message block to get ACE_POSIX_Asynch_Result pointer from the pipe.
  537. ACE_Message_Block message_block_;
  538. /// Pipe for the communication between Proactor and the
  539. /// Asynch_Accept/Asynch_Connect and other post_completions
  540. ACE_Pipe pipe_;
  541. /// To do asynch_read on the pipe.
  542. ACE_POSIX_Asynch_Read_Stream read_stream_;
  543. /// Default constructor. Shouldnt be called.
  544. ACE_AIOCB_Notify_Pipe_Manager (void);
  545. };
  546. ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager (ACE_POSIX_AIOCB_Proactor *posix_aiocb_proactor)
  547. : posix_aiocb_proactor_ (posix_aiocb_proactor),
  548. message_block_ (sizeof (2)),
  549. read_stream_ (posix_aiocb_proactor)
  550. {
  551. // Open the pipe.
  552. this->pipe_.open ();
  553. // Set write side in NONBLOCK mode
  554. ACE::set_flags (this->pipe_.write_handle (), ACE_NONBLOCK);
  555. // Set read side in BLOCK mode
  556. ACE::clr_flags (this->pipe_.read_handle (), ACE_NONBLOCK);
  557. // Let AIOCB_Proactor know about our handle
  558. posix_aiocb_proactor_->set_notify_handle (this->pipe_.read_handle ());
  559. // Open the read stream.
  560. if (this->read_stream_.open (this->proxy (),
  561. this->pipe_.read_handle (),
  562. 0, // Completion Key
  563. 0) // Proactor
  564. == -1)
  565. ACE_ERROR ((LM_ERROR,
  566. ACE_TEXT("%N:%l:%p\n"),
  567. ACE_TEXT("ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager:")
  568. ACE_TEXT("Open on Read Stream failed")));
  569. // Issue an asynch_read on the read_stream of the notify pipe.
  570. if (this->read_stream_.read (this->message_block_,
  571. 1, // enough to read 1 byte
  572. 0, // ACT
  573. 0) // Priority
  574. == -1)
  575. ACE_ERROR ((LM_ERROR,
  576. ACE_TEXT("%N:%l:%p\n"),
  577. ACE_TEXT("ACE_AIOCB_Notify_Pipe_Manager::ACE_AIOCB_Notify_Pipe_Manager:")
  578. ACE_TEXT("Read from pipe failed")));
  579. }
  580. ACE_AIOCB_Notify_Pipe_Manager::~ACE_AIOCB_Notify_Pipe_Manager (void)
  581. {
  582. // 1. try to cancel pending aio
  583. this->read_stream_.cancel ();
  584. // 2. close both handles
  585. // Destuctor of ACE_Pipe does not close handles.
  586. // We can not use ACE_Pipe::close() as it
  587. // closes read_handle and than write_handle.
  588. // In some systems close() may wait for
  589. // completion for all asynch. pending requests.
  590. // So we should close write_handle firstly
  591. // to force read completion ( if 1. does not help )
  592. // and then read_handle and not vice versa
  593. ACE_HANDLE h = this->pipe_.write_handle ();
  594. if (h != ACE_INVALID_HANDLE)
  595. ACE_OS::closesocket (h);
  596. h = this->pipe_.read_handle ();
  597. if ( h != ACE_INVALID_HANDLE)
  598. ACE_OS::closesocket (h);
  599. }
  600. int
  601. ACE_AIOCB_Notify_Pipe_Manager::notify ()
  602. {
  603. // Send the result pointer through the pipe.
  604. char char_send = 0;
  605. ssize_t ret_val = ACE::send (this->pipe_.write_handle (),
  606. &char_send,
  607. sizeof (char_send));
  608. if (ret_val < 0)
  609. {
  610. if (errno != EWOULDBLOCK)
  611. #if 0
  612. ACE_ERROR ((LM_ERROR,
  613. ACE_TEXT ("(%P %t):%p\n"),
  614. ACE_TEXT ("ACE_AIOCB_Notify_Pipe_Manager::notify")
  615. ACE_TEXT ("Error:Writing on to notify pipe failed")));
  616. #endif /* 0 */
  617. return -1;
  618. }
  619. return 0;
  620. }
  621. void
  622. ACE_AIOCB_Notify_Pipe_Manager::handle_read_stream
  623. (const ACE_Asynch_Read_Stream::Result & /*result*/)
  624. {
  625. // 1. Start new read to avoid pipe overflow
  626. // Set the message block properly. Put the <wr_ptr> back in the
  627. // initial position.
  628. if (this->message_block_.length () > 0)
  629. this->message_block_.wr_ptr (this->message_block_.rd_ptr ());
  630. // One accept has completed. Issue a read to handle any
  631. // <post_completion>s in the future.
  632. if (-1 == this->read_stream_.read (this->message_block_,
  633. 1, // enough to read 1 byte
  634. 0, // ACT
  635. 0)) // Priority
  636. ACE_ERROR ((LM_ERROR,
  637. ACE_TEXT ("%N:%l:(%P | %t):%p\n"),
  638. ACE_TEXT ("ACE_AIOCB_Notify_Pipe_Manager::handle_read_stream:")
  639. ACE_TEXT ("Read from pipe failed")));
  640. // 2. Do the upcalls
  641. // this->posix_aiocb_proactor_->process_result_queue ();
  642. }
  643. // Public constructor for common use.
  644. ACE_POSIX_AIOCB_Proactor::ACE_POSIX_AIOCB_Proactor (size_t max_aio_operations)
  645. : aiocb_notify_pipe_manager_ (0),
  646. aiocb_list_ (0),
  647. result_list_ (0),
  648. aiocb_list_max_size_ (max_aio_operations),
  649. aiocb_list_cur_size_ (0),
  650. notify_pipe_read_handle_ (ACE_INVALID_HANDLE),
  651. num_deferred_aiocb_ (0),
  652. num_started_aio_ (0)
  653. {
  654. // Check for correct value for max_aio_operations
  655. check_max_aio_num ();
  656. this->create_result_aiocb_list ();
  657. this->create_notify_manager ();
  658. // start pseudo-asynchronous accept task
  659. // one per all future acceptors
  660. this->get_asynch_pseudo_task().start ();
  661. }
  662. // Special protected constructor for ACE_SUN_Proactor
  663. ACE_POSIX_AIOCB_Proactor::ACE_POSIX_AIOCB_Proactor (size_t max_aio_operations,
  664. ACE_POSIX_Proactor::Proactor_Type)
  665. : aiocb_notify_pipe_manager_ (0),
  666. aiocb_list_ (0),
  667. result_list_ (0),
  668. aiocb_list_max_size_ (max_aio_operations),
  669. aiocb_list_cur_size_ (0),
  670. notify_pipe_read_handle_ (ACE_INVALID_HANDLE),
  671. num_deferred_aiocb_ (0),
  672. num_started_aio_ (0)
  673. {
  674. //check for correct value for max_aio_operations
  675. this->check_max_aio_num ();
  676. this->create_result_aiocb_list ();
  677. // @@ We should create Notify_Pipe_Manager in the derived class to
  678. // provide correct calls for virtual functions !!!
  679. }
  680. // Destructor.
  681. ACE_POSIX_AIOCB_Proactor::~ACE_POSIX_AIOCB_Proactor (void)
  682. {
  683. this->close();
  684. }
  685. ACE_POSIX_Proactor::Proactor_Type
  686. ACE_POSIX_AIOCB_Proactor::get_impl_type (void)
  687. {
  688. return PROACTOR_AIOCB;
  689. }
  690. int
  691. ACE_POSIX_AIOCB_Proactor::close (void)
  692. {
  693. // stop asynch accept task
  694. this->get_asynch_pseudo_task().stop ();
  695. this->delete_notify_manager ();
  696. this->clear_result_queue ();
  697. return this->delete_result_aiocb_list ();
  698. }
  699. void ACE_POSIX_AIOCB_Proactor::set_notify_handle (ACE_HANDLE h)
  700. {
  701. notify_pipe_read_handle_ = h;
  702. }
  703. int ACE_POSIX_AIOCB_Proactor::create_result_aiocb_list (void)
  704. {
  705. if (aiocb_list_ != 0)
  706. return 0;
  707. ACE_NEW_RETURN (aiocb_list_, aiocb *[aiocb_list_max_size_], -1);
  708. ACE_NEW_RETURN (result_list_,
  709. ACE_POSIX_Asynch_Result *[aiocb_list_max_size_],
  710. -1);
  711. // Initialize the array.
  712. for (size_t ai = 0; ai < this->aiocb_list_max_size_; ai++)
  713. {
  714. aiocb_list_[ai] = 0;
  715. result_list_[ai] = 0;
  716. }
  717. return 0;
  718. }
  719. int ACE_POSIX_AIOCB_Proactor::delete_result_aiocb_list (void)
  720. {
  721. if (aiocb_list_ == 0) // already deleted
  722. return 0;
  723. size_t ai;
  724. // Try to cancel all uncompleted operations; POSIX systems may have
  725. // hidden system threads that still can work with our aiocbs!
  726. for (ai = 0; ai < aiocb_list_max_size_; ai++)
  727. if (this->aiocb_list_[ai] != 0) // active operation
  728. this->cancel_aiocb (result_list_[ai]);
  729. int num_pending = 0;
  730. for (ai = 0; ai < aiocb_list_max_size_; ai++)
  731. {
  732. if (this->aiocb_list_[ai] == 0 ) // not active operation
  733. continue;
  734. // Get the error and return status of the aio_ operation.
  735. int error_status = 0;
  736. size_t transfer_count = 0;
  737. int flg_completed = this->get_result_status (result_list_[ai],
  738. error_status,
  739. transfer_count);
  740. //don't delete uncompleted AIOCB's
  741. if (flg_completed == 0) // not completed !!!
  742. {
  743. num_pending++;
  744. #if 0
  745. char * errtxt = ACE_OS::strerror (error_status);
  746. if (errtxt == 0)
  747. errtxt ="?????????";
  748. char * op = (aiocb_list_[ai]->aio_lio_opcode == LIO_WRITE )?
  749. "WRITE":"READ" ;
  750. ACE_ERROR ((LM_ERROR,
  751. ACE_TEXT("slot=%d op=%s status=%d xfercnt=%d %s\n"),
  752. ai,
  753. op,
  754. error_status,
  755. transfer_count,
  756. errtxt));
  757. #endif /* 0 */
  758. }
  759. else // completed , OK
  760. {
  761. delete this->result_list_[ai];
  762. this->result_list_[ai] = 0;
  763. this->aiocb_list_[ai] = 0;
  764. }
  765. }
  766. // If it is not possible cancel some operation (num_pending > 0 ),
  767. // we can do only one thing -report about this
  768. // and complain about POSIX implementation.
  769. // We know that we have memory leaks, but it is better than
  770. // segmentation fault!
  771. ACE_DEBUG
  772. ((LM_DEBUG,
  773. ACE_TEXT("ACE_POSIX_AIOCB_Proactor::delete_result_aiocb_list\n")
  774. ACE_TEXT(" number pending AIO=%d\n"),
  775. num_pending));
  776. delete [] this->aiocb_list_;
  777. this->aiocb_list_ = 0;
  778. delete [] this->result_list_;
  779. this->result_list_ = 0;
  780. return (num_pending == 0 ? 0 : -1);
  781. // ?? or just always return 0;
  782. }
  783. void ACE_POSIX_AIOCB_Proactor::check_max_aio_num ()
  784. {
  785. long max_os_aio_num = ACE_OS::sysconf (_SC_AIO_MAX);
  786. // Define max limit AIO's for concrete OS
  787. // -1 means that there is no limit, but it is not true
  788. // (example, SunOS 5.6)
  789. if (max_os_aio_num > 0 &&
  790. aiocb_list_max_size_ > (unsigned long) max_os_aio_num)
  791. aiocb_list_max_size_ = max_os_aio_num;
  792. #if defined (HPUX) || defined (__FreeBSD__)
  793. // Although HPUX 11.00 allows to start 2048 AIO's for all process in
  794. // system it has a limit 256 max elements for aio_suspend () It is a
  795. // pity, but ...
  796. long max_os_listio_num = ACE_OS::sysconf (_SC_AIO_LISTIO_MAX);
  797. if (max_os_listio_num > 0
  798. && aiocb_list_max_size_ > (unsigned long) max_os_listio_num)
  799. aiocb_list_max_size_ = max_os_listio_num;
  800. #endif /* HPUX || __FreeBSD__ */
  801. // check for user-defined value
  802. // ACE_AIO_MAX_SIZE if defined in POSIX_Proactor.h
  803. if (aiocb_list_max_size_ <= 0
  804. || aiocb_list_max_size_ > ACE_AIO_MAX_SIZE)
  805. aiocb_list_max_size_ = ACE_AIO_MAX_SIZE;
  806. // check for max number files to open
  807. int max_num_files = ACE::max_handles ();
  808. if (max_num_files > 0
  809. && aiocb_list_max_size_ > (unsigned long) max_num_files)
  810. {
  811. ACE::set_handle_limit (aiocb_list_max_size_);
  812. max_num_files = ACE::max_handles ();
  813. }
  814. if (max_num_files > 0
  815. && aiocb_list_max_size_ > (unsigned long) max_num_files)
  816. aiocb_list_max_size_ = (unsigned long) max_num_files;
  817. ACE_DEBUG ((LM_DEBUG,
  818. "(%P | %t) ACE_POSIX_AIOCB_Proactor::Max Number of AIOs=%d\n",
  819. aiocb_list_max_size_));
  820. #if defined(__sgi)
  821. ACE_DEBUG((LM_DEBUG,
  822. ACE_TEXT( "SGI IRIX specific: aio_init!\n")));
  823. //typedef struct aioinit {
  824. // int aio_threads; /* The number of aio threads to start (5) */
  825. // int aio_locks; /* Initial number of preallocated locks (3) */
  826. // int aio_num; /* estimated total simultanious aiobc structs (1000) */
  827. // int aio_usedba; /* Try to use DBA for raw I/O in lio_listio (0) */
  828. // int aio_debug; /* turn on debugging (0) */
  829. // int aio_numusers; /* max number of user sprocs making aio_* calls (5) */
  830. // int aio_reserved[3];
  831. //} aioinit_t;
  832. aioinit_t aioinit;
  833. aioinit.aio_threads = 10; /* The number of aio threads to start (5) */
  834. aioinit.aio_locks = 20; /* Initial number of preallocated locks (3) */
  835. /* estimated total simultaneous aiobc structs (1000) */
  836. aioinit.aio_num = aiocb_list_max_size_;
  837. aioinit.aio_usedba = 0; /* Try to use DBA for raw IO in lio_listio (0) */
  838. aioinit.aio_debug = 0; /* turn on debugging (0) */
  839. aioinit.aio_numusers = 100; /* max number of user sprocs making aio_* calls (5) */
  840. aioinit.aio_reserved[0] = 0;
  841. aioinit.aio_reserved[1] = 0;
  842. aioinit.aio_reserved[2] = 0;
  843. aio_sgi_init (&aioinit);
  844. #endif
  845. return;
  846. }
  847. void
  848. ACE_POSIX_AIOCB_Proactor::create_notify_manager (void)
  849. {
  850. // Remember! this issues a Asynch_Read
  851. // on the notify pipe for doing the Asynch_Accept/Connect.
  852. if (aiocb_notify_pipe_manager_ == 0)
  853. ACE_NEW (aiocb_notify_pipe_manager_,
  854. ACE_AIOCB_Notify_Pipe_Manager (this));
  855. }
  856. void
  857. ACE_POSIX_AIOCB_Proactor::delete_notify_manager (void)
  858. {
  859. // We are responsible for delete as all pointers set to 0 after
  860. // delete, it is save to delete twice
  861. delete aiocb_notify_pipe_manager_;
  862. aiocb_notify_pipe_manager_ = 0;
  863. }
  864. int
  865. ACE_POSIX_AIOCB_Proactor::handle_events (ACE_Time_Value &wait_time)
  866. {
  867. // Decrement <wait_time> with the amount of time spent in the method
  868. ACE_Countdown_Time countdown (&wait_time);
  869. return this->handle_events_i (wait_time.msec ());
  870. }
  871. int
  872. ACE_POSIX_AIOCB_Proactor::handle_events (void)
  873. {
  874. return this->handle_events_i (ACE_INFINITE);
  875. }
  876. int
  877. ACE_POSIX_AIOCB_Proactor::notify_completion(int sig_num)
  878. {
  879. ACE_UNUSED_ARG (sig_num);
  880. return this->aiocb_notify_pipe_manager_->notify ();
  881. }
  882. int
  883. ACE_POSIX_AIOCB_Proactor::post_completion (ACE_POSIX_Asynch_Result *result)
  884. {
  885. ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
  886. int ret_val = this->putq_result (result);
  887. return ret_val;
  888. }
  889. int
  890. ACE_POSIX_AIOCB_Proactor::putq_result (ACE_POSIX_Asynch_Result *result)
  891. {
  892. // this protected method should be called with locked mutex_
  893. // we can't use GUARD as Proactor uses non-recursive mutex
  894. if (!result)
  895. return -1;
  896. int sig_num = result->signal_number ();
  897. int ret_val = this->result_queue_.enqueue_tail (result);
  898. if (ret_val == -1)
  899. ACE_ERROR_RETURN ((LM_ERROR,
  900. "%N:%l:ACE_POSIX_AIOCB_Proactor::putq_result failed\n"),
  901. -1);
  902. this->notify_completion (sig_num);
  903. return 0;
  904. }
  905. ACE_POSIX_Asynch_Result * ACE_POSIX_AIOCB_Proactor::getq_result (void)
  906. {
  907. ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, 0));
  908. ACE_POSIX_Asynch_Result* result = 0;
  909. if (this->result_queue_.dequeue_head (result) != 0)
  910. return 0;
  911. // don't waste time if queue is empty - it is normal
  912. // or check queue size before dequeue_head
  913. // ACE_ERROR_RETURN ((LM_ERROR,
  914. // ACE_TEXT("%N:%l:(%P | %t):%p\n"),
  915. // ACE_TEXT("ACE_POSIX_AIOCB_Proactor::getq_result failed")),
  916. // 0);
  917. return result;
  918. }
  919. int ACE_POSIX_AIOCB_Proactor::clear_result_queue (void)
  920. {
  921. int ret_val = 0;
  922. ACE_POSIX_Asynch_Result* result = 0;
  923. while ((result = this->getq_result ()) != 0)
  924. {
  925. delete result;
  926. ret_val++;
  927. }
  928. return ret_val;
  929. }
  930. int ACE_POSIX_AIOCB_Proactor::process_result_queue (void)
  931. {
  932. int ret_val = 0;
  933. ACE_POSIX_Asynch_Result* result = 0;
  934. while ((result = this->getq_result ()) != 0)
  935. {
  936. this->application_specific_code
  937. (result,
  938. result->bytes_transferred(), // 0, No bytes transferred.
  939. 0, // No completion key.
  940. result->error()); //0, No error.
  941. ret_val++;
  942. }
  943. return ret_val;
  944. }
  945. int
  946. ACE_POSIX_AIOCB_Proactor::handle_events_i (u_long milli_seconds)
  947. {
  948. int result_suspend = 0;
  949. int retval= 0;
  950. if (milli_seconds == ACE_INFINITE)
  951. // Indefinite blocking.
  952. result_suspend = aio_suspend (aiocb_list_,
  953. aiocb_list_max_size_,
  954. 0);
  955. else
  956. {
  957. // Block on <aio_suspend> for <milli_seconds>
  958. timespec timeout;
  959. timeout.tv_sec = milli_seconds / 1000;
  960. timeout.tv_nsec = (milli_seconds - (timeout.tv_sec * 1000)) * 1000000;
  961. result_suspend = aio_suspend (aiocb_list_,
  962. aiocb_list_max_size_,
  963. &timeout);
  964. }
  965. // Check for errors
  966. if (result_suspend == -1)
  967. {
  968. if (errno != EAGAIN && // Timeout
  969. errno != EINTR ) // Interrupted call
  970. ACE_ERROR ((LM_ERROR,
  971. ACE_TEXT ("%N:%l:(%P|%t)::%p\n"),
  972. ACE_TEXT ("handle_events: aio_suspend failed")));
  973. // let continue work
  974. // we should check "post_completed" queue
  975. }
  976. else
  977. {
  978. size_t index = 0;
  979. size_t count = aiocb_list_max_size_; // max number to iterate
  980. int error_status = 0;
  981. size_t transfer_count = 0;
  982. for (;; retval++)
  983. {
  984. ACE_POSIX_Asynch_Result *asynch_result =
  985. find_completed_aio (error_status,
  986. transfer_count,
  987. index,
  988. count);
  989. if (asynch_result == 0)
  990. break;
  991. // Call the application code.
  992. this->application_specific_code (asynch_result,
  993. transfer_count,
  994. 0, // No completion key.
  995. error_status);
  996. }
  997. }
  998. // process post_completed results
  999. retval += this->process_result_queue ();
  1000. return retval > 0 ? 1 : 0;
  1001. }
  1002. int
  1003. ACE_POSIX_AIOCB_Proactor::get_result_status (ACE_POSIX_Asynch_Result *asynch_result,
  1004. int &error_status,
  1005. size_t &transfer_count)
  1006. {
  1007. transfer_count = 0;
  1008. // Get the error status of the aio_ operation.
  1009. // The following aio_ptr anathema is required to work around a bug in an over-aggressive
  1010. // optimizer in GCC 4.1.2.
  1011. aiocb *aio_ptr (asynch_result);
  1012. error_status = aio_error (aio_ptr);
  1013. if (error_status == EINPROGRESS)
  1014. return 0; // not completed
  1015. ssize_t op_return = aio_return (aio_ptr);
  1016. if (op_return > 0)
  1017. transfer_count = static_cast<size_t> (op_return);
  1018. // else transfer_count is already 0, error_status reports the error.
  1019. return 1; // completed
  1020. }
  1021. ACE_POSIX_Asynch_Result *
  1022. ACE_POSIX_AIOCB_Proactor::find_completed_aio (int &error_status,
  1023. size_t &transfer_count,
  1024. size_t &index,
  1025. size_t &count)
  1026. {
  1027. // parameter index defines initial slot to scan
  1028. // parameter count tells us how many slots should we scan
  1029. ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, 0));
  1030. ACE_POSIX_Asynch_Result *asynch_result = 0;
  1031. if (num_started_aio_ == 0) // save time
  1032. return 0;
  1033. for (; count > 0; index++ , count--)
  1034. {
  1035. if (index >= aiocb_list_max_size_) // like a wheel
  1036. index = 0;
  1037. if (aiocb_list_[index] == 0) // Dont process null blocks.
  1038. continue;
  1039. if (0 != this->get_result_status (result_list_[index],
  1040. error_status,
  1041. transfer_count)) // completed
  1042. break;
  1043. } // end for
  1044. if (count == 0) // all processed , nothing found
  1045. return 0;
  1046. asynch_result = result_list_[index];
  1047. aiocb_list_[index] = 0;
  1048. result_list_[index] = 0;
  1049. aiocb_list_cur_size_--;
  1050. num_started_aio_--; // decrement count active aios
  1051. index++; // for next iteration
  1052. count--; // for next iteration
  1053. this->start_deferred_aio ();
  1054. //make attempt to start deferred AIO
  1055. //It is safe as we are protected by mutex_
  1056. return asynch_result;
  1057. }
  1058. int
  1059. ACE_POSIX_AIOCB_Proactor::start_aio (ACE_POSIX_Asynch_Result *result,
  1060. ACE_POSIX_Proactor::Opcode op)
  1061. {
  1062. ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_aio");
  1063. ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1));
  1064. int ret_val = (aiocb_list_cur_size_ >= aiocb_list_max_size_) ? -1 : 0;
  1065. if (result == 0) // Just check the status of the list
  1066. return ret_val;
  1067. // Save operation code in the aiocb
  1068. switch (op)
  1069. {
  1070. case ACE_POSIX_Proactor::ACE_OPCODE_READ:
  1071. result->aio_lio_opcode = LIO_READ;
  1072. break;
  1073. case ACE_POSIX_Proactor::ACE_OPCODE_WRITE:
  1074. result->aio_lio_opcode = LIO_WRITE;
  1075. break;
  1076. default:
  1077. ACE_ERROR_RETURN ((LM_ERROR,
  1078. ACE_TEXT ("%N:%l:(%P|%t)::")
  1079. ACE_TEXT ("start_aio: Invalid op code %d\n"),
  1080. op),
  1081. -1);
  1082. }
  1083. if (ret_val != 0) // No free slot
  1084. {
  1085. errno = EAGAIN;
  1086. return -1;
  1087. }
  1088. // Find a free slot and store.
  1089. ssize_t slot = allocate_aio_slot (result);
  1090. if (slot < 0)
  1091. return -1;
  1092. size_t index = static_cast<size_t> (slot);
  1093. result_list_[index] = result; //Store result ptr anyway
  1094. aiocb_list_cur_size_++;
  1095. ret_val = start_aio_i (result);
  1096. switch (ret_val)
  1097. {
  1098. case 0: // started OK
  1099. aiocb_list_[index] = result;
  1100. return 0;
  1101. case 1: // OS AIO queue overflow
  1102. num_deferred_aiocb_ ++;
  1103. return 0;
  1104. default: // Invalid request, there is no point
  1105. break; // to start it later
  1106. }
  1107. result_list_[index] = 0;
  1108. aiocb_list_cur_size_--;
  1109. return -1;
  1110. }
  1111. ssize_t
  1112. ACE_POSIX_AIOCB_Proactor::allocate_aio_slot (ACE_POSIX_Asynch_Result *result)
  1113. {
  1114. size_t i = 0;
  1115. // we reserve zero slot for ACE_AIOCB_Notify_Pipe_Manager
  1116. // so make check for ACE_AIOCB_Notify_Pipe_Manager request
  1117. if (notify_pipe_read_handle_ == result->aio_fildes) // Notify_Pipe ?
  1118. { // should be free,
  1119. if (result_list_[i] != 0) // only 1 request
  1120. { // is allowed
  1121. errno = EAGAIN;
  1122. ACE_ERROR_RETURN ((LM_ERROR,
  1123. "%N:%l:(%P | %t)::\n"
  1124. "ACE_POSIX_AIOCB_Proactor::allocate_aio_slot:"
  1125. "internal Proactor error 0\n"),
  1126. -1);
  1127. }
  1128. }
  1129. else //try to find free slot as usual, but starting from 1
  1130. {
  1131. for (i= 1; i < this->aiocb_list_max_size_; i++)
  1132. if (result_list_[i] == 0)
  1133. break;
  1134. }
  1135. if (i >= this->aiocb_list_max_size_)
  1136. ACE_ERROR_RETURN ((LM_ERROR,
  1137. "%N:%l:(%P | %t)::\n"
  1138. "ACE_POSIX_AIOCB_Proactor::allocate_aio_slot:"
  1139. "internal Proactor error 1\n"),
  1140. -1);
  1141. //setup OS notification methods for this aio
  1142. result->aio_sigevent.sigev_notify = SIGEV_NONE;
  1143. return static_cast<ssize_t> (i);
  1144. }
  1145. // start_aio_i has new return codes
  1146. // 0 AIO was started successfully
  1147. // 1 AIO was not started, OS AIO queue overflow
  1148. // -1 AIO was not started, other errors
  1149. int
  1150. ACE_POSIX_AIOCB_Proactor::start_aio_i (ACE_POSIX_Asynch_Result *result)
  1151. {
  1152. ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_aio_i");
  1153. int ret_val;
  1154. const ACE_TCHAR *ptype = 0;
  1155. // Start IO
  1156. // The following aio_ptr anathema is required to work around a bug in
  1157. // the optimizer for GCC 4.1.2
  1158. aiocb * aio_ptr (result);
  1159. switch (result->aio_lio_opcode )
  1160. {
  1161. case LIO_READ :
  1162. ptype = ACE_TEXT ("read ");
  1163. ret_val = aio_read (aio_ptr);
  1164. break;
  1165. case LIO_WRITE :
  1166. ptype = ACE_TEXT ("write");
  1167. ret_val = aio_write (aio_ptr);
  1168. break;
  1169. default:
  1170. ptype = ACE_TEXT ("?????");
  1171. ret_val = -1;
  1172. break;
  1173. }
  1174. if (ret_val == 0)
  1175. {
  1176. ++this->num_started_aio_;
  1177. }
  1178. else // if (ret_val == -1)
  1179. {
  1180. if (errno == EAGAIN || errno == ENOMEM) //Ok, it will be deferred AIO
  1181. ret_val = 1;
  1182. else
  1183. ACE_ERROR ((LM_ERROR,
  1184. ACE_TEXT ("%N:%l:(%P | %t)::start_aio_i: aio_%s %p\n"),
  1185. ptype,
  1186. ACE_TEXT ("queueing failed")));
  1187. }
  1188. return ret_val;
  1189. }
  1190. int
  1191. ACE_POSIX_AIOCB_Proactor::start_deferred_aio ()
  1192. {
  1193. ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::start_deferred_aio");
  1194. // This protected method is called from
  1195. // find_completed_aio after any AIO completion
  1196. // We should call this method always with locked
  1197. // ACE_POSIX_AIOCB_Proactor::mutex_
  1198. //
  1199. // It tries to start the first deferred AIO
  1200. // if such exists
  1201. if (num_deferred_aiocb_ == 0)
  1202. return 0; // nothing to do
  1203. size_t i = 0;
  1204. for (i= 0; i < this->aiocb_list_max_size_; i++)
  1205. if (result_list_[i] !=0 // check for
  1206. && aiocb_list_[i] ==0) // deferred AIO
  1207. break;
  1208. if (i >= this->aiocb_list_max_size_)
  1209. ACE_ERROR_RETURN ((LM_ERROR,
  1210. "%N:%l:(%P | %t)::\n"
  1211. "start_deferred_aio:"
  1212. "internal Proactor error 3\n"),
  1213. -1);
  1214. ACE_POSIX_Asynch_Result *result = result_list_[i];
  1215. int ret_val = start_aio_i (result);
  1216. switch (ret_val)
  1217. {
  1218. case 0 : //started OK , decrement count of deferred AIOs
  1219. aiocb_list_[i] = result;
  1220. num_deferred_aiocb_ --;
  1221. return 0;
  1222. case 1 :
  1223. return 0; //try again later
  1224. default : // Invalid Parameters , should never be
  1225. break;
  1226. }
  1227. //AL notify user
  1228. result_list_[i] = 0;
  1229. --aiocb_list_cur_size_;
  1230. --num_deferred_aiocb_;
  1231. result->set_error (errno);
  1232. result->set_bytes_transferred (0);
  1233. this->putq_result (result); // we are with locked mutex_ here !
  1234. return -1;
  1235. }
  1236. int
  1237. ACE_POSIX_AIOCB_Proactor::cancel_aio (ACE_HANDLE handle)
  1238. {
  1239. // This new method should be called from
  1240. // ACE_POSIX_Asynch_Operation instead of usual ::aio_cancel
  1241. // It scans the result_list_ and defines all AIO requests
  1242. // that were issued for handle "handle"
  1243. //
  1244. // For all deferred AIO requests with handle "handle"
  1245. // it removes its from the lists and notifies user
  1246. //
  1247. // For all running AIO requests with handle "handle"
  1248. // it calls ::aio_cancel. According to the POSIX standards
  1249. // we will receive ECANCELED for all ::aio_canceled AIO requests
  1250. // later on return from ::aio_suspend
  1251. ACE_TRACE ("ACE_POSIX_AIOCB_Proactor::cancel_aio");
  1252. int num_total = 0;
  1253. int num_cancelled = 0;
  1254. {
  1255. ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->mutex_, -1));
  1256. size_t ai = 0;
  1257. for (ai = 0; ai < this->aiocb_list_max_size_; ai++)
  1258. {
  1259. if (this->result_list_[ai] == 0) // Skip empty slot
  1260. continue;
  1261. if (this->result_list_[ai]->aio_fildes != handle) // Not ours
  1262. continue;
  1263. ++num_total;
  1264. ACE_POSIX_Asynch_Result *asynch_result = this->result_list_[ai];
  1265. if (this->aiocb_list_[ai] == 0) // Canceling a deferred operation
  1266. {
  1267. num_cancelled++;
  1268. this->num_deferred_aiocb_--;
  1269. this->aiocb_list_[ai] = 0;
  1270. this->result_list_[ai] = 0;
  1271. this->aiocb_list_cur_size_--;
  1272. asynch_result->set_error (ECANCELED);
  1273. asynch_result->set_bytes_transferred (0);
  1274. this->putq_result (asynch_result);
  1275. // we are with locked mutex_ here !
  1276. }
  1277. else // Cancel started aio
  1278. {
  1279. int rc_cancel = this->cancel_aiocb (asynch_result);
  1280. if (rc_cancel == 0) //notification in the future
  1281. num_cancelled++; //it is OS responsiblity
  1282. }
  1283. }
  1284. } // release mutex_
  1285. if (num_total == 0)
  1286. return 1; // ALLDONE
  1287. if (num_cancelled == num_total)
  1288. return 0; // CANCELLED
  1289. return 2; // NOT CANCELLED
  1290. }
  1291. int
  1292. ACE_POSIX_AIOCB_Proactor::cancel_aiocb (ACE_POSIX_Asynch_Result * result)
  1293. {
  1294. // This method is called from cancel_aio
  1295. // to cancel a previously submitted AIO request
  1296. int rc = ::aio_cancel (0, result);
  1297. // Check the return value and return 0/1/2 appropriately.
  1298. if (rc == AIO_CANCELED)
  1299. return 0;
  1300. else if (rc == AIO_ALLDONE)
  1301. return 1;
  1302. else // (rc == AIO_NOTCANCELED)
  1303. return 2;
  1304. }
  1305. // *********************************************************************
  1306. #if defined(ACE_HAS_POSIX_REALTIME_SIGNALS)
  1307. ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor (size_t max_aio_operations)
  1308. : ACE_POSIX_AIOCB_Proactor (max_aio_operations,
  1309. ACE_POSIX_Proactor::PROACTOR_SIG)
  1310. {
  1311. // = Set up the mask we'll use to block waiting for SIGRTMIN. Use that
  1312. // to add it to the signal mask for this thread, and also set the process
  1313. // signal action to pass signal information when we want it.
  1314. // Clear the signal set.
  1315. ACE_OS::sigemptyset (&this->RT_completion_signals_);
  1316. // Add the signal number to the signal set.
  1317. if (ACE_OS::sigaddset (&this->RT_completion_signals_, ACE_SIGRTMIN) == -1)
  1318. ACE_ERROR ((LM_ERROR, ACE_TEXT ("ACE_POSIX_SIG_Proactor: %p\n"),
  1319. ACE_TEXT ("sigaddset")));
  1320. this->block_signals ();
  1321. // Set up the signal action for SIGRTMIN.
  1322. this->setup_signal_handler (ACE_SIGRTMIN);
  1323. // we do not have to create notify manager
  1324. // but we should start pseudo-asynchronous accept task
  1325. // one per all future acceptors
  1326. this->get_asynch_pseudo_task().start ();
  1327. return;
  1328. }
  1329. ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor (const sigset_t signal_set,
  1330. size_t max_aio_operations)
  1331. : ACE_POSIX_AIOCB_Proactor (max_aio_operations,
  1332. ACE_POSIX_Proactor::PROACTOR_SIG)
  1333. {
  1334. // = Keep <Signal_set> with the Proactor, mask all the signals and
  1335. // setup signal actions for the signals in the <signal_set>.
  1336. // = Keep <signal_set> with the Proactor.
  1337. // Empty the signal set first.
  1338. if (sigemptyset (&this->RT_completion_signals_) == -1)
  1339. ACE_ERROR ((LM_ERROR,
  1340. ACE_TEXT("Error:(%P | %t):%p\n"),
  1341. ACE_TEXT("sigemptyset failed")));
  1342. // For each signal number present in the <signal_set>, add it to
  1343. // the signal set we use, and also set up its process signal action
  1344. // to allow signal info to be passed into sigwait/sigtimedwait.
  1345. int member = 0;
  1346. for (int si = ACE_SIGRTMIN; si <= ACE_SIGRTMAX; si++)
  1347. {
  1348. member = sigismember (&signal_set,
  1349. si);
  1350. if (member == -1)
  1351. ACE_ERROR ((LM_ERROR,
  1352. ACE_TEXT("%N:%l:(%P | %t)::%p\n"),
  1353. ACE_TEXT("ACE_POSIX_SIG_Proactor::ACE_POSIX_SIG_Proactor:")
  1354. ACE_TEXT("sigismember failed")));
  1355. else if (member == 1)
  1356. {
  1357. sigaddset (&this->RT_completion_signals_, si);
  1358. this->setup_signal_handler (si);
  1359. }
  1360. }
  1361. // Mask all the signals.
  1362. this->block_signals ();
  1363. // we do not have to create notify manager
  1364. // but we should start pseudo-asynchronous accept task
  1365. // one per all future acceptors
  1366. this->get_asynch_pseudo_task().start ();
  1367. return;
  1368. }
  1369. ACE_POSIX_SIG_Proactor::~ACE_POSIX_SIG_Proactor (void)
  1370. {
  1371. this->close ();
  1372. // @@ Enable the masked signals again.
  1373. }
  1374. ACE_POSIX_Proactor::Proactor_Type
  1375. ACE_POSIX_SIG_Proactor::get_impl_type (void)
  1376. {
  1377. return PROACTOR_SIG;
  1378. }
  1379. int
  1380. ACE_POSIX_SIG_Proactor::handle_events (ACE_Time_Value &wait_time)
  1381. {
  1382. // Decrement <wait_time> with the amount of time spent in the method
  1383. ACE_Countdown_Time countdown (&wait_time);
  1384. return this->handle_events_i (&wait_time);
  1385. }
  1386. int
  1387. ACE_POSIX_SIG_Proactor::handle_events (void)
  1388. {
  1389. return this->handle_events_i (0);
  1390. }
  1391. int
  1392. ACE_POSIX_SIG_Proactor::notify_completion (int sig_num)
  1393. {
  1394. // Get this process id.
  1395. pid_t const pid = ACE_OS::getpid ();
  1396. if (pid == (pid_t) -1)
  1397. ACE_ERROR_RETURN ((LM_ERROR,