in eden/mononoke/cmdlib/src/args/app.rs [631:843]
fn add_blobstore_args<'a, 'b>(&self, app: App<'a, 'b>) -> App<'a, 'b> {
let mut put_arg = Arg::with_name(BLOBSTORE_PUT_BEHAVIOUR_ARG)
.long(BLOBSTORE_PUT_BEHAVIOUR_ARG)
.takes_value(true)
.required(false)
.help("Desired blobstore behaviour when a put is made to an existing key.");
if let Some(special_put_behaviour) = self.special_put_behaviour {
put_arg = put_arg.default_value(special_put_behaviour.into());
} else {
// Add the default here so that it shows in --help
put_arg = put_arg.default_value(DEFAULT_PUT_BEHAVIOUR.into());
}
let mut read_qps_arg = Arg::with_name(READ_QPS_ARG)
.long(READ_QPS_ARG)
.takes_value(true)
.required(false)
.help("Read QPS limit to ThrottledBlob");
if let Some(default) = self.blobstore_read_qps_default {
// Lazy static is nicer to LeakSanitizer than Box::leak
static QPS_FORMATTED: OnceCell<String> = OnceCell::new();
// clap needs &'static str
read_qps_arg =
read_qps_arg.default_value(&QPS_FORMATTED.get_or_init(|| format!("{}", default)));
}
let app = app.arg(
read_qps_arg
)
.arg(
Arg::with_name(WRITE_QPS_ARG)
.long(WRITE_QPS_ARG)
.takes_value(true)
.required(false)
.help("Write QPS limit to ThrottledBlob"),
)
.arg(
Arg::with_name(WRITE_BYTES_ARG)
.long(WRITE_BYTES_ARG)
.takes_value(true)
.required(false)
.help("Write Bytes/s limit to ThrottledBlob"),
)
.arg(
Arg::with_name(READ_BYTES_ARG)
.long(READ_BYTES_ARG)
.takes_value(true)
.required(false)
.help("Read Bytes/s limit to ThrottledBlob"),
)
.arg(
Arg::with_name(READ_BURST_BYTES_ARG)
.long(READ_BURST_BYTES_ARG)
.takes_value(true)
.required(false)
.help("Maximum burst bytes/s limit to ThrottledBlob. Blobs larger than this will error rather than throttle due to consuming too much quota."),
)
.arg(
Arg::with_name(WRITE_BURST_BYTES_ARG)
.long(WRITE_BURST_BYTES_ARG)
.takes_value(true)
.required(false)
.help("Maximum burst bytes/s limit to ThrottledBlob. Blobs larger than this will error rather than throttle due to consuming too much quota."),
)
.arg(
Arg::with_name(BLOBSTORE_BYTES_MIN_THROTTLE_ARG)
.long(BLOBSTORE_BYTES_MIN_THROTTLE_ARG)
.takes_value(true)
.required(false)
.help("Minimum number of bytes ThrottledBlob can count"),
)
.arg(
Arg::with_name(READ_CHAOS_ARG)
.long(READ_CHAOS_ARG)
.takes_value(true)
.required(false)
.help("Rate of errors on reads. Pass N, it will error randomly 1/N times. For multiplexed stores will only apply to the first store in the multiplex."),
)
.arg(
Arg::with_name(WRITE_CHAOS_ARG)
.long(WRITE_CHAOS_ARG)
.takes_value(true)
.required(false)
.help("Rate of errors on writes. Pass N, it will error randomly 1/N times. For multiplexed stores will only apply to the first store in the multiplex."),
)
.arg(
Arg::with_name(WRITE_ZSTD_ARG)
.long(WRITE_ZSTD_ARG)
.takes_value(true)
.required(false)
.possible_values(BOOL_VALUES)
.help("Allows one to override config to enable/disable zstd compression on write via packblob"),
)
.arg(
Arg::with_name(WRITE_ZSTD_LEVEL_ARG)
.long(WRITE_ZSTD_LEVEL_ARG)
.takes_value(true)
.required(false)
.requires(WRITE_ZSTD_ARG)
.help("Override the zstd compression leve used for writes via packblob."),
)
.arg(
Arg::with_name(CACHELIB_ATTEMPT_ZSTD_ARG)
.long(CACHELIB_ATTEMPT_ZSTD_ARG)
.takes_value(true)
.possible_values(BOOL_VALUES)
.required(false)
.default_value(bool_as_str(self.blobstore_cachelib_attempt_zstd_default))
.help("Whether to attempt zstd compression when blobstore is putting things into cachelib over threshold size."),
)
.arg(
put_arg
)
.arg(
Arg::with_name(WITH_READONLY_STORAGE_ARG)
.long(WITH_READONLY_STORAGE_ARG)
.takes_value(true)
.possible_values(BOOL_VALUES)
.default_value(bool_as_str(self.readonly_storage_default.0))
.help("Error on any attempts to write to storage if set to true"),
)
.arg(
Arg::with_name(PUT_MEAN_DELAY_SECS_ARG)
.long(PUT_MEAN_DELAY_SECS_ARG)
.takes_value(true)
.value_name(PUT_MEAN_DELAY_SECS_ARG)
.requires(PUT_STDDEV_DELAY_SECS_ARG)
.help("Mean value of additional delay for blobstore put calls"),
)
.arg(
Arg::with_name(PUT_STDDEV_DELAY_SECS_ARG)
.long(PUT_STDDEV_DELAY_SECS_ARG)
.takes_value(true)
.value_name(PUT_STDDEV_DELAY_SECS_ARG)
.requires(PUT_MEAN_DELAY_SECS_ARG)
.help("Stddev value of additional delay for blobstore put calls"),
)
.arg(
Arg::with_name(GET_MEAN_DELAY_SECS_ARG)
.long(GET_MEAN_DELAY_SECS_ARG)
.takes_value(true)
.value_name(GET_MEAN_DELAY_SECS_ARG)
.requires(GET_STDDEV_DELAY_SECS_ARG)
.help("Mean value of additional delay for blobstore get calls"),
)
.arg(
Arg::with_name(GET_STDDEV_DELAY_SECS_ARG)
.long(GET_STDDEV_DELAY_SECS_ARG)
.takes_value(true)
.value_name(GET_STDDEV_DELAY_SECS_ARG)
.requires(GET_MEAN_DELAY_SECS_ARG)
.help("Stddev value of additional delay for blobstore get calls"),
);
#[cfg(fbcode_build)]
let app = blobstore_factory::ManifoldOptions::add_args(app);
if self.arg_types.contains(&ArgType::Scrub) {
let mut scrub_action_arg = Arg::with_name(BLOBSTORE_SCRUB_ACTION_ARG)
.long(BLOBSTORE_SCRUB_ACTION_ARG)
.takes_value(true)
.required(false)
.possible_values(ScrubAction::VARIANTS)
.help("Enable ScrubBlobstore with the given action. Checks for keys missing from stores. In ReportOnly mode this logs only, otherwise it performs a copy to the missing stores.");
if let Some(default) = self.scrub_action_default {
scrub_action_arg = scrub_action_arg.default_value(default.into());
}
let mut scrub_grace_arg = Arg::with_name(BLOBSTORE_SCRUB_GRACE_ARG)
.long(BLOBSTORE_SCRUB_GRACE_ARG)
.takes_value(true)
.required(false)
.help("Number of seconds grace to give for key to arrive in multiple blobstores or the healer queue when scrubbing");
if let Some(default) = self.scrub_grace_secs_default {
static FORMATTED: OnceCell<String> = OnceCell::new(); // Lazy static is nicer to LeakSanitizer than Box::leak
scrub_grace_arg = scrub_grace_arg
.default_value(&FORMATTED.get_or_init(|| format!("{}", default)));
}
let mut scrub_queue_peek_bound_arg = Arg::with_name(
BLOBSTORE_SCRUB_QUEUE_PEEK_BOUND_ARG,
)
.long(BLOBSTORE_SCRUB_QUEUE_PEEK_BOUND_ARG)
.takes_value(true)
.required(false)
.requires(BLOBSTORE_SCRUB_ACTION_ARG)
.help("Number of seconds within which we consider it worth checking the healer queue.");
if let Some(default) = self.scrub_queue_peek_bound_secs_default {
static FORMATTED: OnceCell<String> = OnceCell::new(); // Lazy static is nicer to LeakSanitizer than Box::leak
scrub_queue_peek_bound_arg = scrub_queue_peek_bound_arg
.default_value(&FORMATTED.get_or_init(|| format!("{}", default)));
};
let mut scrub_action_on_missing_write_mostly_arg =
Arg::with_name(BLOBSTORE_SCRUB_WRITE_MOSTLY_MISSING_ARG)
.long(BLOBSTORE_SCRUB_WRITE_MOSTLY_MISSING_ARG)
.takes_value(true)
.required(false)
.possible_values(ScrubWriteMostly::VARIANTS)
.help(
"Whether to allow missing values from write mostly stores when scrubbing",
);
if let Some(default) = self.scrub_action_on_missing_write_mostly_default {
scrub_action_on_missing_write_mostly_arg =
scrub_action_on_missing_write_mostly_arg.default_value(default.into());
}
app.arg(scrub_action_arg)
.arg(scrub_grace_arg)
.arg(scrub_action_on_missing_write_mostly_arg)
.arg(scrub_queue_peek_bound_arg)
} else {
app
}
}