Commit 9d6518af authored by Jens-Michael Hoffmann's avatar Jens-Michael Hoffmann
Browse files

In the marble DGML files it is now possible to define download policies

for different groups of hosts (in practice per map theme) and usage types.
Only usage type for now is "Browse" when browsing the map. For the planned
"download region" feature we need however to distinguish between "Browse"
and "Bulk" download as this affects the number of allowing concurrent
connections.

As download policies for openstreetmap.org this patch also adds these policies

    <downloadPolicy usage="Browse" maximumConnections="20" />
    <downloadPolicy usage="Bulk" maximumConnections="2" />

to openstreetmap.dgml.

Key points:
- In MarbleModel::setMapTheme the HttpDownloadManager is made aware of download
  policies. This was the best place I could find.
- HttpDownloadManager checks if a download policy which is about to be added
  is in place already.
- GeoSceneTexture is no longer copiable which apparently does no harm.
- If a parser error occurs within a download policy element it is ignored.
  In such a case the default download policy will be used.
- HttpDownloadManager::addJob has got a DownloadUsage parameter which is not yet
  used also because the default of DownloadBrowse is sufficient for now.


svn path=/trunk/KDE/kdeedu/marble/; revision=1073244
parent e0caf112
......@@ -29,6 +29,8 @@
<downloadUrl protocol="http" host="a.tile.openstreetmap.org" path="/" />
<downloadUrl protocol="http" host="b.tile.openstreetmap.org" path="/" />
<downloadUrl protocol="http" host="c.tile.openstreetmap.org" path="/" />
<downloadPolicy usage="Browse" maximumConnections="20" />
<downloadPolicy usage="Bulk" maximumConnections="2" />
</texture>
</layer>
<layer name="standardplaces" backend="geodata">
......
......@@ -27,6 +27,7 @@ namespace Marble
class DownloadPolicyKey
{
friend bool operator<( DownloadPolicyKey const & lhs, DownloadPolicyKey const & rhs );
friend bool operator==( DownloadPolicyKey const & lhs, DownloadPolicyKey const & rhs );
public:
DownloadPolicyKey();
......@@ -46,9 +47,16 @@ class DownloadPolicyKey
DownloadUsage m_usage;
};
inline bool operator==( const DownloadPolicyKey & lhs, const DownloadPolicyKey & rhs )
{
return lhs.m_hostNames == rhs.m_hostNames && lhs.m_usage == rhs.m_usage;
}
class DownloadPolicy
{
friend bool operator==( const DownloadPolicy & lhs, const DownloadPolicy & rhs );
public:
DownloadPolicy();
explicit DownloadPolicy( const DownloadPolicyKey & key );
......@@ -63,6 +71,11 @@ class DownloadPolicy
int m_maximumConnections;
};
inline bool operator==( const DownloadPolicy & lhs, const DownloadPolicy & rhs )
{
return lhs.m_key == rhs.m_key && lhs.m_maximumConnections == rhs.m_maximumConnections;
}
}
#endif
......@@ -148,6 +148,8 @@ void HttpDownloadManager::setDownloadEnabled( const bool enable )
void HttpDownloadManager::addDownloadPolicy( const DownloadPolicy& policy )
{
if ( hasDownloadPolicy( policy ))
return;
DownloadQueueSet * const queueSet = new DownloadQueueSet( policy, this );
connectQueueSet( queueSet );
d->m_queueSets.append( QPair<DownloadPolicyKey, DownloadQueueSet *>
......@@ -160,15 +162,16 @@ StoragePolicy* HttpDownloadManager::storagePolicy() const
}
void HttpDownloadManager::addJob( const QUrl& sourceUrl, const QString& destFileName,
const QString &id )
const QString &id, const DownloadUsage usage )
{
if ( !d->m_downloadEnabled )
return;
DownloadQueueSet * const queueSet = d->findQueues( sourceUrl.host(), DownloadBrowse );
DownloadQueueSet * const queueSet = d->findQueues( sourceUrl.host(), usage );
if ( queueSet->canAcceptJob( sourceUrl, destFileName )) {
HttpJob * const job = d->createJob( sourceUrl, destFileName, id );
if ( job ) {
job->setDownloadUsage( usage );
queueSet->addJob( job );
}
}
......@@ -219,4 +222,18 @@ void HttpDownloadManager::connectQueueSet( DownloadQueueSet * queueSet )
connect( queueSet, SIGNAL( jobRemoved() ), SIGNAL( jobRemoved() ));
}
bool HttpDownloadManager::hasDownloadPolicy( const DownloadPolicy& policy ) const
{
bool found = false;
QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::iterator pos = d->m_queueSets.begin();
QList<QPair<DownloadPolicyKey, DownloadQueueSet*> >::iterator const end = d->m_queueSets.end();
for (; pos != end; ++pos ) {
if ( (*pos).second->downloadPolicy() == policy ) {
found = true;
break;
}
}
return found;
}
#include "HttpDownloadManager.moc"
......@@ -20,6 +20,7 @@
#include <QtCore/QString>
#include <QtCore/QUrl>
#include "global.h"
#include "marble_export.h"
class QTimer;
......@@ -82,7 +83,8 @@ class MARBLE_EXPORT HttpDownloadManager : public QObject
/**
* Adds a new job with a sourceUrl, destination file name and given id.
*/
void addJob( const QUrl& sourceUrl, const QString& destFilename, const QString &id );
void addJob( const QUrl& sourceUrl, const QString& destFilename, const QString &id,
const DownloadUsage usage = DownloadBrowse );
Q_SIGNALS:
......@@ -118,6 +120,7 @@ class MARBLE_EXPORT HttpDownloadManager : public QObject
Q_DISABLE_COPY( HttpDownloadManager )
void connectQueueSet( DownloadQueueSet * );
bool hasDownloadPolicy( const DownloadPolicy& policy ) const;
class Private;
Private * const d;
};
......
......@@ -7,7 +7,7 @@
//
// Copyright 2006-2007 Torsten Rahn <tackat@kde.org>
// Copyright 2007 Inge Wallin <ingwa@kde.org>
// Copyright 2008,2009 Jens-Michael Hoffmann <jensmh@gmx.de>
// Copyright 2008, 2009, 2010 Jens-Michael Hoffmann <jmho@c-xx.com>
// Copyright 2008-2009 Patrick Spendrin <ps_ml@gmx.de>
//
......@@ -304,6 +304,7 @@ void MarbleModel::setMapTheme( GeoSceneDocument* mapTheme,
Projection currentProjection )
{
d->m_mapTheme = mapTheme;
addDownloadPolicies( d->m_mapTheme );
// Some output to show how to use this stuff ...
mDebug() << "DGML2 Name : " << d->m_mapTheme->head()->name();
......@@ -916,6 +917,32 @@ void MarbleModel::reloadMap() const
}
}
void MarbleModel::addDownloadPolicies( GeoSceneDocument *mapTheme )
{
if ( !mapTheme )
return;
if ( !mapTheme->map()->hasTextureLayers() )
return;
// As long as we don't have an Layer Management Class we just lookup
// the name of the layer that has the same name as the theme ID
const QString themeId = d->m_mapTheme->head()->theme();
GeoSceneLayer * const layer = static_cast<GeoSceneLayer*>( d->m_mapTheme->map()->layer( themeId ));
if ( !layer )
return;
GeoSceneTexture * const texture = static_cast<GeoSceneTexture*>( layer->groundDataset() );
if ( !texture )
return;
QList<DownloadPolicy *> policies = texture->downloadPolicies();
QList<DownloadPolicy *>::const_iterator pos = policies.constBegin();
QList<DownloadPolicy *>::const_iterator const end = policies.constEnd();
for (; pos != end; ++pos ) {
d->m_downloadManager->addDownloadPolicy( **pos );
}
}
}
#include "MarbleModel.moc"
......@@ -374,9 +374,11 @@ class MARBLE_EXPORT MarbleModel : public QObject
private:
Q_DISABLE_COPY( MarbleModel )
MarbleModelPrivate * const d;
Q_PRIVATE_SLOT( d, void notifyModelChanged() )
void addDownloadPolicies( GeoSceneDocument *mapTheme );
MarbleModelPrivate * const d;
};
}
......
......@@ -43,6 +43,7 @@ const char* dgmlAttr_host = "host";
const char* dgmlAttr_labelColor = "labelColor";
const char* dgmlAttr_levelZeroColumns = "levelZeroColumns";
const char* dgmlAttr_levelZeroRows = "levelZeroRows";
const char* dgmlAttr_maximumConnections = "maximumConnections";
const char* dgmlAttr_mode = "mode";
const char* dgmlAttr_name = "name";
const char* dgmlAttr_password = "password";
......@@ -55,6 +56,7 @@ const char* dgmlAttr_spacing = "spacing";
const char* dgmlAttr_style = "style";
const char* dgmlAttr_text = "text";
const char* dgmlAttr_type = "type";
const char* dgmlAttr_usage = "usage";
const char* dgmlAttr_user = "user";
const char* dgmlAttr_width = "width";
}
......
......@@ -45,6 +45,7 @@ namespace dgml
extern const char* dgmlAttr_labelColor;
extern const char* dgmlAttr_levelZeroColumns;
extern const char* dgmlAttr_levelZeroRows;
extern const char* dgmlAttr_maximumConnections;
extern const char* dgmlAttr_mode;
extern const char* dgmlAttr_name;
extern const char* dgmlAttr_password;
......@@ -57,6 +58,7 @@ namespace dgml
extern const char* dgmlAttr_style;
extern const char* dgmlAttr_text;
extern const char* dgmlAttr_type;
extern const char* dgmlAttr_usage;
extern const char* dgmlAttr_user;
extern const char* dgmlAttr_width;
}
......
// Copyright 2009, 2010 Jens-Michael Hoffmann <jmho@c-xx.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "DgmlDownloadPolicyTagHandler.h"
#include "DgmlAttributeDictionary.h"
#include "DgmlElementDictionary.h"
#include "GeoParser.h"
#include "GeoSceneTexture.h"
#include "global.h"
namespace Marble
{
namespace dgml
{
static GeoTagHandlerRegistrar handler( GeoTagHandler::QualifiedName( dgmlTag_DownloadPolicy,
dgmlTag_nameSpace20 ),
new DgmlDownloadPolicyTagHandler );
// Error handling:
// Here it is not possible to return an error code or throw an exception
// so in case of an error we just ignore the element.
GeoNode* DgmlDownloadPolicyTagHandler::parse( GeoParser& parser ) const
{
// Check whether the tag is valid
Q_ASSERT( parser.isStartElement() && parser.isValidElement( dgmlTag_DownloadPolicy ));
// Checking for parent item
GeoStackItem parentItem = parser.parentElement();
if ( !parentItem.represents( dgmlTag_Texture )) {
qCritical( "Parse error: parent element is not 'texture'" );
return 0;
}
// Attribute usage
DownloadUsage usage;
const QString usageStr = parser.attribute( dgmlAttr_usage ).trimmed();
if ( usageStr == "Browse" )
usage = DownloadBrowse;
else if ( usageStr == "Bulk" )
usage = DownloadBulk;
else {
qCritical( "Parse error: invalid attribute downloadPolicy/@usage" );
return 0;
}
// Attribute maximumConnections
const QString maximumConnectionsStr = parser.attribute( dgmlAttr_maximumConnections ).trimmed();
bool ok;
const int maximumConnections = maximumConnectionsStr.toInt( &ok );
if ( !ok ) {
qCritical( "Parse error: invalid attribute downloadPolicy/@maximumConnections" );
return 0;
}
parentItem.nodeAs<GeoSceneTexture>()->addDownloadPolicy( usage, maximumConnections );
return 0;
}
}
}
// Copyright 2009 Jens-Michael Hoffmann <jmho@c-xx.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library. If not, see <http://www.gnu.org/licenses/>.
#ifndef MARBLE_DGML_DOWNLOAD_POLICY_TAG_HANDLER_H
#define MARBLE_DGML_DOWNLOAD_POLICY_TAG_HANDLER_H
#include "GeoTagHandler.h"
namespace Marble
{
namespace dgml
{
class DgmlDownloadPolicyTagHandler: public GeoTagHandler
{
public:
virtual GeoNode* parse( GeoParser & ) const;
};
}
}
#endif
......@@ -40,6 +40,7 @@ const char* dgmlTag_Description = "description";
const char* dgmlTag_Dgml = "dgml";
const char* dgmlTag_Discrete = "discrete";
const char* dgmlTag_Document = "document";
const char* dgmlTag_DownloadPolicy = "downloadPolicy";
const char* dgmlTag_DownloadUrl = "downloadUrl";
const char* dgmlTag_Filter = "filter";
const char* dgmlTag_Geodata = "geodata";
......
......@@ -43,6 +43,7 @@ namespace dgml
extern const char* dgmlTag_Discrete;
extern const char* dgmlTag_Dgml;
extern const char* dgmlTag_Document;
extern const char* dgmlTag_DownloadPolicy;
extern const char* dgmlTag_DownloadUrl;
extern const char* dgmlTag_Filter;
extern const char* dgmlTag_Geodata;
......
......@@ -22,7 +22,8 @@
#include "GeoSceneTexture.h"
#include "global.h"
#include "DownloadPolicy.h"
#include "MarbleDebug.h"
namespace Marble
{
......@@ -41,6 +42,11 @@ GeoSceneTexture::GeoSceneTexture( const QString& name )
{
}
GeoSceneTexture::~GeoSceneTexture()
{
qDeleteAll( m_downloadPolicies );
}
QString GeoSceneTexture::sourceDir() const
{
return m_sourceDir;
......@@ -132,9 +138,32 @@ void GeoSceneTexture::addDownloadUrl( const QUrl & url )
m_nextUrl = m_downloadUrls.constBegin();
}
QList<DownloadPolicy *> GeoSceneTexture::downloadPolicies() const
{
return m_downloadPolicies;
}
void GeoSceneTexture::addDownloadPolicy( const DownloadUsage usage, const int maximumConnections )
{
DownloadPolicy * const policy = new DownloadPolicy( DownloadPolicyKey( hostNames(), usage ));
policy->setMaximumConnections( maximumConnections );
m_downloadPolicies.append( policy );
mDebug() << "added download policy" << hostNames() << usage << maximumConnections;
}
QString GeoSceneTexture::type()
{
return "texture";
}
QStringList GeoSceneTexture::hostNames() const
{
QStringList result;
QVector<QUrl>::const_iterator pos = m_downloadUrls.constBegin();
QVector<QUrl>::const_iterator const end = m_downloadUrls.constEnd();
for (; pos != end; ++pos )
result.append( (*pos).host() );
return result;
}
}
......@@ -23,10 +23,13 @@
#ifndef GEOSCENETEXTURE_H
#define GEOSCENETEXTURE_H
#include <QtCore/QList>
#include <QtCore/QStringList>
#include <QtCore/QUrl>
#include <QtCore/QVector>
#include "GeoSceneLayer.h"
#include "global.h"
/**
* @short Texture dataset stored in a layer.
......@@ -34,6 +37,7 @@
namespace Marble
{
class DownloadPolicy;
class GeoSceneTexture : public GeoSceneAbstractDataset
{
......@@ -42,6 +46,7 @@ class GeoSceneTexture : public GeoSceneAbstractDataset
enum Projection { Equirectangular, Mercator };
explicit GeoSceneTexture( const QString& name );
~GeoSceneTexture();
QString sourceDir() const;
void setSourceDir( const QString& sourceDir );
......@@ -70,9 +75,15 @@ class GeoSceneTexture : public GeoSceneAbstractDataset
QUrl downloadUrl();
void addDownloadUrl( const QUrl & );
QList<DownloadPolicy *> downloadPolicies() const;
void addDownloadPolicy( const DownloadUsage usage, const int maximumConnections );
virtual QString type();
private:
Q_DISABLE_COPY( GeoSceneTexture )
QStringList hostNames() const;
QString m_sourceDir;
QString m_installMap;
StorageLayoutMode m_storageLayoutMode;
......@@ -86,6 +97,7 @@ class GeoSceneTexture : public GeoSceneAbstractDataset
/// Points to next Url for the round robin algorithm
QVector<QUrl>::const_iterator m_nextUrl;
QList<DownloadPolicy *> m_downloadPolicies;
};
}
......
......@@ -8,6 +8,7 @@ include_directories(
include( ${QT_USE_FILE} )
set( tilecreator_SRCS
../lib/DownloadPolicy.cpp
../lib/TileCreator.cpp
../lib/TileLoaderHelper.cpp
../lib/geodata/parser/GeoDocument.cpp
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment