/* * MutationTracking.cpp * * This source file is part of the FoundationDB open source project * * Copyright 2013-2020 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 #include "fdbserver/MutationTracking.h" #include "fdbserver/LogProtocolMessage.h" #include "fdbserver/SpanContextMessage.h" #if defined(FDB_CLEAN_BUILD) && MUTATION_TRACKING_ENABLED #error "You cannot use mutation tracking in a clean/release build." #endif // Track up to 2 keys in simulation via enabling MUTATION_TRACKING_ENABLED and setting the keys here. StringRef debugKey = LiteralStringRef(""); StringRef debugKey2 = LiteralStringRef("\xff\xff\xff\xff"); TraceEvent debugMutationEnabled(const char* context, Version version, MutationRef const& mutation) { if ((mutation.type == mutation.ClearRange || mutation.type == mutation.DebugKeyRange) && ((mutation.param1 <= debugKey && mutation.param2 > debugKey) || (mutation.param1 <= debugKey2 && mutation.param2 > debugKey2))) { TraceEvent event("MutationTracking"); event.detail("At", context) .detail("Version", version) .detail("MutationType", typeString[mutation.type]) .detail("KeyBegin", mutation.param1) .detail("KeyEnd", mutation.param2); return event; } else if (mutation.param1 == debugKey || mutation.param1 == debugKey2) { TraceEvent event("MutationTracking"); event.detail("At", context) .detail("Version", version) .detail("MutationType", typeString[mutation.type]) .detail("Key", mutation.param1) .detail("Value", mutation.param2); return event; } else { return TraceEvent(); } } TraceEvent debugKeyRangeEnabled(const char* context, Version version, KeyRangeRef const& keys) { if (keys.contains(debugKey) || keys.contains(debugKey2)) { return debugMutation(context, version, MutationRef(MutationRef::DebugKeyRange, keys.begin, keys.end)); } else { return TraceEvent(); } } TraceEvent debugTagsAndMessageEnabled(const char* context, Version version, StringRef commitBlob) { BinaryReader rdr(commitBlob, AssumeVersion(g_network->protocolVersion())); while (!rdr.empty()) { if (*(int32_t*)rdr.peekBytes(4) == VERSION_HEADER) { int32_t dummy; rdr >> dummy >> version; continue; } TagsAndMessage msg; msg.loadFromArena(&rdr, nullptr); bool logAdapterMessage = std::any_of( msg.tags.begin(), msg.tags.end(), [](const Tag& t) { return t == txsTag || t.locality == tagLocalityTxs; }); StringRef mutationData = msg.getMessageWithoutTags(); uint8_t mutationType = *mutationData.begin(); if (logAdapterMessage) { // Skip the message, as there will always be an idential non-logAdapterMessage mutation // that we can match against in the same commit. } else if (LogProtocolMessage::startsLogProtocolMessage(mutationType)) { BinaryReader br(mutationData, AssumeVersion(rdr.protocolVersion())); LogProtocolMessage lpm; br >> lpm; rdr.setProtocolVersion(br.protocolVersion()); } else if (SpanContextMessage::startsSpanContextMessage(mutationType)) { BinaryReader br(mutationData, AssumeVersion(rdr.protocolVersion())); SpanContextMessage scm; br >> scm; } else { MutationRef m; BinaryReader br(mutationData, AssumeVersion(rdr.protocolVersion())); br >> m; TraceEvent event = debugMutation(context, version, m); if (event.isEnabled()) { event.detail("MessageTags", msg.tags); return event; } } } return TraceEvent(); } #if MUTATION_TRACKING_ENABLED TraceEvent debugMutation(const char* context, Version version, MutationRef const& mutation) { return debugMutationEnabled(context, version, mutation); } TraceEvent debugKeyRange(const char* context, Version version, KeyRangeRef const& keys) { return debugKeyRangeEnabled(context, version, keys); } TraceEvent debugTagsAndMessage(const char* context, Version version, StringRef commitBlob) { return debugTagsAndMessageEnabled(context, version, commitBlob); } #else TraceEvent debugMutation(const char* context, Version version, MutationRef const& mutation) { return TraceEvent(); } TraceEvent debugKeyRange(const char* context, Version version, KeyRangeRef const& keys) { return TraceEvent(); } TraceEvent debugTagsAndMessage(const char* context, Version version, StringRef commitBlob) { return TraceEvent(); } #endif