2014-04-09 21:01:57 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
|
|
|
*
|
|
|
|
* SleepLib Machine Class Implementation
|
|
|
|
*
|
|
|
|
* Copyright (c) 2011-2014 Mark Watkins <jedimark@users.sourceforge.net>
|
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
|
|
* License. See the file COPYING in the main directory of the Linux
|
|
|
|
* distribution for more details. */
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2011-07-30 00:36:31 +00:00
|
|
|
#include <QApplication>
|
2011-07-01 10:10:44 +00:00
|
|
|
#include <QDir>
|
|
|
|
#include <QProgressBar>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QString>
|
|
|
|
#include <QObject>
|
2014-05-21 00:17:31 +00:00
|
|
|
#include <QThreadPool>
|
|
|
|
|
2011-12-17 15:12:35 +00:00
|
|
|
#include <time.h>
|
2011-07-31 20:24:43 +00:00
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
#include "machine.h"
|
|
|
|
#include "profiles.h"
|
|
|
|
#include <algorithm>
|
2011-09-17 12:39:00 +00:00
|
|
|
#include "SleepLib/schema.h"
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
extern QProgressBar *qprogress;
|
2011-06-26 08:30:44 +00:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Machine Base-Class implmementation
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2014-07-11 12:09:38 +00:00
|
|
|
Machine::Machine(MachineID id)
|
2011-06-26 08:30:44 +00:00
|
|
|
{
|
|
|
|
day.clear();
|
2014-04-17 05:58:57 +00:00
|
|
|
highest_sessionid = 0;
|
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
if (!id) {
|
2014-04-23 13:19:56 +00:00
|
|
|
srand(time(nullptr));
|
2011-06-26 08:30:44 +00:00
|
|
|
MachineID temp;
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
do {
|
2011-12-17 14:50:59 +00:00
|
|
|
temp = rand();
|
2014-07-11 12:09:38 +00:00
|
|
|
} while (p_profile->machlist.find(temp) != p_profile->machlist.end());
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
m_id = temp;
|
|
|
|
|
|
|
|
} else { m_id = id; }
|
2014-08-03 13:00:13 +00:00
|
|
|
m_loader = nullptr;
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-07-28 13:56:29 +00:00
|
|
|
// qDebug() << "Create Machine: " << hex << m_id; //%lx",m_id);
|
2014-04-17 05:58:57 +00:00
|
|
|
m_type = MT_UNKNOWN;
|
|
|
|
firstsession = true;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
Machine::~Machine()
|
|
|
|
{
|
2014-07-28 13:56:29 +00:00
|
|
|
qDebug() << "Destroy Machine" << info.loadername << hex << m_id;
|
2014-04-17 05:58:57 +00:00
|
|
|
|
|
|
|
for (QMap<QDate, Day *>::iterator d = day.begin(); d != day.end(); d++) {
|
2011-07-31 20:24:43 +00:00
|
|
|
delete d.value();
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Session *Machine::SessionExists(SessionID session)
|
|
|
|
{
|
2014-04-17 05:58:57 +00:00
|
|
|
if (sessionlist.find(session) != sessionlist.end()) {
|
2011-06-26 08:30:44 +00:00
|
|
|
return sessionlist[session];
|
|
|
|
} else {
|
2014-04-23 13:19:56 +00:00
|
|
|
return nullptr;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
}
|
2011-07-22 13:46:17 +00:00
|
|
|
|
2011-12-30 23:02:45 +00:00
|
|
|
// Find date this session belongs in
|
|
|
|
QDate Machine::pickDate(qint64 first)
|
|
|
|
{
|
2014-07-11 12:09:38 +00:00
|
|
|
QTime split_time = p_profile->session->daySplitTime();
|
|
|
|
int combine_sessions = p_profile->session->combineCloseSessions();
|
2011-12-30 23:02:45 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QDateTime d2 = QDateTime::fromTime_t(first / 1000);
|
2011-12-30 23:02:45 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QDate date = d2.date();
|
|
|
|
QTime time = d2.time();
|
2011-12-30 23:02:45 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
int closest_session = 0;
|
2011-12-30 23:02:45 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
if (time < split_time) {
|
|
|
|
date = date.addDays(-1);
|
2011-12-30 23:02:45 +00:00
|
|
|
} else if (combine_sessions > 0) {
|
2014-04-17 05:58:57 +00:00
|
|
|
QMap<QDate, Day *>::iterator dit = day.find(date.addDays(-1)); // Check Day Before
|
|
|
|
|
2011-12-30 23:02:45 +00:00
|
|
|
if (dit != day.end()) {
|
2014-04-17 05:58:57 +00:00
|
|
|
QDateTime lt = QDateTime::fromTime_t(dit.value()->last() / 1000L);
|
|
|
|
closest_session = lt.secsTo(d2) / 60;
|
|
|
|
|
2011-12-30 23:02:45 +00:00
|
|
|
if (closest_session < combine_sessions) {
|
2014-04-17 05:58:57 +00:00
|
|
|
date = date.addDays(-1);
|
2011-12-30 23:02:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return date;
|
|
|
|
}
|
|
|
|
|
2014-07-11 12:09:38 +00:00
|
|
|
bool Machine::AddSession(Session *s)
|
2011-06-26 08:30:44 +00:00
|
|
|
{
|
2014-05-20 11:51:47 +00:00
|
|
|
Q_ASSERT(s != nullptr);
|
2014-07-15 07:01:47 +00:00
|
|
|
Q_ASSERT(p_profile);
|
|
|
|
Q_ASSERT(p_profile->isOpen());
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-07-11 12:09:38 +00:00
|
|
|
if (p_profile->session->ignoreOlderSessions()) {
|
|
|
|
qint64 ignorebefore = p_profile->session->ignoreOlderSessionsDate().toMSecsSinceEpoch();
|
2014-05-19 07:30:10 +00:00
|
|
|
if (s->last() < ignorebefore) {
|
|
|
|
skipped_sessions++;
|
2014-05-20 11:51:47 +00:00
|
|
|
return false;
|
2014-05-19 07:30:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
if (s->session() > highest_sessionid) {
|
|
|
|
highest_sessionid = s->session();
|
|
|
|
}
|
2011-08-01 08:22:37 +00:00
|
|
|
|
2014-07-30 20:25:06 +00:00
|
|
|
QTime split_time;
|
|
|
|
int combine_sessions;
|
|
|
|
bool locksessions = p_profile->session->lockSummarySessions();
|
|
|
|
|
|
|
|
if (locksessions) {
|
|
|
|
split_time = s->summaryOnly() ? QTime(12,0,0) : p_profile->session->daySplitTime();
|
|
|
|
combine_sessions = s->summaryOnly() ? 0 : p_profile->session->combineCloseSessions();
|
|
|
|
} else {
|
|
|
|
split_time = p_profile->session->daySplitTime();
|
|
|
|
combine_sessions = p_profile->session->combineCloseSessions();
|
|
|
|
}
|
2011-07-03 06:47:23 +00:00
|
|
|
|
2014-07-30 20:25:06 +00:00
|
|
|
int ignore_sessions = p_profile->session->ignoreShortSessions();
|
2014-05-04 18:23:38 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
int session_length = s->last() - s->first();
|
|
|
|
session_length /= 60000;
|
|
|
|
|
|
|
|
sessionlist[s->session()] = s; // To make sure it get's saved later even if it's not wanted.
|
2011-07-03 08:08:14 +00:00
|
|
|
|
2014-07-11 12:09:38 +00:00
|
|
|
//int drift=p_profile->cpap->clockDrift();
|
2012-01-19 15:18:34 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QDateTime d2 = QDateTime::fromTime_t(s->first() / 1000);
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QDate date = d2.date();
|
|
|
|
QTime time = d2.time();
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QMap<QDate, Day *>::iterator dit, nextday;
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
bool combine_next_day = false;
|
|
|
|
int closest_session = 0;
|
2011-07-03 03:38:55 +00:00
|
|
|
|
2014-07-30 20:25:06 +00:00
|
|
|
|
|
|
|
// Multithreaded import screws this up. :(
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
if (time < split_time) {
|
|
|
|
date = date.addDays(-1);
|
2011-08-05 07:52:32 +00:00
|
|
|
} else if (combine_sessions > 0) {
|
2014-04-17 05:58:57 +00:00
|
|
|
dit = day.find(date.addDays(-1)); // Check Day Before
|
|
|
|
|
|
|
|
if (dit != day.end()) {
|
|
|
|
QDateTime lt = QDateTime::fromTime_t(dit.value()->last() / 1000);
|
|
|
|
closest_session = lt.secsTo(d2) / 60;
|
|
|
|
|
|
|
|
if (closest_session < combine_sessions) {
|
|
|
|
date = date.addDays(-1);
|
2014-07-30 20:25:06 +00:00
|
|
|
} else {
|
|
|
|
if ((split_time < time) && (split_time.secsTo(time) < 2)) {
|
|
|
|
if (s->machine()->loaderName() == STR_MACH_ResMed) {
|
|
|
|
date = date.addDays(-1);
|
|
|
|
}
|
|
|
|
}
|
2011-08-05 07:52:32 +00:00
|
|
|
}
|
|
|
|
} else {
|
2014-04-17 05:58:57 +00:00
|
|
|
nextday = day.find(date.addDays(1)); // Check Day Afterwards
|
|
|
|
|
|
|
|
if (nextday != day.end()) {
|
|
|
|
QDateTime lt = QDateTime::fromTime_t(nextday.value()->first() / 1000);
|
|
|
|
closest_session = d2.secsTo(lt) / 60;
|
|
|
|
|
2011-08-05 07:52:32 +00:00
|
|
|
if (closest_session < combine_sessions) {
|
|
|
|
// add todays here. pull all tomorrows records to this date.
|
2014-04-17 05:58:57 +00:00
|
|
|
combine_next_day = true;
|
2011-08-05 07:52:32 +00:00
|
|
|
}
|
2011-07-03 08:08:14 +00:00
|
|
|
}
|
|
|
|
}
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
if (session_length < ignore_sessions) {
|
2014-05-19 07:30:10 +00:00
|
|
|
// keep the session to save importing it again, but don't add it to the day record this time
|
2014-05-20 11:51:47 +00:00
|
|
|
return true;
|
2011-08-05 08:41:45 +00:00
|
|
|
}
|
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
if (!firstsession) {
|
2014-04-17 05:58:57 +00:00
|
|
|
if (firstday > date) { firstday = date; }
|
|
|
|
|
|
|
|
if (lastday < date) { lastday = date; }
|
2011-06-26 08:30:44 +00:00
|
|
|
} else {
|
2014-04-17 05:58:57 +00:00
|
|
|
firstday = lastday = date;
|
|
|
|
firstsession = false;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
2011-07-03 08:08:14 +00:00
|
|
|
|
2011-08-01 08:22:37 +00:00
|
|
|
|
2014-04-23 13:19:56 +00:00
|
|
|
Day *dd = nullptr;
|
2014-04-17 05:58:57 +00:00
|
|
|
dit = day.find(date);
|
|
|
|
|
|
|
|
if (dit == day.end()) {
|
2011-07-02 14:35:50 +00:00
|
|
|
//QString dstr=date.toString("yyyyMMdd");
|
2013-01-17 18:26:11 +00:00
|
|
|
//qDebug("Adding Profile Day %s",dstr.toLatin1().data());
|
2014-04-17 05:58:57 +00:00
|
|
|
dd = new Day(this);
|
|
|
|
day[date] = dd;
|
2011-06-26 08:30:44 +00:00
|
|
|
// Add this Day record to profile
|
2014-07-11 12:09:38 +00:00
|
|
|
p_profile->AddDay(date, dd, m_type);
|
2011-08-01 08:22:37 +00:00
|
|
|
} else {
|
2014-04-17 05:58:57 +00:00
|
|
|
dd = *dit;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2011-08-01 08:22:37 +00:00
|
|
|
dd->AddSession(s);
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2011-08-05 07:52:32 +00:00
|
|
|
if (combine_next_day) {
|
2014-04-17 05:58:57 +00:00
|
|
|
for (QList<Session *>::iterator i = nextday.value()->begin(); i != nextday.value()->end(); i++) {
|
2014-07-25 07:53:48 +00:00
|
|
|
// i may need to do something here
|
2014-07-30 20:25:06 +00:00
|
|
|
if (locksessions && (*i)->summaryOnly()) continue; // can't move summary only sessions..
|
2014-07-25 07:53:48 +00:00
|
|
|
unlinkSession(*i);
|
2014-07-26 12:46:11 +00:00
|
|
|
// Add it back
|
|
|
|
|
|
|
|
sessionlist[(*i)->session()] = *i;
|
|
|
|
|
2011-08-05 07:52:32 +00:00
|
|
|
dd->AddSession(*i);
|
|
|
|
}
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2014-07-25 07:53:48 +00:00
|
|
|
// QMap<QDate, QList<Day *> >::iterator nd = p_profile->daylist.find(date.addDays(1));
|
|
|
|
// if (nd != p_profile->daylist.end()) {
|
|
|
|
// p_profile->unlinkDay(nd.key(), nd.value());
|
|
|
|
// }
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2014-07-25 07:53:48 +00:00
|
|
|
// QList<Day *>::iterator iend = nd.value().end();
|
|
|
|
// for (QList<Day *>::iterator i = nd.value()->begin(); i != iend; ++i) {
|
|
|
|
// if (*i == nextday.value()) {
|
|
|
|
// nd.value().erase(i);
|
|
|
|
// }
|
|
|
|
// }
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2014-07-25 07:53:48 +00:00
|
|
|
// day.erase(nextday);
|
2011-08-05 07:52:32 +00:00
|
|
|
}
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2014-05-20 11:51:47 +00:00
|
|
|
return true;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
|
2014-07-25 07:53:48 +00:00
|
|
|
bool Machine::unlinkDay(Day * d)
|
|
|
|
{
|
|
|
|
return day.remove(day.key(d)) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Machine::unlinkSession(Session * sess)
|
|
|
|
{
|
|
|
|
// Remove the object from the machine object's session list
|
|
|
|
bool b=sessionlist.remove(sess->session());
|
|
|
|
|
|
|
|
QList<QDate> dates;
|
|
|
|
|
|
|
|
QList<Day *> days;
|
|
|
|
QMap<QDate, Day *>::iterator it;
|
|
|
|
|
|
|
|
Day * d;
|
|
|
|
|
|
|
|
// Doing this in case of accidental double linkages
|
|
|
|
for (it = day.begin(); it != day.end(); ++it) {
|
|
|
|
d = it.value();
|
|
|
|
if (it.value()->sessions.contains(sess)) {
|
|
|
|
days.push_back(d);
|
|
|
|
dates.push_back(it.key());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=0; i < days.size(); ++i) {
|
|
|
|
d = days.at(i);
|
|
|
|
if (d->sessions.removeAll(sess)) {
|
|
|
|
b=true;
|
|
|
|
if (d->size() == 0) {
|
|
|
|
day.remove(dates[i]);
|
|
|
|
p_profile->unlinkDay(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
// This functions purpose is murder and mayhem... It deletes all of a machines data.
|
|
|
|
bool Machine::Purge(int secret)
|
|
|
|
{
|
|
|
|
// Boring api key to stop this function getting called by accident :)
|
2014-04-17 05:58:57 +00:00
|
|
|
if (secret != 3478216) { return false; }
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-07-28 13:56:29 +00:00
|
|
|
QString path = getDataPath();
|
2011-06-26 08:30:44 +00:00
|
|
|
|
|
|
|
QDir dir(path);
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
if (!dir.exists()) { // It doesn't exist anyway.
|
2011-09-11 06:16:45 +00:00
|
|
|
return true;
|
2014-04-17 05:58:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!dir.isReadable()) {
|
2011-06-26 08:30:44 +00:00
|
|
|
return false;
|
2014-04-17 05:58:57 +00:00
|
|
|
}
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-07-28 13:56:29 +00:00
|
|
|
qDebug() << "Purging" << info.loadername << info.serial << dir.absoluteFilePath(path);
|
2014-05-19 03:46:02 +00:00
|
|
|
|
2014-07-27 16:35:49 +00:00
|
|
|
// Remove any imported file list
|
|
|
|
QFile impfile(getDataPath()+"/imported_files.csv");
|
|
|
|
impfile.remove();
|
|
|
|
|
2014-05-19 03:46:02 +00:00
|
|
|
// Create a copy of the list so the hash can be manipulated
|
|
|
|
QList<Session *> sessions = sessionlist.values();
|
|
|
|
|
|
|
|
// Clean up any loaded sessions from memory first..
|
|
|
|
bool success = true;
|
|
|
|
for (int i=0; i < sessions.size(); ++i) {
|
|
|
|
Session * sess = sessions[i];
|
|
|
|
if (!sess->Destroy()) {
|
2014-07-28 13:56:29 +00:00
|
|
|
qDebug() << "Could not destroy "+ info.loadername +" ("+info.serial+") session" << sess->session();
|
2014-05-19 03:46:02 +00:00
|
|
|
success = false;
|
|
|
|
} else {
|
2014-07-25 07:53:48 +00:00
|
|
|
// sessionlist.remove(sess->session());
|
2014-05-19 03:46:02 +00:00
|
|
|
}
|
2014-07-25 07:53:48 +00:00
|
|
|
|
2014-05-19 03:46:02 +00:00
|
|
|
delete sess;
|
|
|
|
}
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-05-19 03:46:02 +00:00
|
|
|
// Clean up any straggling files (like from short sessions not being loaded...)
|
2011-06-26 08:30:44 +00:00
|
|
|
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
|
|
|
|
dir.setSorting(QDir::Name);
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QFileInfoList list = dir.entryInfoList();
|
|
|
|
int could_not_kill = 0;
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-05-19 03:46:02 +00:00
|
|
|
int size = list.size();
|
|
|
|
for (int i = 0; i < size; ++i) {
|
2014-04-17 05:58:57 +00:00
|
|
|
QFileInfo fi = list.at(i);
|
|
|
|
QString fullpath = fi.canonicalFilePath();
|
2011-07-20 18:32:47 +00:00
|
|
|
|
2014-05-19 03:46:02 +00:00
|
|
|
QString ext_s = fullpath.section('.', -1);
|
2011-06-26 08:30:44 +00:00
|
|
|
bool ok;
|
2014-04-17 05:58:57 +00:00
|
|
|
ext_s.toInt(&ok, 10);
|
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
if (ok) {
|
2013-09-14 23:32:14 +00:00
|
|
|
qDebug() << "Deleting " << QDir::toNativeSeparators(fullpath);
|
2014-05-19 03:46:02 +00:00
|
|
|
if (!dir.remove(fullpath)) {
|
|
|
|
qDebug() << "Could not purge file" << fullpath;
|
|
|
|
success=false;
|
|
|
|
could_not_kill++;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
qDebug() << "Didn't bother deleting cruft file" << fullpath;
|
|
|
|
// cruft file..
|
|
|
|
}
|
2011-06-26 08:30:44 +00:00
|
|
|
|
|
|
|
}
|
2014-04-17 05:58:57 +00:00
|
|
|
|
|
|
|
if (could_not_kill > 0) {
|
2014-05-19 03:46:02 +00:00
|
|
|
qWarning() << "Could not purge path" << could_not_kill << "files in " << path;
|
|
|
|
return false;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
2014-05-13 02:56:51 +00:00
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
2011-09-13 08:12:07 +00:00
|
|
|
|
2014-08-03 13:00:13 +00:00
|
|
|
void Machine::setLoaderName(QString value)
|
|
|
|
{
|
|
|
|
info.loadername = value;
|
|
|
|
m_loader = GetLoader(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Machine::setInfo(MachineInfo inf)
|
|
|
|
{
|
|
|
|
info = inf;
|
|
|
|
m_loader = GetLoader(inf.loadername);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-17 04:56:04 +00:00
|
|
|
//const quint32 channel_version=1;
|
2014-07-28 13:56:29 +00:00
|
|
|
|
2014-07-27 16:35:49 +00:00
|
|
|
const QString Machine::getDataPath()
|
|
|
|
{
|
2014-07-28 13:56:29 +00:00
|
|
|
return p_profile->Get("{" + STR_GEN_DataFolder + "}/" + info.loadername + "_" + (info.serial.isEmpty() ? hexid() : info.serial)) + "/";
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString Machine::getBackupPath()
|
|
|
|
{
|
|
|
|
return p_profile->Get("{" + STR_GEN_DataFolder + "}/" + info.loadername + "_" + (info.serial.isEmpty() ? hexid() : info.serial) + "/Backup/");
|
2014-07-27 16:35:49 +00:00
|
|
|
}
|
2011-09-13 08:12:07 +00:00
|
|
|
|
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
bool Machine::Load()
|
|
|
|
{
|
2014-07-28 13:56:29 +00:00
|
|
|
QString path = getDataPath();
|
2011-09-13 08:12:07 +00:00
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
QDir dir(path);
|
2013-09-14 23:32:14 +00:00
|
|
|
qDebug() << "Loading " << QDir::toNativeSeparators(path);
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
if (!dir.exists() || !dir.isReadable()) {
|
2011-06-26 08:30:44 +00:00
|
|
|
return false;
|
2014-04-17 05:58:57 +00:00
|
|
|
}
|
2011-06-26 08:30:44 +00:00
|
|
|
|
|
|
|
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
|
|
|
|
dir.setSorting(QDir::Name);
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QFileInfoList list = dir.entryInfoList();
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2011-07-31 20:24:43 +00:00
|
|
|
typedef QVector<QString> StringList;
|
2014-04-17 05:58:57 +00:00
|
|
|
QMap<SessionID, StringList> sessfiles;
|
|
|
|
QMap<SessionID, StringList>::iterator s;
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QString fullpath, ext_s, sesstr;
|
2011-06-26 08:30:44 +00:00
|
|
|
int ext;
|
|
|
|
SessionID sessid;
|
|
|
|
bool ok;
|
2014-04-17 05:58:57 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < list.size(); i++) {
|
|
|
|
QFileInfo fi = list.at(i);
|
|
|
|
fullpath = fi.canonicalFilePath();
|
|
|
|
ext_s = fi.fileName().section(".", -1);
|
|
|
|
ext = ext_s.toInt(&ok, 10);
|
|
|
|
|
|
|
|
if (!ok) { continue; }
|
|
|
|
|
|
|
|
sesstr = fi.fileName().section(".", 0, -2);
|
|
|
|
sessid = sesstr.toLong(&ok, 16);
|
|
|
|
|
|
|
|
if (!ok) { continue; }
|
|
|
|
|
|
|
|
if (sessfiles[sessid].capacity() == 0) { sessfiles[sessid].resize(3); }
|
|
|
|
|
|
|
|
sessfiles[sessid][ext] = fi.canonicalFilePath();
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
int size = sessfiles.size();
|
|
|
|
int cnt = 0;
|
|
|
|
|
|
|
|
for (s = sessfiles.begin(); s != sessfiles.end(); s++) {
|
|
|
|
if ((++cnt % 50) == 0) { // This is slow.. :-/
|
|
|
|
if (qprogress) { qprogress->setValue((float(cnt) / float(size) * 100.0)); }
|
|
|
|
|
2012-01-09 15:38:41 +00:00
|
|
|
QApplication::processEvents();
|
2011-12-23 14:12:04 +00:00
|
|
|
}
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
Session *sess = new Session(this, s.key());
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2011-07-31 20:24:43 +00:00
|
|
|
if (sess->LoadSummary(s.value()[0])) {
|
2014-04-17 05:58:57 +00:00
|
|
|
sess->SetEventFile(s.value()[1]);
|
2014-07-11 12:09:38 +00:00
|
|
|
|
|
|
|
AddSession(sess);
|
2011-07-20 18:32:47 +00:00
|
|
|
} else {
|
2011-07-03 11:49:47 +00:00
|
|
|
qWarning() << "Error unpacking summary data";
|
2011-06-26 08:30:44 +00:00
|
|
|
delete sess;
|
|
|
|
}
|
|
|
|
}
|
2014-04-17 05:58:57 +00:00
|
|
|
|
|
|
|
if (qprogress) { qprogress->setValue(100); }
|
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
2014-07-11 12:09:38 +00:00
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
bool Machine::SaveSession(Session *sess)
|
|
|
|
{
|
2014-07-28 13:56:29 +00:00
|
|
|
QString path = getDataPath();
|
2014-04-17 05:58:57 +00:00
|
|
|
|
|
|
|
if (sess->IsChanged()) { sess->Store(path); }
|
|
|
|
|
2011-07-01 10:10:44 +00:00
|
|
|
return true;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
2011-09-13 08:12:07 +00:00
|
|
|
|
2014-05-20 11:51:47 +00:00
|
|
|
void Machine::queSaveList(Session * sess)
|
|
|
|
{
|
|
|
|
if (!m_save_threads_running) {
|
|
|
|
// Threads aren't being used.. so run the actual immediately...
|
|
|
|
int i = (float(m_donetasks) / float(m_totaltasks) * 100.0);
|
|
|
|
qprogress->setValue(i);
|
|
|
|
QApplication::processEvents();
|
|
|
|
|
|
|
|
sess->UpdateSummaries();
|
2014-07-28 13:56:29 +00:00
|
|
|
sess->Store(getDataPath());
|
2014-05-20 11:51:47 +00:00
|
|
|
|
2014-07-11 12:09:38 +00:00
|
|
|
if (!p_profile->session->cacheSessions()) {
|
2014-05-20 11:51:47 +00:00
|
|
|
sess->TrashEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2014-05-21 00:17:31 +00:00
|
|
|
listMutex.lock();
|
2014-05-20 11:51:47 +00:00
|
|
|
m_savelist.append(sess);
|
2014-05-21 00:17:31 +00:00
|
|
|
listMutex.unlock();
|
2014-05-20 11:51:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Session *Machine::popSaveList()
|
|
|
|
{
|
|
|
|
Session *sess = nullptr;
|
2014-05-21 00:17:31 +00:00
|
|
|
listMutex.lock();
|
2014-05-20 11:51:47 +00:00
|
|
|
|
|
|
|
if (!m_savelist.isEmpty()) {
|
|
|
|
sess = m_savelist.at(0);
|
|
|
|
m_savelist.pop_front();
|
|
|
|
m_donetasks++;
|
|
|
|
}
|
|
|
|
|
2014-05-21 00:17:31 +00:00
|
|
|
listMutex.unlock();
|
2014-05-20 11:51:47 +00:00
|
|
|
return sess;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call any time queing starts
|
|
|
|
void Machine::StartSaveThreads()
|
|
|
|
{
|
|
|
|
m_savelist.clear();
|
2014-06-20 06:17:27 +00:00
|
|
|
if (!p_profile->session->multithreading()) return;
|
2014-05-20 11:51:47 +00:00
|
|
|
|
2014-07-28 13:56:29 +00:00
|
|
|
QString path = getDataPath();
|
2014-05-20 11:51:47 +00:00
|
|
|
|
|
|
|
int threads = QThread::idealThreadCount();
|
|
|
|
savelistSem = new QSemaphore(threads);
|
|
|
|
savelistSem->acquire(threads);
|
|
|
|
|
|
|
|
m_save_threads_running = true;
|
|
|
|
m_donetasks=0;
|
|
|
|
m_totaltasks=0;
|
|
|
|
|
|
|
|
for (int i = 0; i < threads; i++) {
|
2014-06-30 11:20:12 +00:00
|
|
|
SaveThread * thr = new SaveThread(this, path);
|
|
|
|
QObject::connect(thr, SIGNAL(UpdateProgress(int)), qprogress, SLOT(setValue(int)));
|
|
|
|
thread.push_back(thr);
|
2014-05-20 11:51:47 +00:00
|
|
|
thread[i]->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call when all queing is completed
|
|
|
|
void Machine::FinishSaveThreads()
|
|
|
|
{
|
|
|
|
if (!m_save_threads_running)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_save_threads_running = false;
|
|
|
|
|
|
|
|
// Wait for all tasks to finish
|
|
|
|
while (!savelistSem->tryAcquire(thread.size(), 250)) {
|
|
|
|
if (qprogress) {
|
|
|
|
QApplication::processEvents();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < thread.size(); ++i) {
|
|
|
|
while (thread[i]->isRunning()) {
|
|
|
|
SaveThread::msleep(250);
|
|
|
|
QApplication::processEvents();
|
|
|
|
}
|
|
|
|
QObject::disconnect(thread[i], SIGNAL(UpdateProgress(int)), qprogress, SLOT(setValue(int)));
|
|
|
|
|
|
|
|
delete thread[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
delete savelistSem;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveThread::run()
|
|
|
|
{
|
|
|
|
bool running = true;
|
|
|
|
while (running) {
|
|
|
|
Session *sess = machine->popSaveList();
|
|
|
|
if (sess) {
|
|
|
|
if (machine->m_donetasks % 10 == 0) {
|
|
|
|
int i = (float(machine->m_donetasks) / float(machine->m_totaltasks) * 100.0);
|
|
|
|
emit UpdateProgress(i);
|
|
|
|
}
|
|
|
|
sess->UpdateSummaries();
|
2014-05-21 00:17:31 +00:00
|
|
|
machine->saveMutex.lock();
|
2014-05-20 11:51:47 +00:00
|
|
|
sess->Store(path);
|
2014-05-21 00:17:31 +00:00
|
|
|
machine->saveMutex.unlock();
|
2014-05-20 11:51:47 +00:00
|
|
|
|
|
|
|
sess->TrashEvents();
|
|
|
|
} else {
|
|
|
|
if (!machine->m_save_threads_running) {
|
|
|
|
break; // done
|
|
|
|
} else {
|
|
|
|
yieldCurrentThread(); // go do something else for a while
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
machine->savelistSem->release(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-05-21 00:17:31 +00:00
|
|
|
|
|
|
|
class SaveTask:public ImportTask
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SaveTask(Session * s, Machine * m): sess(s), mach(m) {}
|
|
|
|
virtual ~SaveTask() {}
|
|
|
|
virtual void run();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Session * sess;
|
|
|
|
Machine * mach;
|
|
|
|
};
|
|
|
|
|
|
|
|
void SaveTask::run()
|
|
|
|
{
|
|
|
|
sess->UpdateSummaries();
|
|
|
|
mach->saveMutex.lock();
|
2014-07-28 13:56:29 +00:00
|
|
|
sess->Store(mach->getDataPath());
|
2014-05-21 00:17:31 +00:00
|
|
|
mach->saveMutex.unlock();
|
|
|
|
sess->TrashEvents();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Machine::queTask(ImportTask * task)
|
|
|
|
{
|
2014-07-11 12:09:38 +00:00
|
|
|
if (0) { //p_profile->session->multithreading()) {
|
2014-05-21 00:17:31 +00:00
|
|
|
m_tasklist.push_back(task);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
task->run();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Machine::runTasks()
|
|
|
|
{
|
2014-07-11 12:09:38 +00:00
|
|
|
if (0) { //!p_profile->session->multithreading()) {
|
2014-05-21 00:17:31 +00:00
|
|
|
Q_ASSERT(m_tasklist.isEmpty());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QThreadPool * threadpool = QThreadPool::globalInstance();
|
|
|
|
int m_totaltasks=m_tasklist.size();
|
|
|
|
int m_currenttask=0;
|
|
|
|
while (!m_tasklist.isEmpty()) {
|
|
|
|
if (threadpool->tryStart(m_tasklist.at(0))) {
|
|
|
|
m_tasklist.pop_front();
|
|
|
|
float f = float(m_currenttask) / float(m_totaltasks) * 100.0;
|
|
|
|
qprogress->setValue(f);
|
|
|
|
m_currenttask++;
|
|
|
|
}
|
|
|
|
QApplication::processEvents();
|
|
|
|
}
|
|
|
|
QThreadPool::globalInstance()->waitForDone(-1);
|
|
|
|
}
|
|
|
|
|
2011-06-26 08:30:44 +00:00
|
|
|
bool Machine::Save()
|
|
|
|
{
|
2011-10-21 05:50:31 +00:00
|
|
|
//int size;
|
2014-04-17 05:58:57 +00:00
|
|
|
int cnt = 0;
|
2011-06-26 08:30:44 +00:00
|
|
|
|
2014-07-28 13:56:29 +00:00
|
|
|
QString path = getDataPath();
|
2011-09-13 08:12:07 +00:00
|
|
|
QDir dir(path);
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2011-09-13 08:12:07 +00:00
|
|
|
if (!dir.exists()) {
|
|
|
|
dir.mkdir(path);
|
|
|
|
}
|
|
|
|
|
2014-04-17 05:58:57 +00:00
|
|
|
QHash<SessionID, Session *>::iterator s;
|
2011-07-21 12:03:06 +00:00
|
|
|
|
2011-09-08 18:38:07 +00:00
|
|
|
m_savelist.clear();
|
2014-04-17 05:58:57 +00:00
|
|
|
|
|
|
|
for (s = sessionlist.begin(); s != sessionlist.end(); s++) {
|
2011-08-05 07:52:32 +00:00
|
|
|
cnt++;
|
2014-04-17 05:58:57 +00:00
|
|
|
|
2011-09-08 18:38:07 +00:00
|
|
|
if ((*s)->IsChanged()) {
|
2014-05-21 00:17:31 +00:00
|
|
|
queTask(new SaveTask(*s, this));
|
2011-09-08 18:38:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 00:17:31 +00:00
|
|
|
runTasks();
|
2011-06-26 08:30:44 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CPAP implmementation
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2014-07-11 12:09:38 +00:00
|
|
|
CPAP::CPAP(MachineID id): Machine(id)
|
2011-06-26 08:30:44 +00:00
|
|
|
{
|
2014-04-17 05:58:57 +00:00
|
|
|
m_type = MT_CPAP;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CPAP::~CPAP()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Oximeter Class implmementation
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2014-07-11 12:09:38 +00:00
|
|
|
Oximeter::Oximeter(MachineID id): Machine(id)
|
2011-06-26 08:30:44 +00:00
|
|
|
{
|
2014-04-17 05:58:57 +00:00
|
|
|
m_type = MT_OXIMETER;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Oximeter::~Oximeter()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// SleepStage Class implmementation
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2014-07-11 12:09:38 +00:00
|
|
|
SleepStage::SleepStage(MachineID id): Machine(id)
|
2011-06-26 08:30:44 +00:00
|
|
|
{
|
2014-04-17 05:58:57 +00:00
|
|
|
m_type = MT_SLEEPSTAGE;
|
2011-06-26 08:30:44 +00:00
|
|
|
}
|
|
|
|
SleepStage::~SleepStage()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-04-15 13:59:24 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// PositionSensor Class implmementation
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
2014-07-11 12:09:38 +00:00
|
|
|
PositionSensor::PositionSensor(MachineID id): Machine(id)
|
2014-04-15 13:59:24 +00:00
|
|
|
{
|
2014-04-17 05:58:57 +00:00
|
|
|
m_type = MT_POSITION;
|
2014-04-15 13:59:24 +00:00
|
|
|
}
|
|
|
|
PositionSensor::~PositionSensor()
|
|
|
|
{
|
|
|
|
}
|