Beispiel #1
0
void Async::upload_file(
    Disk          disk,
    const Dirent& ent,
    Stream*       stream,
    on_after_func callback,
    const size_t  CHUNK_SIZE)
{
  disk_transfer(disk, ent,
  [stream] (fs::buffer_t buffer,
            next_func    next) mutable
  {
    auto length = buffer->size();
    // temp
    stream->on_write(
      net::tcp::Connection::WriteCallback::make_packed(
      [length, next] (size_t n) {

        // if all data written, go to next chunk
        debug("<Async::upload_file> %u / %u\n", n, length);
        next(n == length);
      })
    );

    // write chunk to TCP connection
    stream->write(buffer);

  }, callback, CHUNK_SIZE);
}
Beispiel #2
0
/* \param xdf 		pointer to a valid xdffile with mode XDF_READ 
 * \param offset	offset where the current sample pointer must move
 * \param whence	reference of the offset
 *
 * API FUNCTION
 * Reposition the current sample pointer according to the couple 
 * (offset, whence). whence can be SEEK_SET, SEEK_CUR or SEEK_END
 * Upon successful completion, it returns the resulting offset location as
 * measured in number of samples for the begining of the recording.
 * Otherwise -1 is returned and errno is set to indicate the error
 */
API_EXPORTED off_t xdf_seek(struct xdf* xdf, off_t offset, int whence)
{
	off_t curpoint, reqpoint, fileoff;
	int irec, errnum = 0;
	unsigned int nsprec = xdf->ns_per_rec;

	if (!xdf || (xdf->mode != XDF_READ) || (!xdf->ready)) {
		errno = xdf ? EPERM : EINVAL;
		return -1;
	}

	curpoint = (xdf->nrecread < 0 ? 0 : xdf->nrecread)*nsprec
			- xdf->ns_buff;
	if (whence == SEEK_CUR)
		reqpoint = curpoint + offset;
	else if (whence == SEEK_SET)
		reqpoint = offset;
	else if (whence == SEEK_END)
		reqpoint = xdf->nrecord * nsprec + offset;
	else
		return xdf_set_error(EINVAL);
	
	if (reqpoint < 0 || (reqpoint >= (off_t)(xdf->nrecord * nsprec)))
		return xdf_set_error(ERANGE);
	
	irec = reqpoint / nsprec;
	if (irec != xdf->nrecread) {
		if (irec != xdf->nrecread + 1) {

 			pthread_mutex_lock(&(xdf->mtx));
			// Wait for the previous operation to be finished
			while (xdf->order && !xdf->reportval)
				pthread_cond_wait(&(xdf->cond), &(xdf->mtx));
			
			fileoff = irec*xdf->filerec_size + xdf->hdr_offset;
			if ( (lseek(xdf->fd, fileoff, SEEK_SET) < 0)
			     || (read_diskrec(xdf)) )
				errnum = errno;
 			pthread_mutex_unlock(&(xdf->mtx));
			
			if (errnum)
				return xdf_set_error(errnum);

		}

		if (disk_transfer(xdf))
			return -1;
		
		xdf->nrecread = irec;
	}
	xdf->ns_buff = nsprec - reqpoint%nsprec;

	return reqpoint;
}
Beispiel #3
0
/* \param xdf	pointer of a valid xdf file with mode XDF_WRITE
 *
 * Fill the remaining of the current record with 0 and transfer it. This
 * ensures that no previous data will added be truncated because of the end.
 */
static int finish_record(struct xdf* xdf)
{
	char* buffer = xdf->buff + xdf->sample_size * xdf->ns_buff;
	unsigned int ns = xdf->ns_per_rec - xdf->ns_buff;

	if (!xdf->ns_buff)
		return 0;

	// Fill the remaining of the record with 0 values
	while (ns--) {
		memset(buffer, 0, xdf->sample_size);
		buffer += xdf->sample_size;
	}

	return disk_transfer(xdf);
}
Beispiel #4
0
/* \param xdf 	pointer to a valid xdffile with mode XDF_READ 
 * \param ns	number of samples to be read
 * \param other pointer to the arrays holding the output samples
 *
 * API FUNCTION
 * Read samples in the buffer and transfer them to one or several output
 * arrays. The number of arrays that must be provided on the call depends
 * on the specification of the channels.
 * Returns the number of samples read, -1 in case of error
 */
API_EXPORTED ssize_t xdf_read(struct xdf* xdf, size_t ns, ...)
{
	if ((xdf == NULL) || !xdf->ready || (xdf->mode == XDF_WRITE)) {
		errno = (xdf == NULL) ? EINVAL : EPERM;
		return -1;
	}

	unsigned int i, k, ia;
	unsigned int nbatch = xdf->nbatch, samsize = xdf->sample_size;
	char* restrict buff = xdf->buff + samsize * (xdf->ns_per_rec-xdf->ns_buff);
	struct data_batch* batch = xdf->batch;
	char* restrict out[xdf->narrays];
	va_list ap;
	int ret;

	// Initialization of the output buffers
	va_start(ap, ns);
	for (ia=0; ia<xdf->narrays; ia++)
		out[ia] = va_arg(ap, char*);
	va_end(ap);

	for (i=0; i<ns; i++) {
		// Trigger a disk read when the content of buffer is empty
		if (!xdf->ns_buff) {
			if ((ret = disk_transfer(xdf))) 
				return ((ret<0)&&(i==0)) ? -1 : (ssize_t)i;
			buff = xdf->buff;
			xdf->ns_buff = xdf->ns_per_rec;
			xdf->nrecread++;
		}

		// Transfer the sample to the buffer by chunk
		for (k=0; k < nbatch; k++) {
			ia = batch[k].iarray;
			memcpy(out[ia], buff+batch[k].foff, batch[k].len);
			out[ia] += batch[k].mskip;
		}
		buff += samsize;
		xdf->ns_buff--;
	}

	return ns;
}
Beispiel #5
0
/* \param xdf 	pointer to a valid xdffile with mode XDF_WRITE 
 * \param ns	number of samples to be added
 * \param other pointer to the arrays holding the input samples
 *
 * API FUNCTION
 * Add samples coming from one or several input arrays containing the
 * samples. The number of arrays that must be provided on the call depends
 * on the specification of the channels.
 * Returns the number of samples written, -1 in case of error
 */
API_EXPORTED ssize_t xdf_write(struct xdf* xdf, size_t ns, ...)
{
	if ((xdf == NULL) || !xdf->ready || (xdf->mode == XDF_READ)) {
		errno = (xdf == NULL) ? EINVAL : EPERM;
		return -1;
	}

	unsigned int i, k, ia, nsrec = xdf->ns_per_rec;
	unsigned int nbatch = xdf->nbatch, samsize = xdf->sample_size;
	char* restrict buff = xdf->buff + samsize * xdf->ns_buff;
	struct data_batch* batch = xdf->batch;
	const char* restrict in[xdf->narrays];
	va_list ap;

	// Initialization of the input buffers
	va_start(ap, ns);
	for (ia=0; ia<xdf->narrays; ia++)
		in[ia] = va_arg(ap, const char*);
	va_end(ap);

	for (i=0; i<ns; i++) {
		// Write the content of the buffer if full
		if (xdf->ns_buff == nsrec) {
			if (disk_transfer(xdf)) 
				return (i==0) ? -1 : (ssize_t)i;
			buff = xdf->buff;
			xdf->ns_buff = 0;
		}

		// Transfer the sample to the buffer by chunk
		for (k=0; k<nbatch; k++) {
			ia = batch[k].iarray;
			memcpy(buff+batch[k].foff, in[ia], batch[k].len);
			in[ia] += batch[k].mskip;
		}
		buff += samsize;
		xdf->ns_buff++;
	}

	return (ssize_t)ns;
}
Beispiel #6
0
/* \param xdf	pointer to a valid xdf file
 *
 * API FUNCTION
 * Compute the batches, allocate the necessary data for the transfer and
 * Initialize the transfer thread
 */
API_EXPORTED int xdf_prepare_transfer(struct xdf* xdf)
{
	int nbatch;

	if (xdf->ready)
		return -1;

	// Just compute the number of batch (no mem allocated for them yet)
	if ( (nbatch = compute_batches(xdf, 0)) < 0 )
		goto error;
	xdf->nbatch = nbatch;

	// Alloc of temporary entities needed for convertion
	if (alloc_transfer_objects(xdf))
		goto error;

	// Setup batches, convertion parameters
	compute_batches(xdf, 1); // assign batches: memory is now allocated
	setup_convdata(xdf);

	if (xdf->mode == XDF_WRITE) {
		if (init_file_content(xdf))
			goto error;
	}

	if (init_transfer_thread(xdf))
		goto error;

	if (xdf->mode == XDF_READ) {
		disk_transfer(xdf);
		xdf->nrecread = -1;
	}

	xdf->ready = 1;
	return 0;

error:
	free_transfer_objects(xdf);
	xdf->nbatch = 0;
	return -1;
}
Beispiel #7
0
void Async::upload_file(
    Disk          disk,
    const Dirent& ent,
    Connection    conn,
    on_after_func callback,
    const size_t  CHUNK_SIZE)
{
  disk_transfer(disk, ent,
  [conn] (fs::buffer_t buffer,
          size_t       length,
          next_func    next)
  {
    // write chunk to TCP connection
    conn->write(buffer.get(), length,
    [length, next] (size_t n) {

      // if all data written, go to next chunk
      debug("sock write: %u / %u\n", n, length);
      next(n == length);

    }, true);

  }, callback, CHUNK_SIZE);
}