| // 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. |
| // |
| // Flag Tags provide a way to attach arbitrary textual tags to gflags in |
| // a global registry. Kudu uses the following flag tags: |
| // |
| // - "stable": |
| // These flags are considered user-facing APIs. Therefore, the |
| // semantics of the flag should not be changed except between major |
| // versions. Similarly, they must not be removed except between major |
| // versions. |
| // |
| // - "evolving": |
| // These flags are considered user-facing APIs, but are not yet |
| // locked down. For example, they may pertain to a newly introduced |
| // feature that is still being actively developed. These may be changed |
| // between minor versions, but should be suitably release-noted. |
| // |
| // This is the default assumed stability level, but can be tagged |
| // if you'd like to make it explicit. |
| // |
| // - "experimental": |
| // These flags are considered user-facing APIs, but are related to |
| // an experimental feature, or otherwise likely to change or be |
| // removed at any point. Users should not expect any compatibility |
| // of these flags. |
| // |
| // Users must pass --unlock_experimental_flags to use any of these |
| // flags. |
| // |
| // - "hidden": |
| // These flags are for internal use only (e.g. testing) and should |
| // not be included in user-facing documentation. |
| // |
| // - "advanced": |
| // These flags are for advanced users or debugging purposes. While |
| // they aren't likely to be actively harmful (see "unsafe" below), |
| // they're also likely to be used only rarely and should be relegated |
| // to more detailed sections of documentation. |
| // |
| // - "unsafe": |
| // These flags are for internal use only (e.g. testing), and changing |
| // them away from the defaults may result in arbitrarily bad things |
| // happening. These flags are automatically excluded from user-facing |
| // documentation even if they are not also marked 'hidden'. |
| // |
| // Users must pass --unlock_unsafe_flags to use any of these |
| // flags. |
| // |
| // - "runtime": |
| // These flags can be safely changed at runtime via an RPC to the |
| // server. Changing a flag at runtime that does not have this tag is allowed |
| // only if the user specifies a "force_unsafe_change" flag in the RPC. |
| // |
| // NOTE: because gflags are simple global variables, it's important to |
| // think very carefully before tagging a flag with 'runtime'. In particular, |
| // if a string-type flag is marked 'runtime', you should never access it |
| // using the raw 'FLAGS_foo_bar' name. Instead, you must use the |
| // google::GetCommandLineFlagInfo(...) API to make a copy of the flag value |
| // under a lock. Otherwise, the 'std::string' instance could be mutated |
| // underneath the reader causing a crash. |
| // |
| // For primitive-type flags, we assume that reading a variable is atomic. |
| // That is to say that a reader will either see the old value or the new |
| // one, but not some invalid value. However, for the runtime change to |
| // have any effect, you must be sure to use the FLAGS_foo_bar variable directly |
| // rather than initializing some instance variable during program startup. |
| // |
| // - "sensitive": |
| // The values of these flags are considered sensitive and will be redacted |
| // if redaction is enabled. |
| // |
| // A given flag may have zero or more tags associated with it. The system does |
| // not make any attempt to check integrity of the tags - for example, it allows |
| // you to mark a flag as both stable and unstable, even though this makes no |
| // real sense. Nevertheless, you should strive to meet the following requirements: |
| // |
| // - A flag should have exactly no more than one of stable/evolving/experimental |
| // indicating its stability. 'evolving' is considered the default. |
| // - A flag should have no more than one of advanced/hidden indicating visibility |
| // in documentation. If neither is specified, the flag will be in the main |
| // section of the documentation. |
| // - It is likely that most 'experimental' flags will also be 'advanced' or 'hidden', |
| // and that 'stable' flags are not likely to be 'hidden' or 'unsafe'. |
| // |
| // To add a tag to a flag, use the TAG_FLAG macro. For example: |
| // |
| // DEFINE_bool(sometimes_crash, false, "This flag makes Kudu crash a lot"); |
| // TAG_FLAG(sometimes_crash, unsafe); |
| // TAG_FLAG(sometimes_crash, runtime); |
| // |
| // To fetch the list of tags associated with a flag, use 'GetFlagTags'. |
| |
| #ifndef KUDU_UTIL_FLAG_TAGS_H |
| #define KUDU_UTIL_FLAG_TAGS_H |
| |
| #include "kudu/gutil/macros.h" |
| |
| #include <string> |
| #include <unordered_set> |
| |
| namespace kudu { |
| |
| struct FlagTags { |
| enum { |
| stable, |
| evolving, |
| experimental, |
| hidden, |
| advanced, |
| unsafe, |
| runtime, |
| sensitive |
| }; |
| }; |
| |
| // Tag the flag 'flag_name' with the given tag 'tag'. |
| // |
| // This verifies that 'flag_name' is a valid gflag, which must be defined |
| // or declared above the use of the TAG_FLAG macro. |
| // |
| // This also validates that 'tag' is a valid flag as defined in the FlagTags |
| // enum above. |
| #define TAG_FLAG(flag_name, tag) \ |
| namespace { \ |
| ::kudu::flag_tags_internal::FlagTagger t_##flag_name##_##tag( \ |
| AS_STRING(flag_name), AS_STRING(tag)); \ |
| } \ |
| COMPILE_ASSERT(sizeof(decltype(FLAGS_##flag_name)), flag_does_not_exist); \ |
| COMPILE_ASSERT(sizeof(::kudu::FlagTags::tag), invalid_tag) |
| |
| // Fetch the list of flags associated with the given flag. |
| // |
| // If the flag is invalid or has no tags, sets 'tags' to be empty. |
| void GetFlagTags(const std::string& flag_name, |
| std::unordered_set<std::string>* tags); |
| |
| // ------------------------------------------------------------ |
| // Internal implementation details |
| // ------------------------------------------------------------ |
| namespace flag_tags_internal { |
| |
| class FlagTagger { |
| public: |
| FlagTagger(const char* name, const char* tag); |
| ~FlagTagger(); |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(FlagTagger); |
| }; |
| |
| } // namespace flag_tags_internal |
| |
| } // namespace kudu |
| #endif /* KUDU_UTIL_FLAG_TAGS_H */ |