blob: 2a3d7fb1ebf54d9e104467fa6e778abc2dbaff02 [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*****************************************************************************
* Filename: EventRegistration.cc
* Purpose: This file contains functions and structures used in event
* notification and callbacks for remote clients; also has the
* thread that services event notification.
* Created: 2/15/01
*
*
***************************************************************************/
#include "libts.h"
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <string.h>
#include "ink_thread.h"
#include "MgmtSocket.h"
#include "mgmtapi.h"
#include "EventRegistration.h"
#include "CoreAPIShared.h"
#include "NetworkUtilsDefs.h"
#include "NetworkUtilsRemote.h"
#include "EventCallback.h"
CallbackTable *remote_event_callbacks;
/**********************************************************************
* event_poll_thread_main
*
* purpose: thread listens on the client's event socket connection;
* only reads from the event_socket connection and
* processes EVENT_NOTIFY messages; each time client
* makes new event-socket connection to TM, must launch
* a new event_poll_thread_main thread
* input: arg - contains the socket_fd to listen on
* output: NULL - if error
* notes: each time the client's socket connection to TM is reset
* a new thread will be launched as old one dies; there are
* only two places where a new thread is created:
* 1) when client first connects (TSInit call)
* 2) client reconnects() due to a TM restart
* Uses blocking socket; so blocks until receives an event notification.
* Shouldn't need to use select since only waiting for a notification
* message from event_callback_main thread!
**********************************************************************/
void *
event_poll_thread_main(void *arg)
{
TSError err;
int sock_fd;
TSEvent *event_notice = NULL;
sock_fd = *((int *) arg); // should be same as event_socket_fd
// the sock_fd is going to be the one we listen for events on
while (1) {
// possible sock_fd is invalid if TM restarts and client reconnects
if (sock_fd < 0) {
break;
}
// read the entire message, so create TSEvent for the callback
event_notice = TSEventCreate();
err = parse_event_notification(sock_fd, event_notice);
if (err == TS_ERR_NET_READ || err == TS_ERR_NET_EOF) {
break;
} else if (err != TS_ERR_OKAY) {
TSEventDestroy(event_notice);
continue; // skip the message
}
// got event notice; spawn new thread to handle the event's callback functions
ink_thread_create(event_callback_thread, (void *) event_notice, 0, DEFAULT_STACK_SIZE);
}
if (event_notice)
TSEventDestroy(event_notice);
ink_thread_exit(NULL);
return NULL;
}
/**********************************************************************
* event_callback_thread
*
* purpose: Given an event, determines and calls the registered cb functions
* in the CallbackTable for remote events
* input: arg - should be an TSEvent with the event info sent from TM msg
* output: returns when done calling all the callbacks
* notes: None
**********************************************************************/
void *
event_callback_thread(void *arg)
{
TSEvent *event_notice;
EventCallbackT *event_cb;
int index;
event_notice = (TSEvent *) arg;
index = (int) event_notice->id;
LLQ *func_q; // list of callback functions need to call
func_q = create_queue();
if (!func_q) {
if (event_notice)
TSEventDestroy(event_notice);
return NULL;
}
// obtain lock
ink_mutex_acquire(&remote_event_callbacks->event_callback_lock);
TSEventSignalFunc cb;
// check if we have functions to call
if (remote_event_callbacks->event_callback_l[index] && (!queue_is_empty(remote_event_callbacks->event_callback_l[index]))) {
int queue_depth = queue_len(remote_event_callbacks->event_callback_l[index]);
for (int i = 0; i < queue_depth; i++) {
event_cb = (EventCallbackT *) dequeue(remote_event_callbacks->event_callback_l[index]);
cb = event_cb->func;
enqueue(remote_event_callbacks->event_callback_l[index], event_cb);
enqueue(func_q, (void *) cb); // add callback function only to list
}
}
// release lock
ink_mutex_release(&remote_event_callbacks->event_callback_lock);
// execute the callback function
while (!queue_is_empty(func_q)) {
cb = (TSEventSignalFunc) dequeue(func_q);
(*cb) (event_notice->name, event_notice->description, event_notice->priority, NULL);
}
// clean up event notice
TSEventDestroy(event_notice);
delete_queue(func_q);
// all done!
ink_thread_exit(NULL);
return NULL;
}