File indexing completed on 2024-04-28 04:18:52

0001 // vim: set tabstop=4 shiftwidth=4 expandtab:
0002 /*
0003 Gwenview: an image viewer
0004 Copyright 2008 Aurélien Gâteau <agateau@kde.org>
0005 Copyright (C) 2004-2005 by Enrico Ros <eros.kde@email.it>
0006 Copyright (C) 2004-2007 by Albert Astals Cid <aacid@kde.org>
0007 
0008 This program is free software; you can redistribute it and/or
0009 modify it under the terms of the GNU General Public License
0010 as published by the Free Software Foundation; either version 2
0011 of the License, or (at your option) any later version.
0012 
0013 This program is distributed in the hope that it will be useful,
0014 but WITHOUT ANY WARRANTY; without even the implied warranty of
0015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0016 GNU General Public License for more details.
0017 
0018 You should have received a copy of the GNU General Public License
0019 along with this program; if not, write to the Free Software
0020 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
0021 
0022 */
0023 // Self
0024 #include "memoryutils.h"
0025 
0026 // Qt
0027 #include <QFile>
0028 #include <QTextStream>
0029 #include <QTime>
0030 
0031 // System
0032 #ifdef Q_OS_WIN
0033 #define _WIN32_WINNT 0x0500
0034 #include <windows.h>
0035 #elif defined(Q_OS_FREEBSD)
0036 #include <sys/types.h>
0037 
0038 #include <sys/sysctl.h> // Must be included after sys/types.h
0039 #include <vm/vm_param.h>
0040 #endif
0041 
0042 namespace Gwenview
0043 {
0044 namespace MemoryUtils
0045 {
0046 // This code has been copied from okular/core/document.cpp
0047 qulonglong getTotalMemory()
0048 {
0049     static qulonglong cachedValue = 0;
0050     if (cachedValue)
0051         return cachedValue;
0052 
0053 #if defined(Q_OS_LINUX)
0054     // if /proc/meminfo doesn't exist, return 128MB
0055     QFile memFile(QStringLiteral("/proc/meminfo"));
0056     if (!memFile.open(QIODevice::ReadOnly))
0057         return (cachedValue = 134217728);
0058 
0059     QTextStream readStream(&memFile);
0060     while (true) {
0061         QString entry = readStream.readLine();
0062         if (entry.isNull())
0063             break;
0064         if (entry.startsWith(QLatin1String("MemTotal:")))
0065             return (cachedValue = (Q_UINT64_C(1024) * entry.section(QLatin1Char(' '), -2, -2).toULongLong()));
0066     }
0067 #elif defined(Q_OS_FREEBSD)
0068     qulonglong physmem;
0069     int mib[] = {CTL_HW, HW_PHYSMEM};
0070     size_t len = sizeof(physmem);
0071     if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
0072         return (cachedValue = physmem);
0073 #elif defined(Q_OS_WIN)
0074     MEMORYSTATUSEX stat;
0075     stat.dwLength = sizeof(stat);
0076     GlobalMemoryStatusEx(&stat);
0077 
0078     return (cachedValue = stat.ullTotalPhys);
0079 #endif
0080     return (cachedValue = 134217728);
0081 }
0082 
0083 qulonglong getFreeMemory()
0084 {
0085     static QTime lastUpdate = QTime::currentTime().addSecs(-3);
0086     static qulonglong cachedValue = 0;
0087 
0088     if (qAbs(lastUpdate.secsTo(QTime::currentTime())) <= 2)
0089         return cachedValue;
0090 
0091 #if defined(Q_OS_LINUX)
0092     // if /proc/meminfo doesn't exist, return MEMORY FULL
0093     QFile memFile(QStringLiteral("/proc/meminfo"));
0094     if (!memFile.open(QIODevice::ReadOnly))
0095         return 0;
0096 
0097     // read /proc/meminfo and sum up the contents of 'MemFree', 'Buffers'
0098     // and 'Cached' fields. consider swapped memory as used memory.
0099     qulonglong memoryFree = 0;
0100     QString entry;
0101     QTextStream readStream(&memFile);
0102     static const int nElems = 5;
0103     const QString names[nElems] = {QStringLiteral("MemFree:"),
0104                                    QStringLiteral("Buffers:"),
0105                                    QStringLiteral("Cached:"),
0106                                    QStringLiteral("SwapFree:"),
0107                                    QStringLiteral("SwapTotal:")};
0108     qulonglong values[nElems] = {0, 0, 0, 0, 0};
0109     bool foundValues[nElems] = {false, false, false, false, false};
0110     while (true) {
0111         entry = readStream.readLine();
0112         if (entry.isNull())
0113             break;
0114         for (int i = 0; i < nElems; ++i) {
0115             if (entry.startsWith(names[i])) {
0116                 values[i] = entry.section(QLatin1Char(' '), -2, -2).toULongLong(&foundValues[i]);
0117             }
0118         }
0119     }
0120     memFile.close();
0121     bool found = true;
0122     for (int i = 0; found && i < nElems; ++i)
0123         found = found && foundValues[i];
0124     if (found) {
0125         memoryFree = values[0] + values[1] + values[2] + values[3];
0126         if (values[4] > memoryFree)
0127             memoryFree = 0;
0128         else
0129             memoryFree -= values[4];
0130     }
0131 
0132     lastUpdate = QTime::currentTime();
0133 
0134     return (cachedValue = (Q_UINT64_C(1024) * memoryFree));
0135 #elif defined(Q_OS_FREEBSD)
0136     qulonglong cache, inact, free, psize;
0137     size_t cachelen, inactlen, freelen, psizelen;
0138     cachelen = sizeof(cache);
0139     inactlen = sizeof(inact);
0140     freelen = sizeof(free);
0141     psizelen = sizeof(psize);
0142     // sum up inactive, cached and free memory
0143     if (sysctlbyname("vm.stats.vm.v_cache_count", &cache, &cachelen, NULL, 0) == 0
0144         && sysctlbyname("vm.stats.vm.v_inactive_count", &inact, &inactlen, NULL, 0) == 0
0145         && sysctlbyname("vm.stats.vm.v_free_count", &free, &freelen, NULL, 0) == 0
0146         && sysctlbyname("vm.stats.vm.v_page_size", &psize, &psizelen, NULL, 0) == 0) {
0147         lastUpdate = QTime::currentTime();
0148         return (cachedValue = (cache + inact + free) * psize);
0149     } else {
0150         return 0;
0151     }
0152 #elif defined(Q_OS_WIN)
0153     MEMORYSTATUSEX stat;
0154     stat.dwLength = sizeof(stat);
0155     GlobalMemoryStatusEx(&stat);
0156 
0157     lastUpdate = QTime::currentTime();
0158 
0159     return (cachedValue = stat.ullAvailPhys);
0160 #else
0161     // tell the memory is full.. will act as in LOW profile
0162     return 0;
0163 #endif
0164 }
0165 
0166 } // MemoryUtils namespace
0167 
0168 } // Gwenview namespace