MythTV master
filesysteminfo.cpp
Go to the documentation of this file.
1#include "filesysteminfo.h"
2
3#include <QtGlobal>
4
5#include <algorithm>
6
7#include <QByteArray>
8#include <QStorageInfo>
9#include <QString>
10#include <QStringList>
11
12#include "mythcorecontext.h"
13#include "mythlogging.h"
14
16{
17 QStringList list;
18 list.reserve(kLines);
19 list << m_hostname;
20 list << m_path;
21 list << QString::number(m_local);
22 list << QString::number(m_fsid);
23 list << QString::number(m_grpid);
24 list << QString::number(m_blksize);
25 list << QString::number(m_total);
26 list << QString::number(m_used);
27
28 return list;
29}
30
31bool FileSystemInfo::ToStringList(QStringList &list) const
32{
33 list << ToStringList();
34
35 return true;
36}
37
38bool FileSystemInfo::FromStringList(const QStringList &slist)
39{
40 QStringList::const_iterator it = slist.cbegin();
41 return FromStringList(it, slist.cend());
42}
43
54bool FileSystemInfo::FromStringList(QStringList::const_iterator &it,
55 const QStringList::const_iterator& listend)
56{
57 if (std::distance(it, listend) < kLines)
58 {
59 LOG(VB_GENERAL, LOG_ALERT, QStringLiteral("FileSystemInfo::FromStringList, not enough items in list."));
60 clear();
61 it = listend;
62 return false;
63 }
64
65 m_hostname = *it; it++;
66 m_path = *it; it++;
67 m_local = (*it).toLongLong(); it++;
68 m_fsid = (*it).toLongLong(); it++;
69 m_grpid = (*it).toLongLong(); it++;
70 m_blksize = (*it).toLongLong(); it++;
71 m_total = (*it).toLongLong(); it++;
72 m_used = (*it).toLongLong(); it++;
73
74 m_weight = 0;
75
76 return true;
77}
78
80{
81 QStorageInfo info {m_path};
82
83 if (info.isValid() && info.isReady())
84 {
85 m_total = info.bytesTotal();
86 m_used = info.bytesTotal() - info.bytesAvailable();
87 m_blksize = info.blockSize();
88
89 // TODO keep as B not KiB
90 m_total >>= 10;
91 m_used >>= 10;
92
93#ifdef Q_OS_WIN
94 QByteArray device = info.device();
95 m_local = (device.startsWith(R"(\\?\)") && !device.startsWith(R"(\\?\UNC\)")) ||
96 (device.startsWith(R"(\\.\)") && !device.startsWith(R"(\\.\UNC\)"));
97#else // Unix-like
98 m_local = info.device().startsWith("/dev/");
99#endif
100 return true;
101 }
102 return false;
103}
104
105// default: sock = nullptr
107{
108 FileSystemInfoList fsInfos;
109 QStringList strlist(QStringLiteral("QUERY_FREE_SPACE_LIST"));
110
111 if ((sock != nullptr)
112 ? sock->SendReceiveStringList(strlist)
114 )
115 {
116 fsInfos = FileSystemInfoManager::FromStringList(strlist);
117 }
118
119 return fsInfos;
120}
121
122// O(n^2)
124 bool merge, int64_t fuzz,
125 const QString& total_name)
126{
127 int newid = 0;
128 int64_t total_total = 0;
129 int64_t total_used = 0;
130
131 for (
132#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
133 auto* it1 = disks.begin();
134#else
135 auto it1 = disks.begin();
136#endif
137 it1 != disks.end(); ++it1)
138 {
139 if (it1->getFSysID() == -1)
140 {
141 it1->setFSysID(newid++);
142 total_total += it1->getTotalSpace();
143 total_used += it1->getUsedSpace();
144 if (merge)
145 it1->setPath(it1->getHostname().section(".", 0, 0)
146 + ":" + it1->getPath());
147 }
148
149 for (
150#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
151 auto* it2 = it1+1;
152#else
153 auto it2 = it1+1;
154#endif
155 it2 != disks.end(); ++it2)
156 {
157 if (it2->getFSysID() != -1) // disk has already been matched
158 continue;
159
160 // almost certainly guaranteed to be 32 KiB
161 int bSize = std::max( {32 << 10, it1->getBlockSize(), it2->getBlockSize()} );
162 bSize >>= 10;
163 int64_t diffSize = std::abs(it1->getTotalSpace() - it2->getTotalSpace());
164 int64_t diffUsed = std::abs(it1->getUsedSpace() - it2->getUsedSpace());
165
166 if ((diffSize <= bSize) && (diffUsed <= fuzz))
167 {
168 it2->setFSysID(it1->getFSysID());
169
170 if (merge)
171 {
172 if (!it1->getHostname().contains(it2->getHostname()))
173 it1->setHostname(it1->getHostname()
174 + "," + it2->getHostname());
175 it1->setPath(it1->getPath() + ","
176 + it2->getHostname().section(".", 0, 0) + ":"
177 + it2->getPath());
178 disks.erase(it2);
179 it2 = it1;
180 }
181 }
182 }
183 }
184 if (!total_name.isEmpty())
185 {
186 disks.append(FileSystemInfo(total_name, "TotalDiskSpace", false, -2, -2,
187 0, total_total, total_used));
188 }
189}
190
192{
193 FileSystemInfoList fsInfos;
194 fsInfos.reserve((list.size() / FileSystemInfo::kLines) + 1);
195
196 QStringList::const_iterator it = list.cbegin();
197 while (it < list.cend())
198 {
199 fsInfos.push_back(FileSystemInfo(it, list.cend()));
200 }
201
202 return fsInfos;
203}
204
206{
207 QStringList strlist;
208 for (const auto & fsInfo : fsInfos)
209 {
210 strlist << fsInfo.ToStringList();
211 }
212 return strlist;
213}
int m_fsid
set by Consolidate
int m_grpid
set by setGroupID
static constexpr int kLines
number of strings in the serialized stringlist
bool m_local
set based on QStorageInfo::device()
int m_weight
set by setWeight
QStringList ToStringList() const
QString m_hostname
bool FromStringList(const QStringList &slist)
bool refresh()
update filesystem statistics by reading from the storage device
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:26
bool SendReceiveStringList(QStringList &list, uint min_reply_length=0, std::chrono::milliseconds timeoutMS=kLongTimeout)
Definition: mythsocket.cpp:326
QVector< FileSystemInfo > FileSystemInfoList
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MBASE_PUBLIC FileSystemInfoList GetInfoList(MythSocket *sock=nullptr)
MBASE_PUBLIC QStringList ToStringList(const FileSystemInfoList &fsInfos)
MBASE_PUBLIC FileSystemInfoList FromStringList(const QStringList &list)
MBASE_PUBLIC void Consolidate(FileSystemInfoList &disks, bool merge, int64_t fuzz, const QString &total_name={})
dictionary info
Definition: azlyrics.py:7