[editor] Draft upload implementation.

This commit is contained in:
Alex Zolotarev 2016-01-15 09:46:26 +03:00 committed by Sergey Yershov
parent 01be3e6a2c
commit 9ae15519b2
2 changed files with 91 additions and 3 deletions

View file

@ -7,13 +7,18 @@
#include "platform/platform.hpp"
#include "editor/changeset_wrapper.hpp"
#include "editor/osm_auth.hpp"
#include "editor/server_api.hpp"
#include "editor/xml_feature.hpp"
#include "coding/internal/file_data.hpp"
#include "base/logging.hpp"
#include "base/string_utils.hpp"
#include "coding/internal/file_data.hpp"
#include "std/chrono.hpp"
#include "std/future.hpp"
#include "std/tuple.hpp"
#include "std/unordered_map.hpp"
#include "std/unordered_set.hpp"
@ -34,6 +39,10 @@ constexpr char const * kCreateSection = "create";
/// We store edited streets in OSM-compatible way.
constexpr char const * kAddrStreetTag = "addr:street";
constexpr char const * kUploaded = "Uploaded";
constexpr char const * kDeletedFromOSMServer = "Deleted from OSM by someone";
constexpr char const * kNeedsRetry = "Needs Retry";
namespace osm
{
// TODO(AlexZ): Normalize osm multivalue strings for correct merging
@ -519,4 +528,78 @@ bool Editor::IsAddressEditable(FeatureType const & feature) const
return false;
}
void Editor::UploadChanges(string const & key, string const & secret, TChangesetTags const & tags)
{
// TODO(AlexZ): features access should be synchronized.
auto const lambda = [this](string key, string secret, TChangesetTags tags)
{
int uploadedFeaturesCount = 0;
// TODO(AlexZ): insert usefull changeset comments.
ChangesetWrapper changeset({key, secret}, tags);
for (auto & id : m_features)
{
for (auto & offset : id.second)
{
FeatureTypeInfo & fti = offset.second;
// Do not process already uploaded features or those failed permanently.
if (!(fti.m_uploadStatus.empty() || fti.m_uploadStatus == kNeedsRetry))
continue;
// TODO(AlexZ): Create/delete nodes support.
if (fti.m_status != FeatureStatus::Modified)
continue;
XMLFeature feature = fti.m_feature.ToXML();
// TODO(AlexZ): Add areas(ways) upload support.
if (feature.GetType() != XMLFeature::Type::Node)
continue;
try
{
XMLFeature osmFeature = changeset.GetMatchingFeatureFromOSM(feature, fti.m_feature);
XMLFeature const osmFeatureCopy = osmFeature;
osmFeature.ApplyPatch(feature);
// Check to avoid duplicates.
if (osmFeature == osmFeatureCopy)
{
LOG(LWARNING, ("Local changes are equal to OSM, feature was not uploaded, local changes were deleted.", feature));
// TODO(AlexZ): Delete local change.
continue;
}
LOG(LDEBUG, ("Uploading patched feature", osmFeature));
changeset.ModifyNode(osmFeature);
fti.m_uploadStatus = kUploaded;
fti.m_uploadAttemptTimestamp = time(nullptr);
++uploadedFeaturesCount;
}
catch (ChangesetWrapper::OsmObjectWasDeletedException const & ex)
{
fti.m_uploadStatus = kDeletedFromOSMServer;
fti.m_uploadAttemptTimestamp = time(nullptr);
fti.m_uploadError = "Node was deleted from the server.";
LOG(LWARNING, (fti.m_uploadError, ex.what()));
}
catch (RootException const & ex)
{
LOG(LWARNING, (ex.what()));
fti.m_uploadStatus = kNeedsRetry;
fti.m_uploadAttemptTimestamp = time(nullptr);
fti.m_uploadError = ex.what();
}
// TODO(AlexZ): Synchronize save after edits.
// Call Save every time we modify each feature's information.
Save(GetEditorFilePath());
}
}
// TODO(AlexZ): Should we call any callback at the end?
};
// Do not run more than one upload thread at a time.
static auto future = async(launch::async, lambda, key, secret, tags);
auto const status = future.wait_for(milliseconds(0));
if (status == future_status::ready)
future = async(launch::async, lambda, key, secret, tags);
}
} // namespace osm

View file

@ -75,6 +75,11 @@ public:
bool IsNameEditable(FeatureType const & feature) const;
bool IsAddressEditable(FeatureType const & feature) const;
using TChangesetTags = map<string, string>;
/// Tries to upload all local changes to OSM server in a separate thread.
/// @param[in] tags should provide additional information about client to use in changeset.
void UploadChanges(string const & key, string const & secret, TChangesetTags const & tags);
private:
// TODO(AlexZ): Synchronize Save call/make it on a separate thread.
void Save(string const & fullFilePath) const;
@ -87,7 +92,7 @@ private:
string m_street;
time_t m_modificationTimestamp = my::INVALID_TIME_STAMP;
time_t m_uploadAttemptTimestamp = my::INVALID_TIME_STAMP;
/// "" | "ok" | "repeat" | "failed"
/// Is empty if upload has never occured or one of k* constants above otherwise.
string m_uploadStatus;
string m_uploadError;
};