--- a/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp Mon May 03 13:18:40 2010 +0300
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
@@ -44,6 +44,16 @@
#include <commdb.h>
#include <cdbcols.h>
#include <d32dbms.h>
+#include <QEventLoop>
+#include <QTimer>
+#include <QTime> // For randgen seeding
+#include <QtCore> // For randgen seeding
+
+// #define QT_BEARERMGMT_CONFIGMGR_DEBUG
+
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+#include <QDebug>
+#endif
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
#include <cmdestination.h>
@@ -64,10 +74,16 @@
static const int KUserChoiceIAPId = 0;
QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
- : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0), iFirstUpdate(true), iInitOk(true)
+ : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0),
+ iFirstUpdate(true), iInitOk(true), iIgnoringUpdates(false),
+ iTimeToWait(0), iIgnoreEventLoop(0)
{
CActiveScheduler::Add(this);
+ // Seed the randomgenerator
+ qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
+ iIgnoreEventLoop = new QEventLoop(this);
+
registerPlatformCapabilities();
TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
if (error != KErrNone) {
@@ -100,12 +116,9 @@
cpPriv->manager = this;
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
userChoiceConfigurations.insert(cpPriv->id, ptr);
-
updateConfigurations();
updateStatesToSnaps();
-
updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans)
-
// Start monitoring IAP and/or SNAP changes in Symbian CommsDB
startCommsDatabaseNotifications();
iFirstUpdate = false;
@@ -115,22 +128,19 @@
{
Cancel();
- QList<QString> configIdents = snapConfigurations.keys();
- foreach(QString oldIface, configIdents) {
+ foreach (const QString &oldIface, snapConfigurations.keys()) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
priv->isValid = false;
priv->id.clear();
}
- configIdents = accessPointConfigurations.keys();
- foreach(QString oldIface, configIdents) {
+ foreach (const QString &oldIface, accessPointConfigurations.keys()) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
priv->isValid = false;
priv->id.clear();
}
- configIdents = userChoiceConfigurations.keys();
- foreach(QString oldIface, configIdents) {
+ foreach (const QString &oldIface, userChoiceConfigurations.keys()) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = userChoiceConfigurations.take(oldIface);
priv->isValid = false;
priv->id.clear();
@@ -166,6 +176,7 @@
capFlags |= QNetworkConfigurationManager::ForcedRoaming;
#endif
capFlags |= QNetworkConfigurationManager::DataStatistics;
+ capFlags |= QNetworkConfigurationManager::NetworkSessionRequired;
}
void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
@@ -193,7 +204,7 @@
{
QList<QString> knownConfigs = accessPointConfigurations.keys();
QList<QString> knownSnapConfigs = snapConfigurations.keys();
-
+
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
// S60 version is >= Series60 3rd Edition Feature Pack 2
TInt error = KErrNone;
@@ -350,7 +361,7 @@
#endif
updateActiveAccessPoints();
- foreach (QString oldIface, knownConfigs) {
+ foreach (const QString &oldIface, knownConfigs) {
//remove non existing IAP
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
priv->isValid = false;
@@ -360,8 +371,7 @@
emit configurationRemoved(item);
}
// Remove non existing IAP from SNAPs
- QList<QString> snapConfigIdents = snapConfigurations.keys();
- foreach (QString iface, snapConfigIdents) {
+ foreach (const QString &iface, snapConfigurations.keys()) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv2 = snapConfigurations.value(iface);
// => Check if one of the IAPs of the SNAP is active
for (int i=0; i<priv2->serviceNetworkMembers.count(); i++) {
@@ -372,7 +382,7 @@
}
}
}
- foreach (QString oldIface, knownSnapConfigs) {
+ foreach (const QString &oldIface, knownSnapConfigs) {
//remove non existing SNAPs
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
priv->isValid = false;
@@ -619,7 +629,7 @@
}
// Make sure that state of rest of the IAPs won't be Active
- foreach (QString iface, inactiveConfigs) {
+ foreach (const QString &iface, inactiveConfigs) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
if (priv.data()) {
// Configuration is either Defined or Discovered
@@ -665,7 +675,7 @@
}
// Make sure that state of rest of the IAPs won't be Discovered or Active
- foreach (QString iface, unavailableConfigs) {
+ foreach (const QString &iface, unavailableConfigs) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
if (priv.data()) {
// Configuration is Defined
@@ -685,8 +695,7 @@
void QNetworkConfigurationManagerPrivate::updateStatesToSnaps()
{
// Go through SNAPs and set correct state to SNAPs
- QList<QString> snapConfigIdents = snapConfigurations.keys();
- foreach (QString iface, snapConfigIdents) {
+ foreach (const QString &iface, snapConfigurations.keys()) {
bool discovered = false;
bool active = false;
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.value(iface);
@@ -798,23 +807,45 @@
void QNetworkConfigurationManagerPrivate::RunL()
{
+ if (iIgnoringUpdates) {
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
+#endif
+ return;
+ }
if (iStatus != KErrCancel) {
RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
switch (event) {
-// case RDbNotifier::EUnlock: /** All read locks have been removed. */
+ case RDbNotifier::EUnlock: /** All read locks have been removed. */
case RDbNotifier::ECommit: /** A transaction has been committed. */
case RDbNotifier::ERollback: /** A transaction has been rolled back */
case RDbNotifier::ERecover: /** The database has been recovered */
- // Note that if further database events occur while a client is handling
- // a request completion, the notifier records the most significant database
- // event and this is signalled as soon as the client issues the next
- // RequestNotification() request.
- // => Stop recording notifications
- stopCommsDatabaseNotifications();
- TRAPD(error, updateConfigurationsL());
- if (error == KErrNone) {
- updateStatesToSnaps();
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
+#endif
+ iIgnoringUpdates = true;
+ // Other events than ECommit get lower priority. In practice with those events,
+ // we delay_before_updating methods, whereas
+ // with ECommit we _update_before_delaying the reaction to next event.
+ // Few important notes: 1) listening to only ECommit does not seem to be adequate,
+ // but updates will be missed. Hence other events are reacted upon too.
+ // 2) RDbNotifier records the most significant event, and that will be returned once
+ // we issue new RequestNotification, and hence updates will not be missed even
+ // when we are 'not reacting to them' for few seconds.
+ if (event == RDbNotifier::ECommit) {
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
+ waitRandomTime();
+ } else {
+ waitRandomTime();
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
}
+ iIgnoringUpdates = false; // Wait time done, allow updating again
iWaitingCommsDatabaseNotifications = true;
break;
default:
@@ -822,7 +853,6 @@
break;
}
}
-
if (iWaitingCommsDatabaseNotifications) {
if (!IsActive()) {
SetActive();
@@ -882,8 +912,7 @@
}
bool online = false;
- QList<QString> iapConfigs = accessPointConfigurations.keys();
- foreach (QString iface, iapConfigs) {
+ foreach (const QString &iface, accessPointConfigurations.keys()) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
if (priv.data()->state == QNetworkConfiguration::Active) {
online = true;
@@ -912,7 +941,7 @@
unDiscoveredConfigs.removeOne(ident);
}
}
- foreach (QString iface, unDiscoveredConfigs) {
+ foreach (const QString &iface, unDiscoveredConfigs) {
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
if (priv.data()) {
// Configuration is Defined
@@ -928,6 +957,20 @@
}
}
+// Waits for 1..4 seconds.
+void QNetworkConfigurationManagerPrivate::waitRandomTime()
+{
+ iTimeToWait = (qAbs(qrand()) % 5) * 1000;
+ if (iTimeToWait < 1000) {
+ iTimeToWait = 1000;
+ }
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
+#endif
+ QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
+ iIgnoreEventLoop->exec();
+}
+
QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId)
{
QNetworkConfiguration item;