Ejemplo n.º 1
0
cmyth_storagegroup_file_t
cmyth_storagegroup_get_fileinfo(cmyth_conn_t control, char *storagegroup, char *hostname, char *filename)
{
	char msg[256];
	int count = 0;
	int err = 0;
	cmyth_storagegroup_file_t ret = NULL;
	int consumed = 0;
	char tmp_str[2048];

	if (!control) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__);
		return 0;
	}

	pthread_mutex_lock(&control->conn_mutex);

	snprintf(msg, sizeof(msg), "QUERY_SG_FILEQUERY[]:[]%s[]:[]%s[]:[]%s", hostname, storagegroup, filename);

	err = cmyth_send_message(control, msg);
	if (err < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err);
		goto out;
	}

	count = cmyth_rcv_length(control);
	if (count < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count);
		goto out;
	}

	consumed = cmyth_rcv_string(control, &err, tmp_str, sizeof(tmp_str) - 1, count);
	count -= consumed;
	if (err) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count);
		ret = NULL;
		goto out;
	} else if (count == 0) {
		cmyth_dbg(CMYTH_DBG_WARN, "%s: QUERY_SG_FILEQUERY failed(%s)\n", __FUNCTION__, tmp_str);
		ret = NULL;
		goto out;
	}

	ret = cmyth_storagegroup_file_create();
	if (!ret) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for file\n", __FUNCTION__);
		ref_release(ret);
		ret = NULL;
		goto out;
	}
	ret->filename = ref_strdup(tmp_str);

	consumed = cmyth_rcv_string(control, &err, tmp_str, sizeof(tmp_str) - 1, count);
	count -= consumed;
	if (err) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count);
		ref_release(ret);
		ret = NULL;
		goto out;
	}
        ret->lastmodified = atol(tmp_str);

	consumed = cmyth_rcv_new_int64(control, &err, &(ret->size), count, 1);
	count -= consumed;
	if (err) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, count);
		ref_release(ret);
		ret = NULL;
		goto out;
	}

	cmyth_dbg(CMYTH_DBG_DEBUG, "%s: filename: %s\n", __FUNCTION__, ret->filename);

out:
	pthread_mutex_unlock(&control->conn_mutex);
	return ret;
}
Ejemplo n.º 2
0
static int
cmyth_storagegroup_update_fileinfo(cmyth_conn_t control, cmyth_storagegroup_file_t file)
{
	char msg[256];
	int count;
	int err = 0;
	int consumed; /* = profiles;*/
	char tmp_str[2048];

	if (!control) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__);
		return -EINVAL;
	}

	if (!file) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no file specified\n", __FUNCTION__);
		return -EINVAL;
	}

	snprintf(msg, sizeof(msg), "QUERY_SG_FILEQUERY[]:[]%s[]:[]%s[]:[]%s", file->hostname , file->storagegroup, file->filename);

	err = cmyth_send_message(control, msg);
	if (err < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err);
		return err;
	}

	count = cmyth_rcv_length(control);
	if (count < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count);
		return -1;
	}

	consumed = cmyth_rcv_string(control, &err, tmp_str, sizeof(tmp_str) - 1, count);
	count -= consumed;

	if (err) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count);
		return -1;
	} else if (count == 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: QUERY_SG_FILEQUERY failed(%s)\n", __FUNCTION__, tmp_str);
		return -1;
	}

	consumed = cmyth_rcv_string(control, &err, tmp_str, sizeof(tmp_str), count);
	count -= consumed;
	if (err) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count);
		return -1;
	}
	file->lastmodified = atol(tmp_str);

	consumed = cmyth_rcv_new_int64(control, &err, &(file->size), count, 1);
	count -= consumed;
	if (err) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, count);
		return -1;
	}

	return 0;
}
Ejemplo n.º 3
0
/*
 * cmyth_file_read()
 *
 * Scope: PUBLIC
 *
 * Description
 *
 * Request and read a block of data from backend
 *
 * Return Value:
 *
 * Sucess: number of bytes transfered
 *
 * Failure: an int containing -errno
 */
int32_t cmyth_file_read(cmyth_file_t file, char *buf, int32_t len)
{
	int err, count;
	int32_t ret;
	int req, nfds, rec;
	char *end, *cur;
	char msg[256];
	int64_t len64;
	struct timeval tv;
	fd_set fds;

	if (!file || !file->file_data) {
		cmyth_dbg (CMYTH_DBG_ERROR, "%s: no connection\n",
		           __FUNCTION__);
		return -EINVAL;
	}
	if (len == 0)
		return 0;

	if(len > file->file_data->conn_tcp_rcvbuf)
		len = file->file_data->conn_tcp_rcvbuf;

	pthread_mutex_lock (&mutex);

	/* make sure we have outstanding requests that fill the buffer that was called with */
	/* this way we should be able to saturate the network connection better */
	if (file->file_req < file->file_pos + len) {

		snprintf (msg, sizeof (msg),
	            "QUERY_FILETRANSFER %"PRIu32"[]:[]REQUEST_BLOCK[]:[]%"PRId32,
	            file->file_id, (int32_t)(file->file_pos + len - file->file_req));

		if ( (err = cmyth_send_message (file->file_control, msg) ) < 0) {
			cmyth_dbg (CMYTH_DBG_ERROR,
			           "%s: cmyth_send_message() failed (%d)\n",
			           __FUNCTION__, err);
			ret = err;
			goto out;
		}
		req = 1;
	} else {
		req = 0;
	}

	rec = 0;
	cur = buf;
	end = buf+len;

	while (cur == buf || req || rec) {
		if(rec) {
			tv.tv_sec =  0;
			tv.tv_usec = 0;
		} else {
			tv.tv_sec = 20;
			tv.tv_usec = 0;
		}
		nfds = 0;

		FD_ZERO (&fds);
		if (req) {
			if ((int)file->file_control->conn_fd > nfds)
				nfds = (int)file->file_control->conn_fd;
			FD_SET (file->file_control->conn_fd, &fds);
		}
		if ((int)file->file_data->conn_fd > nfds)
			nfds = (int)file->file_data->conn_fd;
		FD_SET (file->file_data->conn_fd, &fds);

		if ((ret = select (nfds+1, &fds, NULL, NULL,&tv)) < 0) {
			cmyth_dbg (CMYTH_DBG_ERROR,
			           "%s: select(() failed (%d)\n",
			           __FUNCTION__, ret);
			goto out;
		}

		if (ret == 0 && !rec) {
			file->file_control->conn_hang = 1;
			file->file_data->conn_hang = 1;
			ret = -ETIMEDOUT;
			goto out;
		}

		/* check control connection */
		if (FD_ISSET(file->file_control->conn_fd, &fds)) {

			if ((count=cmyth_rcv_length (file->file_control)) < 0) {
				cmyth_dbg (CMYTH_DBG_ERROR,
				           "%s: cmyth_rcv_length() failed (%d)\n",
				           __FUNCTION__, count);
				ret = count;
				goto out;
			}

			/*
			 * MythTV originally sent back a signed 32bit value but was changed to a
			 * signed 64bit value in http://svn.mythtv.org/trac/changeset/18011 (1-Aug-2008).
			 *
			 * libcmyth now retrieves the 64-bit signed value, does error-checking,
			 * and then converts to a 32bit signed.
			 *
			 * This rcv_ method needs to be forced to use new_int64 to pull back a
			 * single 64bit number otherwise the handling in rcv_int64 will revert to
			 * the old two 32bit hi and lo long values.
			 */
			if ((ret = cmyth_rcv_new_int64(file->file_control, &err, &len64, count, 1))< 0) {
				cmyth_dbg (CMYTH_DBG_ERROR,
				           "%s: cmyth_rcv_new_int64() failed (%d)\n",
				           __FUNCTION__, ret);
				ret = err;
				goto out;
			}
			if (len64 > 0x7fffffff || len64 < 0) {
				/* -1 seems to be a common result, but isn't valid so use 0 instead. */
				cmyth_dbg (CMYTH_DBG_WARN,
				           "%s: cmyth_rcv_new_int64() returned out of bound value (%"PRId64"). Using 0 instead.\n",
				           __FUNCTION__, len64);
				len64 = 0;
			}
			len = (int32_t)len64;
			req = 0;
			file->file_req += len;

			if (file->file_req < file->file_pos) {
				cmyth_dbg (CMYTH_DBG_ERROR,
				           "%s: received invalid invalid length, read position is ahead of request (req: %"PRId64", pos: %"PRId64", len: %"PRId64")\n",
				           __FUNCTION__, file->file_req, file->file_pos, len64);
				ret = -1;
				goto out;
			}


			/* check if we are already done */
			if (file->file_pos == file->file_req)
				break;
		}

		/* restore direct request fleg */
		rec = 0;

		/* check data connection */
		if (FD_ISSET(file->file_data->conn_fd, &fds)) {
			if (end < cur) {
				cmyth_dbg (CMYTH_DBG_ERROR,
				           "%s: positions invalid on read, bailing out (cur: %x, end: %x)\n",
				           __FUNCTION__, cur, end);
				ret = -1;
				goto out;
			}
			if ((ret = recv (file->file_data->conn_fd, cur, (int32_t)(end - cur), 0)) < 0) {
				cmyth_dbg (CMYTH_DBG_ERROR,
				           "%s: recv() failed (%d)\n",
				           __FUNCTION__, ret);
				goto out;
			}
			cur += ret;
			file->file_pos += ret;
			if(ret)
				rec = 1; /* attempt to read directly again to get all queued packets */
		}
	}

	/* make sure file grows, as we move past length */
	if (file->file_pos > file->file_length)
		file->file_length = file->file_pos;

	ret = (int32_t)(cur - buf);
out:
	pthread_mutex_unlock (&mutex);
	return ret;
}