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






                                                          

                   
                    
                     
                  


                
                    
                      
                   
 
                   
 
               
                  

  
                                          


                    



                                              

                                                              


                                    
 

                            
                          
 
                          

                   


                     




                                          
                               
 
                          
                     

 







                                                                                              
 
                               
                    




                                        
                                                             
                      


                   
                                                                                     
 

                                                                

 
                                                                                              
 
                               


                                  









                                                                           

         
                                  
 





                                                         

                                  
                         
 
                   

 
                                 
                               

  
                                                                              
 
                                
                                                 

                    
                                                                                             


                           
                                           
 
                                                      


                                                                            
                                        
         
 
                                   
                                          
 


                                                                       
                                                
 

                                                                     


                                                                                    
                                                
                 
         
 
                   
                                           
 
                   
 
/*
 * Copyright (c) 2022 Egor Tensin <Egor.Tensin@gmail.com>
 * This file is part of the "cimple" project.
 * For details, see https://github.com/egor-tensin/cimple.
 * Distributed under the MIT License.
 */

#include "worker.h"
#include "ci.h"
#include "command.h"
#include "compiler.h"
#include "const.h"
#include "git.h"
#include "log.h"
#include "msg.h"
#include "process.h"
#include "run_queue.h"
#include "signal.h"

#include <stdlib.h>

struct worker {
	int dummy;
};

int worker_create(struct worker **_worker)
{
	int ret = 0;

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

	struct worker *worker = malloc(sizeof(struct worker));
	if (!worker) {
		log_errno("malloc");
		return -1;
	}

	ret = libgit_init();
	if (ret < 0)
		goto free;

	*_worker = worker;
	return ret;

free:
	free(worker);

	return ret;
}

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

	libgit_shutdown();
	free(worker);
}

static int worker_send_to_server(const struct settings *settings, const struct msg *request,
                                 struct msg **response)
{
	return msg_connect_and_communicate(settings->host, settings->port, request, response);
}

static int worker_send_to_server_argv(const struct settings *settings, const char **argv,
                                      struct msg **response)
{
	struct msg *msg = NULL;
	int ret = 0;

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

	ret = worker_send_to_server(settings, msg, response);
	msg_free(msg);
	return ret;
}

static int worker_send_new_worker(const struct settings *settings, struct msg **task)
{
	static const char *argv[] = {CMD_NEW_WORKER, NULL};
	return worker_send_to_server_argv(settings, argv, task);
}

static int msg_run_handler(const struct msg *request, struct msg **response, UNUSED void *ctx)
{
	struct run *run = NULL;
	struct proc_output result;
	int ret = 0;

	ret = run_from_msg(&run, request);
	if (ret < 0)
		return ret;

	proc_output_init(&result);

	ret = ci_run_git_repo(run_get_url(run), run_get_rev(run), &result);
	if (ret < 0) {
		log_err("Run failed with an error\n");
		goto free_output;
	}

	proc_output_dump(&result);

	static const char *argv[] = {CMD_COMPLETE, NULL};
	ret = msg_from_argv(response, argv);
	if (ret < 0)
		goto free_output;

free_output:
	proc_output_free(&result);

	run_destroy(run);

	return ret;
}

static struct cmd_desc cmds[] = {
    {CMD_RUN, msg_run_handler},
};

int worker_main(UNUSED struct worker *worker, const struct settings *settings)
{
	struct msg *task = NULL;
	struct cmd_dispatcher *dispatcher = NULL;
	int ret = 0;

	ret = cmd_dispatcher_create(&dispatcher, cmds, sizeof(cmds) / sizeof(cmds[0]), NULL);
	if (ret < 0)
		return ret;

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

	ret = worker_send_new_worker(settings, &task);
	if (ret < 0) {
		if ((errno == EINTR || errno == EINVAL) && global_stop_flag)
			ret = 0;
		goto dispatcher_destroy;
	}

	while (!global_stop_flag) {
		struct msg *result = NULL;

		ret = cmd_dispatcher_handle(dispatcher, task, &result);
		msg_free(task);
		if (ret < 0)
			goto dispatcher_destroy;

		ret = worker_send_to_server(settings, result, &task);
		msg_free(result);
		if (ret < 0) {
			if ((errno == EINTR || errno == EINVAL) && global_stop_flag)
				ret = 0;
			goto dispatcher_destroy;
		}
	}

dispatcher_destroy:
	cmd_dispatcher_destroy(dispatcher);

	return ret;
}