aboutsummaryrefslogblamecommitdiffstatshomepage
path: root/src/worker.c
blob: baba9b0f4ad3a9805bfa2dd8cd9d41994b8b232a (plain) (tree)
1
2
3
4
5
6
7
8





                   
                    
                   



















                                                                         

                   







                                          

                                     
                                                






                                                           
                    




                                        
                                         


                              





                       
                                                                                      
 
                    
 
                                                




                                                          



                                                           
                                
 
                 

 






                                                                               

                                  
                    
                                           
            
                                             
 





                                              


                                                   


                                                                                          
                         

         
                 

 

                                                                
 



                            

  

                                                      

  
                                                                               
 

                                     
 
                                                                       
 

                                                              
                                 


                                                            

         





                                                     

 
                                                                            






                                          
                                   

                                   

                                                         





                                                           


                                   

                   
 
#include "worker.h"
#include "ci.h"
#include "git.h"
#include "log.h"
#include "msg.h"
#include "net.h"
#include "process.h"
#include "signal.h"

#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int worker_create(struct worker *worker, const struct settings *settings)
{
	int ret = 0;

	ret = libgit_init();
	if (ret < 0)
		return ret;

	ret = net_connect(settings->host, settings->port);
	if (ret < 0)
		goto git_shutdown;
	worker->fd = ret;

	return ret;

git_shutdown:
	libgit_shutdown();

	return ret;
}

void worker_destroy(struct worker *worker)
{
	print_log("Shutting down\n");

	check_errno(close(worker->fd), "close");
	libgit_shutdown();
}

static int msg_send_new_worker(const struct worker *worker)
{
	static char *argv[] = {"new_worker", NULL};
	struct msg msg;
	int ret = 0;

	ret = msg_from_argv(&msg, argv);
	if (ret < 0)
		return ret;

	ret = msg_send(worker->fd, &msg);
	if (ret < 0)
		goto free_msg;

free_msg:
	msg_free(&msg);

	return ret;
}

static int msg_ci_run_do(const char *url, const char *rev, struct proc_output *result)
{
	int ret = 0;

	ret = ci_run_git_repo(url, rev, result);
	if (ret < 0) {
		print_error("Run failed with an error\n");
		return ret;
	}

	print_log("Process exit code: %d\n", result->ec);
	print_log("Process output:\n%s", result->output);
	if (!result->output || !result->output_len ||
	    result->output[result->output_len - 1] != '\n')
		print_log("\n");

	return 0;
}

static int msg_ci_run_handler(struct worker *worker, const struct msg *request)
{
	struct msg response;
	struct proc_output result;
	int ret = 0;

	ret = msg_ci_run_do(request->argv[1], request->argv[2], &result);
	proc_output_free(&result);

	if (ret < 0)
		ret = msg_error(&response);
	else
		ret = msg_success(&response);

	if (ret < 0)
		return ret;

	ret = msg_send(worker->fd, &response);
	msg_free(&response);
	return ret;
}

static int msg_ci_run_parser(const struct msg *msg)
{
	if (msg->argc != 3) {
		print_error("Invalid number of arguments for a message: %d\n", msg->argc);
		return 0;
	}

	return 1;
}

typedef int (*msg_parser)(const struct msg *msg);
typedef int (*msg_handler)(struct worker *, const struct msg *);

struct msg_descr {
	const char *cmd;
	msg_parser parser;
	msg_handler handler;
};

struct msg_descr messages[] = {
    {"ci_run", msg_ci_run_parser, msg_ci_run_handler},
};

static int worker_msg_handler(struct worker *worker, const struct msg *request)
{
	if (request->argc == 0)
		goto unknown_request;

	size_t numof_messages = sizeof(messages) / sizeof(messages[0]);

	for (size_t i = 0; i < numof_messages; ++i) {
		if (strcmp(messages[i].cmd, request->argv[0]))
			continue;
		if (!messages[i].parser(request))
			continue;
		return messages[i].handler(worker, request);
	}

unknown_request:
	print_error("Received an unknown message\n");
	msg_dump(request);
	struct msg response;
	msg_error(&response);
	return msg_send(worker->fd, &response);
}

int worker_main(struct worker *worker, UNUSED int argc, UNUSED char *argv[])
{
	int ret = 0;

	ret = msg_send_new_worker(worker);
	if (ret < 0)
		return ret;

	while (!global_stop_flag) {
		struct msg request;

		print_log("Waiting for a new command\n");

		ret = msg_recv(worker->fd, &request);
		if (ret < 0)
			return ret;

		ret = worker_msg_handler(worker, &request);
		msg_free(&request);
		if (ret < 0)
			return ret;
	}

	return ret;
}