| 124 | } |
| 125 | |
| 126 | po::variables_map parse_command_line(int argc, char* argv[]) { |
| 127 | auto const default_min_stream_size = 64 * 1024 * 1024L; |
| 128 | auto const default_max_streams = [] { |
| 129 | auto constexpr kFallbackStreamCount = 4; |
| 130 | auto constexpr kStreamsPerCore = 4; |
| 131 | auto const count = std::thread::hardware_concurrency(); |
| 132 | if (count == 0) return kFallbackStreamCount; |
| 133 | return static_cast<int>(count * kStreamsPerCore); |
| 134 | }(); |
| 135 | |
| 136 | po::positional_options_description positional; |
| 137 | for (auto const* name : kPositional) positional.add(name, 1); |
| 138 | po::options_description desc( |
| 139 | "Upload a single GCS object using multiple slices"); |
| 140 | desc.add_options()("help", "produce help message") |
| 141 | // |
| 142 | ("source", po::value<std::string>()->required(), |
| 143 | "set the object file to upload") |
| 144 | // |
| 145 | ("bucket", po::value<std::string>()->required(), |
| 146 | "set the GCS bucket to upload to") |
| 147 | // |
| 148 | ("object", po::value<std::string>()->required(), |
| 149 | "set the GCS object to upload") |
| 150 | // |
| 151 | ("max-streams", po::value<int>()->default_value(default_max_streams), |
| 152 | "number of parallel streams for the upload") |
| 153 | // |
| 154 | ("minimum-stream-size", |
| 155 | po::value<std::int64_t>()->default_value(default_min_stream_size), |
| 156 | "minimum slice size"); |
| 157 | |
| 158 | // parse the input into the map |
| 159 | po::variables_map vm; |
| 160 | |
| 161 | // run notify() for all registered options in the map |
| 162 | try { |
| 163 | po::parsed_options parsed = po::command_line_parser(argc, argv) |
| 164 | .options(desc) |
| 165 | .positional(positional) |
| 166 | .run(); |
| 167 | po::store(parsed, vm); |
| 168 | po::notify(vm); |
| 169 | } catch (std::exception const& ex) { |
| 170 | // if required arguments are missing but help is desired, just print help |
| 171 | if (vm.count("help") > 0 or argc == 1) usage(argv[0], desc); |
| 172 | usage(argv[0], desc, ex.what()); |
| 173 | } |
| 174 | |
| 175 | if (vm.count("help") != 0) usage(argv[0], desc); |
| 176 | |
| 177 | for (std::string opt : kPositional) { |
| 178 | if (not vm[opt].as<std::string>().empty()) continue; |
| 179 | usage(argv[0], desc, fmt::format("the {} argument cannot be empty", opt)); |
| 180 | } |
| 181 | |
| 182 | if (vm["max-streams"].as<int>() == 0) { |
| 183 | usage(argv[0], desc, "the --max-streams option cannot be zero"); |