common/Util.cpp                              |   40 +++--
 common/Util.hpp                              |    4 
 loleaflet/admin.strings.js                   |    2 
 loleaflet/dist/admin/adminAnalytics.html     |   36 +++-
 loleaflet/dist/admin/bootstrap/dashboard.css |   11 +
 loleaflet/src/admin/AdminSocketAnalytics.js  |  215 ++++++++++++++++++---------
 wsd/Admin.cpp                                |   28 +++
 wsd/Admin.hpp                                |    2 
 wsd/AdminModel.cpp                           |   25 +++
 wsd/AdminModel.hpp                           |    7 
 10 files changed, 282 insertions(+), 88 deletions(-)

New commits:
commit 9502741590d293155e7b3546654aa696b045362b
Author: Aditya Dewan <iit2015...@iiita.ac.in>
Date:   Tue Jun 6 06:47:42 2017 +0530

    tdf#107278 admin console: adding graph to track CPU load
    
    Change-Id: Idb07fe4139dd639a49ce1545cc15895f74876b06
    Reviewed-on: https://gerrit.libreoffice.org/38425
    Reviewed-by: pranavk <pran...@collabora.co.uk>
    Tested-by: pranavk <pran...@collabora.co.uk>

diff --git a/common/Util.cpp b/common/Util.cpp
index a94457e8..a61fe6d0 100644
--- a/common/Util.cpp
+++ b/common/Util.cpp
@@ -228,14 +228,38 @@ namespace Util
     size_t getMemoryUsageRSS(const Poco::Process::PID pid)
     {
         static const auto pageSizeBytes = getpagesize();
+        size_t rss = 0;
 
         if (pid > 0)
         {
+            rss = getStatFromPid(pid, 23);
+            rss *= pageSizeBytes;
+            rss /= 1024;
+            return rss;
+        }
+        return 0;
+    }
+
+    size_t getCpuUsage(const Poco::Process::PID pid)
+    {
+        if (pid > 0)
+        {
+            size_t totalJiffies = 0;
+            totalJiffies += getStatFromPid(pid, 13);
+            totalJiffies += getStatFromPid(pid, 14);
+            return totalJiffies;
+        }
+        return 0;
+    }
+
+    size_t getStatFromPid(const Poco::Process::PID pid, int ind)
+    {
+        if (pid > 0)
+        {
             const auto cmd = "/proc/" + std::to_string(pid) + "/stat";
             FILE* fp = fopen(cmd.c_str(), "r");
             if (fp != nullptr)
             {
-                size_t rss = 0;
                 char line[4096] = { 0 };
                 if (fgets(line, sizeof (line), fp))
                 {
@@ -244,25 +268,17 @@ namespace Util
                     auto pos = s.find(' ');
                     while (pos != std::string::npos)
                     {
-                        if (index == 23)
+                        if (index == ind)
                         {
-                            // Convert from memory pages to KB.
-                            rss = strtol(&s[pos], nullptr, 10);
-                            rss *= pageSizeBytes;
-                            rss /= 1024;
-                            break;
+                            fclose(fp);
+                            return strtol(&s[pos], nullptr, 10);
                         }
-
                         ++index;
                         pos = s.find(' ', pos + 1);
                     }
                 }
-
-                fclose(fp);
-                return rss;
             }
         }
-
         return 0;
     }
 
diff --git a/common/Util.hpp b/common/Util.hpp
index 0fbf794d..4f9906e9 100644
--- a/common/Util.hpp
+++ b/common/Util.hpp
@@ -105,6 +105,10 @@ namespace Util
     /// Example: "procmemstats: pid=123 rss=12400 pss=566"
     std::string getMemoryStats(FILE* file);
 
+    size_t getCpuUsage(const Poco::Process::PID pid);
+
+    size_t getStatFromPid(const Poco::Process::PID pid, int ind);
+
     std::string replace(std::string s, const std::string& a, const 
std::string& b);
 
     std::string formatLinesForLog(const std::string& s);
diff --git a/loleaflet/admin.strings.js b/loleaflet/admin.strings.js
index a38f9a0e..9bc38b29 100644
--- a/loleaflet/admin.strings.js
+++ b/loleaflet/admin.strings.js
@@ -25,6 +25,8 @@ l10nstrings.strIdleTime = _('Idle time');
 l10nstrings.strModified = _('Modified');
 l10nstrings.strKill = _('Kill');
 l10nstrings.strGraphs = _('Graphs');
+l10nstrings.strMemoryGraph = _('Memory Graph');
+l10nstrings.strCpuGraph = _('CPU Graph');
 l10nstrings.strSave = _('Save');
 l10nstrings.strMemoryStatsCachesize = _('Cache size of memory statistics');
 l10nstrings.strMemoryStatsInterval = _('Time interval of memory statistics (in 
ms)');
diff --git a/loleaflet/dist/admin/adminAnalytics.html 
b/loleaflet/dist/admin/adminAnalytics.html
index b905619b..10957f24 100644
--- a/loleaflet/dist/admin/adminAnalytics.html
+++ b/loleaflet/dist/admin/adminAnalytics.html
@@ -62,13 +62,35 @@
           </ul>
         </div>
         <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
-          <h1 
class="page-header"><script>document.write(l10nstrings.strGraphs)</script></h1>
-                       <div class="graph-container">
-                         <div class="jumbotron">
-                           <svg id="visualisation" width="1010" 
height="510"></svg>
-                         </div>
-                       </div>
-             </div>
+          <ul class="nav nav-tabs">
+            <li class="active">
+              <a href="#memview" data-toggle="tab">
+                
<h4><script>document.write(l10nstrings.strMemoryGraph)</script></h3>
+              </a>
+            </li>
+            <li>
+              <a href="#cpuview" data-toggle="tab">
+                
<h4><script>document.write(l10nstrings.strCpuGraph)</script></h3>
+              </a>
+            </li>
+          </ul>
+          <div class="tab-content graph-content">
+            <div id="memview" class="active tab-pane">
+              <div class="graph-container">
+                <div>
+                  <svg id="MemVisualisation" width="1010" height="510"></svg>
+                </div>
+              </div>
+            </div>
+            <div id="cpuview" class="tab-pane">
+              <div class="graph-container">
+                <div>
+                  <svg id="CpuVisualisation" width="1010" height="510"></svg>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
       </div>
     </div>
   </body>
diff --git a/loleaflet/dist/admin/bootstrap/dashboard.css 
b/loleaflet/dist/admin/bootstrap/dashboard.css
index cdf37a82..95d62235 100644
--- a/loleaflet/dist/admin/bootstrap/dashboard.css
+++ b/loleaflet/dist/admin/bootstrap/dashboard.css
@@ -138,4 +138,15 @@ tr:hover .dropdown-menu{
 }
 .doc_list_label{
   cursor: pointer;
+}
+
+/*
+ * Graph view buttons
+ */
+
+.nav-tabs > li.active > a{
+  background-color: #f5f5f5;
+}
+.graph-content {
+  background-color: #f5f5f5;
 }
\ No newline at end of file
diff --git a/loleaflet/src/admin/AdminSocketAnalytics.js 
b/loleaflet/src/admin/AdminSocketAnalytics.js
index 898063c0..b09348c2 100644
--- a/loleaflet/src/admin/AdminSocketAnalytics.js
+++ b/loleaflet/src/admin/AdminSocketAnalytics.js
@@ -19,22 +19,23 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
        _cpuStatsSize: 0,
        _cpuStatsInterval: 0,
 
-       _initMemStatsData: function(memStatsSize, memStatsInterval, reset) {
+       _initStatsData: function(option, size, interval, reset) {
+               var actualData;
+
                if (reset) {
-                       this._memStatsData = [];
+                       actualData = [];
                }
 
-               var offset = this._memStatsData.length * memStatsInterval;
-               for (var i = 0; i < memStatsSize; i++) {
-                       this._memStatsData.unshift({time: -(offset), value: 0});
-                       offset += memStatsInterval;
+               var offset = actualData.length * interval;
+               for (var i = 0; i < size; i++) {
+                       actualData.unshift({time: -(offset), value: 0});
+                       offset += interval;
                }
-       },
 
-       _initCpuStatsData: function() {
-               for (var i = 0; i < this._cpuStatsSize; i++) {
-                       this._cpuStatsData.push({time: -((this._cpuStatsSize - 
i - 1) * this._cpuStatsInterval), value: 0});
-               }
+               if (option === 'mem')
+                       this._memStatsData = actualData;
+               else if (option === 'cpu')
+                       this._cpuStatsData = actualData;
        },
 
        onSocketOpen: function() {
@@ -44,19 +45,20 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                this.socket.send('subscribe mem_stats cpu_stats settings');
                this.socket.send('settings');
                this.socket.send('mem_stats');
+               this.socket.send('cpu_stats');
        },
 
-       _createMemData: function() {
-               for (var i = this._memStatsRawData.length - 1, j = 
this._memStatsData.length - 1; i >= 0 && j >= 0; i--, j--) {
-                       this._memStatsData[j].value = 
parseInt(this._memStatsRawData[i]);
-               }
-       },
+       _d3MemXAxis: null,
+       _d3MemYAxis: null,
+       _d3MemLine: null,
+       _xMemScale: null,
+       _yMemScale: null,
 
-       _d3xAxis: null,
-       _d3yAxis: null,
-       _d3line: null,
-       _xScale: null,
-       _yScale: null,
+       _d3CpuXAxis: null,
+       _d3CpuYAxis: null,
+       _d3CpuLine: null,
+       _xCpuScale: null,
+       _yCpuScale: null,
 
        _graphWidth: 1000,
        _graphHeight: 500,
@@ -67,22 +69,28 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                left: 100
        },
 
-       _setUpAxis: function() {
-               this._xScale = 
d3.scale.linear().range([this._graphMargins.left, this._graphWidth - 
this._graphMargins.right]).domain([d3.min(this._memStatsData, function(d) {
+       _setUpAxis: function(option) {
+
+               if (option === 'mem')
+                       data = this._memStatsData;
+               else if (option === 'cpu')
+                       data = this._cpuStatsData;
+
+               xScale = d3.scale.linear().range([this._graphMargins.left, 
this._graphWidth - this._graphMargins.right]).domain([d3.min(data, function(d) {
                        return d.time;
-               }), d3.max(this._memStatsData, function(d) {
+               }), d3.max(data, function(d) {
                        return d.time;
                })]);
 
 
-               this._yScale = d3.scale.linear().range([this._graphHeight - 
this._graphMargins.bottom, 
this._graphMargins.top]).domain([d3.min(this._memStatsData, function(d) {
+               yScale = d3.scale.linear().range([this._graphHeight - 
this._graphMargins.bottom, this._graphMargins.top]).domain([d3.min(data, 
function(d) {
                        return d.value;
-               }), d3.max(this._memStatsData, function(d) {
+               }), d3.max(data, function(d) {
                        return d.value;
                })]);
 
-               this._d3xAxis = d3.svg.axis()
-                       .scale(this._xScale)
+               d3XAxis = d3.svg.axis()
+                       .scale(xScale)
                        .tickFormat(function(d) {
                                d = Math.abs(d / 1000);
                                var units = ['s', 'min', 'hr'];
@@ -92,76 +100,120 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                                return parseInt(d) + units[i] + ' ago';
                        });
 
-               this._d3yAxis = d3.svg.axis()
-                       .scale(this._yScale)
-                       .tickFormat(function (d) {
-                               return Util.humanizeMem(d);
-                       })
-                       .orient('left');
-
-               var xScale = this._xScale;
-               var yScale = this._yScale;
-
-               this._d3line = d3.svg.line()
+               d3Line = d3.svg.line()
                        .x(function(d) {
                                return xScale(d.time);
                        })
                        .y(function(d) {
                                return yScale(d.value);
-                       });
+                       })
+                       .interpolate('basis');
+
+               if (option === 'mem') {
+                       this._xMemScale = xScale;
+                       this._yMemScale = yScale;
+                       this._d3MemXAxis = d3XAxis;
+                       this._d3MemYAxis = d3.svg.axis()
+                               .scale(this._yMemScale)
+                               .tickFormat(function (d) {
+                                       return Util.humanizeMem(d);
+                               })
+                               .orient('left');
+                       this._d3MemLine = d3Line;
+               }
+               else if (option === 'cpu') {
+                       this._xCpuScale = xScale;
+                       this._yCpuScale = yScale;
+                       this._d3CpuXAxis = d3XAxis;
+                       this._d3CpuYAxis = d3.svg.axis()
+                               .scale(this._yCpuScale)
+                               .tickFormat(function (d) {
+                                       return d + '%';
+                               })
+                               .orient('left');
+                       this._d3CpuLine = d3Line;
+               }
        },
 
-       _createMemGraph: function() {
-               var vis = d3.select('#visualisation');
-
-               this._setUpAxis();
+       _createGraph: function(option) {
+               if (option === 'mem') {
+                       var vis = d3.select('#MemVisualisation');
+                       this._setUpAxis('mem');
+                       xAxis = this._d3MemXAxis;
+                       yAxis = this._d3MemYAxis;
+                       line = this._d3MemLine;
+                       data = this._memStatsData;
+               }
+               else if (option === 'cpu') {
+                       var vis = d3.select('#CpuVisualisation');
+                       this._setUpAxis('cpu');
+                       xAxis = this._d3CpuXAxis;
+                       yAxis = this._d3CpuYAxis;
+                       line = this._d3CpuLine;
+                       data = this._cpuStatsData;
+               }
 
                vis.append('svg:g')
                .attr('class', 'x-axis')
                .attr('transform', 'translate(0,' + (this._graphHeight - 
this._graphMargins.bottom) + ')')
-               .call(this._d3xAxis);
+               .call(xAxis);
 
                vis.append('svg:g')
                .attr('class', 'y-axis')
                .attr('transform', 'translate(' + this._graphMargins.left + 
',0)')
-               .call(this._d3yAxis);
+               .call(yAxis);
 
                vis.append('svg:path')
-                       .attr('d', this._d3line(this._memStatsData))
+                       .attr('d', line(data))
                        .attr('class', 'line')
                        .attr('stroke', 'blue')
                        .attr('stroke-width', 2)
                        .attr('fill', 'none');
        },
 
-       _addNewMemData: function(data) {
+       _addNewData: function(oldData, newData) {
                // make a space for new data
-               for (var i = this._memStatsData.length - 1; i > 0; i--) {
-                       this._memStatsData[i].time = this._memStatsData[i - 
1].time;
+               for (var i = oldData.length - 1; i > 0; i--) {
+                       oldData[i].time = oldData[i - 1].time;
                }
 
                // push new data at time '0'
-               this._memStatsData.push({time: 0, value: parseInt(data)});
+               oldData.push({time: 0, value: parseInt(newData)});
 
                // remove extra items
-               if (this._memStatsData.length > this._memStatsSize) {
-                       this._memStatsData.shift();
+               if (oldData.length > this._memStatsSize) {
+                       oldData.shift();
                }
        },
 
        _updateMemGraph: function() {
-               var svg = d3.select('#visualisation');
+               svg = d3.select('#MemVisualisation');
+
+               this._setUpAxis('mem');
+
+               svg.select('.line')
+               .attr('d', this._d3MemLine(this._memStatsData));
+
+               svg.select('.x-axis')
+               .call(this._d3MemXAxis);
+
+               svg.select('.y-axis')
+               .call(this._d3MemYAxis);
+       },
+
+       _updateCpuGraph: function() {
+               svg = d3.select('#CpuVisualisation');
 
-               this._setUpAxis();
+               this._setUpAxis('cpu');
 
                svg.select('.line')
-               .attr('d', this._d3line(this._memStatsData));
+               .attr('d', this._d3CpuLine(this._cpuStatsData));
 
                svg.select('.x-axis')
-               .call(this._d3xAxis);
+               .call(this._d3CpuXAxis);
 
                svg.select('.y-axis')
-               .call(this._d3yAxis);
+               .call(this._d3CpuYAxis);
        },
 
        onSocketMessage: function(e) {
@@ -173,12 +225,10 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                        textMsg = '';
                }
 
-
                if (textMsg.startsWith('settings')) {
                        textMsg = textMsg.substring('settings '.length);
                        textMsg = textMsg.split(' ');
 
-                       //TODO: Add CPU statistics
                        var memStatsSize, memStatsInterval, cpuStatsSize, 
cpuStatsInterval;
                        var i, j, data;
                        memStatsSize = this._memStatsSize;
@@ -204,10 +254,10 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                        // Fix the axes according to changed data
                        if (memStatsInterval !== this._memStatsInterval) {
                                // We can possibly reuse the data with a bit of 
work
-                               this._initMemStatsData(memStatsSize, 
memStatsInterval, true);
+                               this._initStatsData('mem', memStatsSize, 
memStatsInterval, true);
                        }
                        else if (memStatsSize > this._memStatsSize) {
-                               this._initMemStatsData(memStatsSize - 
this._memStatsSize, memStatsInterval, false);
+                               this._initStatsData('mem', memStatsSize - 
this._memStatsSize, memStatsInterval, false);
                        }
                        else {
                                // just strip the extra items
@@ -218,11 +268,24 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
 
                        this._memStatsSize = memStatsSize;
                        this._memStatsInterval = memStatsInterval;
+
+                       // Similar Logic as above for CPU stats
+                       if (cpuStatsInterval !== this._cpuStatsInterval) {
+                               this._initStatsData('cpu', cpuStatsSize, 
cpuStatsInterval, true);
+                       }
+                       else if (cpuStatsSize > this._cpuStatsSize) {
+                               this._initStatsData('cpu', cpuStatsSize - 
this._cpuStatsSize, cpuStatsInterval, false);
+                       }
+                       else {
+                               for (i = 0; i < this._cpuStatsSize - 
cpuStatsSize; i++) {
+                                       this._cpuStatsData.shift();
+                               }
+                       }
+
                        this._cpuStatsSize = cpuStatsSize;
                        this._cpuStatsInterval = cpuStatsInterval;
                }
-               else if (textMsg.startsWith('mem_stats') ||
-                       textMsg.startsWith('cpu_stats')) {
+               else if (textMsg.startsWith('mem_stats')) {
                        textMsg = textMsg.split(' ')[1];
                        if (textMsg.endsWith(',')) {
                                // This is the result of query, not notification
@@ -231,16 +294,34 @@ var AdminSocketAnalytics = AdminSocketBase.extend({
                                        this._memStatsData[i].value = 
parseInt(data[j]);
                                }
 
-                               //this._createMemData(data);
-                               this._createMemGraph();
+                               this._createGraph('mem');
                        }
                        else {
                                // this is a notification data; append to 
_memStatsData
                                data = textMsg.trim();
-                               this._addNewMemData(data);
+                               this._addNewData(this._memStatsData, data);
                                this._updateMemGraph();
                        }
                }
+               else if (textMsg.startsWith('cpu_stats')) {
+                       textMsg = textMsg.split(' ')[1];
+                       if (textMsg.endsWith(',')) {
+                               // This is the result of query, not notification
+                               data = textMsg.substring(0, textMsg.length - 
1).split(',');
+
+                               for (i = this._cpuStatsData.length - 1, j = 
data.length - 1; i >= 0 && j >= 0; i--, j--) {
+                                       this._cpuStatsData[i].value = 
parseInt(data[j]);
+                               }
+
+                               this._createGraph('cpu');
+                       }
+                       else {
+                               // this is a notification data; append to 
_cpuStatsData
+                               data = textMsg.trim();
+                               this._addNewData(this._cpuStatsData, data);
+                               this._updateCpuGraph();
+                       }
+               }
        },
 
        onSocketClose: function() {
diff --git a/wsd/Admin.cpp b/wsd/Admin.cpp
index 1c15aa1d..425a352d 100644
--- a/wsd/Admin.cpp
+++ b/wsd/Admin.cpp
@@ -12,6 +12,7 @@
 #include <cassert>
 #include <mutex>
 #include <sys/poll.h>
+#include <unistd.h>
 
 #include <Poco/Net/HTTPCookie.h>
 #include <Poco/Net/HTTPRequest.h>
@@ -298,8 +299,9 @@ Admin::Admin() :
     _model(AdminModel()),
     _forKitPid(-1),
     _lastTotalMemory(0),
+    _lastJiffies(0),
     _memStatsTaskIntervalMs(5000),
-    _cpuStatsTaskIntervalMs(5000)
+    _cpuStatsTaskIntervalMs(2000)
 {
     LOG_INF("Admin ctor.");
 
@@ -327,9 +329,13 @@ void Admin::pollingThread()
         std::chrono::steady_clock::time_point now = 
std::chrono::steady_clock::now();
         int cpuWait = _cpuStatsTaskIntervalMs -
             std::chrono::duration_cast<std::chrono::milliseconds>(now - 
lastCPU).count();
+
+        size_t currentJiffies = getTotalCpuUsage();
         if (cpuWait <= 0)
         {
-            // TODO: implement me ...
+            auto cpuPercent = 100 * 1000 * currentJiffies / (sysconf 
(_SC_CLK_TCK) * _cpuStatsTaskIntervalMs);
+            _model.addCpuStats(cpuPercent);
+
             lastCPU = now;
             cpuWait += _cpuStatsTaskIntervalMs;
         }
@@ -408,6 +414,24 @@ size_t Admin::getTotalMemoryUsage()
     return totalMem;
 }
 
+size_t Admin::getTotalCpuUsage()
+{
+    const size_t forkitJ = Util::getCpuUsage(_forKitPid);
+    const size_t wsdJ = Util::getCpuUsage(Poco::Process::id());
+    const size_t kitsJ = _model.getKitsJiffies();
+
+    if(_lastJiffies == 0)
+    {
+        _lastJiffies = forkitJ + wsdJ;
+        return 0;
+    }
+
+    const size_t totalJ = ((forkitJ + wsdJ) - _lastJiffies) + kitsJ;
+    _lastJiffies = forkitJ + wsdJ;
+
+    return totalJ;
+}
+
 unsigned Admin::getMemStatsInterval()
 {
     return _memStatsTaskIntervalMs;
diff --git a/wsd/Admin.hpp b/wsd/Admin.hpp
index 2c77e391..91df8108 100644
--- a/wsd/Admin.hpp
+++ b/wsd/Admin.hpp
@@ -70,6 +70,7 @@ public:
     void pollingThread() override;
 
     size_t getTotalMemoryUsage();
+    size_t getTotalCpuUsage();
 
     void modificationAlert(const std::string& dockey, Poco::Process::PID pid, 
bool value);
     /// Update the Admin Model.
@@ -109,6 +110,7 @@ private:
     AdminModel _model;
     int _forKitPid;
     size_t _lastTotalMemory;
+    size_t _lastJiffies;
 
     std::atomic<int> _memStatsTaskIntervalMs;
     std::atomic<int> _cpuStatsTaskIntervalMs;
diff --git a/wsd/AdminModel.cpp b/wsd/AdminModel.cpp
index 1ee088eb..bcbdd1d1 100644
--- a/wsd/AdminModel.cpp
+++ b/wsd/AdminModel.cpp
@@ -271,6 +271,31 @@ unsigned AdminModel::getKitsMemoryUsage()
     return totalMem;
 }
 
+size_t AdminModel::getKitsJiffies()
+{
+    assertCorrectThread();
+
+    size_t totalJ = 0;
+    for (auto& it : _documents)
+    {
+        if (!it.second.isExpired())
+        {
+            const auto pid = it.second.getPid();
+            if (pid > 0)
+            {
+                unsigned newJ = Util::getCpuUsage(pid);
+                unsigned prevJ = it.second.getLastJiffies();
+                if(newJ >= prevJ)
+                {
+                    totalJ += (newJ - prevJ);
+                    it.second.setLastJiffies(newJ);
+                }
+            }
+        }
+    }
+    return totalJ;
+}
+
 void AdminModel::subscribe(int sessionId, const 
std::weak_ptr<WebSocketHandler>& ws)
 {
     assertCorrectThread();
diff --git a/wsd/AdminModel.hpp b/wsd/AdminModel.hpp
index ed83d8cd..90716964 100644
--- a/wsd/AdminModel.hpp
+++ b/wsd/AdminModel.hpp
@@ -54,6 +54,7 @@ public:
           _pid(pid),
           _filename(filename),
           _memoryDirty(0),
+          _lastJiffy(0),
           _start(std::time(nullptr)),
           _lastActivity(_start),
           _sentBytes(0),
@@ -77,6 +78,9 @@ public:
 
     unsigned getActiveViews() const { return _activeViews; }
 
+    unsigned getLastJiffies() const { return _lastJiffy; }
+    void setLastJiffies(size_t newJ) { _lastJiffy = newJ; }
+
     const std::map<std::string, View>& getViews() const { return _views; }
 
     void updateLastActivityTime() { _lastActivity = std::time(nullptr); }
@@ -110,6 +114,8 @@ private:
     std::string _filename;
     /// The dirty (ie. un-shared) memory of the document's Kit process.
     int _memoryDirty;
+    /// Last noted Jiffy count
+    unsigned _lastJiffy;
 
     std::time_t _start;
     std::time_t _lastActivity;
@@ -184,6 +190,7 @@ public:
 
     /// Returns memory consumed by all active loolkit processes
     unsigned getKitsMemoryUsage();
+    size_t getKitsJiffies();
 
     void subscribe(int sessionId, const std::weak_ptr<WebSocketHandler>& ws);
     void subscribe(int sessionId, const std::string& command);
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to