bool TSqlTransaction::begin(QSqlDatabase &database) { if (!database.isValid()) { tSystemError("Can not begin transaction. Invalid database: %s", qPrintable(database.connectionName())); return false; } if (!enabled) return true; bool ok; int id = database.connectionName().left(2).toInt(&ok); if (!ok || id < 0 || id >= databases.count()) { tSystemError("Internal Error [%s:%d]", __FILE__, __LINE__); return false; } if (databases[id].isValid()) { tSystemWarn("Has begun transaction already. database:%s", qPrintable(database.connectionName())); return true; } if (database.transaction()) { tQueryLog("[BEGIN] [databaseId:%d]", id); } databases[id] = database; return true; }
bool TThreadApplicationServer::start(bool debugMode) { if (isListening()) { return true; } bool res = loadLibraries(); if (!res) { if (debugMode) { tSystemError("Failed to load application libraries."); return false; } else { tSystemWarn("Failed to load application libraries."); } } if (listenSocket <= 0 || !setSocketDescriptor(listenSocket)) { tSystemError("Failed to set socket descriptor: %d", listenSocket); return false; } // instantiate if (!debugMode) { TSystemBus::instantiate(); TPublisher::instantiate(); } TUrlRoute::instantiate(); TSqlDatabasePool::instantiate(); TKvsDatabasePool::instantiate(); TStaticInitializeThread::exec(); return true; }
bool TSessionSqlObjectStore::store(TSession &session) { TSqlORMapper<TSessionObject> mapper; TCriteria cri(TSessionObject::Id, TSql::Equal, session.id()); TSessionObject so = mapper.findFirst(cri); #ifndef TF_NO_DEBUG { QByteArray badummy; QDataStream dsdmy(&badummy, QIODevice::ReadWrite); dsdmy << *static_cast<const QVariantMap *>(&session); TSession dummy; dsdmy.device()->seek(0); dsdmy >> *static_cast<QVariantMap *>(&dummy); if (dsdmy.status() != QDataStream::Ok) { tSystemError("Failed to store a session into the cookie store. Must set objects that can be serialized."); } } #endif QDataStream ds(&so.data, QIODevice::WriteOnly); ds << *static_cast<const QVariantMap *>(&session); if (ds.status() != QDataStream::Ok) { tSystemError("Failed to store session. Must set objects that can be serialized."); return false; } if (so.isNull()) { so.id = session.id(); return so.create(); } return so.update(); }
bool TApplicationServer::open() { T_TRACEFUNC(); if (!isListening()) { quint16 port = Tf::app()->treefrogSettings().value("ListenPort").toUInt(); if (!nativeListen(QHostAddress::Any, port)) { tSystemError("listen failed. port:%d", port); return false; } else { tSystemDebug("listen successfully. port:%d", port); } } // Loads libraries if (!libLoaded) { // Sets work directory QString libPath = Tf::app()->libPath(); if (QDir(libPath).exists()) { // To resolve the symbols in the app libraries QDir::setCurrent(libPath); } else { tSystemError("lib directory not found"); return false; } QStringList filter; #if defined(Q_OS_WIN) filter << "controller.dll" << "view.dll"; #elif defined(Q_OS_DARWIN) filter << "libcontroller.dylib" << "libview.dylib"; #elif defined(Q_OS_UNIX) filter << "libcontroller.so" << "libview.so"; #else filter << "libcontroller.*" << "libview.*"; #endif QDir controllerDir("."); QStringList list = controllerDir.entryList(filter, QDir::Files); for (QStringListIterator i(list); i.hasNext(); ) { QString path = controllerDir.absoluteFilePath(i.next()); QLibrary lib(path); if (lib.load()) { tSystemDebug("Library loaded: %s", qPrintable(path)); libLoaded = true; } else { tSystemDebug("%s", qPrintable(lib.errorString())); } } } TUrlRoute::initialize(); TSqlDatabasePool::initialize(); return true; }
/*! Listen for connections on UNIX domain. */ int TApplicationServerBase::nativeListen(const QString &fileDomain, OpenFlag flag) { int sd = -1; struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = PF_UNIX; if (sizeof(addr.sun_path) < (uint)fileDomain.toLatin1().size() + 1) { tSystemError("too long name for UNIX domain socket [%s:%d]", __FILE__, __LINE__); return sd; } strncpy(addr.sun_path, fileDomain.toLatin1().data(), sizeof(addr.sun_path)); // create unix domain socket sd = ::socket(PF_UNIX, SOCK_STREAM, 0); if (sd < 0) { tSystemError("Socket create failed [%s:%d]", __FILE__, __LINE__); return sd; } if (flag == CloseOnExec) { ::fcntl(sd, F_SETFD, FD_CLOEXEC); // set close-on-exec flag } ::fcntl(sd, F_SETFL, ::fcntl(sd, F_GETFL) | O_NONBLOCK); // non-block QFile file(fileDomain); if (file.exists()) { file.remove(); tSystemWarn("File for UNIX domain socket removed: %s", qPrintable(fileDomain)); } // Bind if (::bind(sd, (sockaddr *)&addr, sizeof(sockaddr_un)) < 0) { tSystemError("Bind failed [%s:%d]", __FILE__, __LINE__); goto socket_error; } file.setPermissions((QFile::Permissions)0x777); // Listen if (::listen(sd, 50) < 0) { tSystemError("Listen failed [%s:%d]", __FILE__, __LINE__); goto socket_error; } return sd; socket_error: nativeClose(sd); return -1; }
bool TSessionRedisStore::store(TSession &session) { QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); ds << *static_cast<const QVariantMap *>(&session); data = qCompress(data, 1).toBase64(); #ifndef TF_NO_DEBUG { QByteArray badummy; QDataStream dsdmy(&badummy, QIODevice::ReadWrite); dsdmy << *static_cast<const QVariantMap *>(&session); TSession dummy; dsdmy.device()->seek(0); dsdmy >> *static_cast<QVariantMap *>(&dummy); if (dsdmy.status() != QDataStream::Ok) { tSystemError("Failed to store a session into the cookie store. Must set objects that can be serialized."); } } #endif TRedis redis; tSystemDebug("TSessionRedisStore::store id:%s", session.id().data()); return redis.setEx('_' + session.id(), data, lifeTimeSecs()); }
bool TMongoDriver::updateMulti(const QString &collection, const QVariantMap &criteria, const QVariantMap &object) { if (!isOpen()) { return false; } errorCode = 0; errorString.clear(); bson_error_t error; mongoc_collection_t *col = mongoc_client_get_collection(mongoClient, qPrintable(dbName), qPrintable(collection)); bool res = mongoc_collection_update(col, MONGOC_UPDATE_MULTI_UPDATE, (bson_t *)TBson::toBson(criteria).data(), (bson_t *)TBson::toBson(object).data(), nullptr, &error); setLastCommandStatus(mongoc_collection_get_last_error(col)); mongoc_collection_destroy(col); if (!res) { tSystemError("MongoDB UpdateMulti Error: %s", error.message); errorCode = error.code; errorString = QLatin1String(error.message); } return res; }
bool TSendmailMailer::send() { QMutexLocker locker(&sendMutex); // Global lock for load reduction of mail server if (sendmailCmd.isEmpty()) { return false; } QStringList args; QByteArray rawmail = mailMessage.toByteArray(); const QList<QByteArray> recipients = mailMessage.recipients(); for (auto &recipt : recipients) { args.clear(); args << recipt; QProcess sendmail; sendmail.start(sendmailCmd, args); if (!sendmail.waitForStarted(5000)) { tSystemError("Sendmail error. CMD: %s", qPrintable(sendmailCmd)); return false; } sendmail.write(rawmail); sendmail.write("\n.\n"); sendmail.waitForFinished(); tSystemDebug("Mail sent. Recipients: %s", recipt.data()); } return true; }
bool TSqlObject::create() { // Sets the default value of 'revision' property int index = metaObject()->indexOfProperty(REVISION_PROPERTY_NAME); if (index >= 0) { setProperty(REVISION_PROPERTY_NAME, 1); // 1 : default value } // Sets the values of 'created_at' and 'updated_at' properties for (int i = metaObject()->propertyOffset(); i < metaObject()->propertyCount(); ++i) { const char *propName = metaObject()->property(i).name(); if (QLatin1String("created_at") == propName || QLatin1String("updated_at") == propName) { setProperty(propName, QDateTime::currentDateTime()); } } syncToSqlRecord(); QString ins = TActionContext::currentDatabase().driver()->sqlStatement(QSqlDriver::InsertStatement, tableName(), *static_cast<QSqlRecord *>(this), false); if (ins.isEmpty()) { sqlError = QSqlError(QLatin1String("No fields to insert"), QString(), QSqlError::StatementError); tWarn("SQL statement error, no fields to insert"); return false; } tSystemDebug("SQL statement: %s", qPrintable(ins)); QSqlQuery query(TActionContext::currentDatabase()); bool res = query.exec(ins); sqlError = query.lastError(); if (!res) { tSystemError("SQL insert error: %s", qPrintable(sqlError.text())); } return res; }
bool TSqlObject::remove() { syncToSqlRecord(); QString del = TActionContext::currentDatabase().driver()->sqlStatement(QSqlDriver::DeleteStatement, tableName(), *static_cast<QSqlRecord *>(this), false); if (del.isEmpty()) { sqlError = QSqlError(QLatin1String("Unable to delete row"), QString(), QSqlError::StatementError); return false; } del.append(" WHERE "); int revIndex = metaObject()->indexOfProperty(REVISION_PROPERTY_NAME); if (revIndex >= 0) { bool ok; int revsion = property(REVISION_PROPERTY_NAME).toInt(&ok); if (!ok || revsion <= 0) { sqlError = QSqlError(QLatin1String("Unable to convert the 'revision' property to an int"), QString(), QSqlError::UnknownError); tError("Unable to convert the 'revsion' property to an int, %s", qPrintable(objectName())); return false; } del.append(TSqlQuery::escapeIdentifier(REVISION_PROPERTY_NAME)); del.append("=").append(TSqlQuery::formatValue(revsion)); del.append(" AND "); } const char *pkName = metaObject()->property(metaObject()->propertyOffset() + primaryKeyIndex()).name(); if (primaryKeyIndex() < 0 || !pkName) { QString msg = QString("Not found the primary key for table ") + tableName(); sqlError = QSqlError(msg, QString(), QSqlError::StatementError); tError("%s", qPrintable(msg)); return false; } del.append(TSqlQuery::escapeIdentifier(pkName)); del.append("=").append(TSqlQuery::formatValue(property(pkName))); tSystemDebug("SQL statement: %s", qPrintable(del)); QSqlQuery query(TActionContext::currentDatabase()); bool res = query.exec(del); sqlError = query.lastError(); if (!res) { tSystemError("SQL delete error: %s", qPrintable(sqlError.text())); return false; } // Optimistic lock check if (query.numRowsAffected() != 1) { if (revIndex >= 0) { QString msg = QString("Row was updated or deleted from table ") + tableName() + QLatin1String(" by another transaction"); sqlError = QSqlError(msg, QString(), QSqlError::UnknownError); throw SqlException(msg, __FILE__, __LINE__); } tWarn("Row was deleted by another transaction, %s", qPrintable(tableName())); } clear(); return true; }
TSession TSessionCookieStore::find(const QByteArray &id, const QDateTime &) { TSession session; if (id.isEmpty()) return session; QList<QByteArray> balst = id.split('_'); if (balst.count() == 2 && !balst.value(0).isEmpty() && !balst.value(1).isEmpty()) { QByteArray ba = QByteArray::fromHex(balst.value(0)); QByteArray digest = QCryptographicHash::hash(ba + Tf::app()->appSettings().value("Session.Secret").toByteArray(), QCryptographicHash::Sha1); if (digest != QByteArray::fromHex(balst.value(1))) { tSystemWarn("Recieved a tampered cookie or that of other web application."); //throw SecurityException("Tampered with cookie", __FILE__, __LINE__); return session; } QDataStream ds(&ba, QIODevice::ReadOnly); ds >> *static_cast<QVariantHash *>(&session); if (ds.status() != QDataStream::Ok) { tSystemError("Unable to load a session from the cookie store."); session.clear(); } }
void TFileAioLogger::log(const QByteArray &msg) { QMutexLocker locker(&d->mutex); Q_ASSERT(isOpen()); // check whether last writing is finished if (d->syncBuffer.count() > 0) { struct aiocb *lastcb = d->syncBuffer.last(); if (aio_error(lastcb) != EINPROGRESS) { d->clearSyncBuffer(); } } struct aiocb *cb = new struct aiocb; memset(cb, 0, sizeof(struct aiocb)); cb->aio_fildes = d->fileDescriptor; cb->aio_nbytes = msg.length(); cb->aio_buf = new char[msg.length()]; memcpy((void *)cb->aio_buf, msg.data(), msg.length()); if (tf_aio_write(cb) < 0) { tSystemError("log write failed"); delete[] (char *)cb->aio_buf; delete cb; close(); return; } d->syncBuffer << cb; }
/*! Loads a query from the given file \a filename. */ bool TSqlQuery::load(const QString &filename) { QMutexLocker locker(&cacheMutex); QString query = queryCache.value(filename); if (!query.isEmpty()) { return QSqlQuery::prepare(query); } QDir dir(queryDirPath()); QFile file(dir.filePath(filename)); tSystemDebug("SQL_QUERY_ROOT: %s", qPrintable(dir.dirName())); tSystemDebug("filename: %s", qPrintable(file.fileName())); if (!file.open(QIODevice::ReadOnly)) { tSystemError("Unable to open file: %s", qPrintable(file.fileName())); return false; } query = QObject::tr(file.readAll().constData()); bool res = QSqlQuery::prepare(query); if (res) { // Caches the query-string queryCache.insert(filename, query); } return res; }
bool TMongoDriver::find(const QString &collection, const QVariantMap &criteria, const QVariantMap &orderBy, const QStringList &fields, int limit, int skip, int ) { if (!isOpen()) { return false; } errorCode = 0; errorString.clear(); mongoc_collection_t *col = mongoc_client_get_collection(mongoClient, qPrintable(dbName), qPrintable(collection)); mongoc_cursor_t *cursor = mongoc_collection_find(col, MONGOC_QUERY_NONE, skip, limit, 0, (bson_t *)TBson::toBson(criteria, orderBy).data(), (bson_t *)TBson::toBson(fields).data(), nullptr); /* Read Prefs, nullptr for default */ setLastCommandStatus(mongoc_collection_get_last_error(col)); mongoc_collection_destroy(col); mongoCursor->setCursor(cursor); if (cursor) { bson_error_t error; if (mongoc_cursor_error(cursor, &error)) { errorCode = error.code; errorString = QLatin1String(error.message); } } else { tSystemError("MongoDB Cursor Error"); } return (bool)cursor; }
/*! Reads the settings stored in the file \a logger.ini. */ void TLogger::readSettings() { // Sets the codec QSettings &settings = Tf::app()->loggerSettings(); QByteArray codecName = settings.value(DEFAULT_TEXT_ENCODING).toByteArray().trimmed(); if (!codecName.isEmpty()) { QTextCodec *c = QTextCodec::codecForName(codecName); if (c) { if (c->name() != QTextCodec::codecForLocale()->name()) { codec_ = c; } //tSystemDebug("set log text codec: %s", c->name().data()); } else { tSystemError("log text codec matching the name could be not found: %s", codecName.data()); } } layout_ = settingsValue("Layout", "%m%n").toByteArray(); dateTimeFormat_ = settingsValue("DateTimeFormat").toByteArray(); QByteArray pri = settingsValue("Threshold", "trace").toByteArray().toUpper().trimmed(); threshold_ = priorityHash()->key(pri, TLogger::Trace); QFileInfo fi(settingsValue("Target", "log/app.log").toString()); target_ = (fi.isAbsolute()) ? fi.absoluteFilePath() : Tf::app()->webRootPath() + fi.filePath(); QDir dir = QFileInfo(target_).dir(); if (!dir.exists()) { // Created a directory dir.mkpath("."); } }
bool TSmtpMailer::connectToHost(const QString &hostName, quint16 port) { socket->connectToHost(hostName, port); if (!socket->waitForConnected(5000)) { tSystemError("SMTP server connect error: %s", qPrintable(socket->errorString())); return false; } return (read() == 220); }
QList<TLog> TSharedMemoryLogStream::smRead() { QList<TLog> logs; if (!shareMem->data()) { tSystemError("Shared memory not attached"); return logs; } QByteArray buffer((char *)shareMem->data(), shareMem->size()); QDataStream ds(&buffer, QIODevice::ReadOnly); ds >> logs; if (ds.status() != QDataStream::Ok) { tSystemError("Shared memory read error"); clearBuffer(); return QList<TLog>(); } return logs; }
TEpoll::TEpoll() : epollFd(0), events(new struct epoll_event[MaxEvents]), polling(false), numEvents(0), eventIterator(0), pollingSockets() { epollFd = epoll_create(1); if (epollFd < 0) { tSystemError("Failed epoll_create()"); } }
void ServerManager::errorDetect(QProcess::ProcessError error) { QProcess *server = qobject_cast<QProcess *>(sender()); if (server) { tSystemError("tfserver error detected(%d). [%s]", error, TFSERVER_CMD); //server->close(); // long blocking.. server->kill(); } }
bool TMongoDriver::open(const QString &db, const QString &user, const QString &password, const QString &host, quint16 port, const QString &) { if (host.isEmpty()) { return false; } if (!port) port = MONGO_DEFAULT_PORT; mongo_clear_errors(mongoConnection); mongo_set_op_timeout(mongoConnection, 1000); int status = mongo_client(mongoConnection, qPrintable(host), port); if (status != MONGO_OK) { switch (mongoConnection->err) { case MONGO_CONN_NO_SOCKET: tSystemError("MongoDB socket error: %s", mongoConnection->lasterrstr); break; case MONGO_CONN_FAIL: tSystemError("MongoDB connection failed: %s", mongoConnection->lasterrstr); break; case MONGO_CONN_NOT_MASTER: tSystemDebug("MongoDB not master: %s", mongoConnection->lasterrstr); break; default: tSystemError("MongoDB error: %s", mongoConnection->lasterrstr); break; } return false; } if (!user.isEmpty()) { status = mongo_cmd_authenticate(mongoConnection, qPrintable(db), qPrintable(user), qPrintable(password)); if (status != MONGO_OK) { tSystemDebug("MongoDB authentication error: %s", mongoConnection->lasterrstr); return false; } } return (status == MONGO_OK); }
void TEpoll::dispatchSendData() { TSendData *sd; while (sendRequests.dequeue(sd)) { TEpollSocket *sock = sd->socket; if (Q_UNLIKELY(sock->socketDescriptor() <= 0)) { tSystemDebug("already disconnected: sid:%d", sock->socketId()); continue; } switch (sd->method) { case TSendData::Disconnect: deletePoll(sock); sock->close(); sock->deleteLater(); break; case TSendData::SwitchToWebSocket: { tSystemDebug("Switch to WebSocket"); Q_ASSERT(sd->buffer == nullptr); QByteArray secKey = sd->header.rawHeader("Sec-WebSocket-Key"); tSystemDebug("secKey: %s", secKey.data()); int newsocket = TApplicationServerBase::duplicateSocket(sock->socketDescriptor()); // Switch to WebSocket TEpollWebSocket *ws = new TEpollWebSocket(newsocket, sock->peerAddress(), sd->header); ws->moveToThread(Tf::app()->thread()); addPoll(ws, (EPOLLIN | EPOLLOUT | EPOLLET)); // reset // Stop polling and delete deletePoll(sock); sock->deleteLater(); // WebSocket opening TSession session; QByteArray sessionId = sd->header.cookie(TSession::sessionName()); if (!sessionId.isEmpty()) { // Finds a session session = TSessionManager::instance().findSession(sessionId); } ws->startWorkerForOpening(session); break; } default: tSystemError("Logic error [%s:%d]", __FILE__, __LINE__); if (sd->buffer) { delete sd->buffer; } break; } delete sd; } }
/*! \~english Logs the user \a user in to the system. This is a virtual function. \~japanese ユーザ \a user をシステムへログインさせる \~ \sa userLogout() */ bool TActionController::userLogin(const TAbstractUser *user) { if (!user) { tSystemError("userLogin: null specified"); return false; } if (user->identityKey().isEmpty()) { tSystemError("userLogin: identityKey empty"); return false; } if (isUserLoggedIn()) { tSystemWarn("userLogin: Duplicate login detected. Force logout [user:%s]", qPrintable(identityKeyOfLoginUser())); } session().insert(LOGIN_USER_NAME_KEY, user->identityKey()); return true; }
/*! Finds documents by the criteria \a criteria in the collection and returns a retrieved document as a QVariantMap object. Use the \a fields parameter to control the fields to return. */ QVariantMap TMongoQuery::findOne(const QVariantMap &criteria, const QStringList &fields) { if (!database.isValid()) { tSystemError("TMongoQuery::findOne : driver not loaded"); return QVariantMap(); } lastWriteStatus.clear(); return driver()->findOne(nameSpace, criteria, fields); }
int TMongoQuery::count(const QVariantMap &criteria) { if (!database.isValid()) { tSystemError("TMongoQuery::count : driver not loaded"); return -1; } lastWriteStatus.clear(); return driver()->count(nameSpace, criteria); }
/*! Finds documents by the criteria \a criteria in the collection and returns the number of the documents. Use the \a fields parameter to control the fields to return. \sa TMongoQuery::next() */ int TMongoQuery::find(const QVariantMap &criteria, const QVariantMap &orderBy, const QStringList &fields) { if (!database.isValid()) { tSystemError("TMongoQuery::find : driver not loaded"); return false; } lastWriteStatus.clear(); return driver()->find(nameSpace, criteria, orderBy, fields, queryLimit, queryOffset, 0); }
/*! Removes documents that matches the \a criteria from the collection. */ bool TMongoQuery::remove(const QVariantMap &criteria) { if (!database.isValid()) { tSystemError("TMongoQuery::remove : driver not loaded"); return false; } bool ret = driver()->remove(nameSpace, criteria); lastWriteStatus = driver()->getLastCommandStatus(database.databaseName()); return ret; }
bool TMongoDriver::updateMulti(const QString &ns, const QVariantMap &criteria, const QVariantMap &object) { mongo_clear_errors(mongoConnection); int status = mongo_update(mongoConnection, qPrintable(ns), (const bson *)TBson::toBson(criteria).data(), (const bson *)TBson::toBson(object).data(), MONGO_UPDATE_MULTI, 0); if (status != MONGO_OK) { tSystemError("MongoDB Error: %s", mongoConnection->lasterrstr); return false; } return true; }
bool TMongoDriver::remove(const QString &ns, const QVariantMap &object) { mongo_clear_errors(mongoConnection); int status = mongo_remove(mongoConnection, qPrintable(ns), (const bson *)TBson::toBson(object).data(), 0); if (status != MONGO_OK) { tSystemError("MongoDB Error: %s", mongoConnection->lasterrstr); return false; } return true; }
void TWebApplication::ignoreUnixSignal(int sig, bool ignore) { if (sig < NSIG) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_RESTART; sa.sa_handler = (ignore) ? SIG_IGN : SIG_DFL; if (sigaction(sig, &sa, 0) != 0) tSystemError("sigaction failed errno:%d", errno); } }
/*! Updates an existing document of the selection criteria \a criteria in the collection with new document \a document. When the \a upsert is true, inserts the document in the collection if no document matches the \a criteria. */ bool TMongoQuery::update(const QVariantMap &criteria, const QVariantMap &document, bool upsert) { if (!database.isValid()) { tSystemError("TMongoQuery::update : driver not loaded"); return false; } bool ret = driver()->update(nameSpace, criteria, document, upsert); lastWriteStatus = driver()->getLastCommandStatus(database.databaseName()); return ret; }