(trunk) first draft of changing the FreeSpace API to behave as https://trac.transmissionbt.com/ticket/4076#comment:25 -- libT, rpc, qt, and gtk implementations.

This commit is contained in:
Jordan Lee
2013-02-09 04:05:03 +00:00
parent 794a0c1d80
commit cd09204a6e
31 changed files with 552 additions and 190 deletions

View File

@@ -56,6 +56,7 @@
#endif
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -81,6 +82,8 @@
#include <xfs/xqm.h>
#endif
#include <event2/util.h> /* evutil_ascii_strcasecmp () */
#include "transmission.h"
#include "session.h"
#include "list.h"
@@ -732,7 +735,7 @@ tr_getWebClientDir (const tr_session * session UNUSED)
***/
#ifndef WIN32
static char *
static const char *
getdev (const char * path)
{
#ifdef HAVE_GETMNTENT
@@ -783,7 +786,7 @@ getdev (const char * path)
#endif
}
static char *
static const char *
getfstype (const char * device)
{
@@ -833,12 +836,12 @@ getfstype (const char * device)
#endif
}
static char *
static const char *
getblkdev (const char * path)
{
char * c;
char * dir;
char * device;
const char * device;
dir = tr_strdup(path);
@@ -860,7 +863,7 @@ getblkdev (const char * path)
}
static int64_t
getquota (char * device)
getquota (const char * device)
{
struct dqblk dq;
int64_t limit;
@@ -960,41 +963,24 @@ getxfsquota (char * device)
#endif /* WIN32 */
static int64_t
tr_getQuotaFreeSpace (const char * path, char * device, char * fstype)
tr_getQuotaFreeSpace (const struct tr_device_info * info)
{
int64_t ret=-1;
int64_t ret = -1;
#ifndef WIN32
/* save device for future use */
if (!*device)
{
char * d = getblkdev (path);
if (d == NULL)
return ret;
tr_strlcpy (device, d, PATH_MAX + 1);
}
/* save FS type for future use */
if (!*fstype)
{
char * fs = getfstype (device);
if (fs != NULL)
tr_strlcpy (fstype, fs, PATH_MAX + 1);
}
if (strcasecmp(fstype, "xfs") == 0)
if (info->fstype && !evutil_ascii_strcasecmp(info->fstype, "xfs"))
{
#ifdef HAVE_XQM
ret = getxfsquota(device);
ret = getxfsquota (info->device);
#endif
}
else
{
ret = getquota(device);
ret = getquota (info->device);
}
#endif /* WIN32 */
return ret;
}
@@ -1021,15 +1007,50 @@ tr_getDiskFreeSpace (const char * path)
#endif
}
int64_t
tr_getFreeSpace (const char * path, char * device, char * fstype)
struct tr_device_info *
tr_device_info_create (const char * path)
{
int64_t i = tr_getQuotaFreeSpace (path, device, fstype);
struct tr_device_info * info;
if (i < 0)
i = tr_getDiskFreeSpace (path);
info = tr_new0 (struct tr_device_info, 1);
info->path = tr_strdup (path);
info->device = tr_strdup (getblkdev (path));
info->fstype = tr_strdup (getfstype (path));
return i;
return info;
}
void
tr_device_info_free (struct tr_device_info * info)
{
if (info != NULL)
{
tr_free (info->fstype);
tr_free (info->device);
tr_free (info->path);
tr_free (info);
}
}
int64_t
tr_device_info_get_free_space (const struct tr_device_info * info)
{
int64_t free_space;
if ((info == NULL) || (info->path == NULL))
{
errno = EINVAL;
free_space = -1;
}
else
{
free_space = tr_getQuotaFreeSpace (info);
if (free_space < 0)
free_space = tr_getDiskFreeSpace (info->path);
}
return free_space;
}
/***

View File

@@ -42,9 +42,20 @@ const char * tr_getTorrentDir (const tr_session *);
/** @brief return the directory where the Web Client's web ui files are kept */
const char * tr_getWebClientDir (const tr_session *);
struct tr_device_info
{
char * path;
char * device;
char * fstype;
};
struct tr_device_info * tr_device_info_create (const char * path);
/** If the disk quota is enabled and readable, this returns how much is available in the quota.
Otherwise, it returns how much is available on the disk, or -1 on error. */
int64_t tr_getFreeSpace (const char * path, char * device, char * fstype);
int64_t tr_device_info_get_free_space (const struct tr_device_info * info);
void tr_device_info_free (struct tr_device_info * info);
/** @} */

View File

@@ -78,7 +78,6 @@ static const struct tr_key_struct my_static[] =
{ "done-date", 9 },
{ "doneDate", 8 },
{ "download-dir", 12 },
{ "download-dir-free-space", 23 },
{ "download-queue-enabled", 22 },
{ "download-queue-size", 19 },
{ "downloadCount", 13 },

View File

@@ -88,7 +88,6 @@ enum
TR_KEY_done_date,
TR_KEY_doneDate,
TR_KEY_download_dir,
TR_KEY_download_dir_free_space,
TR_KEY_download_queue_enabled,
TR_KEY_download_queue_size,
TR_KEY_downloadCount,

View File

@@ -106,7 +106,6 @@ test_session_get_and_set (void)
check (tr_variantDictFind (args, TR_KEY_config_dir) != NULL);
check (tr_variantDictFind (args, TR_KEY_dht_enabled) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_dir) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_dir_free_space) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_queue_enabled) != NULL);
check (tr_variantDictFind (args, TR_KEY_download_queue_size) != NULL);
check (tr_variantDictFind (args, TR_KEY_encryption) != NULL);

View File

@@ -1726,8 +1726,8 @@ torrentAdd (tr_session * session,
static const char*
sessionSet (tr_session * session,
tr_variant * args_in,
tr_variant * args_out UNUSED,
tr_variant * args_in,
tr_variant * args_out UNUSED,
struct tr_rpc_idle_data * idle_data UNUSED)
{
int64_t i;
@@ -1905,7 +1905,6 @@ sessionGet (tr_session * s,
tr_variantDictAddStr (d, TR_KEY_download_dir, tr_sessionGetDownloadDir (s));
tr_variantDictAddBool (d, TR_KEY_download_queue_enabled, tr_sessionGetQueueEnabled (s, TR_DOWN));
tr_variantDictAddInt (d, TR_KEY_download_queue_size, tr_sessionGetQueueSize (s, TR_DOWN));
tr_variantDictAddInt (d, TR_KEY_download_dir_free_space, tr_sessionGetDownloadDirFreeSpace (s));
tr_variantDictAddInt (d, TR_KEY_peer_limit_global, tr_sessionGetPeerLimit (s));
tr_variantDictAddInt (d, TR_KEY_peer_limit_per_torrent, tr_sessionGetPeerLimitPerTorrent (s));
tr_variantDictAddStr (d, TR_KEY_incomplete_dir, tr_sessionGetIncompleteDir (s));
@@ -1948,6 +1947,33 @@ sessionGet (tr_session * s,
return NULL;
}
static const char*
freeSpace (tr_session * session,
tr_variant * args_in,
tr_variant * args_out,
struct tr_rpc_idle_data * idle_data UNUSED)
{
int tmperr;
const char * path = NULL;
const char * err = NULL;
int64_t free_space = -1;
/* get the free space */
tr_variantDictFindStr (args_in, TR_KEY_path, &path, NULL);
tmperr = errno;
errno = 0;
free_space = tr_sessionGetDirFreeSpace (session, path);
if (free_space < 0)
err = tr_strerror (errno);
errno = tmperr;
/* response */
if (path != NULL)
tr_variantDictAddStr (args_out, TR_KEY_path, path);
tr_variantDictAddInt (args_out, TR_KEY_size_bytes, free_space);
return err;
}
/***
****
***/
@@ -1978,6 +2004,7 @@ methods[] =
{
{ "port-test", false, portTest },
{ "blocklist-update", false, blocklistUpdate },
{ "free-space", true, freeSpace },
{ "session-close", true, sessionClose },
{ "session-get", true, sessionGet },
{ "session-set", true, sessionSet },

View File

@@ -386,7 +386,7 @@ tr_sessionGetSettings (tr_session * s, tr_variant * d)
tr_variantDictAddBool (d, TR_KEY_dht_enabled, s->isDHTEnabled);
tr_variantDictAddBool (d, TR_KEY_utp_enabled, s->isUTPEnabled);
tr_variantDictAddBool (d, TR_KEY_lpd_enabled, s->isLPDEnabled);
tr_variantDictAddStr (d, TR_KEY_download_dir, s->downloadDir);
tr_variantDictAddStr (d, TR_KEY_download_dir, tr_sessionGetDownloadDir (s));
tr_variantDictAddInt (d, TR_KEY_download_queue_size, tr_sessionGetQueueSize (s, TR_DOWN));
tr_variantDictAddBool (d, TR_KEY_download_queue_enabled, tr_sessionGetQueueEnabled (s, TR_DOWN));
tr_variantDictAddInt (d, TR_KEY_speed_limit_down, tr_sessionGetSpeedLimit_KBps (s, TR_DOWN));
@@ -953,33 +953,40 @@ tr_sessionSet (tr_session * session, tr_variant * settings)
void
tr_sessionSetDownloadDir (tr_session * session, const char * dir)
{
assert (tr_isSession (session));
struct tr_device_info * info = NULL;
if (session->downloadDir != dir)
{
tr_free (session->downloadDir);
session->downloadDir = tr_strdup (dir);
memset (session->downloadDirBlkDev, 0, sizeof(session->downloadDirBlkDev));
memset (session->downloadDirFsType, 0, sizeof(session->downloadDirFsType));
}
assert (tr_isSession (session));
if (dir != NULL)
info = tr_device_info_create (dir);
tr_device_info_free (session->downloadDir);
session->downloadDir = info;
}
const char *
tr_sessionGetDownloadDir (const tr_session * session)
{
assert (tr_isSession (session));
const char * dir = NULL;
return session->downloadDir;
assert (tr_isSession (session));
if ((session != NULL) && (session->downloadDir != NULL))
dir = session->downloadDir->path;
return dir;
}
int64_t
tr_sessionGetDownloadDirFreeSpace (tr_session * session)
tr_sessionGetDirFreeSpace (tr_session * session, const char * dir)
{
assert (tr_isSession (session));
int64_t free_space;
return tr_getFreeSpace (session->downloadDir,
session->downloadDirBlkDev,
session->downloadDirFsType);
if (!tr_strcmp0 (dir, tr_sessionGetDownloadDir (session)))
free_space = tr_device_info_get_free_space (session->downloadDir);
else
free_space = tr_getDirFreeSpace (dir);
return free_space;
}
/***
@@ -1883,12 +1890,12 @@ tr_sessionClose (tr_session * session)
tr_variantFree (session->metainfoLookup);
tr_free (session->metainfoLookup);
}
tr_device_info_free (session->downloadDir);
tr_free (session->torrentDoneScript);
tr_free (session->tag);
tr_free (session->configDir);
tr_free (session->resumeDir);
tr_free (session->torrentDir);
tr_free (session->downloadDir);
tr_free (session->incompleteDir);
tr_free (session->blocklist_url);
tr_free (session->peer_congestion_algorithm);

View File

@@ -56,6 +56,7 @@ struct tr_announcer_udp;
struct tr_bindsockets;
struct tr_cache;
struct tr_fdInfo;
struct tr_device_info;
typedef void (tr_web_config_func)(tr_session * session, void * curl_pointer, const char * url, void * user_data);
@@ -183,15 +184,14 @@ struct tr_session
char * tag;
char * configDir;
char * downloadDir;
char downloadDirBlkDev[TR_PATH_MAX + 1];
char downloadDirFsType[TR_PATH_MAX + 1];
char * resumeDir;
char * torrentDir;
char * incompleteDir;
char * blocklist_url;
struct tr_device_info * downloadDir;
struct tr_list * blocklists;
struct tr_peerMgr * peerMgr;
struct tr_shared * shared;

View File

@@ -452,7 +452,7 @@ tr_ctorNew (const tr_session * session)
tr_ctorSetDeleteSource (ctor, tr_sessionGetDeleteSource (session));
tr_ctorSetPaused (ctor, TR_FALLBACK, tr_sessionGetPaused (session));
tr_ctorSetPeerLimit (ctor, TR_FALLBACK, session->peerLimitPerTorrent);
tr_ctorSetDownloadDir (ctor, TR_FALLBACK, session->downloadDir);
tr_ctorSetDownloadDir (ctor, TR_FALLBACK, tr_sessionGetDownloadDir(session));
}
tr_ctorSetSave (ctor, true);
return ctor;

View File

@@ -82,7 +82,7 @@ tr_torrentName (const tr_torrent * tor)
int
tr_torrentId (const tr_torrent * tor)
{
return tor->uniqueId;
return tor ? tor->uniqueId : -1;
}
tr_torrent*

View File

@@ -291,10 +291,10 @@ void tr_sessionSetDownloadDir (tr_session * session, const char * downloadDir);
const char * tr_sessionGetDownloadDir (const tr_session * session);
/**
* @brief Get available disk space (in bytes) for the default download folder.
* @brief Get available disk space (in bytes) for the specified directory.
* @return zero or positive integer on success, -1 in case of error.
*/
int64_t tr_sessionGetDownloadDirFreeSpace (tr_session * session);
int64_t tr_sessionGetDirFreeSpace (tr_session * session, const char * dir);
/**
* @brief Set the torrent's bandwidth priority.

View File

@@ -420,6 +420,27 @@ tr_fileExists (const char * filename, time_t * mtime)
return ok;
}
int64_t
tr_getDirFreeSpace (const char * dir)
{
int64_t free_space;
if (!dir || !*dir)
{
errno = EINVAL;
free_space = -1;
}
else
{
struct tr_device_info * info;
info = tr_device_info_create (dir);
free_space = tr_device_info_get_free_space (info);
tr_device_info_free (info);
}
return free_space;
}
/****
*****
****/

View File

@@ -140,6 +140,12 @@ char* tr_buildPath (const char * first_element, ...) TR_GNUC_NULL_TERMINATED
bool tr_fileExists (const char * filename, time_t * mtime);
/**
* @brief Get available disk space (in bytes) for the specified folder.
* @return zero or positive integer on success, -1 in case of error.
*/
int64_t tr_getDirFreeSpace (const char * path);
struct event;