remote_pool.c
author Tero Marttila <terom@fixme.fi>
Fri, 06 Jun 2008 03:24:55 +0300
changeset 9 fb6632e6c1bb
child 13 ee426f453cf5
permissions -rw-r--r--
two new modules, remote_node and remote_pool

committer: Tero Marttila <terom@fixme.fi>
#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 *hostname, const char *portname) {
    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 -1;
    }

    return remote_node_init(node_info, hostname, portname);
}

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], *hostname, *portname, *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;
        
        // parse
        if (!parse_hostport(line_buf, &hostname, &portname)) {
            error_flag = 1;
            break;
        }

        // add it to the pool
        if (remote_pool_add(pool_info, hostname, portname)) {
            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];
        }
    }

    // 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;
}