/* * Copyright (c) 2013-2017 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 * */ /** * @file * Wind River CGTS Platform Resource Monitor Resource Notify */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #include "../rmonApi/rmon_nodeMacro.h" /* for ... CREATE_NONBLOCK_INET_UDP_RX_SOCKET */ #include "rmon_resource_notify.h" extern "C" { #include "../rmonApi/rmon_api.h" } #define LOOPBACK_IP "127.0.0.1" #define RX_PORT (2304) static char my_hostname [MAX_HOST_NAME_SIZE+1]; static rmon_socket_type rmon_sock ; static rmon_socket_type * sock_ptr ; /** Client Config mask */ #define CONFIG_CLIENT_MASK (CONFIG_AGENT_PORT |\ CONFIG_CLIENT_API_PORT |\ CONFIG_CLIENT_PORT) /****************************/ /* Initialization Utilities */ /****************************/ /* Initialize the unicast api response message */ /* One time thing ; tx same message all the time. */ int rmon_message_init ( void ) { /* Build the transmit api response message */ memset ( &sock_ptr->tx_message, 0, sizeof (rmon_message_type)); memcpy ( &sock_ptr->tx_message.m[RMON_HEADER_SIZE], my_hostname, strlen(my_hostname)); return (PASS); } int rmon_socket_init ( int port, const char * process_name ) { int on = 1 ; int rc = PASS ; CREATE_NONBLOCK_INET_UDP_RX_SOCKET ( LOOPBACK_IP, port, rmon_sock.rmon_api_sock, rmon_sock.rmon_api_addr, rmon_sock.rmon_api_port, rmon_sock.rmon_api_len, "rmon api socket receive", rc ); if ( rc ) return (rc) ; /* Open the monitoring socket */ rmon_sock.rmon_socket = resource_monitor_initialize ( process_name, port, RMON_RESOURCE_NOT ); //ilog("Resource Monitor API Socket %d\n", rmon_sock.rmon_socket); if ( 0 > rmon_sock.rmon_socket ) { close_syslog(); return (FAIL); } /* Make the socket non-blocking */ rc = ioctl(rmon_sock.rmon_socket, FIONBIO, (char *)&on); if ( 0 > rc ) { //elog("Failed to set rmon socket non-blocking (%d:%m)\n", errno ); return (FAIL_SOCKET_NOBLOCK); } return (PASS); } int daemon_init (int port, const char * process_name ) { int rc = PASS ; /* Initialize socket construct and pointer to it */ memset ( &rmon_sock, 0, sizeof(rmon_sock)); sock_ptr = &rmon_sock ; /* Setup the resmon api rx messaging sockets */ if ( (rc = rmon_socket_init (port, process_name)) != PASS ) { // elog("socket initialization failed (rc:%d)\n", rc); rc = FAIL_SOCKET_INIT; } return (rc); } #define RMON_MAX_LEN (100) int client_service_inbox () { #define MAX_T 100 int bytes = 0 ; char buf[RMON_MAX_LEN] ; socklen_t len = sizeof(struct sockaddr_in) ; char str[RMON_MAX_LEN]; int rc = FAIL; do { memset ( buf,0,RMON_MAX_LEN); memset ( str,0,RMON_MAX_LEN); bytes = recvfrom( rmon_sock.rmon_socket, buf, RMON_MAX_LEN, 0, (struct sockaddr *)&rmon_sock.client_sockAddr, &len); if ( bytes > 0 ) { sscanf ( buf, "%99s", str); if ( str[0] != '\0' ) { if ( strcmp(str, RMON_DONE) == 0) { return (PASS); } } return (FAIL); } else if (( 0 > bytes ) && ( errno != EINTR ) && ( errno != EAGAIN )) { //ilog("problem with test client recv \n"); } } while ( bytes > 0 ) ; return rc; } /* Maximum length of the dynamic resource list */ #define DYNAMIC_RESOURCE_MAX (1024) int main ( int argc, char *argv[] ) { int rc; int port = RX_PORT; const char * process_name = PROCESS_NAME; char res_name[30]; char state[20]; char mount[50]; char type[20]; char device[50]; char volume_group[50]; string delimiter = ","; unsigned long long timeout = DEFAULT_RESPONSE_TIMEOUT; char dynamic_res[DYNAMIC_RESOURCE_MAX]; char resource_name [50]; struct stat fileInfo; struct timespec start, stop; struct flock fl; int fd; bool toNotify = false; vector dynamic_resources; size_t pos; string token; open_syslog(); memset ((char *)&fileInfo, 0 , sizeof(fileInfo)); memset(&res_name[0], 0, sizeof(res_name)); memset(&state[0], 0, sizeof(state)); memset(&mount[0], 0, sizeof(mount)); memset(&type[0], 0, sizeof(type)); memset(&device[0], 0, sizeof(device)); memset(&volume_group[0], 0, sizeof(volume_group)); memset(&dynamic_res[0], 0, sizeof(dynamic_res)); memset(&resource_name[0], 0, sizeof(resource_name)); fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = getpid(); if ((argc > 1) && (strcmp(argv[1],"--help") == 0)) { printf("usage: rmon_resource_notify " "--resource-name " "--resource-state " "--resource-type " "--device " "--mount-point " "--volume_group " "--timeout \n"); close_syslog(); return FAIL; } for (int i=0; i(mmap(0, fileInfo.st_size, PROT_READ, MAP_SHARED, fd, 0)); if (map == MAP_FAILED) { close(fd); // elog("Error mmapping the file"); close_syslog(); return (FAIL); } string oldFile(map); /* extract the resource name */ sscanf(dynamic_res, "%49s", resource_name); string newResource(resource_name); string updatedResource(dynamic_res); dynamic_resources.clear(); if ( oldFile.find(updatedResource) == string::npos ) { if ( oldFile.find(newResource) != string::npos ) { /* the resource exists, update it in the file */ while ((pos = oldFile.find(delimiter)) != string::npos) { /* separate the resources from the file */ token = oldFile.substr(0, pos); if (token.find(newResource) == string::npos) { dynamic_resources.push_back(token); } oldFile.erase(0, pos + delimiter.length()); } oldFile = ""; for (unsigned int i=0; i(mmap(0, textsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); if (map == MAP_FAILED) { close(fd); // elog("Error mmapping the file"); close_syslog(); return (FAIL); } /* write the resource into memory */ memcpy(map, text.c_str(), textsize); /* write the updated list to the disk */ if (msync(map, textsize, MS_SYNC) == -1) { ; // elog("Could not sync the file to disk"); } /* free the mmapped memory */ if (munmap(map, textsize) == -1) { /* unlock the file */ fl.l_type = F_UNLCK; fcntl(fd, F_SETLK, &fl); // elog("Error un-mmapping the file"); close_syslog(); return (FAIL); } } close(fd); /* unlock the file */ fl.l_type = F_UNLCK; fcntl(fd, F_SETLK, &fl); if (!toNotify) { close_syslog(); return (PASS); } /* Check to see if rmond is running */ rc = system("pidof rmond"); if (WEXITSTATUS(rc) != 0) { return (PASS); } rc = daemon_init(port, process_name); if (rc == PASS) { if( clock_gettime( CLOCK_MONOTONIC, &start) == -1 ) { // elog("clock gettime \n" ); close_syslog(); return (FAIL); } rmon_message_init(); rmon_sock.rmon_socket = resource_monitor_get_sel_obj (); std::list socks; socks.clear(); socks.push_front ( rmon_sock.rmon_socket ); socks.sort(); // remove the rmon resource notify flag file // as this will be reset by rmon remove (RESPONSE_RMON_RESOURCE_NOT); /* signal to rmon that the dynamic file has been written */ rc = rmon_notification ( RMON_RESOURCE_NOT ); for ( ; ; ) { /* Initialize the timeval struct */ rmon_sock.waitd.tv_sec = 0; rmon_sock.waitd.tv_usec = SELECT_TIMEOUT * 100; /* Initialize the master fd_set */ FD_ZERO(&rmon_sock.readfds); FD_SET(rmon_sock.rmon_socket, &rmon_sock.readfds); rc = select( socks.back()+1, &rmon_sock.readfds, NULL, NULL, &rmon_sock.waitd); /* If the select time out expired then */ if (( rc < 0 ) || ( rc == 0 )) { /* Check to see if the select call failed. */ /* ... but filter Interrupt signal */ if (( rc < 0 ) && ( errno != EINTR )) { //ilog("Socket Select Failed (rc:%d) %s \n", errno, strerror(errno)); } } if ( FD_ISSET(rmon_sock.rmon_socket, &rmon_sock.readfds)) { rc = client_service_inbox(); if (rc == PASS) { close_syslog(); return PASS; } } if ( clock_gettime( CLOCK_MONOTONIC, &stop) == -1 ) { // elog("clock gettime\n"); return (FAIL); } unsigned long delta = (stop.tv_sec - start.tv_sec) * 1000 + (stop.tv_nsec - start.tv_nsec) / 1000000; if (delta > timeout) { /* we exceeded the timeout. * It may have happened that rmon * sent its acknowledgment but that response * got lost. In that case check for the flag file * as a last ditch effort */ if (access(RESPONSE_RMON_RESOURCE_NOT, F_OK) != -1) { close_syslog() return (PASS); } close_syslog(); return (FAIL); } } } close_syslog(); return FAIL; }