Skip to content

Commit b37bf14

Browse files
Merge request POC.
Implemented merge requests mechanism in a separate RequestBroker class Relates-To: OLPEDGE-1805 Signed-off-by: Mykhailo Kuchma <ext-mykhailo.kuchma@here.com>
1 parent 4b2c2e9 commit b37bf14

File tree

5 files changed

+416
-16
lines changed

5 files changed

+416
-16
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (C) 2019-2020 HERE Europe B.V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
#include "RequestBroker.h"
21+
22+
namespace olp {
23+
namespace dataservice {
24+
namespace read {
25+
26+
namespace {
27+
std::string UniqueId() {
28+
// TODO: generate a better unique id
29+
static unsigned int id = 0;
30+
return std::to_string(id++);
31+
}
32+
} // namespace
33+
34+
void RequestBroker::RequestContext::AddCallback(CallerId id,
35+
Callback callback) {
36+
callbacks[id] = std::move(callback);
37+
}
38+
39+
void RequestBroker::RequestContext::PropagateResponse(DataResponse response) {
40+
for (auto& callback : callbacks) {
41+
callback.second(response);
42+
}
43+
callbacks.clear();
44+
}
45+
46+
// Return true if the operation was canceled
47+
bool RequestBroker::RequestContext::CancelRequest(CallerId id) {
48+
// Cancel individual request
49+
{
50+
auto callback_it = callbacks.find(id);
51+
if (callback_it != callbacks.end()) {
52+
Callback callback = std::move(callback_it->second);
53+
callback(client::ApiError(client::ErrorCode::Cancelled, "Canceled"));
54+
callbacks.erase(callback_it);
55+
} else {
56+
assert(false);
57+
}
58+
}
59+
60+
const bool cancel_operation = callbacks.empty();
61+
62+
if (cancel_operation) {
63+
cancelation_context.CancelOperation();
64+
}
65+
66+
return cancel_operation;
67+
}
68+
69+
client::CancellationContext
70+
RequestBroker::RequestContext::CancelationContext() {
71+
return cancelation_context;
72+
}
73+
74+
RequestBroker::CreateOrAssociateResult RequestBroker::CreateOrAssociateRequest(
75+
RequestId req_id, Callback callback) {
76+
const CallerId caller_id = UniqueId();
77+
GetOrCreateResult result = GetOrCreateContext(req_id);
78+
result.ctx.AddCallback(caller_id, std::move(callback));
79+
return {result.ctx.CancelationContext(), CancelToken(req_id, caller_id),
80+
result.just_created};
81+
}
82+
83+
DataResponseCallback RequestBroker::ResponseHandler(RequestId req_id) {
84+
return [=](DataResponse response) {
85+
PropagateResponse(req_id, std::move(response));
86+
};
87+
}
88+
89+
RequestBroker::GetOrCreateResult RequestBroker::GetOrCreateContext(
90+
RequestId req_id) {
91+
std::unique_lock<std::mutex> lock(mutex_);
92+
93+
auto request_ctx_it = request_map_.find(req_id);
94+
if (request_ctx_it != request_map_.end()) {
95+
return {request_ctx_it->second, false};
96+
} else {
97+
request_ctx_it =
98+
request_map_.insert(std::make_pair(req_id, RequestContext{})).first;
99+
return {request_ctx_it->second, true};
100+
}
101+
}
102+
103+
void RequestBroker::PropagateResponse(RequestId req_id, DataResponse response) {
104+
std::unique_lock<std::mutex> lock(mutex_);
105+
106+
auto request_ctx_it = request_map_.find(req_id);
107+
if (request_ctx_it == request_map_.end()) {
108+
assert(!response.IsSuccessful()); // Expect cancel here
109+
return;
110+
}
111+
112+
auto ctx = std::move(request_ctx_it->second);
113+
request_map_.erase(request_ctx_it);
114+
ctx.PropagateResponse(std::move(response));
115+
}
116+
117+
void RequestBroker::CancelRequest(RequestId req_id, CallerId id) {
118+
std::unique_lock<std::mutex> lock(mutex_);
119+
120+
auto request_ctx_it = request_map_.find(req_id);
121+
if (request_ctx_it == request_map_.end()) {
122+
assert(false);
123+
return;
124+
}
125+
126+
RequestContext& ctx = request_ctx_it->second;
127+
if (ctx.CancelRequest(id)) {
128+
request_map_.erase(request_ctx_it);
129+
}
130+
}
131+
132+
} // namespace read
133+
} // namespace dataservice
134+
} // namespace olp
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (C) 2019-2020 HERE Europe B.V.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
#pragma once
21+
22+
#include <unordered_map>
23+
24+
#include <olp/core/client/CancellationContext.h>
25+
#include <olp/dataservice/read/Types.h>
26+
27+
namespace olp {
28+
namespace dataservice {
29+
namespace read {
30+
31+
class RequestBroker {
32+
public:
33+
using Callback = DataResponseCallback;
34+
using RequestId = std::string;
35+
36+
struct CreateOrAssociateResult {
37+
client::CancellationContext context;
38+
client::CancellationToken caller_cancelation_token;
39+
bool just_created;
40+
};
41+
42+
CreateOrAssociateResult CreateOrAssociateRequest(RequestId req_id,
43+
Callback callback);
44+
45+
DataResponseCallback ResponseHandler(RequestId req_id);
46+
47+
private:
48+
using CallerId = std::string;
49+
50+
class RequestContext {
51+
public:
52+
void AddCallback(CallerId id, Callback callback);
53+
void PropagateResponse(DataResponse response);
54+
// Return true if the operation was canceled
55+
bool CancelRequest(CallerId id);
56+
57+
client::CancellationContext CancelationContext();
58+
59+
private:
60+
client::CancellationContext cancelation_context;
61+
std::unordered_map<CallerId, DataResponseCallback> callbacks;
62+
};
63+
64+
using RequestMap = std::unordered_map<RequestId, RequestContext>;
65+
66+
inline client::CancellationToken CancelToken(RequestId req_id, CallerId id) {
67+
return client::CancellationToken([=]() { CancelRequest(req_id, id); });
68+
}
69+
70+
struct GetOrCreateResult {
71+
RequestContext& ctx;
72+
bool just_created;
73+
};
74+
75+
GetOrCreateResult GetOrCreateContext(RequestId req_id);
76+
77+
void PropagateResponse(RequestId req_id, DataResponse response);
78+
79+
void CancelRequest(RequestId req_id, CallerId id);
80+
81+
std::mutex mutex_;
82+
RequestMap request_map_;
83+
};
84+
85+
} // namespace read
86+
} // namespace dataservice
87+
} // namespace olp

olp-cpp-sdk-dataservice-read/src/VersionedLayerClientImpl.cpp

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -152,24 +152,37 @@ client::CancellationToken VersionedLayerClientImpl::GetData(
152152
auto layer_id = layer_id_;
153153
auto settings = settings_;
154154

155-
auto data_task =
156-
[=](client::CancellationContext context) mutable -> DataResponse {
157-
if (!request.GetDataHandle()) {
158-
auto version_response = GetVersion(request.GetBillingTag(),
159-
request.GetFetchOption(), context);
160-
if (!version_response.IsSuccessful()) {
161-
return version_response.GetError();
155+
auto request_id = request.CreateKey(layer_id);
156+
157+
auto result =
158+
broker_.CreateOrAssociateRequest(request_id, std::move(callback));
159+
160+
if (result.just_created) {
161+
// We just created a task, so trigger a real one and consume the
162+
// CancellationContext provided.
163+
auto data_task =
164+
[=](client::CancellationContext context) mutable -> DataResponse {
165+
if (!request.GetDataHandle()) {
166+
auto version_response = GetVersion(request.GetBillingTag(),
167+
request.GetFetchOption(), context);
168+
if (!version_response.IsSuccessful()) {
169+
return version_response.GetError();
170+
}
171+
request.WithVersion(version_response.GetResult().GetVersion());
162172
}
163-
request.WithVersion(version_response.GetResult().GetVersion());
164-
}
165173

166-
return repository::DataRepository::GetVersionedData(
167-
std::move(catalog), std::move(layer_id), std::move(request), context,
168-
std::move(settings));
169-
};
174+
return repository::DataRepository::GetVersionedData(
175+
std::move(catalog), std::move(layer_id), std::move(request),
176+
context, std::move(settings));
177+
};
170178

171-
return AddTask(settings.task_scheduler, pending_requests_,
172-
std::move(data_task), std::move(callback));
179+
// We don't care about result here since we are passing the context
180+
// outside.
181+
AddTask(settings.task_scheduler, pending_requests_, std::move(data_task),
182+
broker_.ResponseHandler(request_id), result.context);
183+
}
184+
185+
return result.caller_cancelation_token;
173186
};
174187

175188
return ScheduleFetch(std::move(schedule_get_data), std::move(request),

olp-cpp-sdk-dataservice-read/src/VersionedLayerClientImpl.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
#include <memory>
2323

24-
#include <boost/optional.hpp>
2524
#include <olp/core/client/CancellationContext.h>
2625
#include <olp/core/client/CancellationToken.h>
2726
#include <olp/core/client/HRN.h>
@@ -33,6 +32,8 @@
3332
#include <olp/dataservice/read/PrefetchTilesRequest.h>
3433
#include <olp/dataservice/read/TileRequest.h>
3534
#include <olp/dataservice/read/Types.h>
35+
#include <boost/optional.hpp>
36+
#include "RequestBroker.h"
3637
#include "repositories/ExecuteOrSchedule.inl"
3738

3839
namespace olp {
@@ -93,6 +94,7 @@ class VersionedLayerClientImpl {
9394
client::HRN catalog_;
9495
std::string layer_id_;
9596
client::OlpClientSettings settings_;
97+
RequestBroker broker_;
9698
std::shared_ptr<client::PendingRequests> pending_requests_;
9799
std::atomic<int64_t> catalog_version_;
98100
};

0 commit comments

Comments
 (0)