Skip to content

Commit

Permalink
Transition FileSystemInfo into a proper class rather than a glorified
Browse files Browse the repository at this point in the history
struct.  Add methods for pulling local information, and communication
over backend protocol.
  • Loading branch information
wagnerrp committed Jun 6, 2011
1 parent 2034fb1 commit 65e877a
Show file tree
Hide file tree
Showing 14 changed files with 531 additions and 300 deletions.
256 changes: 256 additions & 0 deletions mythtv/libs/libmyth/filesysteminfo.cpp
@@ -0,0 +1,256 @@
#include <unistd.h>
#include <cstdlib>
#include "compat.h"

#ifdef linux
#include <sys/vfs.h>
#include <sys/sysinfo.h>
#endif

#if CONFIG_DARWIN
#include <mach/mach.h>
#endif

#ifdef BSD
#include <sys/param.h>
#include <sys/mount.h> // for struct statfs
#endif

using namespace std;

#include <QList>
#include <QString>
#include <QStringList>

#include "filesysteminfo.h"
#include "mythcoreutil.h"

// for serialization
#define INT_TO_LIST(x) do { list << QString::number(x); } while (0)
#define DATETIME_TO_LIST(x) INT_TO_LIST((x).toTime_t())
#define STR_TO_LIST(x) do { list << (x); } while (0)

// for deserialization
#define NEXT_STR() do { if (it == listend) \
{ \
VERBOSE(VB_IMPORTANT, listerror); \
clear(); \
return false; \
} \
ts = *it++; } while (0)
#define INT_FROM_LIST(x) do { NEXT_STR(); (x) = ts.toLongLong(); } while (0)
#define ENUM_FROM_LIST(x, y) do { NEXT_STR(); (x) = ((y)ts.toInt()); } while (0)
#define DATETIME_FROM_LIST(x) \
do { NEXT_STR(); (x).setTime_t(ts.toUInt()); } while (0)
#define STR_FROM_LIST(x) do { NEXT_STR(); (x) = ts; } while (0)

#define LOC QString("FileSystemInfo: ")
#define LOC_ERR QString("FileSystemInfo, error: ")

FileSystemInfo::FileSystemInfo(void) :
m_hostname(""), m_path(""), m_local(false), m_fsid(-1),
m_grpid(-1), m_blksize(4096), m_total(0), m_used(0)
{
}

FileSystemInfo::FileSystemInfo(const FileSystemInfo &other)
{
clone(other);
}

FileSystemInfo::FileSystemInfo(QString hostname, QString path, bool local,
int fsid, int groupid, int blksize, long long total, long long used) :
m_hostname(hostname), m_path(path), m_local(local), m_fsid(fsid),
m_grpid(groupid), m_blksize(blksize), m_total(total), m_used(used)
{
}

FileSystemInfo::FileSystemInfo(QStringList::const_iterator &it,
QStringList::const_iterator end)
{
FromStringList(it, end);
}

FileSystemInfo::FileSystemInfo(const QStringList &slist)
{
FromStringList(slist);
}

void FileSystemInfo::clone(const FileSystemInfo &other)
{
m_hostname = other.m_hostname;
m_path = other.m_path;
m_local = other.m_local;
m_fsid = other.m_fsid;
m_grpid = other.m_grpid;
m_blksize = other.m_blksize;
m_total = other.m_total;
m_used = other.m_used;
}

FileSystemInfo &FileSystemInfo::operator=(const FileSystemInfo &other)
{
clone(other);
return *this;
}

void FileSystemInfo::clear(void)
{
m_hostname = "";
m_path = "";
m_local = false;
m_fsid = -1;
m_grpid = -1;
m_blksize = 4096;
m_total = 0;
m_used = 0;
}

bool FileSystemInfo::ToStringList(QStringList &list) const
{
STR_TO_LIST(m_hostname);
STR_TO_LIST(m_path);
INT_TO_LIST(m_local);
INT_TO_LIST(m_fsid);
INT_TO_LIST(m_grpid);
INT_TO_LIST(m_blksize);
INT_TO_LIST(m_total);
INT_TO_LIST(m_used);

return true;
}

bool FileSystemInfo::FromStringList(const QStringList &slist)
{
QStringList::const_iterator it = slist.constBegin();
return FromStringList(it, slist.constEnd());
}

bool FileSystemInfo::FromStringList(QStringList::const_iterator &it,
QStringList::const_iterator listend)
{
QString listerror = LOC + "FromStringList, not enough items in list.";
QString ts;

STR_FROM_LIST(m_hostname);
STR_FROM_LIST(m_path);
INT_FROM_LIST(m_local);
INT_FROM_LIST(m_fsid);
INT_FROM_LIST(m_grpid);
INT_FROM_LIST(m_blksize);
INT_FROM_LIST(m_total);
INT_FROM_LIST(m_used);

return true;
}

const QList<FileSystemInfo> FileSystemInfo::RemoteGetInfo(MythSocket *sock)
{
FileSystemInfo fsInfo;
QList<FileSystemInfo> fsInfos;
QStringList strlist(QString("QUERY_FREE_SPACE_LIST"));

bool sent;

if (sock)
sent = sock->SendReceiveStringList(strlist);
else
sent = gCoreContext->SendReceiveStringList(strlist);

if (sent)
{
int numdisks = strlist.size()/NUMDISKINFOLINES;

QStringList::const_iterator it = strlist.begin();
for (int i = 0; i < numdisks; i++)
{
fsInfo.FromStringList(it, strlist.end());
fsInfos.append(fsInfo);
}
}

return fsInfos;
}

void FileSystemInfo::Consolidate(QList<FileSystemInfo> &disks,
bool merge, size_t fuzz)
{
int newid = 0;

QList<FileSystemInfo>::iterator it1, it2;
for (it1 = disks.begin(); it1 != disks.end(); ++it1)
{
if (it1->getFSysID() == -1)
{
it1->setFSysID(newid++);
if (merge)
it1->setPath(it1->getHostname().section(".", 0, 0)
+ ":" + it1->getPath());
}

for (it2 = it1+1; it2 != disks.end(); ++it2)
{
if (it2->getFSysID() != -1) // disk has already been matched
continue;

int bSize = max(32, max(it1->getBlockSize(), it2->getBlockSize())
/ 1024);
long long diffSize = it1->getTotalSpace() - it2->getTotalSpace();
long long diffUsed = it1->getUsedSpace() - it2->getUsedSpace();

if (diffSize < 0)
diffSize = 0 - diffSize;
if (diffUsed < 0)
diffUsed = 0 - diffUsed;

if ((diffSize <= bSize) && ((size_t)diffUsed <= fuzz))
{
it2->setFSysID(it1->getFSysID());

if (merge)
{
if (!it1->getHostname().contains(it2->getHostname()))
it1->setHostname(it1->getHostname()
+ "," + it2->getHostname());
it1->setPath(it1->getPath() + ","
+ it2->getHostname().section(".", 0, 0) + ":"
+ it2->getPath());
disks.erase(it2);
it2 = it1;
}
}
}
}
}

void FileSystemInfo::PopulateDiskSpace(void)
{
long long total = -1, used = -1;
getDiskSpace(getPath().toAscii().constData(), total, used);
setTotalSpace(total);
setUsedSpace(used);
}

void FileSystemInfo::PopulateFSProp(void)
{
struct statfs statbuf;
memset(&statbuf, 0, sizeof(statbuf));

if (!statfs(getPath().toLocal8Bit().constData(), &statbuf))
{
#if CONFIG_DARWIN
char *fstypename = statbuf.f_fstypename;
if ((!strcmp(fstypename, "nfs")) || // NFS|FTP
(!strcmp(fstypename, "afpfs")) || // AppleShare
(!strcmp(fstypename, "smbfs"))) // SMB
setLocal(false);
#elif __linux__
long fstype = statbuf.f_type;
if ((fstype == 0x6969) || // NFS
(fstype == 0x517B) || // SMB
(fstype == (long)0xFF534D42)) // CIFS
setLocal(false);
#endif
setBlockSize(statbuf.f_bsize);
}
}
80 changes: 80 additions & 0 deletions mythtv/libs/libmyth/filesysteminfo.h
@@ -0,0 +1,80 @@
#ifndef DISKINFO_H_
#define DISKINFO_H_
#define NUMDISKINFOLINES 8

using namespace std;

#include <QList>
#include <QString>
#include <QStringList>

#include "mythexp.h"
#include "mythsocket.h"
#include "mythcorecontext.h"

class MPUBLIC FileSystemInfo : public QObject
{
Q_OBJECT
public:
FileSystemInfo();
FileSystemInfo(const FileSystemInfo &other);
FileSystemInfo(QString hostname, QString path, bool local, int fsid,
int groupid, int blksize, long long total, long long used);
FileSystemInfo(QStringList::const_iterator &it,
QStringList::const_iterator end);
FileSystemInfo(const QStringList &slist);

~FileSystemInfo(void) {};

FileSystemInfo &operator=(const FileSystemInfo &other);
virtual void clone(const FileSystemInfo &other);
void clear(void);

// information gets
QString getHostname(void) const { return m_hostname; }
QString getPath(void) const { return m_path; }
bool isLocal(void) const { return m_local; }
int getFSysID(void) const { return m_fsid; }
int getGroupID(void) const { return m_grpid; }
int getBlockSize(void) const { return m_blksize; }
long long getTotalSpace(void) const { return m_total; }
long long getUsedSpace(void) const { return m_used; }
int getWeight(void) const { return m_weight; }

long long getFreeSpace(void) const { return m_total-m_used; }

// information puts
void setHostname(QString hostname) { m_hostname = hostname; }
void setPath(QString path) { m_path = path; }
void setLocal(bool local = true) { m_local = local; }
void setFSysID(int id) { m_fsid = id; }
void setGroupID(int id) { m_grpid = id; }
void setBlockSize(int size) { m_blksize = size; }
void setTotalSpace(long long size) { m_total = size; }
void setUsedSpace(long long size) { m_used = size; }
void setWeight(int weight) { m_weight = weight; }

bool ToStringList(QStringList &slist) const;

static const QList<FileSystemInfo> RemoteGetInfo(MythSocket *sock=NULL);
static void Consolidate(QList<FileSystemInfo> &disks, bool merge=true,
size_t fuzz=14000);
void PopulateDiskSpace(void);
void PopulateFSProp(void);

private:
bool FromStringList(const QStringList &slist);
bool FromStringList(QStringList::const_iterator &it,
QStringList::const_iterator listend);

QString m_hostname;
QString m_path;
bool m_local;
int m_fsid;
int m_grpid;
int m_blksize;
long long m_total;
long long m_used;
int m_weight;
};
#endif
4 changes: 3 additions & 1 deletion mythtv/libs/libmyth/libmyth.pro
Expand Up @@ -36,6 +36,7 @@ HEADERS += programinfo.h programinfoupdater.h
HEADERS += programtypes.h recordingtypes.h
HEADERS += mythrssmanager.h netgrabbermanager.h
HEADERS += rssparse.h netutils.h
HEADERS += filesysteminfo.h

# remove when everything is switched to mythui
HEADERS += virtualkeyboard_qt.h
Expand Down Expand Up @@ -65,6 +66,7 @@ SOURCES += programinfo.cpp programinfoupdater.cpp
SOURCES += programtypes.cpp recordingtypes.cpp
SOURCES += mythrssmanager.cpp netgrabbermanager.cpp
SOURCES += rssparse.cpp netutils.cpp
SOURCES += filesysteminfo.cpp

# remove when everything is switched to mythui
SOURCES += virtualkeyboard_qt.cpp
Expand Down Expand Up @@ -109,7 +111,7 @@ inc.files += visual.h volumebase.h output.h langsettings.h
inc.files += mythexp.h mythpluginapi.h storagegroupeditor.h
inc.files += mythconfigdialogs.h mythconfiggroups.h
inc.files += mythterminal.h
inc.files += remoteutil.h
inc.files += remoteutil.h filesysteminfo.h
inc.files += programinfo.h hardwareprofile.h
inc.files += programtypes.h recordingtypes.h
inc.files += mythrssmanager.h netgrabbermanager.h
Expand Down

0 comments on commit 65e877a

Please sign in to comment.