175 lines
4.7 KiB
C++
175 lines
4.7 KiB
C++
/*
|
|
* AuditUtils.actor.cpp
|
|
*
|
|
* This source file is part of the FoundationDB open source project
|
|
*
|
|
* Copyright 2013-2022 Apple Inc. and the FoundationDB project authors
|
|
*
|
|
* Licensed 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 "fdbclient/AuditUtils.actor.h"
|
|
|
|
#include "fdbclient/Audit.h"
|
|
#include "fdbclient/FDBTypes.h"
|
|
#include "fdbclient/NativeAPI.actor.h"
|
|
#include "fdbclient/ClientKnobs.h"
|
|
|
|
#include "flow/actorcompiler.h" // has to be last include
|
|
|
|
ACTOR static Future<std::vector<AuditStorageState>> getLatestAuditStatesImpl(Transaction* tr, AuditType type, int num) {
|
|
state std::vector<AuditStorageState> auditStates;
|
|
|
|
loop {
|
|
auditStates.clear();
|
|
try {
|
|
RangeResult res = wait(tr->getRange(auditKeyRange(type), num, Snapshot::False, Reverse::True));
|
|
for (int i = 0; i < res.size(); ++i) {
|
|
auditStates.push_back(decodeAuditStorageState(res[i].value));
|
|
}
|
|
break;
|
|
} catch (Error& e) {
|
|
wait(tr->onError(e));
|
|
}
|
|
}
|
|
|
|
return auditStates;
|
|
}
|
|
|
|
ACTOR Future<UID> persistNewAuditState(Database cx, AuditStorageState auditState) {
|
|
ASSERT(!auditState.id.isValid());
|
|
state Transaction tr(cx);
|
|
state UID auditId;
|
|
|
|
loop {
|
|
try {
|
|
std::vector<AuditStorageState> auditStates = wait(getLatestAuditStatesImpl(&tr, auditState.getType(), 1));
|
|
uint64_t nextId = 1;
|
|
if (!auditStates.empty()) {
|
|
nextId = auditStates.front().id.first() + 1;
|
|
}
|
|
auditId = UID(nextId, 0LL);
|
|
auditState.id = auditId;
|
|
tr.set(auditKey(auditState.getType(), auditId), auditStorageStateValue(auditState));
|
|
wait(tr.commit());
|
|
TraceEvent("PersistedNewAuditState", auditId).detail("AuditKey", auditKey(auditState.getType(), auditId));
|
|
break;
|
|
} catch (Error& e) {
|
|
wait(tr.onError(e));
|
|
}
|
|
}
|
|
|
|
return auditId;
|
|
}
|
|
|
|
ACTOR Future<Void> persistAuditState(Database cx, AuditStorageState auditState) {
|
|
state Transaction tr(cx);
|
|
|
|
loop {
|
|
try {
|
|
tr.set(auditKey(auditState.getType(), auditState.id), auditStorageStateValue(auditState));
|
|
wait(tr.commit());
|
|
break;
|
|
} catch (Error& e) {
|
|
wait(tr.onError(e));
|
|
}
|
|
}
|
|
|
|
return Void();
|
|
}
|
|
|
|
ACTOR Future<AuditStorageState> getAuditState(Database cx, AuditType type, UID id) {
|
|
state Transaction tr(cx);
|
|
state Optional<Value> res;
|
|
|
|
loop {
|
|
try {
|
|
Optional<Value> res_ = wait(tr.get(auditKey(type, id)));
|
|
res = res_;
|
|
TraceEvent("ReadAuditState", id).detail("AuditKey", auditKey(type, id));
|
|
break;
|
|
} catch (Error& e) {
|
|
wait(tr.onError(e));
|
|
}
|
|
}
|
|
|
|
if (!res.present()) {
|
|
throw key_not_found();
|
|
}
|
|
|
|
return decodeAuditStorageState(res.get());
|
|
}
|
|
|
|
ACTOR Future<std::vector<AuditStorageState>> getLatestAuditStates(Database cx, AuditType type, int num) {
|
|
Transaction tr(cx);
|
|
std::vector<AuditStorageState> auditStates = wait(getLatestAuditStatesImpl(&tr, type, num));
|
|
return auditStates;
|
|
}
|
|
|
|
ACTOR Future<Void> persistAuditStateMap(Database cx, AuditStorageState auditState) {
|
|
state Transaction tr(cx);
|
|
|
|
loop {
|
|
try {
|
|
wait(krmSetRange(
|
|
&tr, auditRangePrefixFor(auditState.id), auditState.range, auditStorageStateValue(auditState)));
|
|
break;
|
|
} catch (Error& e) {
|
|
wait(tr.onError(e));
|
|
}
|
|
}
|
|
|
|
return Void();
|
|
}
|
|
|
|
ACTOR Future<std::vector<AuditStorageState>> getAuditStateForRange(Database cx, UID id, KeyRange range) {
|
|
state RangeResult auditStates;
|
|
state Transaction tr(cx);
|
|
|
|
loop {
|
|
try {
|
|
RangeResult res_ = wait(krmGetRanges(&tr,
|
|
auditRangePrefixFor(id),
|
|
range,
|
|
CLIENT_KNOBS->KRM_GET_RANGE_LIMIT,
|
|
CLIENT_KNOBS->KRM_GET_RANGE_LIMIT_BYTES));
|
|
auditStates = res_;
|
|
break;
|
|
} catch (Error& e) {
|
|
wait(tr.onError(e));
|
|
}
|
|
}
|
|
|
|
std::vector<AuditStorageState> res;
|
|
for (int i = 0; i < auditStates.size() - 1; ++i) {
|
|
KeyRange currentRange = KeyRangeRef(auditStates[i].key, auditStates[i + 1].key);
|
|
AuditStorageState auditState;
|
|
if (!auditStates[i].value.empty()) {
|
|
AuditStorageState auditState = decodeAuditStorageState(auditStates[i].value);
|
|
}
|
|
auditState.range = currentRange;
|
|
res.push_back(auditState);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
StringRef auditTypeToString(const AuditType type) {
|
|
switch (type) {
|
|
case AuditType::Invalid:
|
|
return "Invalid"_sr;
|
|
case AuditType::ValidateHA:
|
|
return "ValidateHA"_sr;
|
|
}
|
|
return "Invalid"_sr;
|
|
} |