Example #1
0
/**
 * Spawns an instance of the FM component.
 * 
 * @param instance Instance number the component belongs to 
 * @param component Integer representation of the component 
 *  				(1 = SM, 2 = FE)
 * @return int PID spawned or -1 if an error has occurred
 */
int spawn(const unsigned int instance, const int component){
	sigset_t mask;
	int *pids;
	int pid;
	char prog[32], name[32];
	if (instance >= FM_MAX_INSTANCES){
		fprintf(stderr, "Invalid instance number.\n");
		return -1;
	}
	if ((pids = componentToPIDArray(component)) == NULL){
		fprintf(stderr, "spawn: Invalid component number %d.\n", component);
		return -1;
	}
	if (pids[instance] != 0 && kill(pids[instance], 0) == 0){
		fprintf(stderr, "Instance %d of %s is already running.\n", instance, componentToString(component));
		return -1;
	}
	if (!config.instance[instance].component[component].enabled){
		fprintf(stderr, "Instance %d of %s is not enabled. Please enable instance in %s\n", instance, componentToString(component), FM_XML_CONFIG);
		return -1;
	}
	switch(pid = fork()){
	case 0:
		sigemptyset(&mask);
		sigaddset(&mask,SIGTERM);
		sigaddset(&mask,SIGCHLD);
		sigaddset(&mask,SIGHUP);
		sigprocmask(SIG_UNBLOCK, &mask, NULL);
		sprintf(prog, "/usr/lib/opa-fm/runtime/%s", componentToExecName(component));
		sprintf(name, "%s_%d", componentToExecName(component), instance);
		execle(prog, prog, "-e", name, NULL, nullEnv);
		break;
	case -1:
		fprintf(stderr, "Failed to start %s for instance %d.\n", componentToString(component), instance);
		break;
	default:
		fprintf(stdout, "Started instance %d of %s.\n", instance, componentToString(component));
		if(pid > 0) pids[instance] = pid;
		break;
	}
	return pid;
}
Example #2
0
/**
 * Kills instance of FM component 
 * 
 * @param instance Instance number the component belongs to
 * @param component Integer representation of the component 
 *  				(1 = SM, 2 = FE)
 * @return int Returns 0 if process was properly terminated, 
 *  	   otherwise -1 on error.
 */
int pkill(const unsigned int instance, const int component){
	int *pids;
	int pid;
	int status;
	int ret;
	if(instance >= FM_MAX_INSTANCES){
		fprintf(stderr, "Invalid instance number.\n");
		return -1;
	}
	if((pids = componentToPIDArray(component)) == NULL){
		fprintf(stderr, "pkill: Invalid component number %d.\n", component);
		return -1;
	}
	pid = pids[instance];
	if(!pid) return 0;
	if(kill(pid, 0) == 0){
		kill(pid, SIGTERM);							// Here we send a SIGTERM to the PID specified.
		sleep(component == SM_COMPONENT ? 3 : 1); 				// Wait 3 seconds for SM to die from SIGTERM, only 1 sec for FE
		ret = waitpid((pid_t)pid, &status, WUNTRACED | WNOHANG);		// Reap the children if they're already dead. Because zombies are bad, mmkay.
		if(!ret){								// Checks for insubordinate children
			kill(pid, SIGKILL);						// Order a hit on them
			sleep(component == SM_COMPONENT ? 3 : 1);			// Allow 1-3 seconds for murder
			ret = waitpid((pid_t)pid, &status, WUNTRACED | WNOHANG);	// Reap
			if(!ret){							// Report all survivors
				fprintf(stderr, "Failed to kill %s from instance %d\n", componentToString(component), instance);
				return -1;
			}
		}
		instanceRestarts[instance].components[component].lastUpdate = 0;	// Make sure to reset restart timer to prevent manual stop/restart from counting against component
		fprintf(stdout, "Stopped instance %d of %s.\n", instance, componentToString(component));
	} else {
		fprintf(stderr, "Instance %d of %s not running.\n", instance, componentToString(component));
	}
	pids[instance] = 0;	// PID not running or doesn't exist
	return 0;
}
Example #3
0
/**
 * Function to parse values passed through named pipe to the 
 * daemon. 
 * 
 * @param buf Pointer to the string extracted from the named 
 *  		  pipe
 * 
 * @return int Returns 1 if the daemon recieved a command to 
 *  	   stop.
 */
int parseInput(char *buf){
	char *token;
	int i, c;
	struct thread_data *thread = NULL;
	pthread_t thread_id[FM_MAX_INSTANCES*FM_NUM_COMPONENTS];
	token = strtok(buf, " ");
	if(token == NULL){
		fprintf(stderr, "Received invalid input. Ignoring.\n");
		return 0;
	}
	if(strncmp(token, "sig_chld", 8) == 0){
		int i = 0, pid = 0, stat = 0;
		unsigned int instance = 0, component = 0;
		while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
			for(i = 0; i < FM_MAX_INSTANCES; ++i){
				if(smPID[i] == pid){
					component = SM_COMPONENT;
					instance = i;
					break;
				} else if (fePID[i] == pid){
					component = FE_COMPONENT;
					instance = i;
					break;
				}
			}
			if(component == 0){
				continue;
			}
			fprintf(stderr, "%s component of instance %d has terminated with exit code %d\n", componentToString(component), instance, stat);
			if(stat == 0 || stat == 1){ //Skip restarting these components if expected (return 0) or user error (return 1)
				if(stat == 1)
					fprintf(stderr, "Check opafm.xml config for invalid settings.\n");
				return 0;
			}
			if(checkRestarts(instance, component)){
				//Component has failed too many times
				doStop = 3;
				return 0;
			}
			if (pkill(instance, component) == 0){
				spawn(instance, component);
			} else {
				//Failed to kill child. Might be a zombie.
				doStop = 3;
				return 0;
			}
		}
	} else if(!strncmp(token, "stop", 4) || !strncmp(token, "sig_term", 8)){
		token = strtok(NULL, " ");
		if(token == NULL) token = "a";
		switch(token[0]){
		case '0':	// Kill both SM and FE for this instance number.
			doStop = 1;
			token = strtok(NULL, " ");
			if(token == NULL){
				fprintf(stderr, "Received invalid input. Ignoring.\n");
				return 0;
			}
			i = atoi((const char*)token);
			if(i >= FM_MAX_INSTANCES || i < 0){
				fprintf(stderr, "Received invalid input. Ignoring.\n");
				return 0;
			}
			for(c = FM_NUM_COMPONENTS - 1; c >= 1; --c){
				thread = calloc(1, sizeof(struct thread_data));
				if(thread == NULL){
					fprintf(stderr, "Failed to allocate thread struct.\n");
					return 0;
				}
				thread->instance = i;
				thread->component = c;
				pthread_create(&thread_id[c], NULL, &kill_thread, thread);
			}
			for(c = 1; c < FM_NUM_COMPONENTS; ++c){
				pthread_join(thread_id[c], NULL);
			}
			break;
		case '1':	// SM and FE are treated the same so this prevents code redundancy
		case '2':
			c = atoi((const char*)token);
			token = strtok(NULL, " ");
			if(token == NULL){
				fprintf(stderr, "Received invalid input. Ignoring.\n");
				return 0;
			}
			i = atoi((const char*)token);
			pkill(i, c);
			break;
		case 'a':	// Kill all running instances.
			doStop = 1;
			for(i = 0; i < FM_MAX_INSTANCES; ++i){
				for(c = 1; c < FM_NUM_COMPONENTS; ++c){
					thread = calloc(1, sizeof(struct thread_data));
					if(thread == NULL){
						fprintf(stderr, "Failed to allocate thread struct.\n");
						return 0;
					}
					thread->instance = i;
					thread->component = c;
					pthread_create(&thread_id[i*FM_NUM_COMPONENTS+c], NULL, &kill_thread, thread);
				}
			}
			for(i = 0; i < FM_MAX_INSTANCES; ++i){
				for(c = 1; c < FM_NUM_COMPONENTS; ++c){
        	                        pthread_join(thread_id[i*FM_NUM_COMPONENTS+c], NULL);
                	        }
			}
			return 1;
		default:
			fprintf(stderr, "Unknown component value. (%d)\n", token[0]);
		}
		return 0;
	}
	if(strncmp(token, "start", 5) == 0){
		token = strtok(NULL, " ");
		if(token == NULL){
			fprintf(stderr, "Received invalid input. Ignoring.\n");
			return 0;
		}
		switch(token[0]){
		case '0':
			token = strtok(NULL, " ");
			if(token == NULL){
				fprintf(stderr, "Received invalid input. Ignoring.\n");
				return 0;
			}
			i = atoi((const char*)token);
			if(i > FM_MAX_INSTANCES){	//Adding additional instance check here to avoid duplicate error messages
				fprintf(stderr, "Received invalid instance number %d. Ignoring.\n", i);
				return 0;
			}
			spawn(i, SM_COMPONENT);
			spawn(i, FE_COMPONENT);
			break;
		case '1':
		case '2':
			c = atoi((const char*)token);
			token = strtok(NULL, " ");
			if(token == NULL){
				fprintf(stderr, "Received invalid input. Ignoring.\n");
				return 0;
			}
			i = atoi((const char*)token);
			spawn(i, c);
			break;
		default:
			fprintf(stderr, "Unknown component value.\n");
		}
	} else if(strncmp(token, "sig_hup", 7) == 0){
		loadConfig();
		updateInstances();
		reloadSMs();
	} else if(strncmp(token, "restart", 7) == 0){
		token = strtok(NULL, " ");
		if(token == NULL){
			fprintf(stderr, "Received invalid input. Ignoring.\n");
			return 0;
		}
		switch(token[0]){
		case '0':
			token = strtok(NULL, " ");
			if(token == NULL){
				fprintf(stderr, "Received invalid input. Ignoring.\n");
				return 0;
			}
			i = atoi((const char*)token);
                        if(i > FM_MAX_INSTANCES){	//Adding additional instance check here to avoid duplicate error messages
                                fprintf(stderr, "Received invalid instance number %d. Ignoring.\n", i);
                                return 0;
                        }
			if(pkill(i, SM_COMPONENT) == 0)
				spawn(i, SM_COMPONENT);
			if(pkill(i, FE_COMPONENT) == 0)
				spawn(i, FE_COMPONENT);
			break;
		case '1':
		case '2':
			c = atoi((const char*)token);
			token = strtok(NULL, " ");
			if(token == NULL){
				fprintf(stderr, "Received invalid input. Ignoring.\n");
				return 0;
			}
			i = atoi((const char*)token);
			if(pkill(i, c) == 0)
				spawn(i, c);
			break;
		default:
			fprintf(stderr, "Unknown component value.\n");
		}
	}
	return 0;
}
QXmlStreamWriter& SimpleLoggerRoutingInfo::write(QXmlStreamWriter& writer) const
{
  writer.writeStartElement("SimpleLoggerRoutingInfo");

  if (m_name.length() > 0)
  {
    XMLUtility::writeElement(writer, "Name", m_name);
  }
  XMLUtility::writeElement(writer, "Enabled", XMLUtility::booleanToString(m_enabled));

  if (m_levels != nullptr && m_levels->size() > 0)
  {
    QMap<MessageCategory, int>::const_iterator i;
    for (i = m_levels->begin(); i != m_levels->end(); ++i)
    {
      XMLUtility::writeElementAttribute(writer, "Level", QString::number(i.value()), "MessageCategory", categoryToString(i.key(), -1));
    }
  }

  if (m_routing != nullptr && m_routing->size() > 0)
  {
    QMap<MessageRouting, bool>::const_iterator i;
    for (i = m_routing->begin(); i != m_routing->end(); ++i)
    {
      XMLUtility::writeElementAttribute(writer, "Routing", XMLUtility::booleanToString(i.value()), "MessageRouting", routingToString(i.key(), -1));
    }
  }

  if (m_locationRegExp != nullptr)
  {
    XMLUtility::write(writer, *m_locationRegExp, "LocationRegEx");
  }

  if (m_messageRegExp != nullptr)
  {
    XMLUtility::write(writer, *m_messageRegExp, "MessageRegEx");
  }

  if (m_format.size() > 0)
  {
    for (int i=0; i<m_format.size(); ++i)
    {
      const QPair<MessageComponent, QString>& comp = m_format.at(i);
      XMLUtility::writeElementAttribute(writer, "Format", comp.second, "MessageComponent", componentToString(comp.first, comp.second.length()));
    }
  }

  writer.writeEndElement();
  return writer;
}