remote_pool.c
author Tero Marttila <terom@fixme.fi>
Wed, 27 Aug 2008 21:30:32 +0300
changeset 41 540737bf6bac
parent 26 6d615203d963
permissions -rw-r--r--
sending requests, and partial support for receiving -- incomplete, not tested
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include "remote_pool.h"
#include "common.h"

void remote_pool_init (struct remote_pool *pool_info) {
    memset(pool_info, 0, sizeof(*pool_info));
}

int remote_pool_add (struct remote_pool *pool_info, const char *addr_spec) {
    int i;
    struct remote_node *node_info = NULL;
    
    // find a free remote_node entry and store its pointer in node_info
    for (i = 0; i < REMOTE_POOL_MAX; i++) {
        if (!pool_info->nodes[i].valid) {
            node_info = &pool_info->nodes[i];
            break;
        }
    }

    if (!node_info)
        ERROR("remote_pool_add: pool full, consider increasing REMOTE_POOL_MAX");

    return remote_node_init(node_info, addr_spec);

error:
    return -1;
}

int remote_pool_load (struct remote_pool *pool_info, const char *filename) {
    // open the file
    FILE *fh = fopen(filename, "r");

    if (!fh) {
        perr("remote_pool_load: fopen(%s)", filename);
        return -1;
    }
    
    // read it in line-by-line
    char line_buf[POOL_FILE_LINE_LENGTH], *c;
    
    // non-ferror error indicator
    int error_flag = 0;

    while (1) {
        // read in a line
        if (!fgets(line_buf, POOL_FILE_LINE_LENGTH, fh)) {
            perr("remote_pool_load: fgets");
            break;
        }

        // strip comments
        c = strchr(line_buf, '#');

        if (c)
            *c = '\0';
        
        // skip empty lines
        for (c = line_buf; *c != '\0'; c++)
            if (!isspace(*c))
                break;

        if (*c == '\0')
            continue;

        // add it to the pool
        if (remote_pool_add(pool_info, line_buf)) {
            error_flag = 1;
            break;
        }
    }
    
    // pick up ferrors if otherwise fine
    error_flag = error_flag || ferror(fh);
    
    // close the fd
    fclose(fh);
    
    // error return?
    if (error_flag)
        return -1;
    
    return 0;
}

struct remote_node *remote_pool_get (struct remote_pool *pool_info) {
    int i;
    struct remote_node *node_info = NULL;

    // find a the appropriate remote_node entry and store its pointer in node_info
    for (i = 0; i < REMOTE_POOL_MAX; i++) {
        if (pool_info->nodes[i].valid && (node_info == NULL || pool_info->nodes[i].current_load < node_info->current_load)) {
            node_info = &pool_info->nodes[i];
        }
    }
    
    if (node_info) {
        // add one to its load, because that's probably correct, and works if we pick multiple nodes from the pool at the same time
        node_info->current_load++;
    }

    // either NULL or the right remote_info
    return node_info;
}

int remote_pool_size (struct remote_pool *pool_info) {
    int i, size = 0;

    for (i = 0; i < REMOTE_POOL_MAX; i++) {
        if (pool_info->nodes[i].valid) {
            size++;
        }
    }
    
    return size;
}