// rdloglock.cpp // // Log locking routines for Rivendell // // (C) Copyright 2017-2021 Fred Gleason // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // #include "rdapplication.h" #include "rddb.h" #include "rdescape_string.h" #include "rdloglock.h" RDLogLock::RDLogLock(const QString &log_name,RDUser *user,RDStation *station, QObject *parent) : QObject(parent) { lock_log_name=log_name; lock_user=user; lock_station=station; lock_locked=false; lock_timer=new QTimer(this); connect(lock_timer,SIGNAL(timeout()),this,SLOT(updateLock())); } RDLogLock::~RDLogLock() { if(lock_locked) { clearLock(); } delete lock_timer; } bool RDLogLock::isLocked() const { return lock_locked; } bool RDLogLock::tryLock(QString *username,QString *stationname, QHostAddress *addr) { bool ret=false; QString guid=RDLogLock::makeGuid(lock_station->name()); *username=lock_user->name(); *stationname=lock_station->name(); addr->setAddress(lock_station->address().toString()); if(RDLogLock::tryLock(username,stationname,addr,lock_log_name,guid)) { lock_timer->start(RD_LOG_LOCK_TIMEOUT/2); lock_guid=guid; lock_locked=true; ret=true; } return ret; } void RDLogLock::clearLock() { RDLogLock::clearLock(lock_guid); lock_guid=QString(); lock_timer->stop(); lock_locked=false; } void RDLogLock::updateLock() { RDLogLock::updateLock(lock_log_name,lock_guid); } bool RDLogLock::tryLock(QString *username,QString *stationname, QHostAddress *addr,const QString &log_name, const QString &guid) { QString sql; RDSqlQuery *q; RDSqlQuery *q1; bool ret=false; QDateTime now=QDateTime::currentDateTime(); sql=QString("update `LOGS` set ")+ "`LOCK_USER_NAME`='"+RDEscapeString(*username)+"',"+ "`LOCK_STATION_NAME`='"+RDEscapeString(*stationname)+"',"+ "`LOCK_IPV4_ADDRESS`='"+RDEscapeString(addr->toString())+"',"+ "`LOCK_GUID`='"+RDEscapeString(guid)+"',"+ "`LOCK_DATETIME`=now() where "+ "(`NAME`='"+RDEscapeString(log_name)+"')&&"+ "((`LOCK_DATETIME` is null)||"+ "(`LOCK_DATETIME`<'"+RDEscapeString(now.addSecs(-RD_LOG_LOCK_TIMEOUT/1000).toString("yyyy-MM-dd hh:mm:ss"))+"'))"; q=new RDSqlQuery(sql); if(q->numRowsAffected()>0) { ret=true; } else { sql=QString("select ")+ "`LOCK_USER_NAME`,"+ "`LOCK_STATION_NAME`,"+ "`LOCK_IPV4_ADDRESS` "+ "from `LOGS` where "+ "`NAME`='"+RDEscapeString(log_name)+"'"; q1=new RDSqlQuery(sql); if(q1->first()) { *username=q1->value(0).toString(); *stationname=q1->value(1).toString(); addr->setAddress(q1->value(2).toString()); } delete q1; } delete q; return ret; } void RDLogLock::updateLock(const QString &log_name,const QString &guid) { QString sql; RDSqlQuery *q; sql=QString("update `LOGS` set ")+ "`LOCK_DATETIME`=now() where "+ "`LOCK_GUID`='"+RDEscapeString(guid)+"'"; q=new RDSqlQuery(sql); if(q->numRowsAffected()==0) { rda->syslog(LOG_WARNING,"lock on log \"%s\" has evaporated!", log_name.toUtf8().constData()); } delete q; } void RDLogLock::clearLock(const QString &guid) { QString sql; sql=QString("update `LOGS` set ")+ "`LOCK_USER_NAME`=null,"+ "`LOCK_STATION_NAME`=null,"+ "`LOCK_IPV4_ADDRESS`=null,"+ "`LOCK_GUID`=null,"+ "`LOCK_DATETIME`=null where "+ "`LOCK_GUID`='"+RDEscapeString(guid)+"'"; RDSqlQuery::apply(sql); } bool RDLogLock::validateLock(const QString &log_name,const QString &guid) { QString sql; RDSqlQuery *q; bool ret=false; QDateTime now=QDateTime::currentDateTime(); sql=QString("select `NAME` from `LOGS` where ")+ "(`NAME`='"+RDEscapeString(log_name)+"')&&"+ "(`LOCK_GUID`='"+RDEscapeString(guid)+"')&&"+ "(`LOCK_DATETIME`>'"+RDEscapeString(now.addSecs(-RD_LOG_LOCK_TIMEOUT/1000). toString("yyyy-MM-dd hh:mm:ss"))+"')"; q=new RDSqlQuery(sql); ret=q->first(); delete q; return ret; } QString RDLogLock::makeGuid(const QString &stationname) { return stationname+QDateTime::currentDateTime(). toString("yyyyMMddhhmmsszzz"); }