Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1896811
  • 博文数量: 333
  • 博客积分: 10791
  • 博客等级: 上将
  • 技术积分: 4314
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-08 07:39
文章分类

全部博文(333)

文章存档

2015年(1)

2011年(116)

2010年(187)

2009年(25)

2008年(3)

2007年(1)

分类: C/C++

2010-03-31 16:07:45

int main(int argc, char **argv)
{
    char *p = NULL, *bindhost = NULL, temp[65];
    int uid, gid, todaemon = 1, flags = 1, c, i;
    struct sockaddr_in server;
    struct linger ling = {0, 0};
    struct matrix *m;
    

    //使用getopt()函数匹配magent选项。getopt()函数参考:
    while(-1 != (c = getopt(argc, argv, "p:u:g:s:Dhvn:l:kb:f:i:"))) {
        switch (c) {
        case 'u'://设置用户
            uid = atoi(optarg);//atoi()函数参考:
            if (uid > 0) {
                setuid(uid);
                seteuid(uid);
            }
            break;
        case 'g':
            gid = atoi(optarg);
            if (gid > 0) {
                setgid(gid);
                setegid(gid);
            }
            break;
        case 'v':
            verbose_mode = 1;
            todaemon = 0;
            break;
        case 'k':
            use_ketama = 1;
            break;
        case 'D':
            todaemon = 0;
            break;
        case 'p':
            port = atoi(optarg);
            break;
        case 'i':
            maxidle = atoi(optarg);
            if (maxidle <= 0) maxidle = 20;
            break;
        case 'n':
            maxconns = atoi(optarg);
            if (maxconns <= 0) maxconns = 4096;
            break;
        case 'f':
            socketpath = optarg;
            break;
        case 'l':
            bindhost = optarg;
            break;

        case 'b':
            if (backupcnt == 0) {
                backups = (struct matrix *) calloc(sizeof(struct matrix), 1);
                if (backups == NULL) {
                    fprintf(stderr, "out of memory for %s\n", optarg);
                    exit(1);
                }
                m = backups;
                backupcnt = 1;
            } else {
                backups = (struct matrix *)realloc(backups, sizeof(struct matrix)*(backupcnt+1));
                if (backups == NULL) {
                    fprintf(stderr, "out of memory for %s\n", optarg);
                    exit(1);
                }
                m = backups + backupcnt;
                backupcnt ++;
            }
            
            p = strchr(optarg, ':');
            if (p == NULL) {
                m->ip = strdup(optarg);
                m->port = 11211;
            } else {
                *p = '\0';
                m->ip = strdup(optarg);
                *p = ':';
                p ++;
                m->port = atoi(p);
                if (m->port <= 0) m->port = 11211;
            }

            m->dstaddr.sin_family = AF_INET;
            m->dstaddr.sin_addr.s_addr = inet_addr(m->ip);
            m->dstaddr.sin_port = htons(m->port);
            
            break;

        case 's': /* server string */
            if (matrixcnt == 0) {
                matrixs = (struct matrix *) calloc(sizeof(struct matrix), 1);
                if (matrixs == NULL) {
                    fprintf(stderr, "out of memory for %s\n", optarg);
                    exit(1);
                }
                m = matrixs;
                matrixcnt = 1;
            } else {
                matrixs = (struct matrix *)realloc(matrixs, sizeof(struct matrix)*(matrixcnt+1));
                if (matrixs == NULL) {
                    fprintf(stderr, "out of memory for %s\n", optarg);
                    exit(1);
                }
                m = matrixs + matrixcnt;
                matrixcnt ++;
            }
            
            p = strchr(optarg, ':');
            if (p == NULL) {
                m->ip = strdup(optarg);
                m->port = 11211;
            } else {
                *p = '\0';
                m->ip = strdup(optarg);
                *p = ':';
                p ++;
                m->port = atoi(p);
                if (m->port <= 0) m->port = 11211;
            }
            m->dstaddr.sin_family = AF_INET;
            m->dstaddr.sin_addr.s_addr = inet_addr(m->ip);
            m->dstaddr.sin_port = htons(m->port);
            
            break;
        case 'h':
        default:
            show_help();
            return 1;
        }
    }

    if (matrixcnt == 0) {
        fprintf(stderr, "please provide -s \"ip:port\" argument\n\n");
        show_help();
        exit(1);
    }

    if (port == 0 && socketpath == NULL) {
        fprintf(stderr, "magent must listen on tcp or unix domain socket\n");
        exit(1);
    }

    if (todaemon && daemon(0, 0) == -1) {
        fprintf(stderr, "failed to be a daemon\n");
        exit(1);
    }

    if (use_ketama) {
        ketama = (struct ketama *)calloc(sizeof(struct ketama), 1);
        if (ketama == NULL) {
            fprintf(stderr, "not enough memory to create ketama\n");
            exit(1);
        } else {
            ketama->count = matrixcnt;
            ketama->weight = (int *)calloc(sizeof(int), ketama->count);
            ketama->name = (char **)calloc(sizeof(char *), ketama->count);
            
            if (ketama->weight == NULL || ketama->name == NULL) {
                fprintf(stderr, "not enough memory to create ketama\n");
                exit(1);
            }

            for (i = 0; i < ketama->count; i ++) {
                ketama->weight[i] = 100;
                ketama->totalweight += ketama->weight[i];
                snprintf(temp, 64, "%s-%d", matrixs[i].ip, matrixs[i].port);
                ketama->name[i] = strdup(temp);
                if (ketama->name[i] == NULL) {
                    fprintf(stderr, "not enough memory to create ketama\n");
                    exit(1);
                }
            }
        }
        if (create_ketama(ketama, 500)) {
            fprintf(stderr, "can't create ketama\n");
            exit(1);
        }

        /* update backup server ketama */
        if (backupcnt > 0) {
            backupkt = (struct ketama *)calloc(sizeof(struct ketama), 1);
            if (backupkt == NULL) {
                fprintf(stderr, "not enough memory to create ketama\n");
                exit(1);
            } else {
                backupkt->count = backupcnt;
                backupkt->weight = (int *)calloc(sizeof(int), backupkt->count);
                backupkt->name = (char **)calloc(sizeof(char *), backupkt->count);
                
                if (backupkt->weight == NULL || backupkt->name == NULL) {
                    fprintf(stderr, "not enough memory to create ketama\n");
                    exit(1);
                }

                for (i = 0; i < backupkt->count; i ++) {
                    backupkt->weight[i] = 100;
                    backupkt->totalweight += backupkt->weight[i];
                    snprintf(temp, 64, "%s-%d", backups[i].ip, backups[i].port);
                    backupkt->name[i] = strdup(temp);
                    if (backupkt->name[i] == NULL) {
                        fprintf(stderr, "not enough memory to create ketama\n");
                        exit(1);
                    }
                }
            }
            if (create_ketama(backupkt, 500)) {
                fprintf(stderr, "can't create backup ketama\n");
                exit(1);
            }
        }

        fprintf(stderr, "using ketama algorithm\n");
    }

    if (port > 0) {
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {
            fprintf(stderr, "CAN'T CREATE NETWORK SOCKET\n");
            return 1;
        }

        fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL)|O_NONBLOCK);

        setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
        setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
        setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));

        memset((char *) &server, 0, sizeof(server));
        server.sin_family = AF_INET;
        if (bindhost == NULL)
            server.sin_addr.s_addr = htonl(INADDR_ANY);
        else
            server.sin_addr.s_addr = inet_addr(bindhost);

        server.sin_port = htons(port);

        if (bind(sockfd, (struct sockaddr *) &server, sizeof(server))) {
            if (errno != EINTR)
                fprintf(stderr, "bind errno = %d: %s\n", errno, strerror(errno));
            close(sockfd);
            exit(1);
        }

        if (listen(sockfd, 512)) {
            fprintf(stderr, "listen errno = %d: %s\n", errno, strerror(errno));
            close(sockfd);
            exit(1);
        }

    }

    if (socketpath)
        server_socket_unix();

    signal(SIGTERM, server_exit);
    signal(SIGINT, server_exit);

    event_init();

    if (sockfd > 0) {
        if (verbose_mode)
            fprintf(stderr, "memcached agent listen at port %d\n", port);
        event_set(&ev_master, sockfd, EV_READ|EV_PERSIST, server_accept, NULL);
        event_add(&ev_master, 0);
    }

    if (unixfd > 0) {
        if (verbose_mode)
            fprintf(stderr, "memcached agent listen at unix domain socket \"%s\"\n", socketpath);
        event_set(&ev_unix, unixfd, EV_READ|EV_PERSIST, server_accept, NULL);
        event_add(&ev_unix, 0);
    }
    event_loop(0);
    server_exit(0);
    return 0;
}


阅读(1865) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~