示例#1
0
/**
 * @param buffer can be NULL, in case when user want to just buffer it or skip some data.
 *
 * Global options that have efffect on this function are following
 * 1) ccx_options.live_stream
 * 2) ccx_options.buffer_input
 * 3) ccx_options.input_source
 * 4) ccx_options.binary_concat
 *
 * TODO instead of using global ccx_options move them to ccx_demuxer
 */
size_t buffered_read_opt (struct ccx_demuxer *ctx, unsigned char *buffer, size_t bytes)
{
	size_t origin_buffer_size = bytes;
	size_t copied   = 0;
	time_t seconds = 0;

	position_sanity_check(ctx);

	if (ccx_options.live_stream > 0)
		time (&seconds);

	if (ccx_options.buffer_input || ctx->filebuffer_pos < ctx->bytesinbuffer)
	{
		// Needs to return data from filebuffer_start+pos to filebuffer_start+pos+bytes-1;
		int eof = (ctx->infd == -1);

		while ((!eof || ccx_options.live_stream) && bytes)
		{
			if (terminate_asap)
				break;
			if (eof)
			{
				// No more data available inmediately, we sleep a while to give time
				// for the data to come up
				sleepandchecktimeout (seconds);
			}
			size_t ready = ctx->bytesinbuffer - ctx->filebuffer_pos;
			if (ready == 0) // We really need to read more
			{
				if (!ccx_options.buffer_input)
				{
					// We got in the buffering code because of the initial buffer for
					// detection stuff. However we don't want more buffering so
					// we do the rest directly on the final buffer.
					int i;
					do
					{
						// No code for network support here, because network is always
						// buffered - if here, then it must be files.
						if (buffer != NULL) // Read
						{
							i = read (ctx->infd, buffer, bytes);
							if( i == -1)
								fatal (EXIT_READ_ERROR, "Error reading input file!\n");
							buffer += i;
						}
						else // Seek
						{
							LLONG op, np;
							op = LSEEK (ctx->infd, 0, SEEK_CUR); // Get current pos
							if (op + bytes < 0) // Would mean moving beyond start of file: Not supported
								return 0;
							np = LSEEK (ctx->infd, bytes, SEEK_CUR); // Pos after moving
							i = (int) (np - op);
						}
						// if both above lseek returned -1 (error); i would be 0 here and
						// in case when its not live stream copied would decrease and bytes would...
						if (i == 0 && ccx_options.live_stream)
						{
							if (ccx_options.input_source == CCX_DS_STDIN)
							{
								ccx_options.live_stream = 0;
								break;
							}
							else
							{
								sleepandchecktimeout (seconds);
							}
						}
						else
						{
							copied += i;
							bytes  -= i;
						}

					}
					while ((i || ccx_options.live_stream ||
								(ccx_options.binary_concat && switch_to_next_file(ctx->parent, copied))) && bytes);
					return copied;
				}
				// Keep the last 8 bytes, so we have a guaranteed
				// working seek (-8) - needed by mythtv.
				int keep = ctx->bytesinbuffer > 8 ? 8 : ctx->bytesinbuffer;
				memmove (ctx->filebuffer, ctx->filebuffer+(FILEBUFFERSIZE-keep),keep);
				int i;
				if (ccx_options.input_source == CCX_DS_FILE || ccx_options.input_source == CCX_DS_STDIN)
					i = read (ctx->infd, ctx->filebuffer + keep, FILEBUFFERSIZE-keep);
				else if (ccx_options.input_source == CCX_DS_TCP)
					i = net_tcp_read(ctx->infd, (char *) ctx->filebuffer + keep, FILEBUFFERSIZE - keep);
				else
					i = recvfrom(ctx->infd,(char *) ctx->filebuffer + keep, FILEBUFFERSIZE - keep, 0, NULL, NULL);
				if (terminate_asap) /* Looks like receiving a signal here will trigger a -1, so check that first */
					break;
				if (i == -1)
					fatal (EXIT_READ_ERROR, "Error reading input stream!\n");
				if (i == 0)
				{
					/* If live stream, don't try to switch - acknowledge eof here as it won't
					   cause a loop end */
					if (ccx_options.live_stream || ((struct lib_ccx_ctx *)ctx->parent)->inputsize <= origin_buffer_size || !(ccx_options.binary_concat && switch_to_next_file(ctx->parent, copied)))
						eof = 1;
				}
				ctx->filebuffer_pos = keep;
				ctx->bytesinbuffer = (int) i + keep;
				ready = i;
			}
			int copy = (int) (ready>=bytes ? bytes:ready);
			if (copy)
			{
				if (buffer != NULL)
				{
					memcpy (buffer, ctx->filebuffer + ctx->filebuffer_pos, copy);
					buffer += copy;
				}
				ctx->filebuffer_pos += copy;
				bytes  -= copy;
				copied += copy;
			}
		}
	}
	else // Read without buffering
	{

		if (buffer != NULL)
		{
			int i;
			while (bytes > 0 && ctx->infd != -1 &&
					((i = read(ctx->infd, buffer, bytes)) != 0 || ccx_options.live_stream ||
					 (ccx_options.binary_concat && switch_to_next_file(ctx->parent, copied))))
			{
				if (terminate_asap)
					break;
				if( i == -1)
					fatal (EXIT_READ_ERROR, "Error reading input file!\n");
				else if (i == 0)
					sleepandchecktimeout (seconds);
				else
				{
					copied += i;
					bytes  -= i;
					buffer += i;
				}
			}
			return copied;
		}
		while (bytes != 0 && ctx->infd != -1)
		{
			LLONG op, np;
			if (terminate_asap)
				break;
			op = LSEEK (ctx->infd, 0, SEEK_CUR); // Get current pos
			if (op + bytes < 0) // Would mean moving beyond start of file: Not supported
				return 0;

			np     = LSEEK (ctx->infd, bytes, SEEK_CUR); // Pos after moving
			if (op == -1 && np == -1) // Possibly a pipe that doesn't like "skipping"
			{
				char c;
				for (size_t i = 0; i<bytes; i++) read(ctx->infd, &c, 1);
				copied = bytes;
			}
			else
				copied = copied + (np - op);
			bytes  = bytes- (unsigned int) copied;
			if (copied == 0)
			{
				if (ccx_options.live_stream)
					sleepandchecktimeout (seconds);
				else
				{
					if (ccx_options.binary_concat)
						switch_to_next_file(ctx->parent, 0);
					else
						break;
				}
			}
		}
	}
	return copied;
}
示例#2
0
文件: net_core.c 项目: Cai900205/test
static void* __net_slice_worker(void* arg)
{
    net_slice_ctx_t* slice_ctx = (net_slice_ctx_t*)arg;
    int slice_num = slice_ctx->slice_num;
    int slice_id = slice_ctx->slice_id;
    int cpu_base = slice_ctx->cpu_base;

    assert(slice_ctx->fd > 0);

    if (cpu_base > 0) {
        cpu_base += (slice_id%4);
        spk_worker_set_affinity(cpu_base);
    }
    zlog_info(net_zc, "slice> spawned: id=%d, cpu=%d", slice_id, cpu_base);

    while (!slice_ctx->quit_req) {
        pthread_mutex_lock(&slice_ctx->lock);
        if(slice_ctx->wptr == slice_ctx->rptr) {
            struct timeval now;
            struct timespec outtime;
            gettimeofday(&now, NULL);
            outtime.tv_sec = now.tv_sec + 1;
            outtime.tv_nsec = now.tv_usec * 1000;
            pthread_cond_timedwait(&slice_ctx->not_empty, &slice_ctx->lock, &outtime);
        }
        if (slice_ctx->wptr == slice_ctx->rptr) {
            pthread_mutex_unlock(&slice_ctx->lock);
            continue;
        }

        assert(slice_ctx->data_chunk.flag == CHUNK_DATA_FLAG__REQ);

        size_t chunk_size = slice_ctx->data_chunk.size;
        size_t slice_sz = chunk_size / slice_num;
        ssize_t access = 0;

        // check chunk_size and slice_sz
        if ((chunk_size % slice_num) ||
                (slice_sz & (0x4000-1))) { // 16k alignment
            zlog_error(net_zc, "illegal chunk_sz: chunk_sz=%zu, slice_num=%d",
                       chunk_size, slice_num);
            access = SPKERR_PARAM;
            goto done;
        }

        if (slice_sz != slice_ctx->slice_sz) {
            zlog_warn(net_zc, "unexpected slice size : slice_sz=%zu, expect=%zu",slice_sz, slice_ctx->slice_sz);
            // this chunk may the last in file
        }

        if (slice_ctx->dir == SPK_DIR_WRITE) {
            // write
            if (slice_ctx->type == net_intf_tcp) {
                access = net_tcp_write(slice_ctx->fd,
                                       slice_ctx->data_chunk.buf + slice_id * slice_sz,slice_sz);
            } else if (slice_ctx->type == net_intf_udp) {
                access = net_udp_write(slice_ctx->fd,
                                       slice_ctx->data_chunk.buf + slice_id * slice_sz,slice_sz,((struct sockaddr*)&slice_ctx->svr_addr));

            }
        } else {
            // read
            if (slice_ctx->type == net_intf_tcp) {
                access = net_tcp_read(slice_ctx->fd,
                                      slice_ctx->data_chunk.buf + slice_id * slice_sz,slice_sz);
            } else if (slice_ctx->type == net_intf_udp) {
                access = net_udp_read(slice_ctx->fd,
                                      slice_ctx->data_chunk.buf + slice_id * slice_sz,slice_sz,((struct sockaddr*)&slice_ctx->svr_addr));

            }
        }

        if (access != slice_sz) {
            zlog_error(net_zc, "failed to access file: dir=%d, "
                       "sock_fd:%d slice_sz=%zu, offset=%ld, ret=%ld, errmsg=\'%s\'",
                       slice_ctx->dir, slice_ctx->fd,slice_sz,
                       slice_id * slice_sz, access, strerror(errno));
            access = SPKERR_EACCESS;
            goto done;
        }

done:
        if (access == slice_sz) {
            slice_ctx->data_chunk.flag = CHUNK_DATA_FLAG__DONE;
        } else {
            slice_ctx->data_chunk.flag = access;
        }
        slice_ctx->rptr++;
        pthread_cond_signal(&slice_ctx->not_full);
        pthread_mutex_unlock(&slice_ctx->lock);
    }
    zlog_info(net_zc, "slice> terminated: id=%d", slice_id);
    return(NULL);
}