diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/libtc/libxio.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/libtc/libxio.c | 812 |
1 files changed, 812 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/libtc/libxio.c b/debian/transcode/transcode-1.1.7/libtc/libxio.c new file mode 100644 index 00000000..fba67b4a --- /dev/null +++ b/debian/transcode/transcode-1.1.7/libtc/libxio.c @@ -0,0 +1,812 @@ +/* + * libxio.c + * + * Copyright (C) Lukas Hejtmanek - January 2004 + * + * This file is part of transcode, a video stream processing tool + * + * transcode is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * transcode is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#undef PACKAGE +#undef VERSION + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef HAVE_IBP +#include <lors.h> +#endif +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <errno.h> +#include <stdarg.h> + +#include "libtc.h" +#include "xio.h" + +#define MAX_HANDLES 256 + +static void * xio_handles[MAX_HANDLES]; +static int xio_initialized = 0; +pthread_mutex_t xio_lock; + +#ifdef HAVE_IBP +#define IBP_URI "lors://" +#define IBP_URI_LEN 7 + +#define BLOCK_SIZE_SHIFT 1024 + +#define LBONE_PORT 6767 +#define LORS_BLOCKSIZE 10*1024 +#define LORS_DURATION 3600 +#define LORS_COPIES 1 +#define LORS_THREADS 1 +#define LORS_TIMEOUT 100 +#define LORS_SERVERS 1 +#define LORS_SIZE 10*1024*1024 + +struct xio_ibp_handle_t { + LorsDepotPool *dp; + LorsExnode *ex; + off_t b_pos; + off_t begin; + off_t end; + void *buffer; + char *filename; + char *lbone_server; + int lbone_port; + int lors_blocksize; + int lors_duration; + int lors_copies; + int lors_threads; + int lors_timeout; + int lors_servers; + off_t lors_size; + int fill_buffer; + int dirty_buffer; + int mode; +}; + +static void * +ibp_open(const char *uri, int mode, int m) +{ + struct xio_ibp_handle_t *handle; + int ret; + + if(strncmp(uri, IBP_URI, IBP_URI_LEN) != 0) { + errno = EINVAL; + return (void *)-1; + } + uri += IBP_URI_LEN; + + handle=(struct xio_ibp_handle_t*)calloc(1, + sizeof(struct xio_ibp_handle_t)); + + // environment setup + handle->lbone_server = getenv("LBONE_SERVER"); + if(getenv("LBONE_PORT")) { + handle->lbone_port = atoi(getenv("LBONE_PORT")); + } else { + handle->lbone_port = LBONE_PORT; + } + + if(getenv("LORS_BLOCKSIZE")) { + handle->lors_blocksize = atoi(getenv("LORS_BLOCKSIZE")); + } else { + if(mode & O_WRONLY || mode & O_CREAT) + handle->lors_blocksize = LORS_BLOCKSIZE; + else + handle->lors_blocksize = 128; + } + + if(getenv("LORS_DURATION")) { + handle->lors_duration = atoi(getenv("LORS_DURATION")); + } else { + handle->lors_duration = LORS_DURATION; + } + + if(getenv("LORS_COPIES")) { + handle->lors_copies = atoi(getenv("LORS_COPIES")); + } else { + handle->lors_copies = LORS_COPIES; + } + + if(getenv("LORS_THREADS")) { + handle->lors_threads = atoi(getenv("LORS_THREADS")); + } else { + handle->lors_threads = LORS_THREADS; + } + + if(getenv("LORS_TIMEOUT")) { + handle->lors_timeout = atoi(getenv("LORS_TIMEOUT")); + } else { + handle->lors_timeout = LORS_TIMEOUT; + } + + if(getenv("LORS_SERVERS")) { + handle->lors_servers = atoi(getenv("LORS_SERVERS")); + } else { + handle->lors_servers = LORS_SERVERS; + } + + if(getenv("LORS_SIZE")) { + handle->lors_servers = atoi(getenv("LORS_SIZE")); + } else { + handle->lors_servers = LORS_SIZE; + } + + if(*uri != '/') { + // get LBONE_SERVER from URI + if(strchr(uri, ':')) { + // port is defined + handle->lbone_server = tc_strndup(uri, + strchr(uri, ':')-uri); + uri = (char *)(strchr(uri, ':')+1); + handle->lbone_port = atoi(uri); + } else { + // only host + handle->lbone_server = tc_strndup(uri, + (int)(strchr(uri, '/')-uri)); + } + uri = (char *)(strchr(uri, '/')+1); + } else { + uri += 1; + } + + if(!strchr(uri, '?')) { + // only filename + handle->filename = strdup(uri); + } else { + // parse options + handle->filename = tc_strndup(uri, (int)(strchr(uri, '?')-uri)); + uri = strchr(uri, '?')+1; + while(uri != (char *)1) { + if(strncmp(uri, "bs", 2) == 0) { + handle->lors_blocksize = atoi(&uri[3]); + } else if(strncmp(uri, "duration", 8) == 0) { + handle->lors_duration = atoi(&uri[9]); + } else if(strncmp(uri, "copies", 6) == 0) { + handle->lors_copies = atoi(&uri[7]); + } else if(strncmp(uri, "threads", 7) == 0) { + handle->lors_threads = atoi(&uri[8]); + } else if(strncmp(uri, "timeout", 7) == 0) { + handle->lors_timeout = atoi(&uri[8]); + } else if(strncmp(uri, "servers", 7) == 0) { + handle->lors_servers = atoi(&uri[8]); + } else if(strncmp(uri, "size", 4) == 0) { + handle->lors_size = atoi(&uri[5]); + } + uri = strchr(uri, '&') + 1; + } + } + + handle->lors_blocksize *= BLOCK_SIZE_SHIFT; + + handle->mode = mode; + handle->b_pos = 0; + handle->begin = 0; + handle->end = 0; + handle->dirty_buffer = 0; + + if(mode & O_WRONLY || mode & O_CREAT) { + handle->buffer = malloc(handle->lors_blocksize); + if(!handle->buffer) { + free(handle); + errno = EIO; + return (void *)-1; + } + ret = lorsGetDepotPool(&handle->dp, handle->lbone_server, + handle->lbone_port, NULL, + handle->lors_servers, NULL, + handle->lors_size/(1024*1024)+1, + IBP_HARD, + handle->lors_duration, + handle->lors_threads, + handle->lors_timeout, + LORS_CHECKDEPOTS); + if(ret != LORS_SUCCESS) { + errno = EIO; + return (void *)-1; + } + ret = lorsExnodeCreate(&handle->ex); + if (ret != LORS_SUCCESS) { + errno = EIO; + return (void *)-1; + } + } + if(mode & O_RDONLY || !mode) { + handle->buffer = malloc(handle->lors_blocksize); + handle->fill_buffer = 1; + ret = lorsFileDeserialize(&handle->ex, handle->filename, NULL); + if(ret != LORS_SUCCESS) { + errno = EIO; + return (void *)-1; + } + ret = lorsUpdateDepotPool(handle->ex, &handle->dp, + handle->lbone_server, 0, + NULL, handle->lors_threads, + handle->lors_timeout, 0); + if(ret != LORS_SUCCESS) { + errno = EIO; + return (void *)-1; + } + } + return (void *)handle; +} + + +static int +ibp_flush(void *handle) +{ + struct xio_ibp_handle_t *hdl = (struct xio_ibp_handle_t *)handle; + int ret; + LorsSet *set; + + if(hdl->dirty_buffer == 0) { + return 0; + } + + ret = lorsQuery(hdl->ex, &set, hdl->begin, hdl->end, + LORS_QUERY_REMOVE); + if(ret != LORS_SUCCESS) { + errno = EINVAL; + return -1; + } + + if(jrb_empty(set->mapping_map)) { + ret = lorsSetInit(&set, hdl->end/hdl->lors_threads, 1, 0); + if(ret != LORS_SUCCESS) { + errno = EIO; + return -1; + } + + ret = lorsSetStore(set, hdl->dp, hdl->buffer, + hdl->begin, hdl->end, NULL, + hdl->lors_threads, + hdl->lors_timeout, LORS_RETRY_UNTIL_TIMEOUT); + + if(ret != LORS_SUCCESS) { + lorsSetFree(set,LORS_FREE_MAPPINGS); + errno = EIO; + return -1; + } + } else { + set->copies=hdl->lors_copies; + set->data_blocksize=hdl->end/hdl->lors_threads; + ret = lorsSetUpdate(set, hdl->dp, hdl->buffer, + hdl->begin, hdl->end, + hdl->lors_threads,hdl->lors_timeout, + LORS_RETRY_UNTIL_TIMEOUT); + if(ret != LORS_SUCCESS) { + lorsSetFree(set,LORS_FREE_MAPPINGS); + errno=EIO; + return -1; + } + } + + ret = lorsAppendSet(hdl->ex, set); + if(ret != LORS_SUCCESS) { + lorsSetFree(set, LORS_FREE_MAPPINGS); + errno=EIO; + return -1; + } + + lorsSetFree(set,0); + + hdl->begin += hdl->b_pos; + + hdl->end = 0; + + ret = lorsFileSerialize(hdl->ex, hdl->filename, 0, 0); + + if(ret != LORS_SUCCESS) { + perror("file serialize"); + } + + hdl->dirty_buffer = 0; + return 0; +} + +static ssize_t +ibp_write(void *handle, const void *buffer, size_t size) +{ + struct xio_ibp_handle_t *hdl = (struct xio_ibp_handle_t *)handle; + + pthread_testcancel(); + pthread_mutex_lock(&xio_lock); + pthread_testcancel(); + if(size > hdl->lors_blocksize) + size = hdl->lors_blocksize; + + if(!hdl || !buffer || hdl->mode == O_RDONLY || !hdl->buffer) { + errno = EINVAL; + pthread_mutex_unlock(&xio_lock); + return -1; + } + + hdl->dirty_buffer = 1; + + if(hdl->b_pos + size >= hdl->lors_blocksize) { + if(ibp_flush(handle)) { + errno = EIO; + pthread_mutex_unlock(&xio_lock); + return -1; + } + hdl->b_pos = 0; + } + + memcpy((char *)hdl->buffer + hdl->b_pos, buffer, size); + hdl->b_pos += size; + if(hdl->end < hdl->b_pos) + hdl->end = hdl->b_pos; + + pthread_mutex_unlock(&xio_lock); + return size; +} + +static ssize_t +ibp_read(void *handle, void *buffer, size_t size) +{ + struct xio_ibp_handle_t *hdl = (struct xio_ibp_handle_t *)handle; + int ret; + int msize=size; + LorsSet *set; + + pthread_testcancel(); + pthread_mutex_lock(&xio_lock); + pthread_testcancel(); + + if(hdl->mode == O_WRONLY) { + errno = EINVAL; + pthread_mutex_unlock(&xio_lock); + return -1; + } + + if(size > hdl->lors_blocksize - hdl->b_pos) + msize = hdl->lors_blocksize - hdl->b_pos; + + if(hdl->b_pos < hdl->lors_blocksize && !hdl->fill_buffer) { + memcpy(buffer, hdl->buffer+hdl->b_pos, msize); + hdl->b_pos += msize; + pthread_mutex_unlock(&xio_lock); + return msize; + } + + hdl->fill_buffer = 0; + + ret = lorsQuery(hdl->ex, &set, hdl->begin + hdl->b_pos, + hdl->lors_blocksize, 0); + if(ret != LORS_SUCCESS) { + pthread_mutex_unlock(&xio_lock); + return 0; + } + + ret = lorsSetLoad(set, hdl->buffer, hdl->begin + hdl->b_pos, + hdl->lors_blocksize, hdl->lors_blocksize, + NULL, hdl->lors_threads, hdl->lors_timeout, 0); + + lorsSetFree(set, 0); + + if(ret < 0) { + errno = EIO; + pthread_mutex_unlock(&xio_lock); + return -1; + } + + hdl->begin += hdl->b_pos; + + if(size > ret) + size = ret; + + hdl->b_pos = size; + memcpy(buffer, hdl->buffer, size); + pthread_mutex_unlock(&xio_lock); + return size; +} + +static off_t +ibp_lseek(void *handle, off_t offs, int mode) +{ + struct xio_ibp_handle_t *hdl = (struct xio_ibp_handle_t *)handle; + + pthread_mutex_lock(&xio_lock); + pthread_testcancel(); + if(mode == SEEK_SET) { + if(offs - hdl->begin > hdl->lors_blocksize || + offs < hdl->begin) { + if(ibp_flush(handle)) { + errno = EIO; + pthread_mutex_unlock(&xio_lock); + return -1; + } + hdl->fill_buffer = 1; + hdl->begin = offs; + hdl->b_pos = 0; + } else { + hdl->b_pos = offs - hdl->begin; + } + } + else if(mode == SEEK_CUR) { + if(hdl->b_pos + offs > hdl->lors_blocksize || + hdl->b_pos + offs < 0) { + if(ibp_flush(handle)) { + errno = EIO; + pthread_mutex_unlock(&xio_lock); + return -1; + } + hdl->fill_buffer = 1; + hdl->begin = hdl->begin + hdl->b_pos + offs; + hdl->b_pos = 0; + } else { + hdl->b_pos += offs; + } + } else if(mode == SEEK_END) { + if(ibp_flush(handle)) { + errno = EIO; + pthread_mutex_unlock(&xio_lock); + return -1; + } + hdl->fill_buffer = 1; + hdl->begin = hdl->ex->logical_length + offs; + hdl->b_pos = 0; + } else { + errno=EINVAL; + pthread_mutex_unlock(&xio_lock); + return(-1); + } + + pthread_mutex_unlock(&xio_lock); + return hdl->begin + hdl->b_pos; +} + +static int +ibp_close(void *handle) +{ + struct xio_ibp_handle_t *hdl = (struct xio_ibp_handle_t *)handle; + int ret; + + pthread_mutex_lock(&xio_lock); + pthread_testcancel(); + if(hdl->mode & O_WRONLY || hdl->mode & O_CREAT) { + if(hdl->dirty_buffer) + ibp_flush(handle); + else { + ret = lorsFileSerialize(hdl->ex, hdl->filename, 0, 0); + if(ret != LORS_SUCCESS) { + perror("file serialize"); + } + } + } + if(hdl->buffer) + free(hdl->buffer); + ret = lorsExnodeFree(hdl->ex); + if(ret != LORS_SUCCESS) { + perror("exnode free"); + } + if(!hdl) { + pthread_mutex_unlock(&xio_lock); + return 0; + } + if(hdl->dp) + lorsFreeDepotPool(hdl->dp); + pthread_mutex_unlock(&xio_lock); + free(hdl); + return 0; +} + +static int +ibp_ftruncate(void *stream, off_t length) +{ + struct xio_ibp_handle_t* hdl = (struct xio_ibp_handle_t*)stream; + int ret; + LorsSet *set; + + pthread_mutex_lock(&xio_lock); + pthread_testcancel(); + ibp_flush(stream); + hdl->b_pos = 0; + if(length == hdl->ex->logical_length) { + pthread_mutex_unlock(&xio_lock); + return 0; + } + + ret = lorsQuery(hdl->ex, &set, length, + hdl->ex->logical_length-length, 0); + if(ret != LORS_SUCCESS) { + pthread_mutex_unlock(&xio_lock); + errno = EINVAL; + return -1; + } + ret = lorsSetTrim(set, length, hdl->ex->logical_length-length, + 1, 20, LORS_TRIM_ALL); + lorsSetFree(set, 0); + if(ret != LORS_SUCCESS) { + pthread_mutex_unlock(&xio_lock); + errno = EIO; + return -1; + } + pthread_mutex_unlock(&xio_lock); + return 0; +} + +static char * +ibp_lorstoname(char *file_name) +{ + char * uri = file_name; + if(strncmp(uri, IBP_URI, IBP_URI_LEN) != 0) { + return strdup(uri); + } + uri += IBP_URI_LEN; + uri = (char *)(strchr(uri, '/')+1); + if(!strchr(uri, '?')) { + return strdup(uri); + } + return tc_strndup(uri, (int)(strchr(uri, '?')-uri)); +} + +static int +ibp_stat(const char *file_name, struct stat *buf) +{ + LorsExnode *exnode; + int ret; + char *fn; + + fn = ibp_lorstoname((char *)file_name); + ret = lorsFileDeserialize(&exnode, fn, NULL); + if(ret!=0) { + errno=EACCES; + return -1; + } + if(stat(fn, buf) == -1) { + free(fn); + return -1; + } + buf->st_ino=-1; + buf->st_dev=-1; + buf->st_size=exnode->logical_length; + lorsExnodeFree(exnode); + free(fn); + return 0; +} + +static int +ibp_lstat(const char *file_name, struct stat *buf) +{ + char *fn = ibp_lorstoname((char *)file_name); + if(lstat(fn,buf) == -1) { + free(fn); + return -1; + } + free(fn); + return 0; +} + +static int +ibp_fstat(void *stream, struct stat *buf) +{ + struct xio_ibp_handle_t *hdl = (struct xio_ibp_handle_t *)stream; + + return ibp_stat(hdl->filename,buf); +} + +#endif + + + +#define XIO_VALID_FD(fd) \ + ((fd) > 2 && (fd) < MAX_HANDLES) + +#define XIO_HAS_HANDLE(fd) \ + (XIO_VALID_FD(fd) && (xio_handles[(fd)] != NULL)) + +#define XIO_CHECK_INIT \ + if(!xio_initialized) { \ + xio_init(); \ + xio_initialized = 1; \ + } + +static void +xio_init(void) +{ + int i; + + for (i = 0; i < MAX_HANDLES; i++) { + xio_handles[i] = NULL; + } + + pthread_mutex_init(&xio_lock, NULL); +} + +int +xio_open(const char *pathname, int flags, ...) +{ + int i; + int hid; + int mode = 0; + + XIO_CHECK_INIT; + + if(flags & O_CREAT) { + va_list arg; + va_start(arg, flags); + mode = va_arg(arg, int); + va_end(arg); + } + + pthread_mutex_lock(&xio_lock); + /* Find free IO handle, skipping stdin, stdout, stderr */ + for(i = 3; xio_handles[i] != NULL && i < MAX_HANDLES; i++) { + ; /* do nothing in loop body */ + } + hid = (i == MAX_HANDLES) ?-1 :i; + pthread_mutex_unlock(&xio_lock); + + if(hid == -1) { + errno = EIO; + return -1; + } + +#ifdef HAVE_IBP + if(strncmp(pathname, IBP_URI, IBP_URI_LEN) == 0) { + // IBP uri + xio_handles[hid] = ibp_open(pathname, flags, mode); + if(!xio_handles[hid]) { + errno = EIO; + return -1; + } + return hid; + } +#endif + return open(pathname, flags, mode); +} + +ssize_t +xio_read(int fd, void *buf, size_t count) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(XIO_HAS_HANDLE(fd)) { + return ibp_read(xio_handles[fd], buf, count); + } +#endif + return read(fd, buf, count); +} + +ssize_t +xio_write(int fd, const void *buf, size_t count) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(XIO_HAS_HANDLE(fd)) { + return ibp_write(xio_handles[fd], buf, count); + } +#endif + return write(fd, buf, count); +} + +int +xio_ftruncate(int fd, off_t length) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(XIO_HAS_HANDLE(fd)) { + return ibp_ftruncate(xio_handles[fd], length) + } +#endif + return ftruncate(fd, length); +} + +off_t +xio_lseek(int fd, off_t offset, int whence) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(XIO_HAS_HANDLE(fd)) { + return ibp_lseek(xio_handles[fd], offset, whence); + } +#endif + return lseek(fd, offset, whence); +} + +int +xio_close(int fd) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(XIO_HAS_HANDLE(fd)) { + int ret = ibp_close(xio_handles[fd]); + xio_handles[fd] = NULL; + return ret; + } +#endif + return close(fd); +} + +int +xio_stat(const char *file_name, struct stat *buf) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(strncmp(file_name, IBP_URI, IBP_URI_LEN) == 0) { + return ibp_stat(file_name, buf); + } +#endif + return stat(file_name, buf); +} + +int +xio_lstat(const char *file_name, struct stat *buf) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(strncmp(file_name, IBP_URI, IBP_URI_LEN) == 0) { + return ibp_lstat(file_name, buf); + } +#endif + return lstat(file_name, buf); +} + +int +xio_rename(const char *oldpath, const char *newpath) +{ +#ifdef HAVE_IBP + char *old, *old_p; + char *newp; + int ret; + + if(strncmp(IBP_URI, oldpath, IBP_URI_LEN) == 0) { + old_p = old = strdup(oldpath); + old = strchr(old + IBP_URI_LEN,'/')+1; + if(strchr(old, '?')) { + *(strchr(old, '?')) = 0; + } + + newp = malloc(strlen(old)+1+4); + snprintf(newp, strlen(old)+1+4, "%s%s", old, &newpath[strlen(newpath)-4]); + ret = rename(old, newp); + free(old_p); + return ret; + } +#endif + return rename(oldpath, newpath); +} + +int +xio_fstat(int fd, struct stat *buf) +{ + XIO_CHECK_INIT; + +#ifdef HAVE_IBP + if(XIO_HAS_HANDLE(fd)) { + return ibp_fstat(xio_handles[fd], buf) + } +#endif + return fstat(fd, buf); +} |
