chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include <gflags/gflags.h>
|
||||
#include "brpc/cluster_recover_policy.h"
|
||||
#include "butil/scoped_lock.h"
|
||||
#include "butil/synchronization/lock.h"
|
||||
#include "brpc/server_id.h"
|
||||
#include "brpc/socket.h"
|
||||
#include "butil/fast_rand.h"
|
||||
#include "butil/time.h"
|
||||
#include "butil/string_splitter.h"
|
||||
|
||||
namespace brpc {
|
||||
|
||||
DEFINE_int64(detect_available_server_interval_ms, 10, "The interval "
|
||||
"to detect available server count in DefaultClusterRecoverPolicy");
|
||||
|
||||
DefaultClusterRecoverPolicy::DefaultClusterRecoverPolicy(
|
||||
int64_t min_working_instances, int64_t hold_seconds)
|
||||
: _recovering(false)
|
||||
, _min_working_instances(min_working_instances)
|
||||
, _last_usable(0)
|
||||
, _last_usable_change_time_ms(0)
|
||||
, _hold_seconds(hold_seconds)
|
||||
, _usable_cache(0)
|
||||
, _usable_cache_time_ms(0) { }
|
||||
|
||||
void DefaultClusterRecoverPolicy::StartRecover() {
|
||||
std::unique_lock<butil::Mutex> mu(_mutex);
|
||||
_recovering = true;
|
||||
}
|
||||
|
||||
bool DefaultClusterRecoverPolicy::StopRecoverIfNecessary() {
|
||||
if (!_recovering) {
|
||||
return false;
|
||||
}
|
||||
int64_t now_ms = butil::cpuwide_time_ms();
|
||||
std::unique_lock<butil::Mutex> mu(_mutex);
|
||||
if (_last_usable_change_time_ms != 0 && _last_usable != 0 &&
|
||||
(now_ms - _last_usable_change_time_ms > _hold_seconds * 1000)) {
|
||||
_recovering = false;
|
||||
_last_usable = 0;
|
||||
_last_usable_change_time_ms = 0;
|
||||
mu.unlock();
|
||||
return false;
|
||||
}
|
||||
mu.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t DefaultClusterRecoverPolicy::GetUsableServerCount(
|
||||
int64_t now_ms, const std::vector<ServerId>& server_list) {
|
||||
if (now_ms - _usable_cache_time_ms < FLAGS_detect_available_server_interval_ms) {
|
||||
return _usable_cache;
|
||||
}
|
||||
uint64_t usable = 0;
|
||||
size_t n = server_list.size();
|
||||
SocketUniquePtr ptr;
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
if (Socket::Address(server_list[i].id, &ptr) == 0
|
||||
&& ptr->IsAvailable()) {
|
||||
usable++;
|
||||
}
|
||||
}
|
||||
{
|
||||
std::unique_lock<butil::Mutex> mu(_mutex);
|
||||
_usable_cache = usable;
|
||||
_usable_cache_time_ms = now_ms;
|
||||
}
|
||||
return _usable_cache;
|
||||
}
|
||||
|
||||
|
||||
bool DefaultClusterRecoverPolicy::DoReject(const std::vector<ServerId>& server_list) {
|
||||
if (!_recovering) {
|
||||
return false;
|
||||
}
|
||||
int64_t now_ms = butil::cpuwide_time_ms();
|
||||
uint64_t usable = GetUsableServerCount(now_ms, server_list);
|
||||
if (_last_usable != usable) {
|
||||
std::unique_lock<butil::Mutex> mu(_mutex);
|
||||
if (_last_usable != usable) {
|
||||
_last_usable = usable;
|
||||
_last_usable_change_time_ms = now_ms;
|
||||
}
|
||||
}
|
||||
if (butil::fast_rand_less_than(_min_working_instances) >= usable) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetRecoverPolicyByParams(const butil::StringPiece& params,
|
||||
std::shared_ptr<ClusterRecoverPolicy>* ptr_out) {
|
||||
int64_t min_working_instances = -1;
|
||||
int64_t hold_seconds = -1;
|
||||
bool has_meet_params = false;
|
||||
for (butil::KeyValuePairsSplitter sp(params.begin(), params.end(), ' ', '=');
|
||||
sp; ++sp) {
|
||||
if (sp.value().empty()) {
|
||||
LOG(ERROR) << "Empty value for " << sp.key() << " in lb parameter";
|
||||
return false;
|
||||
}
|
||||
if (sp.key() == "min_working_instances") {
|
||||
if (!butil::StringToInt64(sp.value(), &min_working_instances)) {
|
||||
return false;
|
||||
}
|
||||
has_meet_params = true;
|
||||
continue;
|
||||
} else if (sp.key() == "hold_seconds") {
|
||||
if (!butil::StringToInt64(sp.value(), &hold_seconds)) {
|
||||
return false;
|
||||
}
|
||||
has_meet_params = true;
|
||||
continue;
|
||||
}
|
||||
LOG(ERROR) << "Failed to set this unknown parameters " << sp.key_and_value();
|
||||
return false;
|
||||
}
|
||||
if (min_working_instances > 0 && hold_seconds > 0) {
|
||||
ptr_out->reset(
|
||||
new DefaultClusterRecoverPolicy(min_working_instances, hold_seconds));
|
||||
} else if (has_meet_params) {
|
||||
// In this case, user set some params but not in the right way, just return
|
||||
// false to let user take care of this situation.
|
||||
LOG(ERROR) << "Invalid params=`" << params << "'";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace brpc
|
||||
Reference in New Issue
Block a user