MySQL und Shared-memory Verbindung [gelöst]

Alles rund um die Programmierung mit Qt
Antworten
patrikD
Beiträge: 22
Registriert: 21. Mai 2007 14:01

MySQL und Shared-memory Verbindung [gelöst]

Beitrag von patrikD »

Hallo zusammen,

hat hier jemand schon mal erfolgreich über Qt eine Shared-memory-connection zu einem standalone MySQL-Server hin bekommen?
Ich bekomm das einfach nicht hin. Verbindung über TCP funktioniert gut aber wenn ich die Konfiguration auf Shared mem umstelle dann kommt immer:
"Can't connect to MySQL server on 'localhost' (10061) QMYSQL: Unable to connect"
Umstellen der Konf. bedeutet:
mysql.ini:

Code: Alles auswählen

skip-networking
shared-memory
shared-memory-base-name=TestApplication
enable-named-pipe
socket=mysql-TestApplication.sock
bind-address=127.0.0.1
port=3333
init-connect="SET NAMES UTF8"
basedir="../"
datadir="../Data/"
default-character-set=UTF8
collation_server=utf8_unicode_ci
default-storage-engine=INNODB
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
Und bei der Connection:

Code: Alles auswählen

setConnectOptions("protocol=memory;shared-memory-base-name=TestApplication;");
MySQL Version: 5.1.26, QT 4.3.4

Danke,
Patrik
Zuletzt geändert von patrikD am 5. August 2008 15:42, insgesamt 1-mal geändert.
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag von patrik08 »

wo ist das "Shared" auf dem server oder auf dem client?
lese QSharedDataPointer..

Ich mache mir eine QUrl zum mysql verbinden
sieht so aus : mysql://username:pass@host:port/database

doch befor ich den mysql client auf dem server abfrage mache ich den port scan .. da man keinen TimeOut setzen kann in qmysql

den port muss innerhalb 500 millisekunden erreichbar sein...

Code: Alles auswählen

class ScanPort : public QThread
{
    Q_OBJECT
public:
  void SetUrl( QUrl check_url , int maxtime = 500 , QObject * redirect = 0 )
  {
    url =  check_url;
    receiver = redirect;
    Timeout = maxtime;
    setTerminationEnabled(true);
  }
protected:
void run()
{
    QTime st = QTime::currentTime();
    m_Socket = new QTcpSocket();
    m_Socket->connectToHost(url.host(),url.port(),QIODevice::ReadOnly);
    if (m_Socket->waitForConnected(Timeout))  {
        if (m_Socket->waitForReadyRead(Timeout)) {
            ////////////qDebug() << "### connect ok port " << url.port();
            QTextStream *t = new QTextStream( m_Socket );
            t->setCodec(QTextCodec::codecForMib(106));
            int loops = 0;
                   while (!t->atEnd()) {
                      loops++;
                      response = t->readLine();
                      ///////qDebug() << loops << " line  " << response;
                    }
            emit result(url.port(),runtime(st),true);
            quit();
        } else {
        m_Socket->close();
        ////////qDebug() << "### connect nooo on  port " << url.port();
        emit result(url.port(),runtime(st),false);
        quit();
        }
    } else {
        m_Socket->close();
        /////////qDebug() << "### connect nooo on  port " << url.port();
        emit result(url.port(),runtime(st),false);
        quit();
    }
}
int runtime( QTime go )
{
    QTime now = QTime::currentTime();
    return go.msecsTo ( now );
}
signals:
   void result(int,int,bool);  /* port , time , true = ok */
private:
    QString response;
    int Timeout;
    QTcpSocket *m_Socket;
    uint millisecond;
    QUrl url;
    QObject* receiver;
};


wenn das der fall ist dann verbinde ich den mysql client ...
bei unterbrechung gebe ich mit signale dass ganze von vorne...
fuktioniert aber nur wenn ich den envoirment QT_FATAL_WARNINGS = 1 setze ... warum weiss ich auch nicht...
wenn ich QT_FATAL_WARNINGS nicht setze sturtz die apps..
ich nehme an das es die Q_ASSERT (false) unterdruckt... und trotzdem weiter geht...
.........................
speack português italiano deutsch english castellà qt
patrikD
Beiträge: 22
Registriert: 21. Mai 2007 14:01

Beitrag von patrikD »

Hi Patrik,

danke für die Antwort. Leider löst das mein Problem nicht :( Will ja keine TCP-Verbindung(u.a. wegen FireWall). Das Shared mem läuft nicht über QSharedDataPointer sondern über den impliziten Mechanismus der von MySQL als Verbindungsmöglichkeit angeboten wird. (und hoffentlich vom Treiber-Plugin unterstützt wird)

Lg
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Beitrag von patrik08 »

patrikD hat geschrieben:Hi Patrik,
n MySQL als Verbindungsmöglichkeit angeboten wird. (und hoffentlich vom Treiber-Plugin unterstützt wird)
Lg
Eben nicht.. QMYSQL kann eben nur dass essenzielle was normal brauchbar ist.
Es is aber nicht schwierig sich eine statische lib von mysql zu schreiben.

Ich habe auch bereits eine lib geschrieben fuer sqlite3 die mit qt geht ...
https://qtexcel-xslt.svn.sourceforge.ne ... ite_table/
.........................
speack português italiano deutsch english castellà qt
patrikD
Beiträge: 22
Registriert: 21. Mai 2007 14:01

Beitrag von patrikD »

Holla die Waldfee......
Ganz so viel Aufwand wollt ich mir nicht machen. Ist es nicht vielleicht möglich den Treiber anzupassen, so das er den Parameter unterstützt?
Vielleicht versteh ich das ja falsch, aber ich hab den Treiber als Wrapper für die MySql-dll gesehen. Also einfach ne High-Level-API für die dll-Aufrufe.

Lg
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Sollt es auch sein ... iss aber leider nur so, dass die standard methoden abgedeckt werden.
versuch mal z.b. die verbindung zum Mysql-Server mit SSL zu verschluesseln ! Die mysql-Api bietet da funktionen fuer an, in dem Mysql plugin von der QT, zumidnest bis version 4.3 ... aber in der 4.4 hab ich auf die schnelle auch noch nix gesehen ... kann man diese parameter ned setzen.
Man muss also haendisch eingreifen ... und nen eigenes plugin entwickeln (wobei man da viel kopieren koennt, weil so viel aendert sich ned ... )
oder man arbeitet gleich auf mysql-api ebene ....

Ciao ...
patrikD
Beiträge: 22
Registriert: 21. Mai 2007 14:01

Beitrag von patrikD »

Für alle die es interessiert, hier die Lösung: (nicht die schönste aber funzt)
in qsql_mysql.cpp QMYSQLDriver::open umbauen, so das sie zusätzliche Params akzeptiert.


Code: Alles auswählen

bool QMYSQLDriver::open(const QString& db,
                         const QString& user,
                         const QString& password,
                         const QString& host,
                         int port,
                         const QString& connOpts)
{

    if (isOpen())
        close();

    /* This is a hack to get MySQL's stored procedure support working.
       Since a stored procedure _may_ return multiple result sets,
       we have to enable CLIEN_MULTI_STATEMENTS here, otherwise _any_
       stored procedure call will fail.
    */
    unsigned int optionFlags = Q_CLIENT_MULTI_STATEMENTS;
    const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts));
    QString unixSocket;

	//changes for adding additional params for the connection PD 04.08.08
	QStringList addOptions;

    // extract the real options from the string
    for (int i = 0; i < opts.count(); ++i) {
        QString tmp(opts.at(i).simplified());
        int idx;
        if ((idx = tmp.indexOf(QLatin1Char('='))) != -1) {
            QString val = tmp.mid(idx + 1).simplified();
            QString opt = tmp.left(idx).simplified();
            if (opt == QLatin1String("UNIX_SOCKET"))
                unixSocket = val;
            else if (val == QLatin1String("TRUE") || val == QLatin1String("1"))
                setOptionFlag(optionFlags, tmp.left(idx).simplified());
			else {
                //qWarning("QMYSQLDriver::open: Illegal connect option value '%s'", tmp.toLocal8Bit().constData());
				//add additional params
				addOptions.append(tmp);
			}
        } else {
            setOptionFlag(optionFlags, tmp);
        }
    }


	if (d->mysql = mysql_init((MYSQL*) 0) ) { 
		//add additional options  before connect
		if (addOptions.count()){
			for (int j = 0; j < addOptions.count(); ++j) {
				QString tmp(opts.at(j).simplified());
				int idx;
				if ((idx = tmp.indexOf(QLatin1Char('='))) != -1) {
					QString val = tmp.mid(idx + 1).simplified();
					QString opt = tmp.left(idx).simplified();
					if (val.length() && opt.length()){
						//shared mem
						if (opt == QLatin1String("protocol")){
							if (val == QLatin1String("MEMORY")){
								mysql_protocol_type value = MYSQL_PROTOCOL_MEMORY;
								mysql_options(d->mysql, MYSQL_OPT_PROTOCOL, (int*)&value);
							}
						} else if ( (opt == QLatin1String("shared-memory-base-name")) && val.length()  ){
								mysql_options(d->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, val.toLatin1());
						}
					}
				}
			}
		}// end if (addOptions.count())


		if(mysql_real_connect(d->mysql,
							   host.isNull() ? static_cast<const char *>(0)
											 : host.toLocal8Bit().constData(),
							   user.isNull() ? static_cast<const char *>(0)
											 : user.toLocal8Bit().constData(),
							   password.isNull() ? static_cast<const char *>(0)
												 : password.toLocal8Bit().constData(),
							   db.isNull() ? static_cast<const char *>(0)
										   : db.toLocal8Bit().constData(),
							   (port > -1) ? port : 0,
							   unixSocket.isNull() ? static_cast<const char *>(0)
										   : unixSocket.toLocal8Bit().constData(),
							   optionFlags))
		{
			if (!db.isEmpty() && mysql_select_db(d->mysql, db.toLocal8Bit().constData())) {
				setLastError(qMakeError(tr("Unable to open database '") + db +
							 QLatin1Char('\''), QSqlError::ConnectionError, d));
				mysql_close(d->mysql);
				setOpenError(true);
				return false;
			}
		} else {
			setLastError(qMakeError(tr("Unable to connect"),
						 QSqlError::ConnectionError, d));
			mysql_close(d->mysql);
			setOpenError(true);
			return false;
		}
	} else {
		setLastError(qMakeError(tr("Unable to init"),
					 QSqlError::ConnectionError, d));
		setOpenError(true);
		return false;
	}
pfid
Beiträge: 535
Registriert: 22. Februar 2008 16:59

Beitrag von pfid »

Okay wollte das eben mal bei mir testen, was mir auffällt:
wie wird addOptions übergeben?
Antworten