diff --git a/ChangeLog b/ChangeLog index 76b2a249..0abe487c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16512,3 +16512,10 @@ 2017-12-18 Fred Gleason * Updated 'NEWS'. * Incremented the package version to 2.17.0int08. +2017-12-18 Fred Gleason + * Added a 'LOGS.LOCK_USER_NAME' field to the database. + * Added a 'LOGS.LOCK_STATION_NAME' field to the database. + * Added a 'LOGS.LOCK_IPV4_ADDRESS' field to the database. + * Added a 'LOGS.LOCK_DATETIME' field to the database. + * Incremented the database version to 273. + * Added log locking logic to rdlogedit(1). diff --git a/docs/tables/logs.txt b/docs/tables/logs.txt index a4ec85d3..152d6d8f 100644 --- a/docs/tables/logs.txt +++ b/docs/tables/logs.txt @@ -26,3 +26,8 @@ MUSIC_LINKS int MUSIC_LINKED enum('N','Y') TRAFFIC_LINKS int TRAFFIC_LINKED enum('N','Y') +NEXT_ID int(11) +LOCK_USER_NAME char(255) From USER.LOGIN_NAME +LOCK_STATION_NAME char(64) From STATIONS.NAME +LOCK_IPV4_ADDRESS char(16) +LOCK_DATETIME datetime diff --git a/lib/Makefile.am b/lib/Makefile.am index 669fda28..0c999bf7 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -166,10 +166,11 @@ dist_librd_la_SOURCES = dbversion.h\ rdlivewiredestination.cpp rdlivewiredestination.h\ rdlivewiresource.cpp rdlivewiresource.h\ rdlog.cpp rdlog.h\ - rdlogfilter.cpp rdlogfilter.h\ - rdlogedit_conf.cpp rdlogedit_conf.h\ rdlog_event.cpp rdlog_event.h\ rdlog_line.cpp rdlog_line.h\ + rdlogedit_conf.cpp rdlogedit_conf.h\ + rdlogfilter.cpp rdlogfilter.h\ + rdloglock.cpp rdloglock.h\ rdmacro.cpp rdmacro.h\ rdmacro_event.cpp rdmacro_event.h\ rdmarker_bar.cpp rdmarker_bar.h\ @@ -302,6 +303,7 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\ moc_rdlistview.cpp\ moc_rdlivewire.cpp\ moc_rdlogfilter.cpp\ + moc_rdloglock.cpp\ moc_rdmacro_event.cpp\ moc_rdmarker_bar.cpp\ moc_rdmarker_edit.cpp\ diff --git a/lib/dbversion.h b/lib/dbversion.h index d9652274..8dbbd90f 100644 --- a/lib/dbversion.h +++ b/lib/dbversion.h @@ -24,7 +24,7 @@ /* * Current Database Version */ -#define RD_VERSION_DATABASE 272 +#define RD_VERSION_DATABASE 273 #endif // DBVERSION_H diff --git a/lib/lib.pro b/lib/lib.pro index 46497f34..744cd316 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -89,6 +89,7 @@ SOURCES += rdlog_event.cpp SOURCES += rdlog_line.cpp SOURCES += rdlogedit_conf.cpp SOURCES += rdlogfilter.cpp +SOURCES += rdloglock.cpp SOURCES += rdmacro.cpp SOURCES += rdmacro_event.cpp SOURCES += rdoneshot.cpp @@ -230,6 +231,7 @@ HEADERS += rdlog_event.h HEADERS += rdlog_line.h HEADERS += rdlogedit_conf.h HEADERS += rdlogfilter.h +HEADERS += rdloglock.h HEADERS += rdmacro.h HEADERS += rdmacro_event.h HEADERS += rdoneshot.h diff --git a/lib/rd.h b/lib/rd.h index 417296c4..5adf8c1d 100644 --- a/lib/rd.h +++ b/lib/rd.h @@ -567,4 +567,10 @@ */ #define RD_LOGFILTER_LIMIT_QUAN 14 +/* + * Log Locking Timeout + */ +#define RD_LOG_LOCK_TIMEOUT 30000 + + #endif // RD_H diff --git a/lib/rdloglock.cpp b/lib/rdloglock.cpp new file mode 100644 index 00000000..d9f5109e --- /dev/null +++ b/lib/rdloglock.cpp @@ -0,0 +1,147 @@ +// rdloglock.cpp +// +// Log locking routines for Rivendell +// +// (C) Copyright 2017 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. +// + +#ifndef WIN32 +#include +#endif // WIN32 + +#include + +#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) +{ + QString sql; + RDSqlQuery *q; + RDSqlQuery *q1; + bool ret=false; + QDateTime now=QDateTime::currentDateTime(); + + sql=QString("update LOGS set ")+ + "LOCK_USER_NAME=\""+RDEscapeString(lock_user->name())+"\","+ + "LOCK_STATION_NAME=\""+RDEscapeString(lock_station->name())+"\","+ + "LOCK_IPV4_ADDRESS=\""+RDEscapeString(lock_station->address().toString())+ + "\","+ + "LOCK_DATETIME=now() where "+ + "(NAME=\""+RDEscapeString(lock_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) { + lock_timer->start(RD_LOG_LOCK_TIMEOUT/2); + lock_locked=true; + ret=true; + } + else { + sql=QString("select ")+ + "LOCK_USER_NAME,"+ + "LOCK_STATION_NAME,"+ + "LOCK_IPV4_ADDRESS "+ + "from LOGS where "+ + "NAME=\""+RDEscapeString(lock_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::clearLock() +{ + QString sql; + RDSqlQuery *q; + + sql=QString("update LOGS set ")+ + "LOCK_USER_NAME=null,"+ + "LOCK_STATION_NAME=null,"+ + "LOCK_IPV4_ADDRESS=null,"+ + "LOCK_DATETIME=null where "+ + "(NAME=\""+RDEscapeString(lock_log_name)+"\")&&"+ + "(LOCK_USER_NAME=\""+RDEscapeString(lock_user->name())+"\")&&"+ + "(LOCK_STATION_NAME=\""+RDEscapeString(lock_station->name())+"\")&&"+ + "(LOCK_IPV4_ADDRESS=\""+RDEscapeString(lock_station->address().toString())+ + "\")"; + q=new RDSqlQuery(sql); + delete q; + lock_timer->stop(); + lock_locked=false; +} + + +void RDLogLock::updateLock() +{ + QString sql; + RDSqlQuery *q; + + sql=QString("update LOGS set ")+ + "LOCK_DATETIME=now() where "+ + "(NAME=\""+RDEscapeString(lock_log_name)+"\")&&"+ + "(LOCK_USER_NAME=\""+RDEscapeString(lock_user->name())+"\")&&"+ + "(LOCK_STATION_NAME=\""+RDEscapeString(lock_station->name())+"\")&&"+ + "(LOCK_IPV4_ADDRESS=\""+RDEscapeString(lock_station->address().toString())+ + "\")"; + q=new RDSqlQuery(sql); +#ifndef WIN32 + if(q->numRowsAffected()==0) { + syslog(LOG_WARNING,"lock on log \"%s\" has gone stale", + (const char *)lock_log_name); + } +#endif // WIN32 + delete q; +} diff --git a/lib/rdloglock.h b/lib/rdloglock.h new file mode 100644 index 00000000..59f6a20a --- /dev/null +++ b/lib/rdloglock.h @@ -0,0 +1,55 @@ +// rdloglock.h +// +// Log locking routines for Rivendell +// +// (C) Copyright 2017 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. +// + +#ifndef RDLOGLOCK_H +#define RDLOGLOCK_H + +#include +#include +#include + +#include +#include +#include + +class RDLogLock : public QObject +{ + Q_OBJECT; + public: + RDLogLock(const QString &log_name,RDUser *user,RDStation *station, + QObject *parent=0); + ~RDLogLock(); + bool isLocked() const; + bool tryLock(QString *username,QString *stationname,QHostAddress *addr); + void clearLock(); + + private slots: + void updateLock(); + + private: + QString lock_log_name; + RDUser *lock_user; + RDStation *lock_station; + QTimer *lock_timer; + bool lock_locked; +}; + + +#endif // RDLOGLOCK_H diff --git a/rdadmin/createdb.cpp b/rdadmin/createdb.cpp index ff0a457d..213d9814 100644 --- a/rdadmin/createdb.cpp +++ b/rdadmin/createdb.cpp @@ -984,6 +984,10 @@ bool CreateDb(QString name,QString pwd,RDConfig *config) "TRAFFIC_LINKS int default 0,"+ "TRAFFIC_LINKED enum('N','Y') default 'N',"+ "NEXT_ID int default 0,"+ + "LOCK_USER_NAME char(255),"+ + "LOCK_STATION_NAME char(64),"+ + "LOCK_IPV4_ADDRESS char(16),"+ + "LOCK_DATETIME datetime,"+ "index NAME_IDX (NAME,LOG_EXISTS),"+ "index SERVICE_IDX (SERVICE),"+ "index DESCRIPTION_IDX (DESCRIPTION),"+ @@ -7975,6 +7979,28 @@ int UpdateDb(int ver,RDConfig *config) delete q; } + if(ver<273) { + sql=QString("alter table LOGS ")+ + "add column LOCK_USER_NAME char(255) after NEXT_ID"; + q=new RDSqlQuery(sql,false); + delete q; + + sql=QString("alter table LOGS ")+ + "add column LOCK_STATION_NAME char(64) after LOCK_USER_NAME"; + q=new RDSqlQuery(sql,false); + delete q; + + sql=QString("alter table LOGS ")+ + "add column LOCK_IPV4_ADDRESS char(16) after LOCK_STATION_NAME"; + q=new RDSqlQuery(sql,false); + delete q; + + sql=QString("alter table LOGS ")+ + "add column LOCK_DATETIME datetime after LOCK_IPV4_ADDRESS"; + q=new RDSqlQuery(sql,false); + delete q; + } + // // Maintainer's Note: diff --git a/rdlogedit/edit_log.cpp b/rdlogedit/edit_log.cpp index c3d8c090..9544845a 100644 --- a/rdlogedit/edit_log.cpp +++ b/rdlogedit/edit_log.cpp @@ -147,8 +147,9 @@ EditLog::EditLog(QString logname,QString *filter,QString *group, edit_log=new RDLog(edit_logname); // - // Log Events + // Log Data Structures // + edit_log_lock=new RDLogLock(edit_logname,rduser,rdstation_conf,this); edit_log_event=new RDLogEvent(RDLog::tableName(edit_logname)); edit_log_event->load(true); @@ -639,6 +640,24 @@ QSizePolicy EditLog::sizePolicy() const } +int EditLog::exec() +{ + QString username; + QString stationname; + QHostAddress addr; + + if(!edit_log_lock->tryLock(&username,&stationname,&addr)) { + QMessageBox::warning(this,"RDLogEdit - "+tr("Log Locked"), + tr("Log already being edited by")+" "+ + username+"@"+stationname+" ["+ + addr.toString()+"]."); + return 1; + } + + return QDialog::exec(); +} + + void EditLog::descriptionChangedData(const QString &) { SetLogModified(true); diff --git a/rdlogedit/edit_log.h b/rdlogedit/edit_log.h index 447433e7..d0e0853c 100644 --- a/rdlogedit/edit_log.h +++ b/rdlogedit/edit_log.h @@ -33,12 +33,13 @@ #include #include -#include +#include #include #include -#include -#include +#include #include +#include +#include #include "drop_listview.h" #include "list_reports.h" @@ -61,6 +62,9 @@ class EditLog : public QDialog ~EditLog(); QSize sizeHint() const; QSizePolicy sizePolicy() const; + + public slots: + int exec(); private slots: void descriptionChangedData(const QString &); @@ -187,6 +191,7 @@ class EditLog : public QDialog QLabel *edit_purgedate_label; QDateEdit *edit_purgedate_edit; QPushButton *edit_purgedate_button; + RDLogLock *edit_log_lock; #ifndef WIN32 QPushButton *edit_renderas_button; RenderDialog *edit_render_dialog; diff --git a/rdlogedit/rdlogedit_cs.ts b/rdlogedit/rdlogedit_cs.ts index e01e1853..335bc73c 100644 --- a/rdlogedit/rdlogedit_cs.ts +++ b/rdlogedit/rdlogedit_cs.ts @@ -425,6 +425,18 @@ jež jsou pro vybranou službu zakázány! Error + + User + Uživatel + + + Log Locked + + + + Log already being edited by + + EditLogLine diff --git a/rdlogedit/rdlogedit_de.ts b/rdlogedit/rdlogedit_de.ts index f3c9c202..7229ffcc 100644 --- a/rdlogedit/rdlogedit_de.ts +++ b/rdlogedit/rdlogedit_de.ts @@ -425,6 +425,18 @@ die für den gewählten Service ungültig sind! Error + + User + Benutzer + + + Log Locked + + + + Log already being edited by + + EditLogLine diff --git a/rdlogedit/rdlogedit_es.ts b/rdlogedit/rdlogedit_es.ts index d778c88c..10769b93 100644 --- a/rdlogedit/rdlogedit_es.ts +++ b/rdlogedit/rdlogedit_es.ts @@ -425,6 +425,18 @@ desactivados para el servicio actual! Error + + User + Usuario + + + Log Locked + + + + Log already being edited by + + EditLogLine diff --git a/rdlogedit/rdlogedit_fr.ts b/rdlogedit/rdlogedit_fr.ts index 3da60855..16549b8d 100644 --- a/rdlogedit/rdlogedit_fr.ts +++ b/rdlogedit/rdlogedit_fr.ts @@ -403,6 +403,14 @@ for the selected service! Error + + Log Locked + + + + Log already being edited by + + EditLogLine diff --git a/rdlogedit/rdlogedit_nb.ts b/rdlogedit/rdlogedit_nb.ts index 45d909a6..0af0d24c 100644 --- a/rdlogedit/rdlogedit_nb.ts +++ b/rdlogedit/rdlogedit_nb.ts @@ -432,6 +432,18 @@ skrudd av for denne tenesta! Error + + User + Brukar + + + Log Locked + + + + Log already being edited by + + EditLogLine diff --git a/rdlogedit/rdlogedit_nn.ts b/rdlogedit/rdlogedit_nn.ts index 45d909a6..0af0d24c 100644 --- a/rdlogedit/rdlogedit_nn.ts +++ b/rdlogedit/rdlogedit_nn.ts @@ -432,6 +432,18 @@ skrudd av for denne tenesta! Error + + User + Brukar + + + Log Locked + + + + Log already being edited by + + EditLogLine diff --git a/rdlogedit/rdlogedit_pt_BR.ts b/rdlogedit/rdlogedit_pt_BR.ts index a58dd26f..d411b1a7 100644 --- a/rdlogedit/rdlogedit_pt_BR.ts +++ b/rdlogedit/rdlogedit_pt_BR.ts @@ -427,6 +427,18 @@ para o serviço selecionado! Error + + User + Usuário + + + Log Locked + + + + Log already being edited by + + EditLogLine diff --git a/utils/rdrevert/rdrevert.cpp b/utils/rdrevert/rdrevert.cpp index cda04f80..116e5674 100644 --- a/utils/rdrevert/rdrevert.cpp +++ b/utils/rdrevert/rdrevert.cpp @@ -247,6 +247,10 @@ void MainObject::Revert(int schema) const case 272: Revert272(); break; + + case 273: + Revert273(); + break; } } @@ -758,6 +762,31 @@ void MainObject::Revert272() const } +void MainObject::Revert273() const +{ + QString sql; + QSqlQuery *q; + + sql=QString("alter table LOGS drop column LOCK_DATETIME"); + q=new QSqlQuery(sql); + delete q; + + sql=QString("alter table LOGS drop column LOCK_IPV4_ADDRESS"); + q=new QSqlQuery(sql); + delete q; + + sql=QString("alter table LOGS drop column LOCK_STATION_NAME"); + q=new QSqlQuery(sql); + delete q; + + sql=QString("alter table LOGS drop column LOCK_USER_NAME"); + q=new QSqlQuery(sql); + delete q; + + SetVersion(272); +} + + int MainObject::GetVersion() const { QString sql; @@ -803,6 +832,7 @@ int MainObject::MapSchema(const QString &ver) version_map["2.16"]=263; version_map["2.17"]=268; version_map["2.18"]=272; + version_map["2.19"]=273; // // Normalize String diff --git a/utils/rdrevert/rdrevert.h b/utils/rdrevert/rdrevert.h index 0bd18362..4ffeac64 100644 --- a/utils/rdrevert/rdrevert.h +++ b/utils/rdrevert/rdrevert.h @@ -68,6 +68,7 @@ class MainObject : public QObject void Revert270() const; void Revert271() const; void Revert272() const; + void Revert273() const; int GetVersion() const; void SetVersion(int schema) const; int MapSchema(const QString &ver);