MythTV master
filesysteminfo.cpp
Go to the documentation of this file.
1#include "filesysteminfo.h"
2
3#include <QtGlobal>
4#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
5#include <QtSystemDetection>
6#endif
7
8#include <algorithm>
9
10#include <QByteArray>
11#include <QStorageInfo>
12#include <QString>
13#include <QStringList>
14
15#include "mythcorecontext.h"
16#include "mythlogging.h"
17
19{
20 QStringList list;
21 list.reserve(kLines);
22 list << m_hostname;
23 list << m_path;
24 list << QString::number(m_local);
25 list << QString::number(m_fsid);
26 list << QString::number(m_grpid);
27 list << QString::number(m_blksize);
28 list << QString::number(m_total);
29 list << QString::number(m_used);
30
31 return list;
32}
33
34bool FileSystemInfo::ToStringList(QStringList &list) const
35{
36 list << ToStringList();
37
38 return true;
39}
40
41bool FileSystemInfo::FromStringList(const QStringList &slist)
42{
43 QStringList::const_iterator it = slist.cbegin();
44 return FromStringList(it, slist.cend());
45}
46
57bool FileSystemInfo::FromStringList(QStringList::const_iterator &it,
58 const QStringList::const_iterator& listend)
59{
60 if (std::distance(it, listend) < kLines)
61 {
62 LOG(VB_GENERAL, LOG_ALERT, QStringLiteral("FileSystemInfo::FromStringList, not enough items in list."));
63 clear();
64 it = listend;
65 return false;
66 }
67
68 m_hostname = *it; it++;
69 m_path = *it; it++;
70 m_local = (*it).toLongLong(); it++;
71 m_fsid = (*it).toLongLong(); it++;
72 m_grpid = (*it).toLongLong(); it++;
73 m_blksize = (*it).toLongLong(); it++;
74 m_total = (*it).toLongLong(); it++;
75 m_used = (*it).toLongLong(); it++;
76
77 m_weight = 0;
78
79 return true;
80}
81
83{
84 QStorageInfo info {m_path};
85
86 if (info.isValid() && info.isReady())
87 {
88 m_total = info.bytesTotal();
89 m_used = info.bytesTotal() - info.bytesAvailable();
90 m_blksize = info.blockSize();
91
92 // TODO keep as B not KiB
93 m_total >>= 10;
94 m_used >>= 10;
95
96#ifdef Q_OS_WINDOWS
97 QByteArray device = info.device();
98 m_local = (device.startsWith(R"(\\?\)") && !device.startsWith(R"(\\?\UNC\)")) ||
99 (device.startsWith(R"(\\.\)") && !device.startsWith(R"(\\.\UNC\)"));
100#else // Unix-like
101 m_local = info.device().startsWith("/dev/");
102#endif
103 return true;
104 }
105 return false;
106}
107
108// default: sock = nullptr
110{
111 FileSystemInfoList fsInfos;
112 QStringList strlist(QStringLiteral("QUERY_FREE_SPACE_LIST"));
113
114 if ((sock != nullptr)
115 ? sock->SendReceiveStringList(strlist)
117 )
118 {
119 fsInfos = FileSystemInfoManager::FromStringList(strlist);
120 }
121
122 return fsInfos;
123}
124
125// O(n^2)
127 bool merge, int64_t fuzz,
128 const QString& total_name)
129{
130 int newid = 0;
131 int64_t total_total = 0;
132 int64_t total_used = 0;
133
134 for (
135#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
136 auto* it1 = disks.begin();
137#else
138 auto it1 = disks.begin();
139#endif
140 it1 != disks.end(); ++it1)
141 {
142 if (it1->getFSysID() == -1)
143 {
144 it1->setFSysID(newid++);
145 total_total += it1->getTotalSpace();
146 total_used += it1->getUsedSpace();
147 if (merge)
148 it1->setPath(it1->getHostname().section(".", 0, 0)
149 + ":" + it1->getPath());
150 }
151
152 for (
153#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
154 auto* it2 = it1+1;
155#else
156 auto it2 = it1+1;
157#endif
158 it2 != disks.end(); ++it2)
159 {
160 if (it2->getFSysID() != -1) // disk has already been matched
161 continue;
162
163 // almost certainly guaranteed to be 32 KiB
164 int bSize = std::max( {32 << 10, it1->getBlockSize(), it2->getBlockSize()} );
165 bSize >>= 10;
166 int64_t diffSize = std::abs(it1->getTotalSpace() - it2->getTotalSpace());
167 int64_t diffUsed = std::abs(it1->getUsedSpace() - it2->getUsedSpace());
168
169 if ((diffSize <= bSize) && (diffUsed <= fuzz))
170 {
171 it2->setFSysID(it1->getFSysID());
172
173 if (merge)
174 {
175 if (!it1->getHostname().contains(it2->getHostname()))
176 it1->setHostname(it1->getHostname()
177 + "," + it2->getHostname());
178 it1->setPath(it1->getPath() + ","
179 + it2->getHostname().section(".", 0, 0) + ":"
180 + it2->getPath());
181 disks.erase(it2);
182 it2 = it1;
183 }
184 }
185 }
186 }
187 if (!total_name.isEmpty())
188 {
189 disks.append(FileSystemInfo(total_name, "TotalDiskSpace", false, -2, -2,
190 0, total_total, total_used));
191 }
192}
193
195{
196 FileSystemInfoList fsInfos;
197 fsInfos.reserve((list.size() / FileSystemInfo::kLines) + 1);
198
199 QStringList::const_iterator it = list.cbegin();
200 while (it < list.cend())
201 {
202 fsInfos.push_back(FileSystemInfo(it, list.cend()));
203 }
204
205 return fsInfos;
206}
207
209{
210 QStringList strlist;
211 for (const auto & fsInfo : fsInfos)
212 {
213 strlist << fsInfo.ToStringList();
214 }
215 return strlist;
216}
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:330
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