/* * msa_attach.c - Part of AFD, an automatic file distribution program. * Copyright (c) 1998 - 2022 Holger Kiehl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "afddefs.h" DESCR__S_M3 /* ** NAME ** msa_attach - attaches to the MSA ** ** SYNOPSIS ** int msa_attach(void) ** int msa_attach_passive(void) ** ** DESCRIPTION ** Attaches to the memory mapped area of the MSA (Monitor Status ** Area). The first 8 bytes of this area contains the number of ** AFD's that are being monitored. The rest consist of the ** structure mon_status_area for each AFD. When the function ** returns successful it returns the pointer 'msa' to the begining ** of the first structure. ** ** RETURN VALUES ** SUCCESS when attaching to the MSA successful and sets the ** global pointer 'msa' to the start of the MSA and the size of ** the memory mapped file is returned. Also the MSA ID and the ** number of AFD's in the MSA is returned in 'msa_id' and ** 'no_of_afds' respectively. Otherwise INCORRECT is returned. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 30.08.1998 H.Kiehl Created ** 12.03.2009 H.Kiehl Added function msa_attach_passive(). ** */ DESCR__E_M3 #include #include /* strerror(), strlen() */ #include /* close(), read() */ #include #include #ifdef HAVE_MMAP # include /* mmap(), munmap() */ #endif #ifdef HAVE_FCNTL_H # include /* fcntl() */ #endif #include #include "mondefs.h" /* Global variables. */ extern int msa_fd, msa_id, no_of_afds; #ifdef HAVE_MMAP extern off_t msa_size; #endif extern char *p_work_dir; extern struct mon_status_area *msa; /*############################ msa_attach() #############################*/ int msa_attach(void) { int fd, loop_counter, retries = 0, timeout_loops = 0; char *ptr = NULL, *p_msa_stat_file, msa_id_file[MAX_PATH_LENGTH], msa_stat_file[MAX_PATH_LENGTH]; struct flock wlock = {F_WRLCK, SEEK_SET, 0, 1}, ulock = {F_UNLCK, SEEK_SET, 0, 1}; #ifdef HAVE_STATX struct statx stat_buf; #else struct stat stat_buf; #endif /* Get absolute path of MSA_ID_FILE. */ (void)strcpy(msa_id_file, p_work_dir); (void)strcat(msa_id_file, FIFO_DIR); (void)strcpy(msa_stat_file, msa_id_file); (void)strcat(msa_stat_file, MON_STATUS_FILE); p_msa_stat_file = msa_stat_file + strlen(msa_stat_file); (void)strcat(msa_id_file, MSA_ID_FILE); do { /* Make sure this is not the case when the */ /* no_of_afds is stale. */ if ((no_of_afds < 0) && (msa != NULL)) { /* Unmap from MSA. */ ptr = (char *)msa - AFD_WORD_OFFSET; #ifdef HAVE_MMAP if (munmap((void *)ptr, msa_size) == -1) #else if (munmap_emu((void *)ptr) == -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to munmap() `%s' : %s"), msa_stat_file, strerror(errno)); } else { msa = NULL; } timeout_loops++; if (timeout_loops > 200) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Unable to attach to a new MSA.")); return(INCORRECT); } /* No need to speed things up here. */ my_usleep(400000L); } /* * Retrieve the MSA (Monitor Status Area) ID from MSA_ID_FILE. * Make sure that it is not locked. */ loop_counter = 0; while ((fd = coe_open(msa_id_file, O_RDWR)) == -1) { if (errno == ENOENT) { my_usleep(400000L); if (loop_counter++ > 24) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to coe_open() `%s' : %s"), msa_id_file, strerror(errno)); return(INCORRECT); } } else { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to coe_open() `%s' : %s"), msa_id_file, strerror(errno)); return(INCORRECT); } } /* Check if its locked. */ if (fcntl(fd, F_SETLKW, &wlock) == -1) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Could not set write lock for `%s' : %s"), msa_id_file, strerror(errno)); (void)close(fd); return(INCORRECT); } /* Read the msa_id. */ if (read(fd, &msa_id, sizeof(int)) < 0) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Could not read the value of the msa_id : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } /* Unlock file and close it. */ if (fcntl(fd, F_SETLKW, &ulock) == -1) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Could not unlock `%s' : %s"), msa_id_file, strerror(errno)); (void)close(fd); return(INCORRECT); } if (close(fd) == -1) { system_log(WARN_SIGN, __FILE__, __LINE__, _("Could not close() `%s' : %s"), msa_id_file, strerror(errno)); } (void)snprintf(p_msa_stat_file, MAX_PATH_LENGTH - (p_msa_stat_file - msa_stat_file), ".%d", msa_id); if (msa_fd > 0) { if (close(msa_fd) == -1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, _("close() error : %s"), strerror(errno)); } } if ((msa_fd = coe_open(msa_stat_file, O_RDWR)) == -1) { if (errno == ENOENT) { if (retries++ > 8) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to open() `%s' : %s"), msa_stat_file, strerror(errno)); return(INCORRECT); } else { system_log(WARN_SIGN, __FILE__, __LINE__, _("Failed to open() `%s' : %s"), msa_stat_file, strerror(errno)); (void)sleep(1); continue; } } else { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to open() `%s' : %s"), msa_stat_file, strerror(errno)); return(INCORRECT); } } #ifdef HAVE_STATX if (statx(msa_fd, "", AT_STATX_SYNC_AS_STAT | AT_EMPTY_PATH, STATX_SIZE, &stat_buf) == -1) #else if (fstat(msa_fd, &stat_buf) == -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, #ifdef HAVE_STATX _("Failed to statx() `%s' : %s"), #else _("Failed to fstat() `%s' : %s"), #endif msa_stat_file, strerror(errno)); (void)close(msa_fd); msa_fd = -1; return(INCORRECT); } #ifdef HAVE_MMAP if ((ptr = mmap(NULL, # ifdef HAVE_STATX stat_buf.stx_size, (PROT_READ | PROT_WRITE), # else stat_buf.st_size, (PROT_READ | PROT_WRITE), # endif MAP_SHARED, msa_fd, 0)) == (caddr_t) -1) #else if ((ptr = mmap_emu(NULL, # ifdef HAVE_STATX stat_buf.stx_size, (PROT_READ | PROT_WRITE), # else stat_buf.st_size, (PROT_READ | PROT_WRITE), # endif MAP_SHARED, msa_stat_file, 0)) == (caddr_t) -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, _("mmap() error : %s"), strerror(errno)); (void)close(msa_fd); msa_fd = -1; return(INCORRECT); } /* Read number of AFD's. */ no_of_afds = *(int *)ptr; /* Check MSA version number. */ if ((no_of_afds > 0) && (*(ptr + SIZEOF_INT + 1 + 1 + 1) != CURRENT_MSA_VERSION)) { system_log(WARN_SIGN, __FILE__, __LINE__, _("This code is compiled for of MSA version %d, but the MSA we try to attach is %d."), CURRENT_MSA_VERSION, (int)(*(ptr + SIZEOF_INT + 1 + 1 + 1))); #ifdef HAVE_MMAP # ifdef HAVE_STATX if (munmap(ptr, stat_buf.stx_size) == -1) # else if (munmap(ptr, stat_buf.st_size) == -1) # endif #else if (munmap_emu(ptr) == -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to munmap() MSA : %s"), strerror(errno)); } (void)close(msa_fd); msa_fd = -1; return(INCORRECT_VERSION); } ptr += AFD_WORD_OFFSET; msa = (struct mon_status_area *)ptr; #ifdef HAVE_MMAP # ifdef HAVE_STATX msa_size = stat_buf.stx_size; # else msa_size = stat_buf.st_size; # endif #endif } while (no_of_afds <= 0); return(SUCCESS); } /*######################## msa_attach_passive() #########################*/ int msa_attach_passive(void) { int fd, retries = 0, timeout_loops = 0; char *ptr = NULL, *p_msa_stat_file, msa_id_file[MAX_PATH_LENGTH], msa_stat_file[MAX_PATH_LENGTH]; struct flock rlock = {F_RDLCK, SEEK_SET, 0, 1}; #ifdef HAVE_STATX struct statx stat_buf; #else struct stat stat_buf; #endif /* Get absolute path of MSA_ID_FILE. */ (void)strcpy(msa_id_file, p_work_dir); (void)strcat(msa_id_file, FIFO_DIR); (void)strcpy(msa_stat_file, msa_id_file); (void)strcat(msa_stat_file, MON_STATUS_FILE); p_msa_stat_file = msa_stat_file + strlen(msa_stat_file); (void)strcat(msa_id_file, MSA_ID_FILE); do { /* Make sure this is not the case when the */ /* no_of_afds is stale. */ if ((no_of_afds < 0) && (msa != NULL)) { /* Unmap from MSA. */ ptr = (char *)msa - AFD_WORD_OFFSET; #ifdef HAVE_MMAP if (munmap(ptr, msa_size) == -1) #else if (munmap_emu((void *)ptr) == -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to munmap() `%s' : %s"), msa_stat_file, strerror(errno)); } else { msa = NULL; } timeout_loops++; if (timeout_loops > 200) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Unable to attach to a new MSA.")); return(INCORRECT); } /* No need to speed things up here. */ my_usleep(400000L); } /* Read the MSA ID. */ if ((fd = coe_open(msa_id_file, O_RDONLY)) == -1) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to open() `%s' : %s"), msa_id_file, strerror(errno)); return(INCORRECT); } if (fcntl(fd, F_SETLKW, &rlock) == -1) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Could not get read lock for `%s' : %s"), msa_id_file, strerror(errno)); (void)close(fd); return(INCORRECT); } if (read(fd, &msa_id, sizeof(int)) < 0) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Could not read the value of the msa_id : %s"), strerror(errno)); (void)close(fd); return(INCORRECT); } if (close(fd) == -1) { system_log(WARN_SIGN, __FILE__, __LINE__, _("Could not close() `%s' : %s"), msa_id_file, strerror(errno)); } (void)snprintf(p_msa_stat_file, MAX_PATH_LENGTH - (p_msa_stat_file - msa_stat_file), ".%d", msa_id); if (msa_fd > 0) { if (close(msa_fd) == -1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, _("close() error : %s"), strerror(errno)); } } if ((msa_fd = coe_open(msa_stat_file, O_RDONLY)) == -1) { if (errno == ENOENT) { if (retries++ > 8) { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to open() `%s' : %s"), msa_stat_file, strerror(errno)); return(INCORRECT); } else { system_log(WARN_SIGN, __FILE__, __LINE__, _("Failed to open() `%s' : %s"), msa_stat_file, strerror(errno)); (void)sleep(1); continue; } } else { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to open() `%s' : %s"), msa_stat_file, strerror(errno)); return(INCORRECT); } } #ifdef HAVE_STATX if (statx(msa_fd, "", AT_STATX_SYNC_AS_STAT | AT_EMPTY_PATH, STATX_SIZE, &stat_buf) == -1) #else if (fstat(msa_fd, &stat_buf) == -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, #ifdef HAVE_STATX _("Failed to statx() `%s' : %s"), #else _("Failed to fstat() `%s' : %s"), #endif msa_stat_file, strerror(errno)); (void)close(msa_fd); msa_fd = -1; return(INCORRECT); } #ifdef HAVE_STATX if (stat_buf.stx_size < AFD_WORD_OFFSET) #else if (stat_buf.st_size < AFD_WORD_OFFSET) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, _("MSA not large enough to contain any meaningful data.")); (void)close(msa_fd); msa_fd = -1; return(INCORRECT); } #ifdef HAVE_MMAP if ((ptr = mmap(NULL, # ifdef HAVE_STATX stat_buf.stx_size, PROT_READ, # else stat_buf.st_size, PROT_READ, # endif MAP_SHARED, msa_fd, 0)) == (caddr_t) -1) #else if ((ptr = mmap_emu(NULL, # ifdef HAVE_STATX stat_buf.stx_size, PROT_READ, # else stat_buf.st_size, PROT_READ, # endif MAP_SHARED, msa_stat_file, 0)) == (caddr_t) -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, _("mmap() error : %s"), strerror(errno)); (void)close(msa_fd); msa_fd = -1; return(INCORRECT); } /* Read number of current MSA. */ no_of_afds = *(int *)ptr; /* Check MSA version number. */ if ((no_of_afds > 0) && (*(ptr + SIZEOF_INT + 1 + 1 + 1) != CURRENT_MSA_VERSION)) { system_log(WARN_SIGN, __FILE__, __LINE__, "This code is compiled for of MSA version %d, but the MSA we try to attach is %d.", CURRENT_MSA_VERSION, (int)(*(ptr + SIZEOF_INT + 1 + 1 + 1))); #ifdef HAVE_MMAP # ifdef HAVE_STATX if (munmap(ptr, stat_buf.stx_size) == -1) # else if (munmap(ptr, stat_buf.st_size) == -1) # endif #else if (munmap_emu(ptr) == -1) #endif { system_log(ERROR_SIGN, __FILE__, __LINE__, _("Failed to munmap() MSA : %s"), strerror(errno)); } (void)close(msa_fd); msa_fd = -1; return(INCORRECT_VERSION); } ptr += AFD_WORD_OFFSET; msa = (struct mon_status_area *)ptr; #ifdef HAVE_MMAP # ifdef HAVE_STATX msa_size = stat_buf.stx_size; # else msa_size = stat_buf.st_size; # endif #endif } while (no_of_afds <= 0); return(SUCCESS); }