IEventCallback implementation
| 992 | |
| 993 | // IEventCallback implementation |
| 994 | void eventCallbackFunction(unsigned int length, const UCHAR* items) |
| 995 | /************************************** |
| 996 | * |
| 997 | * s e r v e r _ a s t |
| 998 | * |
| 999 | ************************************** |
| 1000 | * |
| 1001 | * Functional description |
| 1002 | * Send an asynchronous event packet back to client. |
| 1003 | * |
| 1004 | **************************************/ |
| 1005 | { |
| 1006 | rem_port* port = rdb->rdb_port->port_async; |
| 1007 | if (!port || (port->port_flags & PORT_detached)) |
| 1008 | return; |
| 1009 | |
| 1010 | RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION); |
| 1011 | |
| 1012 | if (port->port_flags & PORT_detached) |
| 1013 | return; |
| 1014 | |
| 1015 | // hvlad: it is important to call IEvents::cancel() under protection |
| 1016 | // of async port mutex to avoid crash in rem_port::que_events |
| 1017 | |
| 1018 | const bool allowCancel = event->rvnt_destroyed.compareExchange(0, 1); |
| 1019 | if (!allowCancel) |
| 1020 | return; |
| 1021 | |
| 1022 | if (!(port->port_flags & PORT_disconnect)) |
| 1023 | { |
| 1024 | PACKET packet; |
| 1025 | packet.p_operation = op_event; |
| 1026 | P_EVENT* p_event = &packet.p_event; |
| 1027 | p_event->p_event_database = rdb->rdb_id; |
| 1028 | p_event->p_event_items.cstr_length = length; |
| 1029 | p_event->p_event_items.cstr_address = items; |
| 1030 | p_event->p_event_rid = event->rvnt_id; |
| 1031 | |
| 1032 | port->send(&packet); |
| 1033 | } |
| 1034 | |
| 1035 | if (event->rvnt_iface) |
| 1036 | { |
| 1037 | LocalStatus ls; |
| 1038 | CheckStatusWrapper status_vector(&ls); |
| 1039 | event->rvnt_iface->cancel(&status_vector); |
| 1040 | event->rvnt_iface = NULL; |
| 1041 | } |
| 1042 | } |
| 1043 | |
| 1044 | private: |
| 1045 | Rdb* rdb; |
no test coverage detected