Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support the gflags for cmd parser #221

Open
wants to merge 8 commits into
base: unstable
Choose a base branch
from

Conversation

ChenMiaoi
Copy link
Collaborator

@ChenMiaoi ChenMiaoi commented Mar 17, 2025

Support Cmd:

related issue #215

  • kiwi --config /path/conf
  • kiwi --Version
  • kiwi --usage (original help command)
  • kiwi --port port
  • kiwi --loglevel level
  • kiwi --slaveof addr
  • kiwi --redis_compatible_mode
  • kiwi --use_raft yes/no
  • kiwi --raft_ip ip
  • kiwi --ips [x.x.x.x ::x::x::x::x ...]

All options support validity checks, EXCEPT for IPV6, which supports incomplete validity checks.

NOT SUPPORT THE SHORT COMMAND.

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced new command-line options enabling users to toggle Raft usage, specify a list of IP addresses, and set a dedicated Raft IP.
    • Added a command for displaying usage information for the Kiwi application.
  • Bug Fixes

    • Corrected the command used to start the Redis server by replacing the outdated -c flag with the --config flag.
  • Refactor

    • Enhanced argument parsing and validation for a more robust and streamlined configuration experience.
    • Improved handling of configuration settings related to IP addresses and Raft usage.
    • Updated documentation to clarify command-line options for running the application.

Copy link

coderabbitai bot commented Mar 17, 2025

Walkthrough

This pull request updates the Kiwi server's command-line argument parsing by replacing getopt_long with the gflags library and adding new flags. It modifies the usage output and introduces additional IP address checks and validations. Additionally, the Options class is extended with methods and members to handle the new Raft-related settings and IP configurations, while file handling now utilizes std::filesystem for improved processing.

Changes

File(s) Change Summary
src/kiwi.cc Replaced getopt_long with gflags for command-line parsing; added new flags (--use_raft, --raft_ip, --ips, --config); updated Usage and Init functions; introduced IP validation functions and PrintParsedFlags; updated file handling with std::filesystem.
src/options.h Added new methods (SetIps, GetIps, SetUseRaft, GetUseRaft, SetRaftIp, GetRaftIp) and member variables (ips_, use_raft, raft_ip) in the Options class to manage new configuration settings.
tests/support/server.tcl Modified the command to start the Redis server to use the --config flag instead of -c for specifying the configuration file.
README.md Added a new "Usage" section with the command ./bin/kiwi --usage; updated "Run" section command from ./bin/kiwi ./etc/conf/kiwi.conf to ./bin/kiwi [--config] ./etc/conf/kiwi.conf.

Possibly related PRs

Suggested reviewers

  • marsevilspirit
  • AlexStocks

Poem

I'm a little rabbit on the run,
Hopping through code under the sun.
Flags and IPs now bright and new,
With gflags and Options in a bouncy view.
Cheers to changes—let's code and have fun! 🐰

Happy coding from my burrow to you!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
src/kiwi.cc (4)

27-27: Remove or confirm necessity of <getopt.h>
Since the code now relies on gflags, verify whether <getopt.h> is still needed. If not, consider removing it.


102-111: New gflags definitions
All flags are clearly introduced. If you expect many more flags, consider a consistent naming convention (e.g., kiwi_*) for clarity.


113-124: Potential edge case with SplitIPs
Consecutive delimiters or trailing whitespace could yield empty tokens. Consider trimming or filtering out empty results for robustness.


140-162: Strict IPv4 parsing
Leading zeros for segments are disallowed, which might reject some addresses users commonly expect (e.g., 192.168.000.100). If this is intended behavior, no change is needed; otherwise, consider relaxing the rule.

src/options.h (1)

49-51: Private member variables
Naming is clear; if you prefer uniform naming with a trailing underscore (e.g., use_raft_, raft_ip_) to match cfg_file_, consider updating for consistency.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd0d12d and 08c32db.

📒 Files selected for processing (2)
  • src/kiwi.cc (6 hunks)
  • src/options.h (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_macos
  • GitHub Check: build_on_ubuntu
🔇 Additional comments (23)
src/kiwi.cc (18)

21-21: Use of std::filesystem
This inclusion is consistent with the new file-handling logic. Ensure your build environment supports C++17 or above.


75-84: Updated usage text
The usage text aligns with the newly added flags. Optionally, you can use gflags' built-in usage function (ShowUsageWithFlags) for lower maintenance.


90-92: Example usage
Adding examples for --use_raft, --ips, and --raft_ip makes it clearer for end users.


126-138: PrintParsedFlags added
A helpful feature for debugging. Keep in mind not to print sensitive information if secure flags are introduced in the future.


169-191: Consistent IP checks
Routing through CheckIPAddress ensures uniform logic for both IPv4 and IPv6. Once the IPv6 checker is implemented, this should be robust.


194-195: Switch to gflags
Parsing non-help flags is appropriate. Verify how unknown flags are handled, especially if you anticipate user typos.


197-199: Condition for --usage
Returning false to prompt usage elsewhere is a clear approach. Looks good.


201-204: Condition for --Version
Cleanly exits with a version summary. Straightforward and user-friendly.


207-217: Filesystem-based config validation
Good approach to confirm the path is valid and readable. No major concerns.


222-228: Unusual port requirement
Rejecting ports ≤ 1234 can be limiting. Typically, only ports < 1024 require elevated privileges. Confirm if this stricter check is intentional.


239-246: Slaveof format
Ingesting host:port is standard. Ensure empty or malformed strings are reported clearly.


248-250: Redis compatibility mode
Straight toggle for enabling Redis-like behavior. Implementation is straightforward.


252-260: Use Raft flag
Restricting to "yes" or "no" is explicit and ensures clarity for end users.


262-268: Raft IP validation
Using CheckIPAddress is a good approach to prevent invalid IP addresses.


270-279: Multiple IP addresses
Splitting and validating each address is robust. This approach neatly ensures all addresses meet your IP criteria.


364-366: Assigning raft-ip
Correctly propagates the raft IP to config if provided.


397-399: Populating g_config.ips
Copying IPs from options_ into g_config is consistent with other fields.


528-528: Printing parsed flags in main
Useful for troubleshooting unexpected flag values.

src/options.h (5)

32-33: Set/Get for ips_
These methods allow flexible handling of multiple IP addresses.


36-36: Setter for use_raft
Appropriately named. Ensure external validation (yes/no) continues to be enforced.


38-38: Getter for use_raft
Simple accessor; no issues identified.


40-40: Setter for raft_ip
Straightforward assignment. Matches typical setter patterns.


42-42: Getter for raft_ip
No concerns—consistent naming and usage.

src/kiwi.cc Outdated
Comment on lines 164 to 167
static inline bool IsValidIPv6(const std::vector<std::string>& addrs) {
//! TODO should impl the ipv6 check
return true;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

IPv6 validation is incomplete
IsValidIPv6 always returns true, making it prone to accepting invalid IPv6 strings.

Would you like me to propose an improved IPv6 validation to address this TODO?

src/kiwi.cc Outdated
Comment on lines 360 to 297
if (!options_.GetUseRaft().empty()) {
g_config.Set("use-raft", "yes", true);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Forcing "use-raft" to "yes"
If GetUseRaft() is set to "no", this code still sets "use-raft" to "yes.".

Proposed fix:

-if (!options_.GetUseRaft().empty()) {
-    g_config.Set("use-raft", "yes", true);
+if (options_.GetUseRaft() == "yes") {
+    g_config.Set("use-raft", "yes", true);
+} else if (options_.GetUseRaft() == "no") {
+    g_config.Set("use-raft", "no", true);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!options_.GetUseRaft().empty()) {
g_config.Set("use-raft", "yes", true);
}
if (options_.GetUseRaft() == "yes") {
g_config.Set("use-raft", "yes", true);
} else if (options_.GetUseRaft() == "no") {
g_config.Set("use-raft", "no", true);
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/kiwi.cc (2)

113-124: Consider improving the IP splitting function

The SplitIPs function might not handle edge cases such as consecutive separators correctly.

Consider this more robust implementation:

-static inline std::vector<std::string> SplitIPs(const std::string& ips, const std::string& sep) {
-  std::vector<std::string> ipList;
-  size_t start = 0;
-  size_t end = ips.find(sep);
-  while (end != std::string::npos) {
-    ipList.push_back(ips.substr(start, end - start));
-    start = end + sep.size();
-    end = ips.find(sep, start);
-  }
-  ipList.emplace_back(ips.substr(start, end));
-  return ipList;
+static inline std::vector<std::string> SplitIPs(const std::string& ips, const std::string& sep) {
+  std::vector<std::string> ipList;
+  size_t start = 0;
+  size_t end = 0;
+  
+  while ((end = ips.find(sep, start)) != std::string::npos) {
+    if (end > start) {  // Skip empty segments
+      ipList.push_back(ips.substr(start, end - start));
+    }
+    start = end + sep.size();
+  }
+  
+  // Add the last segment if it's not empty
+  if (start < ips.length()) {
+    ipList.push_back(ips.substr(start));
+  }
+  
+  return ipList;
}

169-191: IP address detection logic can be improved

The current approach to detect IPv4/IPv6 addresses is simplified and might lead to false positives. The commented-out code suggests a more thorough approach was considered.

Consider implementing a more robust check that properly handles edge cases:

static inline bool CheckIPAddress(const std::string& ip) {
-  bool isv4 = ip.find('.') != std::string::npos;
-  bool isv6 = ip.find(':') != std::string::npos;
-  if (!isv4 && !isv6) {
-    return false;
-  }
-  std::vector<std::string> addrs = SplitIPs(ip, isv4 ? "." : "::");
-
-  if (isv4) {
-    return IsValidIPv4(addrs);
-  } else {
-    return IsValidIPv6(addrs);
-  }
+  // Count dots and colons to determine IP format
+  int dots = 0, colons = 0;
+  for (char c : ip) {
+    dots += (c == '.');
+    colons += (c == ':');
+  }
+  
+  // IPv4 should have exactly 3 dots (4 segments)
+  if (dots == 3 && colons == 0) {
+    std::vector<std::string> addrs = SplitIPs(ip, ".");
+    return IsValidIPv4(addrs);
+  }
+  
+  // IPv6 should have several colons and no dots
+  // (simplified check - full IPv6 validation in IsValidIPv6)
+  if (colons > 0 && dots == 0) {
+    std::vector<std::string> addrs = SplitIPs(ip, ":");
+    return IsValidIPv6(addrs);
+  }
+  
+  return false;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 08c32db and 94cf9fa.

📒 Files selected for processing (1)
  • src/kiwi.cc (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_ubuntu
  • GitHub Check: build_on_macos
🔇 Additional comments (18)
src/kiwi.cc (18)

21-21: Good addition of the filesystem header

The inclusion of <filesystem> is appropriate for the file path handling that will be used in the command-line parsing.


75-84: Improved command-line interface documentation

The updated usage information provides clear and consistent descriptions of the available command options. This enhances user experience by making the interface more intuitive.


90-92: Good examples for new command options

The additional examples for the new command options help users understand how to use the new Raft and IP-related parameters correctly.


102-111: Appropriate flag definitions with clear descriptions

The gflags definitions match the documented usage and provide appropriate default values. Each flag has a clear description that aligns with its purpose.


140-162: Thorough IPv4 validation

The IPv4 validation function is comprehensive, checking for:

  • Correct number of segments (4)
  • Valid numeric range for each segment (0-255)
  • No leading zeros (except for standalone zero)
  • All characters are digits

This approach provides robust validation to prevent invalid IP addresses.


164-167: IPv6 validation is incomplete

IsValidIPv6 always returns true, making it prone to accepting invalid IPv6 strings.


193-204: Good transition to gflags for argument parsing

The switch to gflags simplifies the command-line parsing logic and allows for more organized and maintainable code. The early handling of --usage and --Version flags is appropriate.


207-217: Improved file path handling with std::filesystem

Using std::filesystem for configuration file validation is a modern and robust approach. The code properly checks if the file exists and has read permissions before proceeding.


222-228: Proper port validation with appropriate error message

The port validation ensures that privileged ports (<1234) are not used without root permissions, which is a good security practice.


230-237: Loglevel mismatch

Your usage prompt suggests info and error, but the code only accepts [debug, verbose, notice, warning]. This can lead to user confusion.


239-246: Proper slaveof format validation

The code correctly validates the slaveof format using sscanf to extract the host and port, providing a clear error message if the format is invalid.


252-260: Good validation for use_raft flag

The code properly validates that the use_raft flag is set to either "yes" or "no", with case-insensitive comparison, providing a clear error message if neither option is chosen.


262-268: Raft IP validation with clear error messaging

The code correctly validates the Raft IP address format using the CheckIPAddress function and provides a specific error message if the validation fails.


270-279: Thorough IP list validation

The code properly parses the space-separated IP list and validates each IP individually, providing specific error messages for any invalid IP addresses.


360-362: Forcing "use-raft" to "yes"

If GetUseRaft() is set to "no", this code will still set the configuration value, which ensures consistency between command-line options and the internal configuration.


364-366: Good Raft IP configuration

The code correctly configures the Raft IP address in the global configuration if provided via command-line arguments.


397-399: IP list properly propagated to configuration

The code correctly transfers the IP list from command-line options to the global configuration when provided.


528-528: Useful debugging information

Adding the call to PrintParsedFlags() provides useful debugging information, making it easier to troubleshoot command-line parsing issues.

Copy link
Collaborator

@marsevilspirit marsevilspirit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI 没有过, 我们要确保CI都通过,来保证质量,请看一下

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/kiwi.cc (2)

76-78: ⚠️ Potential issue

Usage help and implementation mismatch.

The usage help mentions log levels like info and error, but the implementation in lines 175-182 only accepts debug, verbose, notice, and warning. This inconsistency can lead to user confusion.

This issue was previously identified in a past review. Apply this fix to ensure consistency:

-    if (FLAGS_loglevel != "debug" && FLAGS_loglevel != "verbose" && FLAGS_loglevel != "notice" &&
-        FLAGS_loglevel != "warning") {
+    if (FLAGS_loglevel != "debug" && FLAGS_loglevel != "verbose" && FLAGS_loglevel != "notice" &&
+        FLAGS_loglevel != "warning" && FLAGS_loglevel != "info" && FLAGS_loglevel != "error") {
       std::cerr << "You must choose one of [debug, verbose, notice, warning, info, error].\n";
       return false;
    }

175-180: ⚠️ Potential issue

Loglevel validation inconsistency.

The error message doesn't match the actual validation, and both don't match the usage help in line 78. This can lead to user confusion.

As noted in past review comments, apply this fix:

-    if (FLAGS_loglevel != "debug" && FLAGS_loglevel != "verbose" && FLAGS_loglevel != "notice" &&
-        FLAGS_loglevel != "warning") {
-      std::cerr << "You must be choose one of [debug, verbose, notice, warning]." << "\n";
+    if (FLAGS_loglevel != "debug" && FLAGS_loglevel != "verbose" && FLAGS_loglevel != "notice" &&
+        FLAGS_loglevel != "warning" && FLAGS_loglevel != "info" && FLAGS_loglevel != "error") {
+      std::cerr << "You must choose one of [debug, verbose, notice, warning, info, error]." << "\n";
       return false;
    }
🧹 Nitpick comments (2)
src/kiwi.cc (2)

153-154: Avoid namespace aliases.

Per the project guidelines in past review comments, namespace aliases should be avoided. Use std::filesystem directly instead of creating a namespace alias.

Apply this change:

-    namespace fs = std::filesystem;
-    std::filesystem::path config_path(FLAGS_config);
+    std::filesystem::path config_path(FLAGS_config);

And update line 155-156 to use std::filesystem instead of fs.


167-171: Port validation should be more comprehensive.

The current port validation only checks if the port is less than or equal to 1234. This doesn't fully validate that the port is in the valid range (1-65535) and doesn't check if the port is already in use.

Consider enhancing the validation with:

-    if (FLAGS_port <= 1234) {
+    if (FLAGS_port <= 1234 || FLAGS_port > 65535) {
       std::cerr << "You should have root privileges but now NOT support." << "\n";
       return false;
     }

Checking if a port is already in use would require additional system calls and is more complex, but would be a valuable addition for user experience.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce8a53e and 9890e0d.

📒 Files selected for processing (1)
  • src/kiwi.cc (6 hunks)
🔇 Additional comments (4)
src/kiwi.cc (4)

113-124: Good IP splitting implementation.

The SplitIPs function correctly parses space-separated IP addresses. However, no validation is performed on the individual IP addresses to ensure they are correctly formatted.

I noticed that IP validation is mentioned as a future optimization in past review comments, so this approach is acceptable for now.


295-297: Proper use-raft configuration.

The implementation now correctly sets the "use-raft" configuration value to the user-specified value, addressing a previous issue where it was always set to "yes".


332-334: IP configuration now properly applied.

The implementation correctly sets the global IP configuration based on user-provided IPs.


463-465: Good debugging practice.

Printing parsed flags in debug builds helps with troubleshooting without cluttering production logs.

@luky116 luky116 mentioned this pull request Jan 18, 2025
21 tasks
@marsevilspirit
Copy link
Collaborator

这个pr还在继续推进吗

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


Is this PR still moving forward

@ChenMiaoi
Copy link
Collaborator Author

这个pr还在继续推进吗

sure, I‘ll try to learn tcl why it failed

@AlexStocks
Copy link
Contributor

这个pr还在继续推进吗

sure, I‘ll try to learn tcl why it failed

maybe u should merge the latest codes firstly

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/kiwi.cc (4)

113-124: Consider supporting comma-separated addresses in SplitIPs.

Currently, SplitIPs only uses a space delimiter. In some workflows, IPs are often separated by commas; supporting both delimiters would offer more flexibility.

- auto ips = SplitIPs(FLAGS_ips, " ");
+ // Example approach:
+ auto addressList = SplitIPs(FLAGS_ips, " ");
+ if (addressList.size() == 1) {
+   addressList = SplitIPs(FLAGS_ips, ",");
+ }

147-150: Exit call vs. returning a status code.

When FLAGS_Version is specified, the code calls exit(EXIT_SUCCESS). Consider returning an appropriate status code from ParseArgs so the caller remains in control of final application cleanup.


167-173: Port lower-bound warning message.

Rejecting ports <= 1234 is quite arbitrary. The message about root privileges may confuse users who attempt to use ports from 1 to 1023 but interpret 1234 as a strange cutoff.


207-209: Raft IP assignment.

This is direct and straightforward. Consider adding a check for empty or invalid IP in the future if you decide to enforce more thorough validation.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9890e0d and 52a33bf.

📒 Files selected for processing (2)
  • src/kiwi.cc (6 hunks)
  • src/options.h (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/kiwi.cc (4)
src/options.h (5)
  • use_raft (38-38)
  • ips (32-32)
  • ips (32-32)
  • raft_ip (42-42)
  • redis_compatible_mode (30-30)
src/config_parser.h (1)
  • cout (39-46)
src/kiwi.h (2)
  • argc (43-43)
  • options_ (44-44)
src/client.h (4)
  • argv (217-217)
  • argv (217-217)
  • str (152-152)
  • str (152-152)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_ubuntu
  • GitHub Check: build_on_macos
🔇 Additional comments (16)
src/kiwi.cc (15)

21-21: Include usage looks fine.

The <filesystem> and "gflags/gflags.h" headers are properly included for the newly introduced functionality. Please ensure that the build environment supports C++17 (or later) for <filesystem>.

Also applies to: 27-27


75-93: Mismatch between short and long flags in the usage message.

According to the PR description, short flags like -v or -h are not supported. However, the usage text here still references them (e.g., -v, -h, -p). This can confuse end-users expecting these short flags to work.

Would you like to remove short flags from the usage text, or implement proper support for them?


102-112: New gflags definitions approved.

Each of these flags has clear naming and a succinct description. Ensure your CI environment is set up to handle the new gflags dependency.


126-138: Printing parsed flags is beneficial for debugging.

The PrintParsedFlags function is a nice addition. Be mindful of potentially sensitive info (e.g., passwords) that might get logged here in future expansions.


141-145: Potential edge case with built-in help.

By using ParseCommandLineNonHelpFlags, the built-in --help mechanism of gflags is skipped. If the user runs --help, they only see the fallback usage text. This may be intentional, but confirm if that is the desired behavior.


152-166: Configuration file checks appear correct.

File existence and permissions are validated via std::filesystem, and a fallback warning is shown if no file is specified. This flow is straightforward and avoids accidental misconfiguration.


175-181: Inconsistent loglevel values with usage text.

The usage text states possible values like info or error, but the code only accepts [debug, verbose, notice, warning].


184-191: Slave address parsing logic is clear.

The parsing relies on 'host:port' format. This looks fine as a minimal approach for specifying a single slave address.


193-195: Redis compatibility mode flag.

This is straightforward. If more advanced Redis-compat checks are introduced later, ensure to re-verify the pipelines for possible divergences from real Redis.


197-205: Raft usage check is well-defined.

Accepting only "yes" or "no" ensures clarity. Converting to lowercase is good for robust user input handling.


211-214: Loading IPs from the multi-address flag.

SplitIPs captures the space-delimited addresses. Good straightforward approach; check for edge cases regarding IPv6 placeholders.


295-297: Raft usage saved to config.

Now it truly respects the user's yes or no choice (unlike the old forced "yes" approach).


299-302: Raft IP saved to config.

Implementation is consistent and minimal. Confirm that subsequent logic also accepts an empty string if the user does not specify an IP.


332-335: Merging IPs from flags into config.

options_.GetIps() is placed into g_config.ips so the server can bind multiple addresses. Looks good as is.


463-465: Debug-only print invocation.

Printing parsed flags within a conditional compilation block helps debug builds without polluting production logs.

src/options.h (1)

32-42: New IP and Raft-related setters/getters look consistent.

These additions properly manage IP lists, Raft usage string, and Raft IP. The naming is consistent with the rest of the class and integrates smoothly with kiwi.cc.

Also applies to: 49-51

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
src/kiwi.cc (3)

113-124: ⚠️ Potential issue

Missing IP validation in SplitIPs function

While the function correctly splits IP addresses, it doesn't validate that the IPs are actually valid. This is especially important for IPv6 addresses as mentioned in the PR objectives.

Consider adding IP validation for both IPv4 and IPv6:

static inline std::vector<std::string> SplitIPs(const std::string& ips, const std::string& sep) {
  std::vector<std::string> ipList;
  size_t start = 0;
  size_t end = ips.find(sep);
  while (end != std::string::npos) {
-    ipList.push_back(ips.substr(start, end - start));
+    std::string ip = ips.substr(start, end - start);
+    // Add validation here before adding to the list
+    ipList.push_back(ip);
    start = end + sep.size();
    end = ips.find(sep, start);
  }
-  ipList.emplace_back(ips.substr(start, end));
+  std::string ip = ips.substr(start, end);
+  // Add validation here before adding to the list
+  ipList.emplace_back(ip);
  return ipList;
}

295-297: ⚠️ Potential issue

Incorrect setting of use-raft configuration

The code needs to respect the user's choice of "yes" or "no" for the use_raft option.

if (!options_.GetUseRaft().empty()) {
-  g_config.Set("use-raft", options_.GetUseRaft(), true);
+  g_config.Set("use-raft", options_.GetUseRaft(), true);
}

175-182: ⚠️ Potential issue

Loglevel validation doesn't match usage message

The usage message (line 78) suggests that "info" and "error" are valid log levels, but the validation check doesn't include them.

if (FLAGS_loglevel != "debug" && FLAGS_loglevel != "verbose" && FLAGS_loglevel != "notice" &&
-    FLAGS_loglevel != "warning") {
-  std::cerr << "You must be choose one of [debug, verbose, notice, warning]." << "\n";
+    FLAGS_loglevel != "warning" && FLAGS_loglevel != "info" && FLAGS_loglevel != "error") {
+  std::cerr << "You must choose one of [debug, verbose, notice, warning, info, error]." << "\n";
  return false;
}
🧹 Nitpick comments (1)
src/kiwi.cc (1)

207-209: Missing validation for Raft IP address

The code sets the Raft IP without validating if it's a valid IP address format.

Consider adding IP validation before setting the Raft IP:

if (!FLAGS_raft_ip.empty()) {
+  // Add IP validation here
+  if (!IsValidIP(FLAGS_raft_ip)) {
+    std::cerr << "Invalid Raft IP address format." << "\n";
+    return false;
+  }
  options_.SetRaftIp(FLAGS_raft_ip);
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52a33bf and 15b7699.

📒 Files selected for processing (2)
  • src/kiwi.cc (6 hunks)
  • tests/support/server.tcl (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tests/support/server.tcl
🧰 Additional context used
🧬 Code Definitions (1)
src/kiwi.cc (4)
src/options.h (3)
  • use_raft (38-38)
  • raft_ip (42-42)
  • redis_compatible_mode (30-30)
src/config_parser.h (1)
  • cout (39-46)
src/kiwi.h (2)
  • argc (43-43)
  • options_ (44-44)
src/replication.h (1)
  • master_ (139-139)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_ubuntu
  • GitHub Check: build_on_macos
🔇 Additional comments (6)
src/kiwi.cc (6)

75-84: LGTM: Clear and improved usage message

The updated usage message clearly documents all the new command-line options, with good formatting and consistency.


102-111: Command-line flags defined properly with gflags

The transition to gflags for command-line argument parsing is a good improvement that simplifies the code and provides better handling of command options.


126-138: Good debugging helper function

The PrintParsedFlags function is a helpful debugging tool that clearly displays all parsed command-line options.


152-159: LGTM: Good filesystem check implementation

The code properly checks if the configuration file exists, is a regular file, and has the appropriate read permissions.


197-205: LGTM: Good option validation

The code properly validates the use_raft option by converting it to lowercase and checking that it's either "yes" or "no".


463-465: LGTM: Good debugging print

Only printing the parsed flags in debug builds is a good practice.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/kiwi.cc (1)

21-27: Avoid using a namespace alias for std::filesystem
A previous reviewer explicitly recommended using std::filesystem without an alias. Consider removing the alias to adhere to that style guide.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15b7699 and cc922fa.

📒 Files selected for processing (2)
  • src/kiwi.cc (6 hunks)
  • tests/support/server.tcl (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/support/server.tcl
🧰 Additional context used
🧬 Code Definitions (1)
src/kiwi.cc (2)
src/options.h (5)
  • use_raft (38-38)
  • ips (32-32)
  • ips (32-32)
  • raft_ip (42-42)
  • redis_compatible_mode (30-30)
src/kiwi.h (2)
  • argc (43-43)
  • options_ (44-44)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_macos
  • GitHub Check: build_on_ubuntu
🔇 Additional comments (12)
src/kiwi.cc (12)

72-93: Verify short flags usage
You display short flags (-v, -h, -p, etc.) in the usage, but gflags definitions only handle long flags. This discrepancy may confuse users.

Would you like to remove the short flags from the usage text or introduce short versions in the gflags definitions?


102-112: gflags-based definitions
The new flag definitions appear suitably aligned with your command-line requirements.


113-124: Edge-case handling in SplitIPs
Splitting on spaces alone can yield empty elements if multiple spaces are used. Consider ignoring empty entries for a cleaner IP list.

Additionally, IPv6 validation is still incomplete, as previously noted.


126-138: Clear debugging utility
PrintParsedFlags() usefully logs the final parsed flags for debugging.


141-149: Shifting argv elements
You remove the first argument and shift the array manually. Ensure no flags appear before the config file path to prevent conflicts or unexpected parsing behavior.


157-160: Immediate exit on version
Terminating after printing version info is standard practice; no concerns here.


190-197: Log level mismatch
The usage mentions "info" and "error," but the code restricts levels to [debug, verbose, notice, warning]. This is the same issue identified earlier.


226-229: IPv6 address checks
This PR continues to accept IPv6 strings at face value. Known incomplete validation remains unresolved, as previously discussed.


311-313: Respecting user raft choice
Previously, "use-raft" was forced to "yes." Now the code properly sets it to the user's input.


314-317: Conditional raft IP injection
If no Raft IP is specified, the code correctly omits it in the global config.


347-349: Runtime IP binding
Assigning options_.GetIps() to g_config.ips ensures the server listens on the user-provided addresses.


478-480: Debug-only flag output
Conditially printing parsed flags when BUILD_DEBUG is enabled is a neat, minimal-impact debugging aid.

@AlexStocks AlexStocks requested a review from lqxhub March 29, 2025 13:03
Copy link
Collaborator

@marsevilspirit marsevilspirit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

REAMDE改一下

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/kiwi.cc (2)

72-84: Inconsistent formatting in usage output

The usage examples show [--config] with square brackets (implying it's optional), but in the options description it's shown without brackets. This could confuse users about whether the flag is required.

-  std::cerr << "  kiwi [--config] [/path/to/kiwi.conf] [options]\n";
+  std::cerr << "  kiwi --config /path/to/kiwi.conf [options]\n";

Similarly, update the example lines 88-89, 93-95 for consistency.


171-172: Mixing namespace alias with full namespace

You define a namespace alias namespace fs = std::filesystem but then immediately use the full std::filesystem::path. This is inconsistent and makes the code harder to read.

-    namespace fs = std::filesystem;
-    std::filesystem::path config_path(conf_file);
+    namespace fs = std::filesystem;
+    fs::path config_path(conf_file);

Alternatively, per the previous review comment ("先不要使用namespace, 都用std::filesystem就行"), you could remove the namespace alias entirely:

-    namespace fs = std::filesystem;
-    std::filesystem::path config_path(conf_file);
+    std::filesystem::path config_path(conf_file);

And update the subsequent lines to use std::filesystem:: instead of fs::.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc922fa and 8795afc.

📒 Files selected for processing (2)
  • README.md (1 hunks)
  • src/kiwi.cc (6 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/kiwi.cc (6)
src/options.h (3)
  • use_raft (38-38)
  • raft_ip (42-42)
  • redis_compatible_mode (30-30)
src/config_parser.h (1)
  • cout (39-46)
src/kiwi.h (2)
  • argc (43-43)
  • options_ (44-44)
src/client.h (4)
  • argv (217-217)
  • argv (217-217)
  • str (152-152)
  • str (152-152)
src/helper.h (1)
  • str (25-25)
src/replication.h (1)
  • master_ (139-139)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_ubuntu
  • GitHub Check: build_on_macos
🔇 Additional comments (11)
README.md (2)

36-40: Good addition of usage section!

The new usage section provides a clear way for users to access help information about the command-line interface, which aligns well with the enhanced command parser capabilities.


45-45: Correctly updated command syntax with the new flag

This change properly updates the run command to use the new --config flag for specifying the configuration file path, making it consistent with the updated command-line interface.

src/kiwi.cc (9)

21-21: Good use of std::filesystem for improved file handling

Using the C++17 filesystem library is a good choice for more robust file path handling and permissions checking.


105-114: Well-structured flag definitions using gflags

The transition from getopt_long to gflags for command-line argument parsing is a good improvement. The flag definitions are clear, strongly typed, and include descriptive help messages.


129-141: Helpful debug function for displaying parsed flags

The PrintParsedFlags function is a useful addition for debugging purposes, helping developers verify that command-line arguments are parsed correctly.


195-200: Log level validation doesn't match usage examples

The validation logic only accepts debug, verbose, notice, and warning, but the usage message in line 78 suggests info and error are also valid options.


217-226: Good validation for use_raft flag

The code properly validates that the use_raft value is either "yes" or "no", with case-insensitive comparison, which is user-friendly.


316-318: Fixed the use-raft config setting

This correctly addresses a previous issue where the code was forcing "use-raft" to "yes" even when it was explicitly set to "no". Now it properly respects the user's choice.


320-322: Proper handling of IP configurations

The code now correctly handles the Raft IP address and the list of IP addresses, ensuring that the configuration is updated appropriately based on command-line arguments.

Also applies to: 353-355


484-486: Useful debug output of parsed flags

Conditionally printing the parsed flags in debug mode is a good practice for troubleshooting without cluttering normal operation.


116-127:

❓ Verification inconclusive

Function to split IP addresses lacks validation

While the splitting function works correctly to separate IP addresses, there's no validation to ensure the IP strings are valid IPv4 or IPv6 addresses.

I notice there was a previous comment about IPv6 validation being incomplete. Is this intentional, or do you plan to add validation later? If validation is needed, you might want to implement proper checks for both IPv4 and IPv6 formats.


🏁 Script executed:

#!/bin/bash
# Check if there are any IP validation functions in the codebase
rg -A 10 "IsValid(IP|Ipv4|Ipv6)" --include "*.h" --include "*.cc"

Length of output: 509


Attention: IP Validation in SplitIPs Function

After re-running our search with corrected flags, no IP validation functions (e.g. IsValidIP, IsValidIpv4, or IsValidIpv6) were identified in the codebase. This confirms that the SplitIPs function in src/kiwi.cc indeed does not perform any validation on the IP address strings.

  • Please verify whether this omission is intentional.
  • If validation is required, consider implementing proper checks for both IPv4 and IPv6 addresses, either within the splitting function or by calling dedicated helper functions.

🏁 Script executed:

#!/bin/bash
# Re-run command with corrected file filtering using ripgrep globs for C++ header and source files
rg -A 10 "IsValid(IP|Ipv4|Ipv6)" -g "*.h" -g "*.cc"

Length of output: 175


Attention: Missing IP Validation in SplitIPs Function

The function in src/kiwi.cc (lines 116–127) correctly splits the input string by the provided delimiter but does not perform any checks to ensure that each substring is a valid IPv4 or IPv6 address. A search for any validation functions (e.g., IsValidIP, IsValidIpv4, or IsValidIpv6) produced no results, which suggests that there is currently no IP validation in the codebase.

  • Please confirm whether the omission of IP validation is intentional.
  • If validation is required, consider adding appropriate checks—either within this function or by integrating dedicated helper functions.

Copy link
Collaborator

@marsevilspirit marsevilspirit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/kiwi.cc (1)

88-89: Duplicate example command.

The same example appears on two consecutive lines.

  kiwi [--config] /path/kiwi.conf
- kiwi [--config] /path/kiwi.conf
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8795afc and 66d46a5.

📒 Files selected for processing (2)
  • README.md (1 hunks)
  • src/kiwi.cc (6 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
src/kiwi.cc (7)
src/options.h (4)
  • use_raft (38-38)
  • ips (32-32)
  • ips (32-32)
  • raft_ip (42-42)
src/config_parser.h (1)
  • cout (39-46)
src/kiwi.h (2)
  • argc (43-43)
  • options_ (44-44)
src/client.h (4)
  • argv (217-217)
  • argv (217-217)
  • str (152-152)
  • str (152-152)
src/helper.h (1)
  • str (25-25)
src/helper.cc (2)
  • str (82-84)
  • str (82-82)
src/replication.h (1)
  • master_ (139-139)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build_on_ubuntu
  • GitHub Check: build_on_macos
🔇 Additional comments (16)
README.md (2)

36-40: Good addition of the Usage section.

Adding a specific section for viewing command-line options makes it easier for users to discover available functionality.


45-45: Clear documentation of the optional config flag.

The updated command format clearly shows that the --config flag is optional when specifying the configuration file path, matching the implementation in the code.

src/kiwi.cc (14)

21-21: Good use of std::filesystem for file operations.

Adding the filesystem header is appropriate for the improved file path handling in this PR.


27-27: Appropriate inclusion of gflags library.

Using gflags for command-line parsing is a good choice for handling complex options in a maintainable way.


72-84: Comprehensive usage information for the new flags.

The updated usage output clearly describes all the new command options, making it easier for users to understand how to use the application.


105-114: Well-structured flag definitions.

The flags are clearly defined with appropriate types and helpful descriptions.


116-127: IP address parsing utility.

The SplitIPs function effectively parses space-separated IP addresses.

Though not required based on previous feedback, consider adding IP validation in a future update.


129-141: Helpful debug function for displaying parsed flags.

PrintParsedFlags provides a clear view of all parsed command-line options, which will be valuable for troubleshooting.


143-163: Improved argument parsing with positional argument support.

The new implementation allows for both kiwi config.conf and kiwi --config config.conf formats, providing flexibility for users.


170-180: Proper file existence and permission checking.

Using std::filesystem to verify the configuration file's existence and readability is a good practice that prevents runtime errors.


217-226: Good validation for the use_raft flag.

The code correctly validates that the use_raft flag is either "yes" or "no", and converts the input to lowercase for case-insensitive comparison.


232-235: Proper handling of IP list.

The code correctly splits and stores multiple IP addresses from the command line.


316-318: Correct handling of use-raft configuration.

The implementation correctly passes the user's choice for use-raft to the configuration.


353-355: Proper IP configuration.

The code correctly sets the global IP configuration from command-line options when provided.


484-486: Good debugging output.

Conditionally printing parsed flags in debug builds helps with troubleshooting without affecting production performance.


195-200:

✅ Verification successful

Log level validation doesn't match usage text.

The validation checks for debug, verbose, notice, and warning, but the usage text in line 78 suggests additional options may be valid. This could confuse users.


🏁 Script executed:

#!/bin/bash
# Check if there's a mismatch between the log levels mentioned in the usage text and those actually validated

# Extract log levels from usage text
USAGE_LEVELS=$(grep -o "Set the log level.*" src/kiwi.cc | grep -o "(e.g., [^)]*)" | sed 's/(e.g., //g' | sed 's/)//g')
echo "Log levels mentioned in usage: $USAGE_LEVELS"

# Extract log levels from validation code
VALIDATION_LEVELS=$(grep -A 3 "FLAGS_loglevel !=" src/kiwi.cc | grep -o '"[^"]*"' | tr -d '"' | tr '\n' ' ')
echo "Log levels checked in validation: $VALIDATION_LEVELS"

# Check if there are levels in usage that aren't in validation
for level in $(echo $USAGE_LEVELS | tr ',' ' '); do
  if ! echo "$VALIDATION_LEVELS" | grep -q "$level"; then
    echo "WARNING: Level '$level' is mentioned in usage but not validated in code"
  fi
done

Length of output: 1501


Log level usage and validation are consistent.
After verification, both the usage text and the validation logic only recognize the log levels "debug", "verbose", "notice", and "warning". No additional log levels are present, so the current implementation is correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants