Find a random port number to use for the application server to avoid conflicts

with any other apps that may have already bound to the default port used by CP.
pull/3/head
Dave Page 2013-10-04 17:12:10 +01:00
parent a1524f3726
commit 457a842cec
7 changed files with 64 additions and 38 deletions

View File

@ -32,8 +32,12 @@
// Constructor // Constructor
BrowserWindow::BrowserWindow() BrowserWindow::BrowserWindow(quint16 port)
{ {
// Setup the URL the browser will connect to
m_appServerUrl = QString("http://localhost:%1").arg(port);
// Setup the UI
createActions(); createActions();
createMenus(); createMenus();
@ -48,9 +52,9 @@ BrowserWindow::BrowserWindow()
restoreState(settings.value("windowState").toByteArray()); restoreState(settings.value("windowState").toByteArray());
// Display the app // Display the app
m_initialload = true; m_initialLoad = true;
m_loadattempt = 1; m_loadAttempt = 1;
webView->setUrl(PGA_SERVER_URL); webView->setUrl(QString("http://localhost/:%1").arg(9876));
} }
@ -106,43 +110,38 @@ void BrowserWindow::createMenus()
// Process loading finished signals from the web view. // Process loading finished signals from the web view.
void BrowserWindow::finishLoading(bool ok) void BrowserWindow::finishLoading(bool ok)
{ {
if (m_initialload && !ok) if (m_initialLoad && !ok)
{ {
// The load attempt failed. Try again up to 4 times with an // The load attempt failed. Try again up to 4 times with an
// incremental backoff. // incremental backoff.
if (m_loadattempt < 5) if (m_loadAttempt < 5)
{ {
qDebug() << "Initial load failed. Retrying in" << m_loadattempt << "seconds."; if (m_loadAttempt > 1)
if (m_loadattempt == 1)
{ {
webView->setHtml(tr("<p>Connecting...</p>")); qDebug() << "Initial connection failed. Retrying in" << m_loadAttempt << "seconds.";
webView->setHtml(QString(tr("<p>Failed to connect to the pgAdmin application server. Retrying in %1 seconds, ") +
tr("or click <a href=\"%2\">here</a> to try again now.</p>")).arg(m_loadAttempt).arg(m_appServerUrl));
} }
else else
{ {
webView->setHtml(QString(tr("<p>Failed to connect to the pgAdmin application server. Retrying in %1 seconds, ") + webView->setHtml(QString(tr("<p>Connecting to the application server...</p>")));
tr("or click <a href=\"%2\">here</a> to try again now.</p>")).arg(m_loadattempt).arg(PGA_SERVER_URL));
} }
pause(m_loadattempt); pause(m_loadAttempt);
webView->setUrl(PGA_SERVER_URL); webView->setUrl(m_appServerUrl);
m_loadAttempt++;
// Even if the server comes up while we're looping, Linux won't
// properly display the HTML data unless we explicitly process events.
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
m_loadattempt++;
return; return;
} }
else else
{ {
qDebug() << "Initial page load failed after multiple attempts. Aborting."; qDebug() << "Initial connection failed after multiple attempts. Aborting.";
webView->setHtml(QString(tr("<p>Failed to connect to the pgAdmin application server. ") + webView->setHtml(QString(tr("<p>Failed to connect to the pgAdmin application server. ") +
tr("Click <a href=\"%1\">here</a> to try again.</p>")).arg(PGA_SERVER_URL)); tr("Click <a href=\"%1\">here</a> to try again.</p>")).arg(m_appServerUrl));
} }
} }
m_initialload = false; m_initialLoad = false;
} }

View File

@ -34,7 +34,7 @@ class BrowserWindow : public QMainWindow
Q_OBJECT Q_OBJECT
public: public:
BrowserWindow(); BrowserWindow(quint16 port);
protected: protected:
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
@ -47,6 +47,7 @@ private slots:
void about(); void about();
private: private:
QString m_appServerUrl;
QWebView *webView; QWebView *webView;
QMenu *fileMenu; QMenu *fileMenu;
QMenu *helpMenu; QMenu *helpMenu;
@ -54,8 +55,8 @@ private:
QAction *exitAction; QAction *exitAction;
QAction *aboutAction; QAction *aboutAction;
bool m_initialload; bool m_initialLoad;
int m_loadattempt; int m_loadAttempt;
void createActions(); void createActions();
void createMenus(); void createMenus();

View File

@ -22,8 +22,11 @@
// App headers // App headers
#include "Server.h" #include "Server.h"
Server::Server() Server::Server(quint16 port)
{ {
// Appserver port
m_port = port;
// Initialise Python // Initialise Python
Py_SetProgramName(PGA_APP_NAME.toUtf8().data()); Py_SetProgramName(PGA_APP_NAME.toUtf8().data());
Py_Initialize(); Py_Initialize();
@ -74,6 +77,9 @@ void Server::run()
return; return;
} }
// Set the port number
PyRun_SimpleString(QString("PGADMIN_PORT = %1").arg(m_port).toLatin1());
if (PyRun_SimpleFile(cp, m_appfile.toUtf8().data()) != 0) if (PyRun_SimpleFile(cp, m_appfile.toUtf8().data()) != 0)
setError("Failed to launch the application server, server thread exiting."); setError("Failed to launch the application server, server thread exiting.");

View File

@ -23,7 +23,7 @@ class Server : public QThread
Q_OBJECT Q_OBJECT
public: public:
Server(); Server(quint16 port);
~Server(); ~Server();
bool Init(); bool Init();
@ -37,6 +37,8 @@ private:
QString m_appfile; QString m_appfile;
QString m_error; QString m_error;
quint16 m_port;
}; };
#endif // SERVER_H #endif // SERVER_H

View File

@ -38,13 +38,17 @@ int main(int argc, char * argv[])
QCoreApplication::setOrganizationDomain("pgadmin.org"); QCoreApplication::setOrganizationDomain("pgadmin.org");
QCoreApplication::setApplicationName(PGA_APP_NAME); QCoreApplication::setApplicationName(PGA_APP_NAME);
// Find an unused port number.
QTcpSocket socket;
socket.bind(0, QAbstractSocket::DontShareAddress);
quint16 port = socket.localPort();
// Fire up the webserver // Fire up the webserver
// TODO: Find an unused port number to use Server *server = new Server(port);
Server *server = new Server();
if (!server->Init()) if (!server->Init())
{ {
qDebug() << server->getError(); qDebug() << server->getError();
QString error("An error occurred initialising the application server:\n\n" + server->getError()); QString error("An error occurred initialising the application server:\n\n" + server->getError());
QMessageBox::critical(NULL, QString("Fatal Error"), error); QMessageBox::critical(NULL, QString("Fatal Error"), error);
@ -55,11 +59,10 @@ int main(int argc, char * argv[])
server->start(); server->start();
// Create & show the main window // Create & show the main window
BrowserWindow browserWindow; BrowserWindow browserWindow(port);
browserWindow.show(); browserWindow.show();
// Go! // Go!
return app.exec(); return app.exec();
} }

View File

@ -28,7 +28,4 @@
// Application name // Application name
const QString PGA_APP_NAME = QString("pgAdmin 4"); const QString PGA_APP_NAME = QString("pgAdmin 4");
// Server URL
const QString PGA_SERVER_URL = QString("http://127.0.0.1:8080");
#endif // PGADMIN4_H #endif // PGADMIN4_H

View File

@ -7,11 +7,14 @@ includedir = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect
if includedir not in sys.path: if includedir not in sys.path:
sys.path.insert(0, includedir) sys.path.insert(0, includedir)
# Do some stuff # Rock n' roll...
import cherrypy import cherrypy
from time import time,ctime from time import time,ctime
class HelloWorld(object):
# This is the main application class that we'll run under CherryPy. For now,
# we'll just output some basic HTML so we can see that everything is running.
class pgAdmin4(object):
def index(self): def index(self):
output = """ output = """
Today is <b>%s</b> Today is <b>%s</b>
@ -21,6 +24,21 @@ Today is <b>%s</b>
<a href="http://www.pgadmin.org/">pgAdmin 4</a>""" % ctime(time()) <a href="http://www.pgadmin.org/">pgAdmin 4</a>""" % ctime(time())
return output return output
index.exposed = True index.exposed = True
cherrypy.quickstart(HelloWorld())
# Start the web server. The port number should have already been set by the
# runtime if we're running in desktop mode, otherwise we'll just use the
# CherryPy default.
try:
cherrypy.server.socket_port = PGADMIN_PORT
except:
pass
try:
cherrypy.quickstart(pgAdmin4())
except IOError:
print "Unexpected error: ", sys.exc_info()[0]