Пример #1
0
static inline int __flush_send_buffer(struct send_buffer *s, struct connection_pair *cp){
	register int j, l;

	lock_send_buffer(s);
	l= (s->end_ptr - s->start_ptr);

	if(l <= 0){
		unlock_send_buffer(s);
	   	return l;
	}

	for (j = 0; j < cp->n_remote; ++j) {
		if (!cp->remote[j].socketfd)
			continue;

		if (write (cp->remote[j].socketfd, s->start_ptr, l) < 0) {
			close(cp->remote[j].socketfd);
			fclose(cp->remote[j].socketfp);
			memset(&cp->remote[j], 0, sizeof(struct connection));
			continue;
		}
	}

	s->end_ptr = s->start_ptr;
	unlock_send_buffer(s);
	return l;
}
Пример #2
0
int get_chunk_from_buffer(struct sb_config *sb, void **ptr, unsigned int chunk_size, struct send_buffer **s){
	unsigned int unoccupied;

	/* first try */
	lock_whole_buffer(sb);
	*s= &(sb->buffers[sb->current_buffer]);
	unlock_whole_buffer(sb);

	lock_send_buffer(*s);
	unoccupied= (sb->buffer_size - ((*s)->end_ptr - (*s)->start_ptr));

	if (unoccupied >= chunk_size) {
		(*ptr)= (*s)->end_ptr;
		(*s)->end_ptr += chunk_size;
		unlock_send_buffer(*s);
		return 0;
	}
	unlock_send_buffer(*s);

	/* move to next buffer and try */
	lock_whole_buffer(sb);
	++(sb->current_buffer);
	sb->current_buffer %= sb->n_buffers;
	*s = &(sb->buffers[sb->current_buffer]);
	unlock_whole_buffer(sb);

	lock_send_buffer(*s);
	unoccupied = (sb->buffer_size - ((*s)->end_ptr - (*s)->start_ptr));
	if (unoccupied >= chunk_size) {
		(*ptr)= (*s)->end_ptr;
		(*s)->end_ptr += chunk_size;
		unlock_send_buffer(*s);
		return 0;
	}
	unlock_send_buffer(*s);

	/* no memory left in buffer to fit chunk_size */
	*s=NULL;
	return -1;
}
Пример #3
0
int copy_to_send_buffer(struct sb_config *sb, void *p, unsigned int len)
{
	struct send_buffer *tmp = &(sb->buffers[sb->current_buffer]);
	unsigned int unoccupied;

	lock_send_buffer(tmp);
	unoccupied = (sb->buffer_size - (tmp->end_ptr - tmp->start_ptr));

	if (unoccupied >= len) {
		memcpy(tmp->end_ptr, p, len);
		tmp->end_ptr += len;
		unlock_send_buffer(tmp);
		return 0;
	}
	unlock_send_buffer(tmp);

	pthread_mutex_lock(&sb->lock);
	++(sb->current_buffer);
	sb->current_buffer %= sb->n_buffers;
	pthread_mutex_unlock(&sb->lock);

	tmp = &(sb->buffers[sb->current_buffer]);

	lock_send_buffer(tmp);
	unoccupied = (sb->buffer_size - (tmp->end_ptr - tmp->start_ptr));

	if (unoccupied >= len) { /* used to be (unoccupied < len) WHY?? */
		memcpy(tmp->end_ptr, p, len);
		tmp->end_ptr += len;
		unlock_send_buffer(tmp);
		return 0;
	}
	unlock_send_buffer(tmp);

	return -1;
}
Пример #4
0
static inline int flush_send_buffer(struct sb_config *sb, struct send_buffer *s, struct connection_pair *cp){
	register int j, l;
	int fs, fc;
	void *ptr;

	lock_send_buffer(s);


	/* find first flushable chunk */
	bit_ffs(s->bitmap, sb->chunks_in_a_buffer, &fs);
	if(fs == -1){ /* nothing flushable */
		unlock_send_buffer(s);
		return 0;
	}

	/* find first non-flushable chunk */
	bit_ffc(s->bitmap, sb->chunks_in_a_buffer, &fc);
	if(fc == -1){ /* everything is flushable */
		l= (s->end_ptr - s->start_ptr);
		fprintf(stderr, "flushing everything (%d bytes).", l);

		for (j = 0; j < cp->n_remote; ++j) {
			if (!cp->remote[j].socketfd)
				continue;

			if (write (cp->remote[j].socketfd, s->start_ptr, l) < 0) {
					close(cp->remote[j].socketfd);
					fclose(cp->remote[j].socketfp);
					memset(&cp->remote[j], 0, sizeof(struct connection));
					continue;
			}
		}

		s->end_ptr = s->start_ptr;
		bit_nclear(s->bitmap, 0, (sb->chunks_in_a_buffer - 1));
		unlock_send_buffer(s);
		return l;
	}
	
	/* some chunks flushable, some not. flush the first available window and
	 * only that. this keeps the flush-window moving in only forward direction
	 */
	ptr= (fs == 0)? (s->start_ptr): ((s->start_ptr) + (fs * sb->chunk_size));
	l= ((fc - fs) * sb->chunk_size);
	fprintf(stderr, "flushing a range (%d bytes).", l);
	for (j = 0; j < cp->n_remote; ++j) {
		if (!cp->remote[j].socketfd)
			continue;

		if (write (cp->remote[j].socketfd, ptr, l) < 0) {
				close(cp->remote[j].socketfd);
				fclose(cp->remote[j].socketfp);
				memset(&cp->remote[j], 0, sizeof(struct connection));
				continue;
		}
	}

	/* when and only when the last chunk is flushed, reset the buffer */
	if(s->end_ptr == (ptr + l)){
		s->end_ptr= s->start_ptr;
		bit_nclear(s->bitmap, 0, (sb->chunks_in_a_buffer - 1));
	}

	unlock_send_buffer(s);
	return l;
}