Initial import of CVS-v2_8_branch

This commit is contained in:
Fred Gleason
2014-08-12 15:13:02 -04:00
commit afd67c7af8
1508 changed files with 405304 additions and 0 deletions

45
rdrepld/Makefile.am Normal file
View File

@@ -0,0 +1,45 @@
## automake.am
##
## rdrepld/ Makefile.am for Rivendell
##
## (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
##
## $Id: Makefile.am,v 1.2 2010/07/29 19:32:37 cvs Exp $
##
## 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.
##
##
## Use automake to process this into a Makefile.in
AM_CPPFLAGS = -Wall @QT_CXXFLAGS@
INCLUDES = -I$(top_srcdir)/lib
LIBS = @QT_LIBS@ -L$(top_srcdir)/lib
MOC = @QT_MOC@
# QT's Meta Object Compiler (moc)
moc_%.cpp: %.h
$(MOC) $< -o $@
bin_PROGRAMS = rdrepld
dist_rdrepld_SOURCES = globals.h\
rdrepld.cpp rdrepld.h \
replconfig.cpp replconfig.h\
replfactory.cpp replfactory.h\
citadelxds.cpp citadelxds.h
nodist_rdrepld_SOURCES = moc_rdrepld.cpp
rdrepld_LDADD = @LIB_RDLIBS@ @LIBVORBIS@
CLEANFILES = *~ moc_*
DISTCLEANFILES = moc_*
MAINTAINERCLEANFILES = *~ Makefile.in configure aclocal.m4 moc_* *.tar.gz

464
rdrepld/citadelxds.cpp Normal file
View File

@@ -0,0 +1,464 @@
// citadelxds.cpp
//
// Replicator implementation for the Citadel XDS Portal
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: citadelxds.cpp,v 1.6 2012/03/02 22:33:51 cvs Exp $
//
// 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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <qfileinfo.h>
#include <qdatetime.h>
#include <rddb.h>
#include <rdconf.h>
#include <rdaudioconvert.h>
#include <rdupload.h>
#include <rdcut.h>
#include <rdcart.h>
#include <rdescape_string.h>
#include <rdstringlist.h>
#include <rddelete.h>
#include <citadelxds.h>
#define RD_MAX_CART_NUMBER 999999
CitadelXds::CitadelXds(ReplConfig *config)
: ReplFactory(config)
{
QString sql;
RDSqlQuery *q;
sql="select LAST_ISCI_XREFERENCE from VERSION";
q=new RDSqlQuery(sql);
if(q->first()) {
xds_isci_datetime=q->value(0).toDateTime();
}
delete q;
}
void CitadelXds::startProcess()
{
CheckIsciXreference();
CheckCarts();
}
bool CitadelXds::processCart(const unsigned cartnum)
{
QString sql;
RDSqlQuery *q;
bool ret=false;
sql=QString().sprintf("select FILENAME from ISCI_XREFERENCE \
where (CART_NUMBER=%u)&&(LATEST_DATE>=now())&&\
((TYPE=\"R\")||(TYPE=\"B\"))",cartnum);
q=new RDSqlQuery(sql);
if(q->first()) {
ret=PostCut(RDCut::cutName(cartnum,1),q->value(0).toString());
}
delete q;
return ret;
}
void CitadelXds::CheckIsciXreference()
{
QString sql;
RDSqlQuery *q;
QFileInfo *fi=new QFileInfo(rdsystem->isciXreferencePath());
if(fi->exists()) {
if(fi->lastModified()>xds_isci_datetime) {
if(LoadIsciXreference(rdsystem->isciXreferencePath())) {
sql="update VERSION set LAST_ISCI_XREFERENCE=now()";
q=new RDSqlQuery(sql);
delete q;
xds_isci_datetime=QDateTime(QDate::currentDate(),QTime::currentTime());
PurgeCuts();
}
}
}
else {
rdconfig->log("rdrepld",RDConfig::LogErr,
QString().sprintf("unable to load ISCI cross reference file \"%s\"",
(const char *)rdsystem->isciXreferencePath()));
}
delete fi;
}
bool CitadelXds::LoadIsciXreference(const QString &filename)
{
FILE *f=NULL;
char line[1024];
QString sql;
RDSqlQuery *q;
RDStringList fields;
unsigned cartnum;
QStringList datelist;
QDate date;
bool ok=false;
unsigned linenum=3;
if((f=fopen(filename,"r"))==NULL) {
rdconfig->log("rdrepld",RDConfig::LogErr,
QString().sprintf("unable to load ISCI cross reference file \"%s\" [%s]",
(const char *)rdsystem->isciXreferencePath(),
strerror(errno)));
return false;
}
//
// Purge Old Data
//
sql="delete from ISCI_XREFERENCE";
q=new RDSqlQuery(sql);
delete q;
//
// Skip Header
//
fgets(line,1024,f);
fgets(line,1024,f);
//
// Load Records
//
while(fgets(line,1024,f)!=NULL) {
fields=fields.split(",",line,"\"");
if(fields.size()==9) {
for(unsigned i=0;i<fields.size();i++) {
fields[i]=fields[i].replace("\"","").stripWhiteSpace();
}
cartnum=fields[3].right(fields[3].length()-1).toUInt(&ok);
if(ok&&(cartnum<=RD_MAX_CART_NUMBER)) {
datelist=datelist.split("/",fields[6]);
if(datelist.size()==3) {
date.setYMD(datelist[2].toInt()+2000,datelist[0].toInt(),
datelist[1].toInt());
if(ValidateFilename(fields[8])) {
if(date.isValid()) {
sql=QString("insert into ISCI_XREFERENCE set ")+
"CART_NUMBER="+QString().sprintf("%u",cartnum)+","+
"ISCI=\""+RDEscapeString(fields[4])+"\","+
"FILENAME=\""+RDEscapeString(fields[8])+"\","+
"LATEST_DATE=\""+date.toString("yyyy/MM/dd")+"\","+
"TYPE=\""+RDEscapeString(fields[0])+"\","+
"ADVERTISER_NAME=\""+RDEscapeString(fields[1])+"\","+
"PRODUCT_NAME=\""+RDEscapeString(fields[2])+"\","+
"CREATIVE_TITLE=\""+RDEscapeString(fields[5])+"\","+
"REGION_NAME=\""+RDEscapeString(fields[7])+"\"";
q=new RDSqlQuery(sql);
delete q;
}
else {
rdconfig->log("rdrepld",RDConfig::LogWarning,QString().
sprintf("invalid date in line %d of \"%s\"",
linenum,(const char *)filename));
}
}
else {
rdconfig->log("rdrepld",RDConfig::LogWarning,QString().
sprintf("invalid FILENAME field \"%s\" in line %d of \"%s\"",
(const char *)fields[8],linenum,(const char *)filename));
}
}
else {
rdconfig->log("rdrepld",RDConfig::LogWarning,QString().
sprintf("invalid date in line %d of \"%s\"",
linenum,(const char *)filename));
}
}
else {
rdconfig->log("rdrepld",RDConfig::LogDebug,QString().
sprintf("missing/invalid cart number in line %d of \"%s\"",
linenum,(const char *)filename));
}
}
else {
rdconfig->log("rdrepld",RDConfig::LogWarning,QString().
sprintf("line %d malformed in \"%s\"",
linenum,(const char *)filename));
}
linenum++;
}
//
// Clean Up
//
rdconfig->log("rdrepld",RDConfig::LogInfo,
QString().sprintf("loaded ISCI cross reference file \"%s\"",
(const char *)rdsystem->isciXreferencePath()));
fclose(f);
return true;
}
bool CitadelXds::ValidateFilename(const QString &filename)
{
bool ret=true;
//
// List of illegal characters taken from 'Illegal Characters4.doc'
// from Citadel
//
ret=ret&&(filename.find(" ")<0);
ret=ret&&(filename.find("\"")<0);
ret=ret&&(filename.find("%")<0);
ret=ret&&(filename.find("*")<0);
ret=ret&&(filename.find("+")<0);
ret=ret&&(filename.find("/")<0);
ret=ret&&(filename.find(":")<0);
ret=ret&&(filename.find(";")<0);
ret=ret&&(filename.find("<")<0);
ret=ret&&(filename.find("=")<0);
ret=ret&&(filename.find(">")<0);
ret=ret&&(filename.find("?")<0);
ret=ret&&(filename.find("@")<0);
ret=ret&&(filename.find("[")<0);
ret=ret&&(filename.find("\\")<0);
ret=ret&&(filename.find("]")<0);
ret=ret&&(filename.find("^")<0);
ret=ret&&(filename.find("{")<0);
ret=ret&&(filename.find("|")<0);
ret=ret&&(filename.find("}")<0);
return ret;
}
void CitadelXds::CheckCarts()
{
QString sql;
RDSqlQuery *q;
RDSqlQuery *q1;
RDSqlQuery *q2;
QString now=QDateTime(QDate::currentDate(),QTime::currentTime()).addDays(-6).
toString("yyyy-MM-dd hh:mm:ss");
//
// Generate Update List
//
sql="select CART_NUMBER,FILENAME from ISCI_XREFERENCE \
where (LATEST_DATE>=now())&&((TYPE=\"R\")||(TYPE=\"B\"))";
q=new RDSqlQuery(sql);
while(q->next()) {
sql=QString().sprintf("select REPL_CART_STATE.ID from \
REPL_CART_STATE left join CUTS \
on REPL_CART_STATE.CART_NUMBER=CUTS.CART_NUMBER \
where (CUTS.ORIGIN_DATETIME<REPL_CART_STATE.ITEM_DATETIME)&&\
(REPL_CART_STATE.REPLICATOR_NAME=\"%s\")&&\
(REPL_CART_STATE.CART_NUMBER=%u)&&\
(REPL_CART_STATE.POSTED_FILENAME=\"%s\")&&\
(REPL_CART_STATE.ITEM_DATETIME>\"%s\")&&\
(REPL_CART_STATE.REPOST=\"N\")",
(const char *)RDEscapeString(config()->name()),
q->value(0).toUInt(),
(const char *)RDEscapeString(q->value(1).toString()),
(const char *)now);
q1=new RDSqlQuery(sql);
if(!q1->first()) {
if(PostCut(RDCut::cutName(q->value(0).toUInt(),1),
q->value(1).toString())) {
sql=QString().sprintf("select ID from REPL_CART_STATE where \
(REPLICATOR_NAME=\"%s\")&&\
(CART_NUMBER=%u)&&\
(POSTED_FILENAME=\"%s\")",
(const char *)RDEscapeString(config()->name()),
q->value(0).toUInt(),
(const char *)RDEscapeString(q->value(1).
toString()));
q2=new RDSqlQuery(sql);
if(q2->first()) {
sql=QString().sprintf("update REPL_CART_STATE set\
ITEM_DATETIME=now(),\
REPOST=\"N\" where \
(REPLICATOR_NAME=\"%s\")&&\
(CART_NUMBER=%u)&&\
(POSTED_FILENAME=\"%s\")",
(const char *)RDEscapeString(config()->name()),
q->value(0).toUInt(),
(const char *)RDEscapeString(q->value(1).
toString()));
}
else {
sql=QString().sprintf("insert into REPL_CART_STATE set \
ITEM_DATETIME=now(),\
REPOST=\"N\",\
REPLICATOR_NAME=\"%s\",\
CART_NUMBER=%u,\
POSTED_FILENAME=\"%s\"",
(const char *)RDEscapeString(config()->name()),
q->value(0).toUInt(),
(const char *)RDEscapeString(q->value(1).
toString()));
}
delete q2;
q2=new RDSqlQuery(sql);
delete q2;
}
}
delete q1;
}
delete q;
}
bool CitadelXds::PostCut(const QString &cutname,const QString &filename)
{
//
// Export File
//
RDAudioConvert::ErrorCode conv_err;
RDUpload::ErrorCode upload_err;
float speed_ratio=1.0;
RDCut *cut=new RDCut(cutname);
if(!cut->exists()) {
delete cut;
return false;
}
if(cut->length()==0) {
delete cut;
return true;
}
RDCart *cart=new RDCart(cut->cartNumber());
if(cart->enforceLength()) {
speed_ratio=(float)cut->length()/(float)cart->forcedLength();
}
RDSettings *settings=new RDSettings();
QString tempfile=RDTempDir()+"/"+filename;
RDAudioConvert *conv=new RDAudioConvert(rdconfig->stationName());
conv->setSourceFile(RDCut::pathName(cutname));
conv->setDestinationFile(tempfile);
conv->setRange(cut->startPoint(),cut->endPoint());
conv->setSpeedRatio(speed_ratio);
settings->setFormat(config()->format());
settings->setChannels(config()->channels());
settings->setSampleRate(config()->sampleRate());
settings->setBitRate(config()->bitRate());
settings->setQuality(config()->quality());
settings->setNormalizationLevel(config()->normalizeLevel()/1000);
conv->setDestinationSettings(settings);
delete cart;
delete cut;
switch(conv_err=conv->convert()) {
case RDAudioConvert::ErrorOk:
break;
default:
rdconfig->log("rdrepld",RDConfig::LogErr,
QString().sprintf("CitadelXds: audio conversion failed: %s, cutname: %s",
(const char *)RDAudioConvert::errorText(conv_err),
(const char *)cutname));
delete conv;
delete settings;
return false;
}
delete conv;
delete settings;
//
// Upload File
//
RDUpload *upload=new RDUpload(rdconfig->stationName());
upload->setSourceFile(tempfile);
upload->setDestinationUrl(config()->url()+"/"+filename);
switch(upload_err=upload->runUpload(config()->urlUsername(),
config()->urlPassword(),
rdconfig->logXloadDebugData())) {
case RDUpload::ErrorOk:
break;
default:
rdconfig->log("rdrepld",RDConfig::LogErr,
QString().sprintf("CitadelXds: audio upload failed: %s",
(const char *)RDUpload::errorText(upload_err)));
unlink(tempfile);
delete upload;
return false;
}
unlink(tempfile);
delete upload;
rdconfig->log("rdrepld",RDConfig::LogInfo,
QString().sprintf("CitadelXds: uploaded cut %s to %s/%s",
(const char *)cutname,
(const char *)config()->url(),
(const char *)filename));
return true;
}
void CitadelXds::PurgeCuts()
{
QString sql;
RDSqlQuery *q;
RDSqlQuery *q1;
RDSqlQuery *q2;
RDDelete *conv;
RDDelete::ErrorCode conv_err;
sql=QString().sprintf("select ID,POSTED_FILENAME from REPL_CART_STATE \
where REPLICATOR_NAME=\"%s\"",
(const char *)RDEscapeString(config()->name()));
q=new RDSqlQuery(sql);
while(q->next()) {
sql=QString().
sprintf("select ID from ISCI_XREFERENCE where FILENAME=\"%s\"",
(const char *)RDEscapeString(q->value(1).toString()));
q1=new RDSqlQuery(sql);
if(!q1->first()) {
QString path=config()->url();
if(path.right(1)!="/") {
path+="/";
}
QUrl url(path+q->value(1).toString());
conv=new RDDelete();
conv->setTargetUrl(url);
if((conv_err=conv->runDelete(config()->urlUsername(),
config()->urlPassword(),
rdconfig->logXloadDebugData()))==
RDDelete::ErrorOk) {
sql=QString().sprintf("delete from REPL_CART_STATE where ID=%d",
q->value(0).toInt());
q2=new RDSqlQuery(sql);
delete q2;
rdconfig->log("rdrepld",RDConfig::LogInfo,
QString().sprintf("purged \"%s\" for replicator \"%s\"",
(const char *)url.toString(),
(const char *)config()->name()));
}
else {
rdconfig->log("rdrepld",RDConfig::LogErr,
QString().sprintf("unable to delete \"%s\" for replicator \"%s\" [%s]",
(const char *)url.toString(),
(const char *)config()->name(),
(const char *)RDDelete::errorText(conv_err)));
}
delete conv;
}
delete q1;
}
delete q;
}

46
rdrepld/citadelxds.h Normal file
View File

@@ -0,0 +1,46 @@
// citadelxds.h
//
// Replicator implementation for the Citadel XDS Portal
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: citadelxds.h,v 1.3 2011/10/17 18:48:41 cvs Exp $
//
// 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 CITADELXDS_H
#define CITADELXDS_H
#include <replfactory.h>
class CitadelXds : public ReplFactory
{
public:
CitadelXds(ReplConfig *config);
void startProcess();
bool processCart(const unsigned cartnum);
private:
void CheckIsciXreference();
bool LoadIsciXreference(const QString &filename);
bool ValidateFilename(const QString &filename);
void CheckCarts();
bool PostCut(const QString &cutname,const QString &filename);
void PurgeCuts();
QDateTime xds_isci_datetime;
};
#endif // CITADELXDS_H

32
rdrepld/globals.h Normal file
View File

@@ -0,0 +1,32 @@
// globals.h
//
// The Rivendell Replicator Daemon Global Definitions
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: globals.h,v 1.2 2010/07/29 19:32:37 cvs Exp $
//
// 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 GLOBALS_H
#define GLOBALS_H
#include <rdconfig.h>
#include <rdsystem.h>
extern RDConfig *rdconfig;
extern RDSystem *rdsystem;
#endif // GLOBALS_H

301
rdrepld/rdrepld.cpp Normal file
View File

@@ -0,0 +1,301 @@
// rdcatchd.cpp
//
// The Rivendell Replicator Daemon
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: rdrepld.cpp,v 1.4 2011/06/21 22:20:44 cvs Exp $
//
// 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 <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <qapplication.h>
#include <rddb.h>
#include <rdconf.h>
#include <rdcmd_switch.h>
#include <rdescape_string.h>
#include <rdcart.h>
#include <dbversion.h>
#include <globals.h>
#include <citadelxds.h>
#include <rdrepld.h>
RDConfig *rdconfig;
RDSystem *rdsystem;
void SigHandler(int signum)
{
pid_t local_pid;
switch(signum) {
case SIGINT:
case SIGTERM:
RDDeletePid(RD_PID_DIR,"rdrepld.pid");
exit(0);
break;
case SIGCHLD:
local_pid=waitpid(-1,NULL,WNOHANG);
while(local_pid>0) {
local_pid=waitpid(-1,NULL,WNOHANG);
}
signal(SIGCHLD,SigHandler);
return;
}
}
MainObject::MainObject(QObject *parent,const char *name)
:QObject(parent,name)
{
bool skip_db_check=false;
unsigned schema=0;
//
// Load the config
//
rdconfig=new RDConfig();
rdconfig->load();
//
// Read Command Options
//
RDCmdSwitch *cmd=
new RDCmdSwitch(qApp->argc(),qApp->argv(),"rdrepld",RDREPLD_USAGE);
for(unsigned i=0;i<cmd->keys();i++) {
if(cmd->key(i)=="--skip-db-check") {
skip_db_check=true;
}
}
//
// Make sure we're the only instance running
//
if(RDCheckDaemon(RD_RDREPLD_PID)) {
printf("rdrepld: aborting - multiple instances not allowed");
exit(1);
}
//
// Initialize Data Structures
//
debug=false;
//
// Calculate Temporary Directory
//
repl_temp_dir=RDTempDir();
//
// Open Database
//
QString err (tr("ERROR rdrepld aborting - "));
repl_db=RDInitDb(&schema,&err);
if(!repl_db) {
printf(err.ascii());
exit(1);
}
if((schema!=RD_VERSION_DATABASE)&&(!skip_db_check)) {
fprintf(stderr,"rdrepld: database version mismatch, should be %u, is %u\n",
RD_VERSION_DATABASE,schema);
exit(256);
}
connect (RDDbStatus(),SIGNAL(logText(RDConfig::LogPriority,const QString &)),
this,SLOT(log(RDConfig::LogPriority,const QString &)));
//
// System Configuration
//
rdsystem=new RDSystem();
//
// Station Configuration
//
repl_station=new RDStation(rdconfig->stationName());
//
// Detach
//
if(qApp->argc()==1) {
RDDetach(rdconfig->logCoreDumpDirectory());
}
else {
debug=true;
}
::signal(SIGINT,SigHandler);
::signal(SIGTERM,SigHandler);
::signal(SIGCHLD,SigHandler);
if(!RDWritePid(RD_PID_DIR,"rdrepld.pid")) {
printf("rdrepld: aborting - can't write pid file\n");
exit(1);
}
//
// Start the Main Loop
//
repl_loop_timer=new QTimer(this,"repl_loop_timer");
connect(repl_loop_timer,SIGNAL(timeout()),this,SLOT(mainLoop()));
repl_loop_timer->start(RD_RDREPL_SCAN_INTERVAL,true);
rdconfig->log("rdrepld",RDConfig::LogNotice,"started");
}
void MainObject::mainLoop()
{
LoadReplicators();
ProcessCarts();
FreeReplicators();
repl_loop_timer->start(RD_RDREPL_SCAN_INTERVAL,true);
}
void MainObject::log(RDConfig::LogPriority prio,const QString &msg)
{
rdconfig->log("rdrepld",prio,msg);
}
void MainObject::ProcessCarts()
{
QString sql;
RDSqlQuery *q;
RDSqlQuery *q1;
RDSqlQuery *q2;
QString repl_name;
QString where;
bool stale;
for(unsigned i=0;i<repl_replicators.size();i++) {
where="";
repl_name=repl_replicators[i]->config()->name();
sql=QString().
sprintf("select GROUP_NAME from REPLICATOR_MAP \
where REPLICATOR_NAME=\"%s\"",
(const char *)RDEscapeString(repl_name));
q=new RDSqlQuery(sql);
while(q->next()) {
where+=QString().
sprintf("(GROUP_NAME=\"%s\")||",
(const char *)RDEscapeString(q->value(0).toString()));
}
delete q;
where=where.left(where.length()-2);
sql=QString().sprintf("select NUMBER,TYPE,METADATA_DATETIME \
from CART where %s",
(const char *)where);
q=new RDSqlQuery(sql);
while(q->next()) {
sql=QString().sprintf("select ID,ITEM_DATETIME from REPL_CART_STATE \
where (REPLICATOR_NAME=\"%s\")&&\
(CART_NUMBER=%u)",
(const char *)RDEscapeString(repl_name),
q->value(0).toUInt());
q1=new RDSqlQuery(sql);
if(q1->first()) {
stale=q->value(2).toDateTime()>q1->value(1).toDateTime();
}
else {
stale=true;
}
if(stale) {
if(repl_replicators[i]->processCart(q->value(0).toUInt())) {
if(q1->isValid()) {
sql=QString().sprintf("update REPL_CART_STATE set \
ITEM_DATETIME=now() where ID=%u",
q1->value(0).toUInt());
}
else {
sql=QString().sprintf("insert into REPL_CART_STATE set \
REPLICATOR_NAME=\"%s\",\
CART_NUMBER=%u,\
ITEM_DATETIME=now()",
(const char *)RDEscapeString(repl_name),
q->value(0).toUInt());
}
q2=new RDSqlQuery(sql);
delete q2;
}
}
delete q1;
}
delete q;
}
}
void MainObject::LoadReplicators()
{
QString sql;
RDSqlQuery *q;
ReplConfig *config;
sql=QString().
sprintf("select NAME,TYPE_ID,FORMAT,CHANNELS,SAMPRATE,\
BITRATE,QUALITY,URL,URL_USERNAME,URL_PASSWORD,\
ENABLE_METADATA,NORMALIZATION_LEVEL from \
REPLICATORS where STATION_NAME=\"%s\"",
(const char *)RDEscapeString(rdconfig->stationName()));
q=new RDSqlQuery(sql);
while(q->next()) {
config=new ReplConfig();
config->setName(q->value(0).toString());
config->setType((RDReplicator::Type)q->value(1).toUInt());
config->setFormat((RDSettings::Format)q->value(2).toUInt());
config->setChannels(q->value(3).toUInt());
config->setSampleRate(q->value(4).toUInt());
config->setBitRate(q->value(5).toUInt());
config->setQuality(q->value(6).toUInt());
config->setUrl(q->value(7).toString());
config->setUrlUsername(q->value(8).toString());
config->setUrlPassword(q->value(9).toString());
config->setEnableMetadata(RDBool(q->value(10).toString()));
config->setNormalizeLevel(q->value(11).toInt());
switch(config->type()) {
case RDReplicator::TypeCitadelXds:
repl_replicators.push_back(new CitadelXds(config));
break;
case RDReplicator::TypeLast:
break;
}
repl_replicators.back()->startProcess();
}
delete q;
}
void MainObject::FreeReplicators()
{
for(unsigned i=0;i<repl_replicators.size();i++) {
delete repl_replicators[i];
}
repl_replicators.clear();
}
int main(int argc,char *argv[])
{
QApplication a(argc,argv,false);
new MainObject(NULL,"main");
return a.exec();
}

65
rdrepld/rdrepld.h Normal file
View File

@@ -0,0 +1,65 @@
// rdrepld.h
//
// The Rivendell Replicator Daemon
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: rdrepld.h,v 1.2 2010/07/29 19:32:37 cvs Exp $
//
// 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 RDREPLD_H
#define RDREPLD_H
#include <vector>
#include <qobject.h>
#include <qtimer.h>
#include <rdcheck_daemons.h>
#include <rdsystem.h>
#include <rdstation.h>
#include <rdconfig.h>
#include <replfactory.h>
#define RDREPLD_USAGE "[-d][--event-id=<id>]\n\nOptions:\n\n-d\n Set 'debug' mode, causing rdrepld(8) to stay in the foreground\n and print debugging info on standard output.\n\n"
#define RD_RDREPLD_PID "rdrepl.pid"
#define RD_RDREPL_SCAN_INTERVAL 10000
class MainObject : public QObject
{
Q_OBJECT
public:
MainObject(QObject *parent=0,const char *name=0);
private slots:
void mainLoop();
void log(RDConfig::LogPriority prio,const QString &line);
private:
void ProcessCarts();
void LoadReplicators();
void FreeReplicators();
QTimer *repl_loop_timer;
QString repl_temp_dir;
RDStation *repl_station;
QSqlDatabase *repl_db;
std::vector<ReplFactory *> repl_replicators;
bool debug;
};
#endif // RDREPLD_H

216
rdrepld/replconfig.cpp Normal file
View File

@@ -0,0 +1,216 @@
// replconfig.cpp
//
// A container class for a Rivendell replication configuration
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: replconfig.cpp,v 1.2 2010/07/29 19:32:37 cvs Exp $
//
// 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 <rd.h>
#include <replconfig.h>
ReplConfig::ReplConfig()
{
clear();
}
RDReplicator::Type ReplConfig::type() const
{
return repl_type;
}
void ReplConfig::setType(RDReplicator::Type type)
{
repl_type=type;
}
QString ReplConfig::name() const
{
return repl_name;
}
void ReplConfig::setName(const QString &str)
{
repl_name=str;
}
QString ReplConfig::stationName() const
{
return repl_station_name;
}
void ReplConfig::setStationName(const QString &str)
{
repl_station_name=str;
}
QString ReplConfig::description() const
{
return repl_description;
}
void ReplConfig::setDescription(const QString &str)
{
repl_description=str;
}
RDSettings::Format ReplConfig::format() const
{
return repl_format;
}
void ReplConfig::setFormat(RDSettings::Format fmt)
{
repl_format=fmt;
}
unsigned ReplConfig::channels() const
{
return repl_channels;
}
void ReplConfig::setChannels(unsigned chans)
{
repl_channels=chans;
}
unsigned ReplConfig::sampleRate() const
{
return repl_sample_rate;
}
void ReplConfig::setSampleRate(unsigned rate)
{
repl_sample_rate=rate;
}
unsigned ReplConfig::bitRate() const
{
return repl_bit_rate;
}
void ReplConfig::setBitRate(unsigned rate)
{
repl_bit_rate=rate;
}
unsigned ReplConfig::quality() const
{
return repl_quality;
}
void ReplConfig::setQuality(unsigned qual)
{
repl_quality=qual;
}
QString ReplConfig::url() const
{
return repl_url;
}
void ReplConfig::setUrl(const QString &str)
{
repl_url=str;
}
QString ReplConfig::urlUsername() const
{
return repl_url_username;
}
void ReplConfig::setUrlUsername(const QString &str)
{
repl_url_username=str;
}
QString ReplConfig::urlPassword() const
{
return repl_url_password;
}
void ReplConfig::setUrlPassword(const QString &str)
{
repl_url_password=str;
}
bool ReplConfig::enableMetadata() const
{
return repl_enable_metadata;
}
void ReplConfig::setEnableMetadata(bool state)
{
repl_enable_metadata=state;
}
int ReplConfig::normalizeLevel() const
{
return repl_normalize_level;
}
void ReplConfig::setNormalizeLevel(int lvl)
{
repl_normalize_level=lvl;
}
void ReplConfig::clear()
{
repl_name="";
repl_station_name="";
repl_description="";
repl_format=RDSettings::Pcm16;
repl_channels=2;
repl_sample_rate=RD_DEFAULT_SAMPLE_RATE;
repl_bit_rate=0;
repl_quality=0;
repl_url="";
repl_url_username="";
repl_url_password="";
repl_enable_metadata=false;
repl_normalize_level=0;
}

83
rdrepld/replconfig.h Normal file
View File

@@ -0,0 +1,83 @@
// replconfig.h
//
// A container class for a Rivendell replication configuration
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: replconfig.h,v 1.2 2010/07/29 19:32:37 cvs Exp $
//
// 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 REPLCONFIG_H
#define REPLCONFIG_H
#include <qtimer.h>
#include <rdsettings.h>
#include <rdreplicator.h>
class ReplConfig
{
public:
ReplConfig();
RDReplicator::Type type() const;
void setType(RDReplicator::Type type);
QString name() const;
void setName(const QString &str);
QString stationName() const;
void setStationName(const QString &str);
QString description() const;
void setDescription(const QString &str);
RDSettings::Format format() const;
void setFormat(RDSettings::Format fmt);
unsigned channels() const;
void setChannels(unsigned chans);
unsigned sampleRate() const;
void setSampleRate(unsigned rate);
unsigned bitRate() const;
void setBitRate(unsigned rate);
unsigned quality() const;
void setQuality(unsigned qual);
QString url() const;
void setUrl(const QString &str);
QString urlUsername() const;
void setUrlUsername(const QString &str);
QString urlPassword() const;
void setUrlPassword(const QString &str);
bool enableMetadata() const;
void setEnableMetadata(bool state);
int normalizeLevel() const;
void setNormalizeLevel(int lvl);
void clear();
private:
QString repl_name;
RDReplicator::Type repl_type;
QString repl_station_name;
QString repl_description;
RDSettings::Format repl_format;
unsigned repl_channels;
unsigned repl_sample_rate;
unsigned repl_bit_rate;
unsigned repl_quality;
QString repl_url;
QString repl_url_username;
QString repl_url_password;
bool repl_enable_metadata;
int repl_normalize_level;
};
#endif // REPLCONFIG_H

40
rdrepld/replfactory.cpp Normal file
View File

@@ -0,0 +1,40 @@
// replfactory.cpp
//
// Virtual base class for replicator methods
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: replfactory.cpp,v 1.2 2010/07/29 19:32:37 cvs Exp $
//
// 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 <replfactory.h>
ReplFactory::ReplFactory(ReplConfig *config)
{
repl_config=config;
}
ReplFactory::~ReplFactory()
{
delete repl_config;
}
ReplConfig *ReplFactory::config() const
{
return repl_config;
}

43
rdrepld/replfactory.h Normal file
View File

@@ -0,0 +1,43 @@
// replfactory.h
//
// Virtual base class for replicator methods
//
// (C) Copyright 2010 Fred Gleason <fredg@paravelsystems.com>
//
// $Id: replfactory.h,v 1.2 2010/07/29 19:32:37 cvs Exp $
//
// 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 REPLFACTORY_H
#define REPLFACTORY_H
#include <globals.h>
#include <replconfig.h>
class ReplFactory
{
public:
ReplFactory(ReplConfig *config);
~ReplFactory();
ReplConfig *config() const;
virtual void startProcess()=0;
virtual bool processCart(const unsigned cartnum)=0;
private:
ReplConfig *repl_config;
};
#endif // REPLCONFIG_H