示例#1
0
文件: ulib.c 项目: stiletto/oops
int
winsock_init(void)
{
WORD	wVersionRequested;
WSADATA	wsaData;
int	rc;

    wVersionRequested = MAKEWORD(2, 0);
    if ( (rc = WSAStartup(wVersionRequested, &wsaData)) != 0 ) {
	my_xlog(LOG_SEVERE, "winsock_init(): Can't init WinSock environment: %d", rc);
	return(-1);
    }

    if ( LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) ||
	 HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) {
	my_xlog(LOG_SEVERE, "winsock_init(): Current WinSock version is %d.%d. Version %d.%d required.",
		LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
		LOBYTE(wVersionRequested), HIBYTE(wVersionRequested));
	WSACleanup();
	return(-1);
    }

    my_xlog(LOG_PRINT, "winsock_init(): %s %s\n",
	    wsaData.szDescription, wsaData.szSystemStatus);

    return(0);
}
static int
downgrade(struct request *rq, struct mem_obj *obj)
{
    int	res = 0;
    char	*transfer_encoding = NULL;
#if	defined(HAVE_ZLIB)
    char	*content_encoding = NULL;
#endif	/* HAVE_ZLIB */
    if ( (rq->http_major  < obj->httpv_major) ||
            (rq->http_minor  < obj->httpv_minor) ) {
        res |= DOWNGRADE_ANSWER;
        if ( obj->headers )
            transfer_encoding = attr_value(obj->headers, "Transfer-Encoding");
        if ( transfer_encoding && !strncasecmp("chunked", transfer_encoding, 7)) {
            my_xlog(OOPS_LOG_HTTP|OOPS_LOG_DBG, "downgrade(): Turn on Chunked Gateway.\n");
            res |= UNCHUNK_ANSWER;
        }
    }
#if	defined(HAVE_ZLIB)
    content_encoding = attr_value(obj->headers, "Content-Encoding");
    if ( content_encoding && !strncasecmp(content_encoding, "gzip", 4) ) {
        /* we ungzip if useragent won't accept gzip	*/
        char	*ua_accept = attr_value(rq->av_pairs, "accept-encoding");

        if ( !ua_accept || !(strstr(ua_accept, "gzip")) )
            res |= UNGZIP_ANSWER;
    }
#endif
    return(res);
}
示例#3
0
文件: common.cpp 项目: dolfly/kingate
/* read with timeout */
int
readt(int so, char* buf, int len, int tmo)
{
int		to_read = len, sr,  got;
char		*p = buf;
struct	pollarg	pollarg;

	if ( so < 0 ) return(0);
	if ( len <= 0 ) return(0);

	pollarg.fd = so;
	pollarg.request = FD_POLL_RD;
	sr = poll_descriptors(1, &pollarg, tmo*1000);
	if ( sr < 0 ) {
	//	if ( ERRNO == EINTR ) return(readed);
		return(sr);
	}
	if ( sr == 0 ) {
		/* timeout */
		return(-2);
	}
	if ( IS_HUPED(&pollarg) ) return(0);
	/* have somethng to read	*/
	got = recv(so, p, to_read,0);
	if ( got == 0 ) {
	    my_xlog(OOPS_LOG_DBG|OOPS_LOG_INFORM, "readt(): got: %d, tmo: %d, to_read: %d\n", got, tmo, to_read);
	}
	return(got);
}
示例#4
0
文件: ulib.c 项目: stiletto/oops
long
pwrite(HANDLE fh, void *buf, size_t nbyte, off_t offset)
{
DWORD		NumberOfBytesWrite;
OVERLAPPED	Overlapped;

    Overlapped.Offset     = offset;
    Overlapped.OffsetHigh = 0;
    Overlapped.hEvent     = NULL;

    if ( WriteFile((HANDLE)fh, buf, (DWORD)nbyte,
		  &NumberOfBytesWrite, &Overlapped) == 0 ) {
	if ( ERRNO == ERROR_IO_PENDING ) {
	    if ( GetOverlappedResult(fh, &Overlapped,
				     &NumberOfBytesWrite, TRUE) == 0 )
		goto err;
	} else
	    goto err;
    }

done:
    set_errno(0);
    return(NumberOfBytesWrite);

err:
    my_xlog(LOG_SEVERE, "pwrite(): WriteFile(): ERRNO = (%d): %m\n", ERRNO);
    return(-1);
}
示例#5
0
文件: ulib.c 项目: stiletto/oops
long
pread(HANDLE fh, void *buf, size_t nbyte, off_t offset)
{
DWORD		NumberOfBytesRead;
OVERLAPPED	Overlapped;

    if ( nbyte == 0 ) return 0;

    Overlapped.Offset     = offset;
    Overlapped.OffsetHigh = 0;
    Overlapped.hEvent     = NULL;

    if ( ReadFile(fh, buf, (DWORD)nbyte,
		  &NumberOfBytesRead, &Overlapped) == 0 ) {
	if ( ERRNO == ERROR_IO_PENDING ) {
	    if ( GetOverlappedResult(fh, &Overlapped,
				     &NumberOfBytesRead, TRUE) == 0 )
		goto err;
	} else
	    goto err;

    }

done:
    set_errno(0);
    return(NumberOfBytesRead);

err:
    if ( ERRNO == ERROR_HANDLE_EOF )
	goto done;

    my_xlog(LOG_SEVERE, "pread(): ReadFile(): ERRNO = (%d): %m\n", ERRNO);
    return(-1);
}
示例#6
0
文件: ulib.c 项目: stiletto/oops
int
fcntl(int fd, int cmd, ...)
{
va_list		args;
int		arg = 0;
int		res;

    switch(cmd) {
    case F_GETFL:
	res = 0;
	my_xlog(LOG_DBG, "fcntl(F_GETFL): fd = %d, res = %d\n", fd, res);
	goto done;

    case F_SETFL:
	va_start(args, cmd);
	arg = va_arg(args, int);
	va_end(args);

	if (arg & O_NONBLOCK) {
	    unsigned long	nonb = 1;
	    if ( (res = ioctlsocket(fd, FIONBIO, &nonb)) != 0 ) {
		my_xlog(LOG_SEVERE, "fcntl(F_SETFL): ioctlsocket(fd = %d, O_NONBLOCK): res = %d, nonb = %d, %m\n",
			fd, res, nonb);
		res = -1;
		goto done;
	    }
	    my_xlog(LOG_DBG, "fcntl(F_SETFL): ioctlsocket(fd = %d, O_NONBLOCK): res = %d, nonb = %d\n",
		    fd, res, nonb);
	    goto done;
	}
	if (arg & O_BLOCK) {
	    unsigned long	nonb = 0;
	    if ( (res = ioctlsocket(fd, FIONBIO, &nonb)) != 0 ) {
		my_xlog(LOG_SEVERE, "fcntl(F_SETFL): ioctlsocket(fd = %d, O_BLOCK): res = %d, nonb = %d, %m\n",
			fd, res, nonb);
		res = -1;
		goto done;
	    }
	    my_xlog(LOG_DBG, "fcntl(F_SETFL): ioctlsocket(fd = %d, O_BLOCK): res = %d, nonb = %d\n",
		    fd, res, nonb);
	    goto done;
	}
	set_errno(ERROR_NOT_SUPPORTED);
	res = -1;
	my_xlog(LOG_DBG, "fcntl(F_SETFL): ioctlsocket(fd = %d, %d): res = %d, %m\n",
		fd, arg, res);
	goto done;

    default:
	set_errno(ERROR_NOT_SUPPORTED);
	res = -1;
	my_xlog(LOG_DBG, "fcntl(%d): fd = %d, res = %d, %m\n", cmd, fd, res);
	goto done;
    }

done:

    return res;
}
示例#7
0
int
sess_traffic_load(struct request *rq)
{
    int	cbytes, bw;

    if ( !rq || !(bw = rq->sess_bw) ) return(0);
    cbytes = rq->s0_sent;
    my_xlog(OOPS_LOG_SEVERE, "Session bw: %d\n", (cbytes*100)/bw);
    return((cbytes*100)/bw);
}
示例#8
0
文件: ulib.c 项目: stiletto/oops
int
winsock_shutdown(void)
{
int	rc;

    if ( (rc = WSACleanup()) != 0 ) {
	my_xlog(LOG_SEVERE, "winsock_shutdown(): Can't shutdown WinSock environment: %d\n", rc);
	return(-1);
    }
    return(0);
}
inline static int add_header_av(char* avtext, struct mem_obj *obj)
{
    struct	av	*new_t = NULL, *next;
    char		*attr = avtext, *sp = avtext, *val, holder;
    char		*new_attr = NULL, *new_val = NULL;
    char		nullstr[1];

    if ( *sp == 0 ) return(-1);
    while( *sp && IS_SPACE(*sp) ) sp++;
    while( *sp && !IS_SPACE(*sp) && (*sp != ':') ) sp++;
    if ( !*sp ) {
        my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "add_header_av(): Invalid header string: '%s'\n", avtext);
        nullstr[0] = 0;
        sp = nullstr;
    }
    if ( *sp == ':' ) sp++;
    holder = *sp;
    *sp = 0;
    if ( !strlen(attr) ) return(-1);
    new_t = (struct av *)xmalloc(sizeof(*new_t), "add_header_av(): for av pair");
    if ( !new_t ) goto failed;
    new_attr = (char *)xmalloc( strlen(attr)+1, "add_header_av(): for new_attr" );
    if ( !new_attr ) goto failed;
    strcpy(new_attr, attr);
    *sp = holder;
    val = sp;
    while( *val && IS_SPACE(*val) ) val++;
    /*if ( !*val ) goto failed;*/
    new_val = (char *)xmalloc( strlen(val) + 1, "add_header_av(): for new_val");
    if ( !new_val ) goto failed;
    strcpy(new_val, val);
    new_t->attr = new_attr;
    new_t->val  = new_val;
    new_t->next = NULL;
    if ( !obj->headers ) {
        obj->headers = new_t;
    } else {
        next = obj->headers;
        while (next->next) next=next->next;
        next->next=new_t;
    }
    return(0);

failed:
    *sp = holder;
    if ( new_t ) free(new_t);
    if ( new_attr ) free(new_attr);
    if ( new_val ) free(new_val);
    return(-1);
}
示例#10
0
文件: ulib.c 项目: stiletto/oops
HANDLE
open_storage(const char *path, int oflag, /* mode_t mode */...)
{
HANDLE			fHandle;
DWORD			DesiredAccess = 0;
SECURITY_ATTRIBUTES	SecurityAttributes;
DWORD			CreationDistribution = OPEN_EXISTING;

    if ( oflag & O_CREAT )
	CreationDistribution = OPEN_ALWAYS;

    if ( oflag & O_RDONLY )
	DesiredAccess = GENERIC_READ;

    if ( oflag & O_RDWR )
	DesiredAccess = GENERIC_READ|GENERIC_WRITE;

    SecurityAttributes.lpSecurityDescriptor = NULL;
    SecurityAttributes.bInheritHandle	    = TRUE;

    if ( (fHandle = CreateFile(path,
			       DesiredAccess,
			       FILE_SHARE_READ|FILE_SHARE_WRITE,
			       &SecurityAttributes,
			       CreationDistribution,
			       FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
/*			       FILE_FLAG_WRITE_THROUGH,*/
/*			       FILE_FLAG_NO_BUFFERING  */
/*			       FILE_FLAG_RANDOM_ACCESS */
			       NULL)) == INVALID_HANDLE_VALUE ) {
	my_xlog(LOG_SEVERE, "open_storage(): CreateFile(): ERRNO = (%d): %m\n", ERRNO);
	return((HANDLE)-1);
    }

    return(fHandle);
}
static int
load_body(struct request *rq,struct mem_obj *obj)
{
//	char	*answer = NULL;
//	struct	server_answ	answ_state;
    struct pollarg pollarg[2];
    //struct	av		*header = NULL;
    int r=0;
    unsigned body_size=obj->container->used;
    char answer[ANSW_SIZE+1];
// 	unsigned c_time=rq->client->set_time(0);
//	unsigned s_time=rq->server->set_time(0);

    if(obj->container && obj->container->used>0) {
        if(rq->server->send(obj->container->data,obj->container->used)<=0) {
            //printf("cann't send to client\n");
            goto error;
        }
    }
    if(obj->content_length<=0) { //if content-length is zero ,we don't cache it
        //printf("the content-length is zero\n");
        //pump_data(rq->server->get_socket(),rq->client->get_socket());
        if(create_select_pipe(rq->server,rq->client,conf.time_out[HTTP],0,-1)==-2)
            r=1;
        goto error;
    }
    pollarg[0].fd = rq->client->get_socket();
    pollarg[0].request = FD_POLL_RD;
    pollarg[1].fd = rq->server->get_socket();
    pollarg[1].request = FD_POLL_RD;
    forever() {
        if((r = poll_descriptors(2, &pollarg[0], conf.time_out[HTTP]*1000))<=0) {
            klog(DEBUG_LOG,"poll descriptors is error in file %s line %d\n",__FILE__,__LINE__);
            //	printf("1\n");
            goto done;
        }
        if(IS_READABLE(&pollarg[1]) || IS_HUPED(&pollarg[1])) {
            klog(DEBUG_LOG,"client close the connection in body\n");
            //		printf("2\n");
            goto done;
        }
        if(IS_READABLE(&pollarg[0]))
            r = rq->client->recv_t(answer, ANSW_SIZE,0);
        else {
            klog(DEBUG_LOG,"unknow error is happen\n");
            //	printf("3\n");
            goto done;
        }
        if ( r <=0  )
            goto done;
        body_size += r;
        if(body_size>obj->content_length) {
            //	destroy_obj(obj,0);
            if(rq->server->send(answer,r)<0)
                goto error;
            if(create_select_pipe(rq->server,rq->client,conf.time_out[HTTP],0,-1)==-2)
                r=1;
            goto error;
        }
        /* store data in hot_buff */
        /*		if(writet(so,answer,r,READ_ANSW_TIMEOUT)<=0)
        			goto error;
        */		if(rq->server->send(answer,r)<=0) {
            //		printf("cann't send to client\n");
            goto error;
        }
        if ( store_in_chain(answer, r, obj) ) {
            my_xlog(OOPS_LOG_SEVERE, "fill_mem_obj(): Can't store.\n");
            obj->flags |= FLAG_DEAD;
            //		printf("cann't store in chain\n");
            goto error;
        }
    }
done:
//	rq->server->set_time(s_time);
//	rq->client->set_time(c_time);
    if(body_size<=0 || body_size!=obj->content_length) { //数据不完整,不保存
        //printf("body_size != content_length\n");
        goto error;
    }
    return 1;

error:
//	rq->server->set_time(s_time);
//	rq->client->set_time(c_time);
    SET(obj->flags,FLAG_DEAD);
    return r;
}
/*			if ( (r < 0) && (ERRNO == EAGAIN) )
				goto sel_again;
* /			if ( r <= 0 )
				return so;
			r = write(server_so, b, r);//, conf.time_out[HTTP]);
			if ( r <= 0 ) return server_so;// goto done;
		}
    }
done:
    return -1;
}
*/
inline
static void
analyze_header(char *p, struct server_answ *a)
{
    char	*t;

    // my_xlog(OOPS_LOG_HTTP|OOPS_LOG_DBG, "analyze_header(): ---> `%s'.\n", p);
    if ( !a->status_code ) {
        /* check HTTP/X.X XXX */
        if ( !strncasecmp(p, "HTTP/", 5) ) {
            int	httpv_major, httpv_minor;
            if ( sscanf(p+5, "%d.%d", &httpv_major, &httpv_minor) == 2 ) {
                a->httpv_major = httpv_major;
                a->httpv_minor = httpv_minor;
            }
            t = strchr(p, ' ');
            if ( !t ) {
                my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "analyze_header(): Wrong_header: %s\n", p);
                return;
            }
            a->status_code = atoi(t);
            my_xlog(OOPS_LOG_DBG, "analyze_header(): Status code: %d\n", a->status_code);
        }
        return;
    }

    if ( !strncasecmp(p, "Content-length: ", 16) ) {
        char        *x;
        /* length */
        x=p + 16; /* strlen("content-length: ") */
        while( *x && IS_SPACE(*x) ) x++;
        a->content_len = atoi(x);
        return;
    }
    if ( !strncasecmp(p, "Date: ", 6) ) {
        char        *x;
        /* length */
        x=p + 6; /* strlen("date: ") */
        while( *x && IS_SPACE(*x) ) x++;
        a->times.date  = global_sec_timer;
        if (http_date(x, &a->times.date) ) my_xlog(OOPS_LOG_DBG|OOPS_LOG_INFORM, "analyze_header(): Can't parse date: %s\n", x);
        return;
    }
    if ( !strncasecmp(p, "Last-Modified: ", 15) ) {
        char        *x;
        /* length */
        x=p + 15; /* strlen("date: ") */
        while( *x && IS_SPACE(*x) ) x++;
        if (http_date(x, &a->times.last_modified) ) my_xlog(OOPS_LOG_DBG|OOPS_LOG_INFORM, "analyze_header(): Can't parse date: %s\n", x);
        else
            a->flags |= ANSW_LAST_MODIFIED;
        return;
    }
    if ( !strncasecmp(p, "Pragma: ", 8) ) {
        char        *x;
        /* length */
        x=p + 8; /* strlen("Pragma: ") */
        if ( strstr(x, "no-cache") ) a->flags |= ANSW_NO_STORE;
        return;
    }
    if ( !strncasecmp(p, "Age: ", 5) ) {
        char        *x;
        /* length */
        x=p + 5; /* strlen("Age: ") */
        a->times.age = atoi(x);
        return;
    }
    if ( !strncasecmp(p, "Cache-Control: ", 15) ) {
        char        *x;
        /* length */
        x=p + 15; /* strlen("Cache-Control: ") */
        while( *x && IS_SPACE(*x) ) x++;
        if ( strstr(x, "no-store") )
            a->flags |= ANSW_NO_STORE;
        if ( strstr(x, "no-cache") )
            a->flags |= ANSW_NO_STORE;
        if ( strstr(x, "private") )
            a->flags |= ANSW_NO_STORE;
        if ( strstr(x, "must-revalidate") )
            a->flags |= ANSW_MUST_REVALIDATE;
        if ( !strncasecmp(x, "proxy-revalidate", 15) )
            a->flags |= ANSW_PROXY_REVALIDATE;
        if ( sscanf(x, "max-age = %d", (int*)&a->times.max_age) == 1 )
            a->flags |= ANSW_HAS_MAX_AGE;
    }
    if ( !strncasecmp(p, "Connection: ", 12) ) {
        char        *x;
        /* length */
        x = p + 12; /* strlen("Connection: ") */
        while( *x && IS_SPACE(*x) ) x++;
        if ( !strncasecmp(x, "keep-alive", 10) )
            a->flags |= ANSW_KEEP_ALIVE;
        if ( !strncasecmp(x, "close", 5) )
            a->flags &= ~ANSW_KEEP_ALIVE;
    }
    if (    !TEST(a->flags, ANSW_HAS_EXPIRES)
            && !strncasecmp(p, "Expires: ", 9) ) {
        char        *x;
        /* length */
        x = p + 9; /* strlen("Expires: ") */
        while( *x && IS_SPACE(*x) ) x++;
        a->times.expires  = time(NULL);
        if (http_date(x, &a->times.expires)) {
            my_xlog(OOPS_LOG_DBG|OOPS_LOG_INFORM, "analyze_header(): Can't parse date: %s\n", x);
            return;
        }
        a->flags |= ANSW_HAS_EXPIRES;
        return;
    }
}
示例#13
0
void *
statistics(void *arg)
{
    struct group 	 *group;
    struct peer	 *peer;
    struct oops_stat temp_stat;
    int		 counter = 0, i;
    int		 hits = 0, reqs = 0;
    int		 purge = PURGE_INTERVAL;
    ip_hash_entry_t	*he, *next_he;

    if ( arg ) return (void *)0;

    my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Statistics started.\n");

    bzero(&oops_stat, sizeof(oops_stat));
    start_time = oops_stat.timestamp0 = oops_stat.timestamp = time(NULL);

    forever() {
        global_sec_timer = time(NULL);
        tick_modules();

        if ( ++counter == 60 ) {	/* once per minute */

            LOCK_STATISTICS(oops_stat);
            memcpy(&temp_stat, &oops_stat, sizeof(oops_stat));
            oops_stat.requests_http1 = oops_stat.requests_http0;
            oops_stat.hits1 = oops_stat.hits0;
            oops_stat.requests_http0 = 0;
            oops_stat.hits0 = 0;
            oops_stat.timestamp0 = oops_stat.timestamp;
            oops_stat.timestamp = global_sec_timer;
            oops_stat.drops0 = 0;

            oops_stat.requests_icp1 = oops_stat.requests_icp0;
            oops_stat.requests_icp0 = 0;
            if ( oops_stat.requests_http1 > oops_stat.requests_http0_max )
                oops_stat.requests_http0_max = oops_stat.requests_http1;
            if ( oops_stat.requests_icp1 > oops_stat.requests_icp0_max )
                oops_stat.requests_icp0_max = oops_stat.requests_icp1;
            if ( oops_stat.hits0_max > oops_stat.hits1 )
                oops_stat.hits0_max = oops_stat.hits1;
            if ( oops_stat.clients > oops_stat.clients_max )
                oops_stat.clients_max = oops_stat.clients;
#if	HAVE_GETRUSAGE
            memcpy(&oops_stat.rusage0, &oops_stat.rusage, sizeof(oops_stat.rusage));
            getrusage(RUSAGE_SELF, &oops_stat.rusage);
#endif
            UNLOCK_STATISTICS(oops_stat);
            reqs = temp_stat.requests_http0;
            hits = temp_stat.hits0;
            my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "statistics(): clients      : %d\n", temp_stat.clients);
            my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "statistics(): http_requests: %d\n", temp_stat.requests_http);
            my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "statistics(): icp_requests : %d\n", temp_stat.requests_icp);
            my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "statistics(): req_rate     : %d/s\n", temp_stat.requests_http0/60);
            if ( reqs ) my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "statistics(): hits_rate    : %d%%\n", (hits*100)/reqs);
            else  my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "statistics(): hits_rate    : 0%%\n");
            counter = 0;
        }

        RDLOCK_CONFIG;
        peer = peers;
        while ( peer ) {
            if ( !peer->icp_port ) {
                /* this is not icp peer - different up/down ideology */
                peer = peer->next;
                continue;
            }
            if ( ABS(peer->last_recv - peer->last_sent) > peer_down_interval ) {
                peer->state |=  PEER_DOWN ;
            } else {
                peer->state &= ~PEER_DOWN ;
            }
            peer = peer->next;
        }
        /* run over all groups and move statistics */
        group = groups ;
        if ( group ) {
            while ( group ) {
                /* my_xlog(OOPS_LOG_DBG, "statistics(): transfer : %d bytes/sec\n", MID(bytes)); */
                pthread_mutex_lock(&group->group_mutex);
                group->cs_total.bytes += group->cs0.bytes;
                group->cs_total.requests += group->cs0.requests;
                group->cs2 = group->cs1;
                group->cs1 = group->cs0;
                bzero((void*)&group->cs0, sizeof(group->cs0));
                pthread_mutex_unlock(&group->group_mutex);

                /* remove stale dstdomain cache entries */
                if ( group->dstdomain_cache ) {
                    if ( purge <= 0 ) {
                        if ( hash_operate(group->dstdomain_cache, purge_old_dstd) )
                            purge = PURGE_INTERVAL;
                    } else
                        purge--;
                }
                group = group->next;
            }
        }
        for (i=0; i<IP_HASH_SIZE; i++) {
            pthread_mutex_lock(&ip_hash[i].lock);
            he = ip_hash[i].link;
            while ( he ) {
                pthread_mutex_lock(&he->lock);
                next_he = he->next;
                he->traffic2 = he->traffic1;
                he->traffic1 = he->traffic0;
                he->traffic0 = 0;
                pthread_mutex_unlock(&he->lock);
                if ( !he->refcount )  {
                    if ( global_sec_timer - he->access >= 10 ) {
                        /* unlink and free */
                        if ( !he->prev ) {
                            ip_hash[i].link = he->next;
                        } else {
                            he->prev->next = he->next;
                        }
                        if ( he->next ) he->next->prev = he->prev;
                        pthread_mutex_destroy(&he->lock);
                        free(he);
                    }
                }
                he = next_he;
            }
            pthread_mutex_unlock(&ip_hash[i].lock);
        }
        if ( !counter && statisticslog[0] ) {
            FILE *statl = fopen(statisticslog, "w");

            if ( statl ) {
                fprintf(statl,"clients      : %d\n", (unsigned)temp_stat.clients);
                fprintf(statl,"uptime       : %ld sec.\n", (utime_t)(global_sec_timer-start_time));
                fprintf(statl,"http_requests: %d\n", (unsigned)temp_stat.requests_http);
                fprintf(statl,"http_hits    : %d\n", (unsigned)temp_stat.hits);
                fprintf(statl,"icp_requests : %d\n", (unsigned)temp_stat.requests_icp);
                fprintf(statl,"req_rate     : %d/s\n", (unsigned)(temp_stat.requests_http0/60));
                if ( reqs ) fprintf(statl,"hits_rate    : %d%%\n", (hits*100)/reqs);
                else  fprintf(statl,"hits_rate    : 0%%\n");
                fprintf(statl,"free_space   : %u%%\n", (unsigned)temp_stat.storages_free);
                fclose(statl);
            }
        }
        UNLOCK_CONFIG;

        my_sleep(1);
    }
}