Fixed build
This commit is contained in:
16
README.md
16
README.md
@ -1,12 +1,15 @@
|
|||||||
# Gossip 
|
# Gossip 
|
||||||
|
|
||||||
Gossip protocol is a method for a group of nodes to discover and check the liveliness of a cluster. More information can be found at http://en.wikipedia.org/wiki/Gossip_protocol.
|
Gossip protocol is a method for a group of nodes to discover and check the liveliness of a cluster. More information can
|
||||||
|
be found at http://en.wikipedia.org/wiki/Gossip_protocol.
|
||||||
|
|
||||||
The original implementation was forked from https://code.google.com/p/java-gossip/. Several bug fixes and changes have already been added.
|
The original implementation was forked from https://code.google.com/p/java-gossip/. Several bug fixes and changes have
|
||||||
|
already been added.
|
||||||
|
|
||||||
A set of easily-run examples, illustrating various features of Gossip, are available in the gossip-examples module. The README.md file, in that module described how to run those examples.
|
A set of easily-run examples, illustrating various features of Gossip, are available in the gossip-examples module. The
|
||||||
|
README.md file, in that module described how to run those examples.
|
||||||
|
|
||||||
Below, a list of code snippits which show how to incorproate Apache Gossip into your project.
|
Below, a list of code snippits which show how to incorproate Apache Gossip into your project.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
@ -23,7 +26,8 @@ To gossip you need one or more seed nodes. Seed is just a list of places to init
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Here we start five gossip processes and check that they discover each other. (Normally these are on different hosts but here we give each process a distinct local ip.
|
Here we start five gossip processes and check that they discover each other. (Normally these are on different hosts but
|
||||||
|
here we give each process a distinct local ip.
|
||||||
|
|
||||||
```java
|
```java
|
||||||
List<GossipService> clients = new ArrayList<>();
|
List<GossipService> clients = new ArrayList<>();
|
||||||
@ -64,7 +68,7 @@ For a very simple client setup with a settings file you first need a JSON file s
|
|||||||
|
|
||||||
where:
|
where:
|
||||||
|
|
||||||
* `cluster` - is the name of the cluster
|
* `cluster` - is the name of the cluster
|
||||||
* `id` - is a unique id for this node (you can use any string, but above we use a UUID)
|
* `id` - is a unique id for this node (you can use any string, but above we use a UUID)
|
||||||
* `uri` - is a URI object containing IP/hostname and port to use on the default adapter on the node's machine
|
* `uri` - is a URI object containing IP/hostname and port to use on the default adapter on the node's machine
|
||||||
* `gossip_interval` - how often (in milliseconds) to gossip list of members to other node(s)
|
* `gossip_interval` - how often (in milliseconds) to gossip list of members to other node(s)
|
||||||
|
@ -1,30 +1,38 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<profiles version="12">
|
<profiles version="12">
|
||||||
<profile kind="CodeFormatterProfile" name="Apache UIMA Code Conventions" version="12">
|
<profile kind="CodeFormatterProfile" name="Apache UIMA Code Conventions" version="12">
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
<setting
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="4"/>
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="4"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||||
@ -36,256 +44,349 @@
|
|||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="100"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="100"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
|
||||||
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
<setting
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
<setting
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
value="16"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer"
|
||||||
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
value="do not insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="100"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||||
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration"
|
||||||
</profile>
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||||
|
<setting
|
||||||
|
id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header"
|
||||||
|
value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration"
|
||||||
|
value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="100"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation"
|
||||||
|
value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
@ -16,70 +16,51 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.apache.gossip</groupId>
|
<groupId>org.apache.gossip</groupId>
|
||||||
<artifactId>gossip-parent</artifactId>
|
<artifactId>gossip-parent</artifactId>
|
||||||
|
<version>0.1.3-incubating-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>Gossip Base</name>
|
||||||
|
<artifactId>gossip-base</artifactId>
|
||||||
<version>0.1.3-incubating-SNAPSHOT</version>
|
<version>0.1.3-incubating-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
<name>Gossip Base</name>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>gossip-base</artifactId>
|
<artifactId>jackson-core</artifactId>
|
||||||
<version>0.1.3-incubating-SNAPSHOT</version>
|
<version>${jackson.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependencies>
|
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>jackson-core</artifactId>
|
<artifactId>commons-math3</artifactId>
|
||||||
<version>${jackson.version}</version>
|
<version>3.6.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>commons-math</groupId>
|
<dependency>
|
||||||
<artifactId>commons-math</artifactId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<version>${commons-math.version}</version>
|
<artifactId>jackson-databind</artifactId>
|
||||||
</dependency>
|
<version>${jackson.version}</version>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<dependency>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<groupId>io.dropwizard.metrics</groupId>
|
||||||
<version>${jackson.version}</version>
|
<artifactId>metrics-core</artifactId>
|
||||||
</dependency>
|
<version>${metrics.version}</version>
|
||||||
<dependency>
|
</dependency>
|
||||||
<groupId>io.dropwizard.metrics</groupId>
|
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
|
||||||
<artifactId>metrics-core</artifactId>
|
<dependency>
|
||||||
<version>${metrics.version}</version></dependency>
|
<groupId>org.apache.logging.log4j</groupId>
|
||||||
<dependency>
|
<artifactId>log4j-core</artifactId>
|
||||||
<groupId>log4j</groupId>
|
<version>2.22.0</version>
|
||||||
<artifactId>log4j</artifactId>
|
</dependency>
|
||||||
<version>${log4j.version}</version>
|
</dependencies>
|
||||||
<type>jar</type>
|
|
||||||
<scope>compile</scope>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>javax.jms</groupId>
|
|
||||||
<artifactId>jms</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.sun.jdmk</groupId>
|
|
||||||
<artifactId>jmxtools</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>com.sun.jmx</groupId>
|
|
||||||
<artifactId>jmxri</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-core</artifactId>
|
|
||||||
<version>${mockito.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -17,10 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip;
|
package org.apache.gossip;
|
||||||
|
|
||||||
import org.apache.gossip.lock.LockManagerSettings;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.apache.gossip.lock.LockManagerSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this object the settings used by the GossipService are held.
|
* In this object the settings used by the GossipService are held.
|
||||||
@ -107,26 +106,19 @@ public class GossipSettings {
|
|||||||
this.gossipInterval = gossipInterval;
|
this.gossipInterval = gossipInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the cleanup interval. This is the time between the last heartbeat received from a member
|
|
||||||
* and when it will be marked as dead.
|
|
||||||
*
|
|
||||||
* @param cleanupInterval
|
|
||||||
* The cleanup interval in ms.
|
|
||||||
*/
|
|
||||||
public void setCleanupInterval(int cleanupInterval) {
|
|
||||||
this.cleanupInterval = cleanupInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the gossip interval.
|
* Get the gossip interval.
|
||||||
*
|
*
|
||||||
* @return The gossip interval in ms.
|
* @return The gossip interval in ms.
|
||||||
*/
|
*/
|
||||||
public int getGossipInterval() {
|
public int getGossipInterval() {
|
||||||
return gossipInterval;
|
return gossipInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setGossipInterval(int gossipInterval) {
|
||||||
|
this.gossipInterval = gossipInterval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the clean interval.
|
* Get the clean interval.
|
||||||
*
|
*
|
||||||
@ -136,6 +128,17 @@ public class GossipSettings {
|
|||||||
return cleanupInterval;
|
return cleanupInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the cleanup interval. This is the time between the last heartbeat received from a member
|
||||||
|
* and when it will be marked as dead.
|
||||||
|
*
|
||||||
|
* @param cleanupInterval
|
||||||
|
* The cleanup interval in ms.
|
||||||
|
*/
|
||||||
|
public void setCleanupInterval(int cleanupInterval) {
|
||||||
|
this.cleanupInterval = cleanupInterval;
|
||||||
|
}
|
||||||
|
|
||||||
public int getMinimumSamples() {
|
public int getMinimumSamples() {
|
||||||
return minimumSamples;
|
return minimumSamples;
|
||||||
}
|
}
|
||||||
@ -160,10 +163,6 @@ public class GossipSettings {
|
|||||||
this.convictThreshold = convictThreshold;
|
this.convictThreshold = convictThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGossipInterval(int gossipInterval) {
|
|
||||||
this.gossipInterval = gossipInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDistribution() {
|
public String getDistribution() {
|
||||||
return distribution;
|
return distribution;
|
||||||
}
|
}
|
||||||
|
@ -25,35 +25,35 @@ import org.apache.gossip.accrual.FailureDetector;
|
|||||||
/**
|
/**
|
||||||
* This object represent a gossip member with the properties known locally. These objects are stored
|
* This object represent a gossip member with the properties known locally. These objects are stored
|
||||||
* in the local list of gossip members.
|
* in the local list of gossip members.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class LocalMember extends Member {
|
public class LocalMember extends Member {
|
||||||
/** The failure detector for this member */
|
/** The failure detector for this member */
|
||||||
private transient FailureDetector detector;
|
private transient FailureDetector detector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @param uri The uri of the member
|
||||||
* @param uri
|
* @param id id of the node
|
||||||
* The uri of the member
|
* @param heartbeat The current heartbeat
|
||||||
* @param id
|
|
||||||
* id of the node
|
|
||||||
* @param heartbeat
|
|
||||||
* The current heartbeat
|
|
||||||
*/
|
*/
|
||||||
public LocalMember(String clusterName, URI uri, String id,
|
public LocalMember(
|
||||||
long heartbeat, Map<String,String> properties, int windowSize, int minSamples, String distribution) {
|
String clusterName,
|
||||||
super(clusterName, uri, id, heartbeat, properties );
|
URI uri,
|
||||||
|
String id,
|
||||||
|
long heartbeat,
|
||||||
|
Map<String, String> properties,
|
||||||
|
int windowSize,
|
||||||
|
int minSamples,
|
||||||
|
String distribution) {
|
||||||
|
super(clusterName, uri, id, heartbeat, properties);
|
||||||
detector = new FailureDetector(minSamples, windowSize, distribution);
|
detector = new FailureDetector(minSamples, windowSize, distribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LocalMember(){
|
protected LocalMember() {}
|
||||||
|
|
||||||
}
|
public void recordHeartbeat(long now) {
|
||||||
|
|
||||||
public void recordHeartbeat(long now){
|
|
||||||
detector.recordHeartbeat(now);
|
detector.recordHeartbeat(now);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Double detect(long now) {
|
public Double detect(long now) {
|
||||||
return detector.computePhiMeasure(now);
|
return detector.computePhiMeasure(now);
|
||||||
}
|
}
|
||||||
@ -63,9 +63,18 @@ public class LocalMember extends Member {
|
|||||||
Double d = null;
|
Double d = null;
|
||||||
try {
|
try {
|
||||||
d = detect(System.nanoTime());
|
d = detect(System.nanoTime());
|
||||||
} catch (RuntimeException ex) {}
|
} catch (RuntimeException ex) {
|
||||||
return "LocalGossipMember [uri=" + uri + ", heartbeat=" + heartbeat + ", clusterName="
|
}
|
||||||
+ clusterName + ", id=" + id + ", currentdetect=" + d +" ]";
|
return "LocalGossipMember [uri="
|
||||||
|
+ uri
|
||||||
|
+ ", heartbeat="
|
||||||
|
+ heartbeat
|
||||||
|
+ ", clusterName="
|
||||||
|
+ clusterName
|
||||||
|
+ ", id="
|
||||||
|
+ id
|
||||||
|
+ ", currentdetect="
|
||||||
|
+ d
|
||||||
|
+ " ]";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -21,13 +21,9 @@ import java.net.InetSocketAddress;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/** An abstract class representing a gossip member. */
|
||||||
* An abstract class representing a gossip member.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public abstract class Member implements Comparable<Member> {
|
public abstract class Member implements Comparable<Member> {
|
||||||
|
|
||||||
|
|
||||||
protected URI uri;
|
protected URI uri;
|
||||||
|
|
||||||
protected volatile long heartbeat;
|
protected volatile long heartbeat;
|
||||||
@ -42,21 +38,18 @@ public abstract class Member implements Comparable<Member> {
|
|||||||
protected String id;
|
protected String id;
|
||||||
|
|
||||||
/* properties provided at startup time */
|
/* properties provided at startup time */
|
||||||
protected Map<String,String> properties;
|
protected Map<String, String> properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param clusterName
|
* @param clusterName The name of the cluster
|
||||||
* The name of the cluster
|
* @param uri A URI object containing IP/hostname and port
|
||||||
* @param uri
|
* @param heartbeat The current heartbeat
|
||||||
* A URI object containing IP/hostname and port
|
* @param id An id that may be replaced after contact
|
||||||
* @param heartbeat
|
|
||||||
* The current heartbeat
|
|
||||||
* @param id
|
|
||||||
* An id that may be replaced after contact
|
|
||||||
*/
|
*/
|
||||||
public Member(String clusterName, URI uri, String id, long heartbeat, Map<String,String> properties) {
|
public Member(
|
||||||
|
String clusterName, URI uri, String id, long heartbeat, Map<String, String> properties) {
|
||||||
this.clusterName = clusterName;
|
this.clusterName = clusterName;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.heartbeat = heartbeat;
|
this.heartbeat = heartbeat;
|
||||||
@ -64,20 +57,20 @@ public abstract class Member implements Comparable<Member> {
|
|||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Member(){}
|
protected Member() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the cluster the member belongs to.
|
* Get the name of the cluster the member belongs to.
|
||||||
*
|
*
|
||||||
* @return The cluster name
|
* @return The cluster name
|
||||||
*/
|
*/
|
||||||
public String getClusterName() {
|
public String getClusterName() {
|
||||||
return clusterName;
|
return clusterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The member address in the form IP/host:port Similar to the toString in
|
* @return The member address in the form IP/host:port Similar to the toString in {@link
|
||||||
* {@link InetSocketAddress}
|
* InetSocketAddress}
|
||||||
*/
|
*/
|
||||||
public String computeAddress() {
|
public String computeAddress() {
|
||||||
return uri.getHost() + ":" + uri.getPort();
|
return uri.getHost() + ":" + uri.getPort();
|
||||||
@ -85,7 +78,7 @@ public abstract class Member implements Comparable<Member> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the heartbeat of this gossip member.
|
* Get the heartbeat of this gossip member.
|
||||||
*
|
*
|
||||||
* @return The current heartbeat.
|
* @return The current heartbeat.
|
||||||
*/
|
*/
|
||||||
public long getHeartbeat() {
|
public long getHeartbeat() {
|
||||||
@ -94,9 +87,8 @@ public abstract class Member implements Comparable<Member> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the heartbeat of this gossip member.
|
* Set the heartbeat of this gossip member.
|
||||||
*
|
*
|
||||||
* @param heartbeat
|
* @param heartbeat The new heartbeat.
|
||||||
* The new heartbeat.
|
|
||||||
*/
|
*/
|
||||||
public void setHeartbeat(long heartbeat) {
|
public void setHeartbeat(long heartbeat) {
|
||||||
this.heartbeat = heartbeat;
|
this.heartbeat = heartbeat;
|
||||||
@ -130,8 +122,10 @@ public abstract class Member implements Comparable<Member> {
|
|||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
int result = 1;
|
int result = 1;
|
||||||
String address = computeAddress();
|
String address = computeAddress();
|
||||||
result = prime * result + ((address == null) ? 0 : address.hashCode()) + (clusterName == null ? 0
|
result =
|
||||||
: clusterName.hashCode());
|
prime * result
|
||||||
|
+ ((address == null) ? 0 : address.hashCode())
|
||||||
|
+ (clusterName == null ? 0 : clusterName.hashCode());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +151,7 @@ public abstract class Member implements Comparable<Member> {
|
|||||||
}
|
}
|
||||||
// The object is the same of they both have the same address (hostname and port).
|
// The object is the same of they both have the same address (hostname and port).
|
||||||
return computeAddress().equals(((LocalMember) obj).computeAddress())
|
return computeAddress().equals(((LocalMember) obj).computeAddress())
|
||||||
&& getClusterName().equals(((LocalMember) obj).getClusterName());
|
&& getClusterName().equals(((LocalMember) obj).getClusterName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(Member other) {
|
public int compareTo(Member other) {
|
||||||
|
@ -24,24 +24,21 @@ import java.util.Map;
|
|||||||
/**
|
/**
|
||||||
* The object represents a gossip member with the properties as received from a remote gossip
|
* The object represents a gossip member with the properties as received from a remote gossip
|
||||||
* member.
|
* member.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class RemoteMember extends Member {
|
public class RemoteMember extends Member {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param uri A URI object containing IP/hostname and port
|
||||||
* A URI object containing IP/hostname and port
|
* @param heartbeat The current heartbeat
|
||||||
* @param heartbeat
|
|
||||||
* The current heartbeat
|
|
||||||
*/
|
*/
|
||||||
public RemoteMember(String clusterName, URI uri, String id, long heartbeat, Map<String,String> properties) {
|
public RemoteMember(
|
||||||
|
String clusterName, URI uri, String id, long heartbeat, Map<String, String> properties) {
|
||||||
super(clusterName, uri, id, heartbeat, properties);
|
super(clusterName, uri, id, heartbeat, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteMember(String clusterName, URI uri, String id) {
|
public RemoteMember(String clusterName, URI uri, String id) {
|
||||||
super(clusterName, uri, id, System.nanoTime(), new HashMap<String,String>());
|
super(clusterName, uri, id, System.nanoTime(), new HashMap<String, String>());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip;
|
package org.apache.gossip;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -28,36 +30,26 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This object represents the settings used when starting the gossip service.
|
* This object represents the settings used when starting the gossip service.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class StartupSettings {
|
public class StartupSettings {
|
||||||
private static final Logger log = Logger.getLogger(StartupSettings.class);
|
|
||||||
|
|
||||||
/** The id to use fo the service */
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
private URI uri;
|
|
||||||
|
|
||||||
private String cluster;
|
|
||||||
|
|
||||||
/** The gossip settings used at startup. */
|
|
||||||
private final GossipSettings gossipSettings;
|
|
||||||
|
|
||||||
/** The list with gossip members to start with. */
|
|
||||||
private final List<Member> gossipMembers;
|
|
||||||
|
|
||||||
|
public static final int DEFAULT_BULK_TRANSFER_SIZE = 100;
|
||||||
/** Default setting values */
|
/** Default setting values */
|
||||||
private static final boolean DEFAULT_BULK_TRANSFER = false;
|
private static final boolean DEFAULT_BULK_TRANSFER = false;
|
||||||
public static final int DEFAULT_BULK_TRANSFER_SIZE = 100;
|
/** The gossip settings used at startup. */
|
||||||
|
private final GossipSettings gossipSettings;
|
||||||
|
/** The list with gossip members to start with. */
|
||||||
|
private final List<Member> gossipMembers;
|
||||||
|
/** The id to use fo the service */
|
||||||
|
private String id;
|
||||||
|
private URI uri;
|
||||||
|
private String cluster;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -73,17 +65,9 @@ public class StartupSettings {
|
|||||||
this(id, uri, new GossipSettings(), cluster);
|
this(id, uri, new GossipSettings(), cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
public URI getUri() {
|
|
||||||
return uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUri(URI uri) {
|
|
||||||
this.uri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* The id to be used for this service
|
* The id to be used for this service
|
||||||
* @param uri
|
* @param uri
|
||||||
@ -97,64 +81,9 @@ public class StartupSettings {
|
|||||||
gossipMembers = new ArrayList<>();
|
gossipMembers = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCluster(String cluster) {
|
|
||||||
this.cluster = cluster;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCluster() {
|
|
||||||
return cluster;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the id to be used for this service.
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* The id for this service.
|
|
||||||
*/
|
|
||||||
public void setId(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the id for this service.
|
|
||||||
*
|
|
||||||
* @return the service's id.
|
|
||||||
*/
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the GossipSettings.
|
|
||||||
*
|
|
||||||
* @return The GossipSettings object.
|
|
||||||
*/
|
|
||||||
public GossipSettings getGossipSettings() {
|
|
||||||
return gossipSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a gossip member to the list of members to start with.
|
|
||||||
*
|
|
||||||
* @param member
|
|
||||||
* The member to add.
|
|
||||||
*/
|
|
||||||
public void addGossipMember(Member member) {
|
|
||||||
gossipMembers.add(member);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the list with gossip members.
|
|
||||||
*
|
|
||||||
* @return The gossip members.
|
|
||||||
*/
|
|
||||||
public List<Member> getGossipMembers() {
|
|
||||||
return gossipMembers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the settings for the gossip service from a JSON file.
|
* Parse the settings for the gossip service from a JSON file.
|
||||||
*
|
*
|
||||||
* @param jsonFile
|
* @param jsonFile
|
||||||
* The file object which refers to the JSON config file.
|
* The file object which refers to the JSON config file.
|
||||||
* @return The StartupSettings object with the settings from the config file.
|
* @return The StartupSettings object with the settings from the config file.
|
||||||
@ -162,9 +91,9 @@ public class StartupSettings {
|
|||||||
* Thrown when the file cannot be found.
|
* Thrown when the file cannot be found.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* Thrown when reading the file gives problems.
|
* Thrown when reading the file gives problems.
|
||||||
* @throws URISyntaxException
|
* @throws URISyntaxException
|
||||||
*/
|
*/
|
||||||
public static StartupSettings fromJSONFile(File jsonFile) throws
|
public static StartupSettings fromJSONFile(File jsonFile) throws
|
||||||
FileNotFoundException, IOException, URISyntaxException {
|
FileNotFoundException, IOException, URISyntaxException {
|
||||||
ObjectMapper om = new ObjectMapper();
|
ObjectMapper om = new ObjectMapper();
|
||||||
JsonNode root = om.readTree(jsonFile);
|
JsonNode root = om.readTree(jsonFile);
|
||||||
@ -196,11 +125,11 @@ public class StartupSettings {
|
|||||||
if (cluster == null){
|
if (cluster == null){
|
||||||
throw new IllegalArgumentException("cluster was null. It is required");
|
throw new IllegalArgumentException("cluster was null. It is required");
|
||||||
}
|
}
|
||||||
String transportClass = jsonObject.has("transport_manager_class") ?
|
String transportClass = jsonObject.has("transport_manager_class") ?
|
||||||
jsonObject.get("transport_manager_class").textValue() :
|
jsonObject.get("transport_manager_class").textValue() :
|
||||||
null;
|
null;
|
||||||
String protocolClass = jsonObject.has("protocol_manager_class") ?
|
String protocolClass = jsonObject.has("protocol_manager_class") ?
|
||||||
jsonObject.get("protocol_manager_class").textValue() :
|
jsonObject.get("protocol_manager_class").textValue() :
|
||||||
null;
|
null;
|
||||||
URI uri2 = new URI(uri);
|
URI uri2 = new URI(uri);
|
||||||
GossipSettings gossipSettings = new GossipSettings(gossipInterval, cleanupInterval, windowSize,
|
GossipSettings gossipSettings = new GossipSettings(gossipInterval, cleanupInterval, windowSize,
|
||||||
@ -215,17 +144,79 @@ public class StartupSettings {
|
|||||||
StartupSettings settings = new StartupSettings(id, uri2, gossipSettings, cluster);
|
StartupSettings settings = new StartupSettings(id, uri2, gossipSettings, cluster);
|
||||||
String configMembersDetails = "Config-members [";
|
String configMembersDetails = "Config-members [";
|
||||||
JsonNode membersJSON = jsonObject.get("members");
|
JsonNode membersJSON = jsonObject.get("members");
|
||||||
Iterator<JsonNode> it = membersJSON.iterator();
|
for (JsonNode child : membersJSON) {
|
||||||
while (it.hasNext()){
|
URI uri3 = new URI(child.get("uri").textValue());
|
||||||
JsonNode child = it.next();
|
RemoteMember member = new RemoteMember(child.get("cluster").asText(),
|
||||||
URI uri3 = new URI(child.get("uri").textValue());
|
uri3, "", 0, new HashMap<String, String>()
|
||||||
RemoteMember member = new RemoteMember(child.get("cluster").asText(),
|
);
|
||||||
uri3, "", 0, new HashMap<String,String>());
|
settings.addGossipMember(member);
|
||||||
settings.addGossipMember(member);
|
configMembersDetails += member.computeAddress();
|
||||||
configMembersDetails += member.computeAddress();
|
configMembersDetails += ", ";
|
||||||
configMembersDetails += ", ";
|
}
|
||||||
}
|
|
||||||
log.info(configMembersDetails + "]");
|
log.info(configMembersDetails + "]");
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public URI getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(URI uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCluster() {
|
||||||
|
return cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCluster(String cluster) {
|
||||||
|
this.cluster = cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the id for this service.
|
||||||
|
*
|
||||||
|
* @return the service's id.
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the id to be used for this service.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* The id for this service.
|
||||||
|
*/
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the GossipSettings.
|
||||||
|
*
|
||||||
|
* @return The GossipSettings object.
|
||||||
|
*/
|
||||||
|
public GossipSettings getGossipSettings() {
|
||||||
|
return gossipSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a gossip member to the list of members to start with.
|
||||||
|
*
|
||||||
|
* @param member
|
||||||
|
* The member to add.
|
||||||
|
*/
|
||||||
|
public void addGossipMember(Member member) {
|
||||||
|
gossipMembers.add(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list with gossip members.
|
||||||
|
*
|
||||||
|
* @return The gossip members.
|
||||||
|
*/
|
||||||
|
public List<Member> getGossipMembers() {
|
||||||
|
return gossipMembers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,19 +17,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.accrual;
|
package org.apache.gossip.accrual;
|
||||||
|
|
||||||
import org.apache.commons.math.MathException;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.math.distribution.ExponentialDistributionImpl;
|
import org.apache.commons.math3.distribution.ExponentialDistribution;
|
||||||
import org.apache.commons.math.distribution.NormalDistributionImpl;
|
import org.apache.commons.math3.distribution.NormalDistribution;
|
||||||
import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
|
import org.apache.commons.math3.exception.MathArithmeticException;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class FailureDetector {
|
public class FailureDetector {
|
||||||
|
|
||||||
public static final Logger LOGGER = Logger.getLogger(FailureDetector.class);
|
|
||||||
private final DescriptiveStatistics descriptiveStatistics;
|
private final DescriptiveStatistics descriptiveStatistics;
|
||||||
private final long minimumSamples;
|
private final long minimumSamples;
|
||||||
private volatile long latestHeartbeatMs = -1;
|
|
||||||
private final String distribution;
|
private final String distribution;
|
||||||
|
private volatile long latestHeartbeatMs = -1;
|
||||||
|
|
||||||
public FailureDetector(long minimumSamples, int windowSize, String distribution) {
|
public FailureDetector(long minimumSamples, int windowSize, String distribution) {
|
||||||
descriptiveStatistics = new DescriptiveStatistics(windowSize);
|
descriptiveStatistics = new DescriptiveStatistics(windowSize);
|
||||||
@ -62,18 +62,18 @@ public class FailureDetector {
|
|||||||
double probability;
|
double probability;
|
||||||
if (distribution.equals("normal")) {
|
if (distribution.equals("normal")) {
|
||||||
double standardDeviation = descriptiveStatistics.getStandardDeviation();
|
double standardDeviation = descriptiveStatistics.getStandardDeviation();
|
||||||
standardDeviation = standardDeviation < 0.1 ? 0.1 : standardDeviation;
|
standardDeviation = Math.max(standardDeviation, 0.1);
|
||||||
probability = new NormalDistributionImpl(descriptiveStatistics.getMean(), standardDeviation).cumulativeProbability(delta);
|
probability = new NormalDistribution(descriptiveStatistics.getMean(), standardDeviation).cumulativeProbability(delta);
|
||||||
} else {
|
} else {
|
||||||
probability = new ExponentialDistributionImpl(descriptiveStatistics.getMean()).cumulativeProbability(delta);
|
probability = new ExponentialDistribution(descriptiveStatistics.getMean()).cumulativeProbability(delta);
|
||||||
}
|
}
|
||||||
final double eps = 1e-12;
|
final double eps = 1e-12;
|
||||||
if (1 - probability < eps) {
|
if (1 - probability < eps) {
|
||||||
probability = 1.0;
|
probability = 1.0;
|
||||||
}
|
}
|
||||||
return -1.0d * Math.log10(1.0d - probability);
|
return -1.0d * Math.log10(1.0d - probability);
|
||||||
} catch (MathException | IllegalArgumentException e) {
|
} catch (MathArithmeticException | IllegalArgumentException e) {
|
||||||
LOGGER.debug(e);
|
log.error("Error!", e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,24 +16,24 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Immutable type
|
||||||
* Immutable type
|
|
||||||
*
|
*
|
||||||
* @param <SetType>
|
* @param <SetType>
|
||||||
* @param <MergeReturnType>
|
* @param <MergeReturnType>
|
||||||
*/
|
*/
|
||||||
public interface Crdt<SetType, MergeReturnType extends Crdt<SetType, MergeReturnType>> {
|
public interface Crdt<SetType, MergeReturnType extends Crdt<SetType, MergeReturnType>> {
|
||||||
|
|
||||||
|
|
||||||
MergeReturnType merge(MergeReturnType other);
|
MergeReturnType merge(MergeReturnType other);
|
||||||
|
|
||||||
SetType value();
|
SetType value();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to self optimize. Some CRDTs may use some mechanism to clean up be
|
* Called to self optimize. Some CRDTs may use some mechanism to clean up be removing obsolete
|
||||||
* removing obsolete data outside the scope of merging. IE this could clean up
|
* data outside the scope of merging. IE this could clean up temporal values, old copies etc.
|
||||||
* temporal values, old copies etc.
|
*
|
||||||
* @return the Crdt structure optimized
|
* @return the Crdt structure optimized
|
||||||
*/
|
*/
|
||||||
MergeReturnType optimize();
|
MergeReturnType optimize();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,10 +19,14 @@ package org.apache.gossip.crdt;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
// Interface extends CrdtSet interface with add and remove operation that are guaranteed to be immutable.
|
// Interface extends CrdtSet interface with add and remove operation that are guaranteed to be
|
||||||
// If your implementation provide immutable add/remove operations you can extend AbstractCRDTStringSetTest to check it in the most ways.
|
// immutable.
|
||||||
|
// If your implementation provide immutable add/remove operations you can extend
|
||||||
|
// AbstractCRDTStringSetTest to check it in the most ways.
|
||||||
|
|
||||||
public interface CrdtAddRemoveSet<T, SetType extends Set<T>, R extends CrdtAddRemoveSet<T, SetType, R>> extends CrdtSet<T, SetType, R> {
|
public interface CrdtAddRemoveSet<
|
||||||
|
T, SetType extends Set<T>, R extends CrdtAddRemoveSet<T, SetType, R>>
|
||||||
|
extends CrdtSet<T, SetType, R> {
|
||||||
R add(T element);
|
R add(T element);
|
||||||
|
|
||||||
R remove(T element);
|
R remove(T element);
|
||||||
|
@ -20,35 +20,35 @@ package org.apache.gossip.crdt;
|
|||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public class CrdtBiFunctionMerge implements BiFunction<Crdt,Crdt,Crdt> {
|
public class CrdtBiFunctionMerge implements BiFunction<Crdt, Crdt, Crdt> {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static Crdt applyStatic(Crdt t, Crdt u) {
|
||||||
|
if (t == null && u == null) {
|
||||||
|
return null;
|
||||||
|
} else if (t == null) {
|
||||||
|
return u;
|
||||||
|
} else if (u == null) {
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if (!u.getClass().equals(t.getClass())) {
|
||||||
|
throw new IllegalArgumentException("Can not merge " + t.getClass() + " " + u.getClass());
|
||||||
|
}
|
||||||
|
return t.merge(u);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Crdt apply(Crdt t, Crdt u) {
|
public Crdt apply(Crdt t, Crdt u) {
|
||||||
if (t == null && u == null){
|
if (t == null && u == null) {
|
||||||
return null;
|
return null;
|
||||||
} else if (t == null){
|
} else if (t == null) {
|
||||||
return u;
|
return u;
|
||||||
} else if (u == null){
|
} else if (u == null) {
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
if (! u.getClass().equals(t.getClass())){
|
if (!u.getClass().equals(t.getClass())) {
|
||||||
throw new IllegalArgumentException( "Can not merge " + t.getClass() + " "+ u.getClass());
|
throw new IllegalArgumentException("Can not merge " + t.getClass() + " " + u.getClass());
|
||||||
}
|
|
||||||
return t.merge(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static Crdt applyStatic(Crdt t, Crdt u){
|
|
||||||
if (t == null && u == null){
|
|
||||||
return null;
|
|
||||||
} else if (t == null){
|
|
||||||
return u;
|
|
||||||
} else if (u == null){
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
if (! u.getClass().equals(t.getClass())){
|
|
||||||
throw new IllegalArgumentException( "Can not merge " + t.getClass() + " "+ u.getClass());
|
|
||||||
}
|
}
|
||||||
return t.merge(u);
|
return t.merge(u);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,4 @@
|
|||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
public interface CrdtCounter<ValueType extends Number, R extends CrdtCounter<ValueType, R>>
|
public interface CrdtCounter<ValueType extends Number, R extends CrdtCounter<ValueType, R>>
|
||||||
extends Crdt<ValueType, R> {
|
extends Crdt<ValueType, R> {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -23,6 +23,10 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
import com.fasterxml.jackson.core.Version;
|
import com.fasterxml.jackson.core.Version;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
import org.apache.gossip.lock.vote.MajorityVote;
|
import org.apache.gossip.lock.vote.MajorityVote;
|
||||||
import org.apache.gossip.lock.vote.Vote;
|
import org.apache.gossip.lock.vote.Vote;
|
||||||
@ -31,11 +35,6 @@ import org.apache.gossip.replication.BlackListReplicable;
|
|||||||
import org.apache.gossip.replication.Replicable;
|
import org.apache.gossip.replication.Replicable;
|
||||||
import org.apache.gossip.replication.WhiteListReplicable;
|
import org.apache.gossip.replication.WhiteListReplicable;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
abstract class OrSetMixin<E> {
|
abstract class OrSetMixin<E> {
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
OrSetMixin(@JsonProperty("elements") Map<E, Set<UUID>> w, @JsonProperty("tombstones") Map<E, Set<UUID>> h) { }
|
OrSetMixin(@JsonProperty("elements") Map<E, Set<UUID>> w, @JsonProperty("tombstones") Map<E, Set<UUID>> h) { }
|
||||||
|
@ -19,8 +19,6 @@ package org.apache.gossip.crdt;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface CrdtSet<ElementType, SetType extends Set<ElementType>, R extends CrdtSet<ElementType, SetType, R>>
|
public interface CrdtSet<
|
||||||
extends Crdt<SetType, R> {
|
ElementType, SetType extends Set<ElementType>, R extends CrdtSet<ElementType, SetType, R>>
|
||||||
|
extends Crdt<SetType, R> {}
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -18,10 +18,9 @@
|
|||||||
|
|
||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
import org.apache.gossip.manager.GossipManager;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.apache.gossip.manager.GossipManager;
|
||||||
|
|
||||||
public class GrowOnlyCounter implements CrdtCounter<Long, GrowOnlyCounter> {
|
public class GrowOnlyCounter implements CrdtCounter<Long, GrowOnlyCounter> {
|
||||||
|
|
||||||
|
@ -24,31 +24,30 @@ import java.util.Iterator;
|
|||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class GrowOnlySet<ElementType> implements CrdtSet<ElementType, Set<ElementType>, GrowOnlySet<ElementType>>{
|
public class GrowOnlySet<ElementType>
|
||||||
|
implements CrdtSet<ElementType, Set<ElementType>, GrowOnlySet<ElementType>> {
|
||||||
|
|
||||||
private final Set<ElementType> hidden = new LinkedHashSet<>();
|
private final Set<ElementType> hidden = new LinkedHashSet<>();
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
/*
|
/*
|
||||||
* Used by SerDe
|
* Used by SerDe
|
||||||
*/
|
*/
|
||||||
private GrowOnlySet(){
|
private GrowOnlySet() {}
|
||||||
|
|
||||||
}
|
public GrowOnlySet(Set<ElementType> c) {
|
||||||
|
|
||||||
public GrowOnlySet(Set<ElementType> c){
|
|
||||||
hidden.addAll(c);
|
hidden.addAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GrowOnlySet(Collection<ElementType> c){
|
public GrowOnlySet(Collection<ElementType> c) {
|
||||||
hidden.addAll(c);
|
hidden.addAll(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GrowOnlySet(GrowOnlySet<ElementType> first, GrowOnlySet<ElementType> second){
|
public GrowOnlySet(GrowOnlySet<ElementType> first, GrowOnlySet<ElementType> second) {
|
||||||
hidden.addAll(first.value());
|
hidden.addAll(first.value());
|
||||||
hidden.addAll(second.value());
|
hidden.addAll(second.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GrowOnlySet<ElementType> merge(GrowOnlySet<ElementType> other) {
|
public GrowOnlySet<ElementType> merge(GrowOnlySet<ElementType> other) {
|
||||||
return new GrowOnlySet<>(this, other);
|
return new GrowOnlySet<>(this, other);
|
||||||
@ -60,7 +59,7 @@ public class GrowOnlySet<ElementType> implements CrdtSet<ElementType, Set<Elemen
|
|||||||
copy.addAll(hidden);
|
copy.addAll(hidden);
|
||||||
return Collections.unmodifiableSet(copy);
|
return Collections.unmodifiableSet(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GrowOnlySet<ElementType> optimize() {
|
public GrowOnlySet<ElementType> optimize() {
|
||||||
return new GrowOnlySet<>(hidden);
|
return new GrowOnlySet<>(hidden);
|
||||||
@ -135,23 +134,18 @@ public class GrowOnlySet<ElementType> implements CrdtSet<ElementType, Set<Elemen
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj)
|
if (this == obj) return true;
|
||||||
return true;
|
if (obj == null) return false;
|
||||||
if (obj == null)
|
if (getClass() != obj.getClass()) return false;
|
||||||
return false;
|
|
||||||
if (getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
GrowOnlySet other = (GrowOnlySet) obj;
|
GrowOnlySet other = (GrowOnlySet) obj;
|
||||||
if (hidden == null) {
|
if (hidden == null) {
|
||||||
if (other.hidden != null)
|
if (other.hidden != null) return false;
|
||||||
return false;
|
} else if (!hidden.equals(other.hidden)) return false;
|
||||||
} else if (!hidden.equals(other.hidden))
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ElementType> getElements(){
|
Set<ElementType> getElements() {
|
||||||
return hidden;
|
return hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
import org.apache.gossip.manager.Clock;
|
|
||||||
import org.apache.gossip.manager.SystemClock;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -28,6 +25,8 @@ import java.util.Set;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.gossip.manager.Clock;
|
||||||
|
import org.apache.gossip.manager.SystemClock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Last write wins CrdtSet
|
Last write wins CrdtSet
|
||||||
@ -49,6 +48,82 @@ public class LwwSet<ElementType> implements CrdtAddRemoveSet<ElementType, Set<El
|
|||||||
|
|
||||||
private final Map<ElementType, Timestamps> struct;
|
private final Map<ElementType, Timestamps> struct;
|
||||||
|
|
||||||
|
public LwwSet(){
|
||||||
|
struct = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
public LwwSet(ElementType... elements){
|
||||||
|
this(new HashSet<>(Arrays.asList(elements)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LwwSet(Set<ElementType> set){
|
||||||
|
struct = new HashMap<>();
|
||||||
|
for (ElementType e : set){
|
||||||
|
struct.put(e, new Timestamps().updateAdd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LwwSet(LwwSet<ElementType> first, LwwSet<ElementType> second){
|
||||||
|
Function<ElementType, Timestamps> timestampsFor = p -> {
|
||||||
|
Timestamps firstTs = first.struct.get(p);
|
||||||
|
Timestamps secondTs = second.struct.get(p);
|
||||||
|
if (firstTs == null){
|
||||||
|
return secondTs;
|
||||||
|
}
|
||||||
|
return firstTs.merge(secondTs);
|
||||||
|
};
|
||||||
|
struct = Stream.concat(first.struct.keySet().stream(), second.struct.keySet().stream())
|
||||||
|
.distinct().collect(Collectors.toMap(p -> p, timestampsFor));
|
||||||
|
}
|
||||||
|
|
||||||
|
// for serialization
|
||||||
|
LwwSet(Map<ElementType, Timestamps> struct){
|
||||||
|
this.struct = struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LwwSet<ElementType> add(ElementType e){
|
||||||
|
return this.merge(new LwwSet<>(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<ElementType, Timestamps> getStruct(){
|
||||||
|
return struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LwwSet<ElementType> remove(ElementType e){
|
||||||
|
Timestamps eTimestamps = struct.get(e);
|
||||||
|
if (eTimestamps == null || !eTimestamps.isPresent()){
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
Map<ElementType, Timestamps> changeMap = new HashMap<>();
|
||||||
|
changeMap.put(e, eTimestamps.updateRemove());
|
||||||
|
return this.merge(new LwwSet<>(changeMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LwwSet<ElementType> merge(LwwSet<ElementType> other){
|
||||||
|
return new LwwSet<>(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ElementType> value(){
|
||||||
|
return struct.entrySet().stream()
|
||||||
|
.filter(entry -> entry.getValue().isPresent())
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LwwSet<ElementType> optimize(){
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj){
|
||||||
|
return this == obj || (obj != null && getClass() == obj.getClass() && value().equals(((LwwSet) obj).value()));
|
||||||
|
}
|
||||||
|
|
||||||
static class Timestamps {
|
static class Timestamps {
|
||||||
private final long latestAdd;
|
private final long latestAdd;
|
||||||
private final long latestRemove;
|
private final long latestRemove;
|
||||||
@ -91,81 +166,4 @@ public class LwwSet<ElementType> implements CrdtAddRemoveSet<ElementType, Set<El
|
|||||||
return new Timestamps(Math.max(latestAdd, other.latestAdd), Math.max(latestRemove, other.latestRemove));
|
return new Timestamps(Math.max(latestAdd, other.latestAdd), Math.max(latestRemove, other.latestRemove));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public LwwSet(){
|
|
||||||
struct = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
public LwwSet(ElementType... elements){
|
|
||||||
this(new HashSet<>(Arrays.asList(elements)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LwwSet(Set<ElementType> set){
|
|
||||||
struct = new HashMap<>();
|
|
||||||
for (ElementType e : set){
|
|
||||||
struct.put(e, new Timestamps().updateAdd());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LwwSet(LwwSet<ElementType> first, LwwSet<ElementType> second){
|
|
||||||
Function<ElementType, Timestamps> timestampsFor = p -> {
|
|
||||||
Timestamps firstTs = first.struct.get(p);
|
|
||||||
Timestamps secondTs = second.struct.get(p);
|
|
||||||
if (firstTs == null){
|
|
||||||
return secondTs;
|
|
||||||
}
|
|
||||||
return firstTs.merge(secondTs);
|
|
||||||
};
|
|
||||||
struct = Stream.concat(first.struct.keySet().stream(), second.struct.keySet().stream())
|
|
||||||
.distinct().collect(Collectors.toMap(p -> p, timestampsFor));
|
|
||||||
}
|
|
||||||
|
|
||||||
public LwwSet<ElementType> add(ElementType e){
|
|
||||||
return this.merge(new LwwSet<>(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
// for serialization
|
|
||||||
LwwSet(Map<ElementType, Timestamps> struct){
|
|
||||||
this.struct = struct;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<ElementType, Timestamps> getStruct(){
|
|
||||||
return struct;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public LwwSet<ElementType> remove(ElementType e){
|
|
||||||
Timestamps eTimestamps = struct.get(e);
|
|
||||||
if (eTimestamps == null || !eTimestamps.isPresent()){
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
Map<ElementType, Timestamps> changeMap = new HashMap<>();
|
|
||||||
changeMap.put(e, eTimestamps.updateRemove());
|
|
||||||
return this.merge(new LwwSet<>(changeMap));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LwwSet<ElementType> merge(LwwSet<ElementType> other){
|
|
||||||
return new LwwSet<>(this, other);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<ElementType> value(){
|
|
||||||
return struct.entrySet().stream()
|
|
||||||
.filter(entry -> entry.getValue().isPresent())
|
|
||||||
.map(Map.Entry::getKey)
|
|
||||||
.collect(Collectors.toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LwwSet<ElementType> optimize(){
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj){
|
|
||||||
return this == obj || (obj != null && getClass() == obj.getClass() && value().equals(((LwwSet) obj).value()));
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -37,68 +37,72 @@ import java.util.stream.Stream;
|
|||||||
DataTest - integration test with 2 nodes, MaxChangeSet was serialized/deserialized, sent between nodes, merged
|
DataTest - integration test with 2 nodes, MaxChangeSet was serialized/deserialized, sent between nodes, merged
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class MaxChangeSet<ElementType> implements CrdtAddRemoveSet<ElementType, Set<ElementType>, MaxChangeSet<ElementType>> {
|
public class MaxChangeSet<ElementType>
|
||||||
|
implements CrdtAddRemoveSet<ElementType, Set<ElementType>, MaxChangeSet<ElementType>> {
|
||||||
private final Map<ElementType, Integer> struct;
|
private final Map<ElementType, Integer> struct;
|
||||||
|
|
||||||
public MaxChangeSet(){
|
public MaxChangeSet() {
|
||||||
struct = new HashMap<>();
|
struct = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public MaxChangeSet(ElementType... elements){
|
public MaxChangeSet(ElementType... elements) {
|
||||||
this(new HashSet<>(Arrays.asList(elements)));
|
this(new HashSet<>(Arrays.asList(elements)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MaxChangeSet(Set<ElementType> set){
|
public MaxChangeSet(Set<ElementType> set) {
|
||||||
struct = new HashMap<>();
|
struct = new HashMap<>();
|
||||||
for (ElementType e : set){
|
for (ElementType e : set) {
|
||||||
struct.put(e, 1);
|
struct.put(e, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MaxChangeSet(MaxChangeSet<ElementType> first, MaxChangeSet<ElementType> second){
|
public MaxChangeSet(MaxChangeSet<ElementType> first, MaxChangeSet<ElementType> second) {
|
||||||
Function<ElementType, Integer> valueFor = element ->
|
Function<ElementType, Integer> valueFor =
|
||||||
Math.max(first.struct.getOrDefault(element, 0), second.struct.getOrDefault(element, 0));
|
element ->
|
||||||
struct = Stream.concat(first.struct.keySet().stream(), second.struct.keySet().stream())
|
Math.max(first.struct.getOrDefault(element, 0), second.struct.getOrDefault(element, 0));
|
||||||
.distinct().collect(Collectors.toMap(p -> p, valueFor));
|
struct =
|
||||||
|
Stream.concat(first.struct.keySet().stream(), second.struct.keySet().stream())
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toMap(p -> p, valueFor));
|
||||||
}
|
}
|
||||||
|
|
||||||
// for serialization
|
// for serialization
|
||||||
MaxChangeSet(Map<ElementType, Integer> struct){
|
MaxChangeSet(Map<ElementType, Integer> struct) {
|
||||||
this.struct = struct;
|
this.struct = struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<ElementType, Integer> getStruct(){
|
Map<ElementType, Integer> getStruct() {
|
||||||
return struct;
|
return struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MaxChangeSet<ElementType> increment(ElementType e){
|
private MaxChangeSet<ElementType> increment(ElementType e) {
|
||||||
Map<ElementType, Integer> changeMap = new HashMap<>();
|
Map<ElementType, Integer> changeMap = new HashMap<>();
|
||||||
changeMap.put(e, struct.getOrDefault(e, 0) + 1);
|
changeMap.put(e, struct.getOrDefault(e, 0) + 1);
|
||||||
return this.merge(new MaxChangeSet<>(changeMap));
|
return this.merge(new MaxChangeSet<>(changeMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
public MaxChangeSet<ElementType> add(ElementType e){
|
public MaxChangeSet<ElementType> add(ElementType e) {
|
||||||
if (struct.getOrDefault(e, 0) % 2 == 1){
|
if (struct.getOrDefault(e, 0) % 2 == 1) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return increment(e);
|
return increment(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MaxChangeSet<ElementType> remove(ElementType e){
|
public MaxChangeSet<ElementType> remove(ElementType e) {
|
||||||
if (struct.getOrDefault(e, 0) % 2 == 0){
|
if (struct.getOrDefault(e, 0) % 2 == 0) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return increment(e);
|
return increment(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MaxChangeSet<ElementType> merge(MaxChangeSet<ElementType> other){
|
public MaxChangeSet<ElementType> merge(MaxChangeSet<ElementType> other) {
|
||||||
return new MaxChangeSet<>(this, other);
|
return new MaxChangeSet<>(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ElementType> value(){
|
public Set<ElementType> value() {
|
||||||
return struct.entrySet().stream()
|
return struct.entrySet().stream()
|
||||||
.filter(entry -> (entry.getValue() % 2 == 1))
|
.filter(entry -> (entry.getValue() % 2 == 1))
|
||||||
.map(Map.Entry::getKey)
|
.map(Map.Entry::getKey)
|
||||||
@ -106,12 +110,15 @@ public class MaxChangeSet<ElementType> implements CrdtAddRemoveSet<ElementType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MaxChangeSet<ElementType> optimize(){
|
public MaxChangeSet<ElementType> optimize() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj){
|
public boolean equals(Object obj) {
|
||||||
return this == obj || (obj != null && getClass() == obj.getClass() && value().equals(((MaxChangeSet) obj).value()));
|
return this == obj
|
||||||
|
|| (obj != null
|
||||||
|
&& getClass() == obj.getClass()
|
||||||
|
&& value().equals(((MaxChangeSet) obj).value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ package org.apache.gossip.crdt;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import org.apache.gossip.crdt.OrSet.Builder.Operation;
|
import org.apache.gossip.crdt.OrSet.Builder.Operation;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -83,6 +82,21 @@ public class OrSet<E> implements CrdtAddRemoveSet<E, Set<E>, OrSet<E>> {
|
|||||||
val = computeValue();
|
val = computeValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public OrSet(OrSet<E> left, OrSet<E> right){
|
||||||
|
BiConsumer<Map<E, Set<UUID>>, Map<E, Set<UUID>>> internalMerge = (items, other) -> {
|
||||||
|
for (Entry<E, Set<UUID>> l : other.entrySet()){
|
||||||
|
internalSetMerge(items, l.getKey(), l.getValue());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
internalMerge.accept(elements, left.elements);
|
||||||
|
internalMerge.accept(elements, right.elements);
|
||||||
|
internalMerge.accept(tombstones, left.tombstones);
|
||||||
|
internalMerge.accept(tombstones, right.tombstones);
|
||||||
|
|
||||||
|
val = computeValue();
|
||||||
|
}
|
||||||
|
|
||||||
static Set<UUID> mergeSets(Set<UUID> a, Set<UUID> b) {
|
static Set<UUID> mergeSets(Set<UUID> a, Set<UUID> b) {
|
||||||
if ((a == null || a.isEmpty()) && (b == null || b.isEmpty())) {
|
if ((a == null || a.isEmpty()) && (b == null || b.isEmpty())) {
|
||||||
return null;
|
return null;
|
||||||
@ -99,21 +113,6 @@ public class OrSet<E> implements CrdtAddRemoveSet<E, Set<E>, OrSet<E>> {
|
|||||||
map.merge(key, value, OrSet::mergeSets);
|
map.merge(key, value, OrSet::mergeSets);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OrSet(OrSet<E> left, OrSet<E> right){
|
|
||||||
BiConsumer<Map<E, Set<UUID>>, Map<E, Set<UUID>>> internalMerge = (items, other) -> {
|
|
||||||
for (Entry<E, Set<UUID>> l : other.entrySet()){
|
|
||||||
internalSetMerge(items, l.getKey(), l.getValue());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
internalMerge.accept(elements, left.elements);
|
|
||||||
internalMerge.accept(elements, right.elements);
|
|
||||||
internalMerge.accept(tombstones, left.tombstones);
|
|
||||||
internalMerge.accept(tombstones, right.tombstones);
|
|
||||||
|
|
||||||
val = computeValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public OrSet<E> add(E e) {
|
public OrSet<E> add(E e) {
|
||||||
return this.merge(new OrSet<>(e));
|
return this.merge(new OrSet<>(e));
|
||||||
}
|
}
|
||||||
@ -166,55 +165,18 @@ public class OrSet<E> implements CrdtAddRemoveSet<E, Set<E>, OrSet<E>> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder<E> {
|
|
||||||
public static enum Operation {
|
|
||||||
ADD, REMOVE
|
|
||||||
};
|
|
||||||
|
|
||||||
private class OrSetElement<EL> {
|
|
||||||
EL element;
|
|
||||||
Operation operation;
|
|
||||||
|
|
||||||
private OrSetElement(EL element, Operation operation) {
|
|
||||||
this.element = element;
|
|
||||||
this.operation = operation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<OrSetElement<E>> elements = new ArrayList<>();
|
|
||||||
|
|
||||||
public Builder<E> add(E element) {
|
|
||||||
elements.add(new OrSetElement<E>(element, Operation.ADD));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<E> remove(E element) {
|
|
||||||
elements.add(new OrSetElement<E>(element, Operation.REMOVE));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<E> mutate(E element, Operation operation) {
|
|
||||||
elements.add(new OrSetElement<E>(element, operation));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return value().size();
|
return value().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return value().size() == 0;
|
return value().size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean contains(Object o) {
|
public boolean contains(Object o) {
|
||||||
return value().contains(o);
|
return value().contains(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Iterator<E> iterator() {
|
public Iterator<E> iterator() {
|
||||||
Iterator<E> managed = value().iterator();
|
Iterator<E> managed = value().iterator();
|
||||||
return new Iterator<E>() {
|
return new Iterator<E>() {
|
||||||
@ -233,7 +195,7 @@ public class OrSet<E> implements CrdtAddRemoveSet<E, Set<E>, OrSet<E>> {
|
|||||||
public E next() {
|
public E next() {
|
||||||
return managed.next();
|
return managed.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,4 +266,37 @@ public class OrSet<E> implements CrdtAddRemoveSet<E, Set<E>, OrSet<E>> {
|
|||||||
return tombstones;
|
return tombstones;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Builder<E> {
|
||||||
|
private List<OrSetElement<E>> elements = new ArrayList<>();;
|
||||||
|
|
||||||
|
public Builder<E> add(E element) {
|
||||||
|
elements.add(new OrSetElement<E>(element, Operation.ADD));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<E> remove(E element) {
|
||||||
|
elements.add(new OrSetElement<E>(element, Operation.REMOVE));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder<E> mutate(E element, Operation operation) {
|
||||||
|
elements.add(new OrSetElement<E>(element, operation));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum Operation {
|
||||||
|
ADD, REMOVE
|
||||||
|
}
|
||||||
|
|
||||||
|
private class OrSetElement<EL> {
|
||||||
|
EL element;
|
||||||
|
Operation operation;
|
||||||
|
|
||||||
|
private OrSetElement(EL element, Operation operation) {
|
||||||
|
this.element = element;
|
||||||
|
this.operation = operation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.gossip.manager.GossipManager;
|
import org.apache.gossip.manager.GossipManager;
|
||||||
|
|
||||||
public class PNCounter implements CrdtCounter<Long, PNCounter> {
|
public class PNCounter implements CrdtCounter<Long, PNCounter> {
|
||||||
|
@ -36,57 +36,58 @@ import java.util.stream.Stream;
|
|||||||
DataTest - integration test with 2 nodes, TwoPhaseSet was serialized/deserialized, sent between nodes, merged
|
DataTest - integration test with 2 nodes, TwoPhaseSet was serialized/deserialized, sent between nodes, merged
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TwoPhaseSet<ElementType> implements CrdtAddRemoveSet<ElementType, Set<ElementType>, TwoPhaseSet<ElementType>> {
|
public class TwoPhaseSet<ElementType>
|
||||||
|
implements CrdtAddRemoveSet<ElementType, Set<ElementType>, TwoPhaseSet<ElementType>> {
|
||||||
private final Set<ElementType> added;
|
private final Set<ElementType> added;
|
||||||
private final Set<ElementType> removed;
|
private final Set<ElementType> removed;
|
||||||
|
|
||||||
public TwoPhaseSet(){
|
public TwoPhaseSet() {
|
||||||
added = new HashSet<>();
|
added = new HashSet<>();
|
||||||
removed = new HashSet<>();
|
removed = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public TwoPhaseSet(ElementType... elements){
|
public TwoPhaseSet(ElementType... elements) {
|
||||||
this(new HashSet<>(Arrays.asList(elements)));
|
this(new HashSet<>(Arrays.asList(elements)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TwoPhaseSet(Set<ElementType> set){
|
public TwoPhaseSet(Set<ElementType> set) {
|
||||||
this();
|
this();
|
||||||
for (ElementType e : set){
|
for (ElementType e : set) {
|
||||||
added.add(e);
|
added.add(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TwoPhaseSet(TwoPhaseSet<ElementType> first, TwoPhaseSet<ElementType> second){
|
public TwoPhaseSet(TwoPhaseSet<ElementType> first, TwoPhaseSet<ElementType> second) {
|
||||||
BiFunction<Set<ElementType>, Set<ElementType>, Set<ElementType>> mergeSets = (f, s) ->
|
BiFunction<Set<ElementType>, Set<ElementType>, Set<ElementType>> mergeSets =
|
||||||
Stream.concat(f.stream(), s.stream()).collect(Collectors.toSet());
|
(f, s) -> Stream.concat(f.stream(), s.stream()).collect(Collectors.toSet());
|
||||||
|
|
||||||
added = mergeSets.apply(first.added, second.added);
|
added = mergeSets.apply(first.added, second.added);
|
||||||
removed = mergeSets.apply(first.removed, second.removed);
|
removed = mergeSets.apply(first.removed, second.removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
TwoPhaseSet(Set<ElementType> added, Set<ElementType> removed){
|
TwoPhaseSet(Set<ElementType> added, Set<ElementType> removed) {
|
||||||
this.added = added;
|
this.added = added;
|
||||||
this.removed = removed;
|
this.removed = removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ElementType> getAdded(){
|
Set<ElementType> getAdded() {
|
||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<ElementType> getRemoved(){
|
Set<ElementType> getRemoved() {
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TwoPhaseSet<ElementType> add(ElementType e){
|
public TwoPhaseSet<ElementType> add(ElementType e) {
|
||||||
if (removed.contains(e) || added.contains(e)){
|
if (removed.contains(e) || added.contains(e)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return this.merge(new TwoPhaseSet<>(e));
|
return this.merge(new TwoPhaseSet<>(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TwoPhaseSet<ElementType> remove(ElementType e){
|
public TwoPhaseSet<ElementType> remove(ElementType e) {
|
||||||
if (removed.contains(e) || !added.contains(e)){
|
if (removed.contains(e) || !added.contains(e)) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
Set<ElementType> eSet = new HashSet<>(Collections.singletonList(e));
|
Set<ElementType> eSet = new HashSet<>(Collections.singletonList(e));
|
||||||
@ -94,22 +95,25 @@ public class TwoPhaseSet<ElementType> implements CrdtAddRemoveSet<ElementType, S
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TwoPhaseSet<ElementType> merge(TwoPhaseSet<ElementType> other){
|
public TwoPhaseSet<ElementType> merge(TwoPhaseSet<ElementType> other) {
|
||||||
return new TwoPhaseSet<>(this, other);
|
return new TwoPhaseSet<>(this, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<ElementType> value(){
|
public Set<ElementType> value() {
|
||||||
return added.stream().filter(e -> !removed.contains(e)).collect(Collectors.toSet());
|
return added.stream().filter(e -> !removed.contains(e)).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TwoPhaseSet<ElementType> optimize(){
|
public TwoPhaseSet<ElementType> optimize() {
|
||||||
return new TwoPhaseSet<>(value(), removed);
|
return new TwoPhaseSet<>(value(), removed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj){
|
public boolean equals(Object obj) {
|
||||||
return this == obj || (obj != null && getClass() == obj.getClass() && value().equals(((TwoPhaseSet) obj).value()));
|
return this == obj
|
||||||
|
|| (obj != null
|
||||||
|
&& getClass() == obj.getClass()
|
||||||
|
&& value().equals(((TwoPhaseSet) obj).value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,9 @@
|
|||||||
package org.apache.gossip.event;
|
package org.apache.gossip.event;
|
||||||
|
|
||||||
public enum GossipState {
|
public enum GossipState {
|
||||||
UP("up"), DOWN("down");
|
UP("up"),
|
||||||
|
DOWN("down");
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final String state;
|
private final String state;
|
||||||
|
|
||||||
|
@ -18,17 +18,17 @@
|
|||||||
package org.apache.gossip.event.data;
|
package org.apache.gossip.event.data;
|
||||||
|
|
||||||
public class DataEventConstants {
|
public class DataEventConstants {
|
||||||
|
|
||||||
// MetricRegistry
|
// MetricRegistry
|
||||||
public static final String PER_NODE_DATA_SUBSCRIBERS_SIZE
|
public static final String PER_NODE_DATA_SUBSCRIBERS_SIZE =
|
||||||
= "gossip.event.data.pernode.subscribers.size";
|
"gossip.event.data.pernode.subscribers.size";
|
||||||
public static final String PER_NODE_DATA_SUBSCRIBERS_QUEUE_SIZE
|
public static final String PER_NODE_DATA_SUBSCRIBERS_QUEUE_SIZE =
|
||||||
= "gossip.event.data.pernode.subscribers.queue.size";
|
"gossip.event.data.pernode.subscribers.queue.size";
|
||||||
public static final String SHARED_DATA_SUBSCRIBERS_SIZE
|
public static final String SHARED_DATA_SUBSCRIBERS_SIZE =
|
||||||
= "gossip.event.data.shared.subscribers.size";
|
"gossip.event.data.shared.subscribers.size";
|
||||||
public static final String SHARED_DATA_SUBSCRIBERS_QUEUE_SIZE
|
public static final String SHARED_DATA_SUBSCRIBERS_QUEUE_SIZE =
|
||||||
= "gossip.event.data.shared.subscribers.queue.size";
|
"gossip.event.data.shared.subscribers.queue.size";
|
||||||
|
|
||||||
// Thread pool
|
// Thread pool
|
||||||
public static final int PER_NODE_DATA_QUEUE_SIZE = 64;
|
public static final int PER_NODE_DATA_QUEUE_SIZE = 64;
|
||||||
public static final int PER_NODE_DATA_CORE_POOL_SIZE = 1;
|
public static final int PER_NODE_DATA_CORE_POOL_SIZE = 1;
|
||||||
@ -38,5 +38,4 @@ public class DataEventConstants {
|
|||||||
public static final int SHARED_DATA_CORE_POOL_SIZE = 1;
|
public static final int SHARED_DATA_CORE_POOL_SIZE = 1;
|
||||||
public static final int SHARED_DATA_MAX_POOL_SIZE = 30;
|
public static final int SHARED_DATA_MAX_POOL_SIZE = 30;
|
||||||
public static final int SHARED_DATA_KEEP_ALIVE_TIME_SECONDS = 1;
|
public static final int SHARED_DATA_KEEP_ALIVE_TIME_SECONDS = 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,74 +29,86 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class DataEventManager {
|
public class DataEventManager {
|
||||||
|
|
||||||
private final List<UpdateNodeDataEventHandler> perNodeDataHandlers;
|
private final List<UpdateNodeDataEventHandler> perNodeDataHandlers;
|
||||||
private final BlockingQueue<Runnable> perNodeDataHandlerQueue;
|
private final BlockingQueue<Runnable> perNodeDataHandlerQueue;
|
||||||
private final ExecutorService perNodeDataEventExecutor;
|
private final ExecutorService perNodeDataEventExecutor;
|
||||||
private final List<UpdateSharedDataEventHandler> sharedDataHandlers;
|
private final List<UpdateSharedDataEventHandler> sharedDataHandlers;
|
||||||
private final BlockingQueue<Runnable> sharedDataHandlerQueue;
|
private final BlockingQueue<Runnable> sharedDataHandlerQueue;
|
||||||
private final ExecutorService sharedDataEventExecutor;
|
private final ExecutorService sharedDataEventExecutor;
|
||||||
|
|
||||||
public DataEventManager(MetricRegistry metrics) {
|
public DataEventManager(MetricRegistry metrics) {
|
||||||
perNodeDataHandlers = new CopyOnWriteArrayList<>();
|
perNodeDataHandlers = new CopyOnWriteArrayList<>();
|
||||||
perNodeDataHandlerQueue = new ArrayBlockingQueue<>(DataEventConstants.PER_NODE_DATA_QUEUE_SIZE);
|
perNodeDataHandlerQueue = new ArrayBlockingQueue<>(DataEventConstants.PER_NODE_DATA_QUEUE_SIZE);
|
||||||
perNodeDataEventExecutor = new ThreadPoolExecutor(
|
perNodeDataEventExecutor =
|
||||||
|
new ThreadPoolExecutor(
|
||||||
DataEventConstants.PER_NODE_DATA_CORE_POOL_SIZE,
|
DataEventConstants.PER_NODE_DATA_CORE_POOL_SIZE,
|
||||||
DataEventConstants.PER_NODE_DATA_MAX_POOL_SIZE,
|
DataEventConstants.PER_NODE_DATA_MAX_POOL_SIZE,
|
||||||
DataEventConstants.PER_NODE_DATA_KEEP_ALIVE_TIME_SECONDS, TimeUnit.SECONDS,
|
DataEventConstants.PER_NODE_DATA_KEEP_ALIVE_TIME_SECONDS,
|
||||||
perNodeDataHandlerQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
|
TimeUnit.SECONDS,
|
||||||
|
perNodeDataHandlerQueue,
|
||||||
|
new ThreadPoolExecutor.DiscardOldestPolicy());
|
||||||
|
|
||||||
sharedDataHandlers = new CopyOnWriteArrayList<>();
|
sharedDataHandlers = new CopyOnWriteArrayList<>();
|
||||||
sharedDataHandlerQueue = new ArrayBlockingQueue<>(DataEventConstants.SHARED_DATA_QUEUE_SIZE);
|
sharedDataHandlerQueue = new ArrayBlockingQueue<>(DataEventConstants.SHARED_DATA_QUEUE_SIZE);
|
||||||
sharedDataEventExecutor = new ThreadPoolExecutor(DataEventConstants.SHARED_DATA_CORE_POOL_SIZE,
|
sharedDataEventExecutor =
|
||||||
|
new ThreadPoolExecutor(
|
||||||
|
DataEventConstants.SHARED_DATA_CORE_POOL_SIZE,
|
||||||
DataEventConstants.SHARED_DATA_MAX_POOL_SIZE,
|
DataEventConstants.SHARED_DATA_MAX_POOL_SIZE,
|
||||||
DataEventConstants.SHARED_DATA_KEEP_ALIVE_TIME_SECONDS, TimeUnit.SECONDS,
|
DataEventConstants.SHARED_DATA_KEEP_ALIVE_TIME_SECONDS,
|
||||||
sharedDataHandlerQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
|
TimeUnit.SECONDS,
|
||||||
|
sharedDataHandlerQueue,
|
||||||
metrics.register(DataEventConstants.PER_NODE_DATA_SUBSCRIBERS_SIZE,
|
new ThreadPoolExecutor.DiscardOldestPolicy());
|
||||||
(Gauge<Integer>) () -> perNodeDataHandlers.size());
|
|
||||||
metrics.register(DataEventConstants.PER_NODE_DATA_SUBSCRIBERS_QUEUE_SIZE,
|
metrics.register(
|
||||||
(Gauge<Integer>) () -> perNodeDataHandlerQueue.size());
|
DataEventConstants.PER_NODE_DATA_SUBSCRIBERS_SIZE,
|
||||||
metrics.register(DataEventConstants.SHARED_DATA_SUBSCRIBERS_SIZE,
|
(Gauge<Integer>) () -> perNodeDataHandlers.size());
|
||||||
(Gauge<Integer>) () -> sharedDataHandlers.size());
|
metrics.register(
|
||||||
metrics.register(DataEventConstants.SHARED_DATA_SUBSCRIBERS_QUEUE_SIZE,
|
DataEventConstants.PER_NODE_DATA_SUBSCRIBERS_QUEUE_SIZE,
|
||||||
(Gauge<Integer>) () -> sharedDataHandlerQueue.size());
|
(Gauge<Integer>) () -> perNodeDataHandlerQueue.size());
|
||||||
|
metrics.register(
|
||||||
|
DataEventConstants.SHARED_DATA_SUBSCRIBERS_SIZE,
|
||||||
|
(Gauge<Integer>) () -> sharedDataHandlers.size());
|
||||||
|
metrics.register(
|
||||||
|
DataEventConstants.SHARED_DATA_SUBSCRIBERS_QUEUE_SIZE,
|
||||||
|
(Gauge<Integer>) () -> sharedDataHandlerQueue.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifySharedData(final String key, final Object newValue, final Object oldValue) {
|
public void notifySharedData(final String key, final Object newValue, final Object oldValue) {
|
||||||
sharedDataHandlers.forEach(handler -> sharedDataEventExecutor
|
sharedDataHandlers.forEach(
|
||||||
.execute(() -> handler.onUpdate(key, oldValue, newValue)));
|
handler ->
|
||||||
|
sharedDataEventExecutor.execute(() -> handler.onUpdate(key, oldValue, newValue)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyPerNodeData(final String nodeId, final String key, final Object newValue,
|
public void notifyPerNodeData(
|
||||||
final Object oldValue) {
|
final String nodeId, final String key, final Object newValue, final Object oldValue) {
|
||||||
perNodeDataHandlers.forEach(handler -> perNodeDataEventExecutor
|
perNodeDataHandlers.forEach(
|
||||||
.execute(() -> handler.onUpdate(nodeId, key, oldValue, newValue)));
|
handler ->
|
||||||
|
perNodeDataEventExecutor.execute(
|
||||||
|
() -> handler.onUpdate(nodeId, key, oldValue, newValue)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerPerNodeDataSubscriber(UpdateNodeDataEventHandler handler) {
|
public void registerPerNodeDataSubscriber(UpdateNodeDataEventHandler handler) {
|
||||||
perNodeDataHandlers.add(handler);
|
perNodeDataHandlers.add(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterPerNodeDataSubscriber(UpdateNodeDataEventHandler handler) {
|
public void unregisterPerNodeDataSubscriber(UpdateNodeDataEventHandler handler) {
|
||||||
perNodeDataHandlers.remove(handler);
|
perNodeDataHandlers.remove(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPerNodeSubscribersSize() {
|
public int getPerNodeSubscribersSize() {
|
||||||
return perNodeDataHandlers.size();
|
return perNodeDataHandlers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerSharedDataSubscriber(UpdateSharedDataEventHandler handler) {
|
public void registerSharedDataSubscriber(UpdateSharedDataEventHandler handler) {
|
||||||
sharedDataHandlers.add(handler);
|
sharedDataHandlers.add(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unregisterSharedDataSubscriber(UpdateSharedDataEventHandler handler) {
|
public void unregisterSharedDataSubscriber(UpdateSharedDataEventHandler handler) {
|
||||||
sharedDataHandlers.remove(handler);
|
sharedDataHandlers.remove(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSharedDataSubscribersSize() {
|
public int getSharedDataSubscribersSize() {
|
||||||
return sharedDataHandlers.size();
|
return sharedDataHandlers.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,20 +18,19 @@
|
|||||||
package org.apache.gossip.event.data;
|
package org.apache.gossip.event.data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler interface for the per node data items.
|
* Event handler interface for the per node data items. Classes which implement this interface get
|
||||||
* Classes which implement this interface get notifications when per node data item get changed.
|
* notifications when per node data item get changed.
|
||||||
*/
|
*/
|
||||||
public interface UpdateNodeDataEventHandler {
|
public interface UpdateNodeDataEventHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method get called when a per node datum get changed.
|
* This method get called when a per node datum get changed.
|
||||||
*
|
*
|
||||||
* @param nodeId id of the node that change the value
|
* @param nodeId id of the node that change the value
|
||||||
* @param key key of the datum
|
* @param key key of the datum
|
||||||
* @param oldValue previous value of the datum or null if the datum is discovered
|
* @param oldValue previous value of the datum or null if the datum is discovered for the first
|
||||||
* for the first time
|
* time
|
||||||
* @param newValue updated value of the datum
|
* @param newValue updated value of the datum
|
||||||
*/
|
*/
|
||||||
void onUpdate(String nodeId, String key, Object oldValue, Object newValue);
|
void onUpdate(String nodeId, String key, Object oldValue, Object newValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,16 @@
|
|||||||
package org.apache.gossip.event.data;
|
package org.apache.gossip.event.data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler interface for shared data items.
|
* Event handler interface for shared data items. Classes which implement this interface get
|
||||||
* Classes which implement this interface get notifications when shared data get changed.
|
* notifications when shared data get changed.
|
||||||
*/
|
*/
|
||||||
public interface UpdateSharedDataEventHandler {
|
public interface UpdateSharedDataEventHandler {
|
||||||
/**
|
/**
|
||||||
* This method get called when shared data get changed.
|
* This method get called when shared data get changed.
|
||||||
*
|
*
|
||||||
* @param key key of the shared data item
|
* @param key key of the shared data item
|
||||||
* @param oldValue previous value or null if the data is discovered for the first time
|
* @param oldValue previous value or null if the data is discovered for the first time
|
||||||
* @param newValue updated value of the data item
|
* @param newValue updated value of the data item
|
||||||
*/
|
*/
|
||||||
void onUpdate(String key, Object oldValue, Object newValue);
|
void onUpdate(String key, Object oldValue, Object newValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,6 @@ package org.apache.gossip.lock;
|
|||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.codahale.metrics.Timer;
|
import com.codahale.metrics.Timer;
|
||||||
import org.apache.gossip.Member;
|
|
||||||
import org.apache.gossip.lock.exceptions.VoteFailedException;
|
|
||||||
import org.apache.gossip.lock.vote.MajorityVote;
|
|
||||||
import org.apache.gossip.lock.vote.Vote;
|
|
||||||
import org.apache.gossip.lock.vote.VoteCandidate;
|
|
||||||
import org.apache.gossip.manager.GossipManager;
|
|
||||||
import org.apache.gossip.model.SharedDataMessage;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -43,19 +34,27 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.gossip.Member;
|
||||||
|
import org.apache.gossip.lock.exceptions.VoteFailedException;
|
||||||
|
import org.apache.gossip.lock.vote.MajorityVote;
|
||||||
|
import org.apache.gossip.lock.vote.Vote;
|
||||||
|
import org.apache.gossip.lock.vote.VoteCandidate;
|
||||||
|
import org.apache.gossip.manager.GossipManager;
|
||||||
|
import org.apache.gossip.model.SharedDataMessage;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class LockManager {
|
public class LockManager {
|
||||||
|
|
||||||
public static final Logger LOGGER = Logger.getLogger(LockManager.class);
|
|
||||||
|
|
||||||
|
// For MetricRegistry
|
||||||
|
public static final String LOCK_KEY_SET_SIZE = "gossip.lock.key_set_size";
|
||||||
|
public static final String LOCK_TIME = "gossip.lock.time";
|
||||||
private final GossipManager gossipManager;
|
private final GossipManager gossipManager;
|
||||||
private final LockManagerSettings lockSettings;
|
private final LockManagerSettings lockSettings;
|
||||||
private final ScheduledExecutorService voteService;
|
private final ScheduledExecutorService voteService;
|
||||||
private final AtomicInteger numberOfNodes;
|
private final AtomicInteger numberOfNodes;
|
||||||
private final Set<String> lockKeys;
|
private final Set<String> lockKeys;
|
||||||
// For MetricRegistry
|
|
||||||
public static final String LOCK_KEY_SET_SIZE = "gossip.lock.key_set_size";
|
|
||||||
public static final String LOCK_TIME = "gossip.lock.time";
|
|
||||||
private final Timer lockTimeMetric;
|
private final Timer lockTimeMetric;
|
||||||
|
|
||||||
public LockManager(GossipManager gossipManager, final LockManagerSettings lockManagerSettings,
|
public LockManager(GossipManager gossipManager, final LockManagerSettings lockManagerSettings,
|
||||||
@ -95,20 +94,16 @@ public class LockManager {
|
|||||||
|
|
||||||
long passedCandidates = voteResultMap.values().stream().filter(aBoolean -> aBoolean).count();
|
long passedCandidates = voteResultMap.values().stream().filter(aBoolean -> aBoolean).count();
|
||||||
String myNodeId = gossipManager.getMyself().getId();
|
String myNodeId = gossipManager.getMyself().getId();
|
||||||
if (LOGGER.isDebugEnabled()) {
|
log.debug("NodeId=" + myNodeId + ", VoteMap=" + voteResultMap + ", WinnerCount="
|
||||||
LOGGER.debug("NodeId=" + myNodeId + ", VoteMap=" + voteResultMap + ", WinnerCount="
|
|
||||||
+ passedCandidates);
|
+ passedCandidates);
|
||||||
}
|
|
||||||
// Check for possible dead lock when no candidates were won
|
// Check for possible dead lock when no candidates were won
|
||||||
if (passedCandidates == 0) {
|
if (passedCandidates == 0) {
|
||||||
if (isDeadLock(voteCandidatesMap)) {
|
if (isDeadLock(voteCandidatesMap)) {
|
||||||
deadlockDetectCount++;
|
deadlockDetectCount++;
|
||||||
// Testing for deadlock is not always correct, therefore test for continues deadlocks
|
// Testing for deadlock is not always correct, therefore test for continues deadlocks
|
||||||
if (deadlockDetectCount >= lockSettings.getDeadlockDetectionThreshold()) {
|
if (deadlockDetectCount >= lockSettings.getDeadlockDetectionThreshold()) {
|
||||||
if (LOGGER.isDebugEnabled()) {
|
log.debug("Deadlock detected from node " + myNodeId + ". VoteCandidatesMap="
|
||||||
LOGGER.debug("Deadlock detected from node " + myNodeId + ". VoteCandidatesMap="
|
|
||||||
+ voteCandidatesMap);
|
+ voteCandidatesMap);
|
||||||
}
|
|
||||||
preventDeadLock(voteCandidatesMap);
|
preventDeadLock(voteCandidatesMap);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -251,9 +246,7 @@ public class LockManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOGGER.isDebugEnabled()) {
|
log.debug("Node " + myNodeId + " give up votes to node " + selectedCandidateId);
|
||||||
LOGGER.debug("Node " + myNodeId + " give up votes to node " + selectedCandidateId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getVotedCandidateNodeId(String nodeId,
|
private String getVotedCandidateNodeId(String nodeId,
|
||||||
|
@ -20,9 +20,7 @@ package org.apache.gossip.lock;
|
|||||||
import org.apache.gossip.lock.vote.RandomVoteSelector;
|
import org.apache.gossip.lock.vote.RandomVoteSelector;
|
||||||
import org.apache.gossip.lock.vote.VoteSelector;
|
import org.apache.gossip.lock.vote.VoteSelector;
|
||||||
|
|
||||||
/**
|
/** Stores the lock manager related settings. */
|
||||||
* Stores the lock manager related settings.
|
|
||||||
*/
|
|
||||||
public class LockManagerSettings {
|
public class LockManagerSettings {
|
||||||
// Time between vote updates in ms. Default is 1 second.
|
// Time between vote updates in ms. Default is 1 second.
|
||||||
private final int voteUpdateInterval;
|
private final int voteUpdateInterval;
|
||||||
@ -35,30 +33,32 @@ public class LockManagerSettings {
|
|||||||
// Wait time between vote result calculation. Default is 1000
|
// Wait time between vote result calculation. Default is 1000
|
||||||
private final int resultCalculationDelay;
|
private final int resultCalculationDelay;
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct LockManagerSettings with default settings.
|
|
||||||
*/
|
|
||||||
public static LockManagerSettings getLockManagerDefaultSettings() {
|
|
||||||
return new LockManagerSettings(1000, new RandomVoteSelector(), -1, 3, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a custom LockManagerSettings
|
* Construct a custom LockManagerSettings
|
||||||
*
|
*
|
||||||
* @param voteUpdateInterval Time between vote updates in milliseconds.
|
* @param voteUpdateInterval Time between vote updates in milliseconds.
|
||||||
* @param voteSelector Vote selection algorithm. Cannot be null
|
* @param voteSelector Vote selection algorithm. Cannot be null
|
||||||
* @param numberOfNodes Number of nodes available for voting. Set to negative value for auto calculate
|
* @param numberOfNodes Number of nodes available for voting. Set to negative value for auto
|
||||||
|
* calculate
|
||||||
* @param deadlockDetectionThreshold Number of times to test for deadlock before preventing
|
* @param deadlockDetectionThreshold Number of times to test for deadlock before preventing
|
||||||
* @param resultCalculationDelay Wait time between vote result calculation
|
* @param resultCalculationDelay Wait time between vote result calculation
|
||||||
*/
|
*/
|
||||||
public LockManagerSettings(int voteUpdateInterval, VoteSelector voteSelector, int numberOfNodes,
|
public LockManagerSettings(
|
||||||
int deadlockDetectionThreshold, int resultCalculationDelay) {
|
int voteUpdateInterval,
|
||||||
|
VoteSelector voteSelector,
|
||||||
|
int numberOfNodes,
|
||||||
|
int deadlockDetectionThreshold,
|
||||||
|
int resultCalculationDelay) {
|
||||||
this.voteUpdateInterval = voteUpdateInterval;
|
this.voteUpdateInterval = voteUpdateInterval;
|
||||||
this.voteSelector = voteSelector;
|
this.voteSelector = voteSelector;
|
||||||
this.numberOfNodes = numberOfNodes;
|
this.numberOfNodes = numberOfNodes;
|
||||||
this.deadlockDetectionThreshold = deadlockDetectionThreshold;
|
this.deadlockDetectionThreshold = deadlockDetectionThreshold;
|
||||||
this.resultCalculationDelay = resultCalculationDelay;
|
this.resultCalculationDelay = resultCalculationDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Construct LockManagerSettings with default settings. */
|
||||||
|
public static LockManagerSettings getLockManagerDefaultSettings() {
|
||||||
|
return new LockManagerSettings(1000, new RandomVoteSelector(), -1, 3, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVoteUpdateInterval() {
|
public int getVoteUpdateInterval() {
|
||||||
|
@ -17,9 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.lock.exceptions;
|
package org.apache.gossip.lock.exceptions;
|
||||||
|
|
||||||
/**
|
/** This exception is thrown when the lock based voting is failed. */
|
||||||
* This exception is thrown when the lock based voting is failed.
|
|
||||||
*/
|
|
||||||
public class VoteFailedException extends Exception {
|
public class VoteFailedException extends Exception {
|
||||||
/**
|
/**
|
||||||
* Constructs a new VoteFailedException with the specified detail message.
|
* Constructs a new VoteFailedException with the specified detail message.
|
||||||
@ -31,11 +29,10 @@ public class VoteFailedException extends Exception {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new VoteFailedException with the specified detail message and
|
* Constructs a new VoteFailedException with the specified detail message and cause.
|
||||||
* cause.
|
|
||||||
*
|
*
|
||||||
* @param message the detail message
|
* @param message the detail message
|
||||||
* @param cause the cause for this exception
|
* @param cause the cause for this exception
|
||||||
*/
|
*/
|
||||||
public VoteFailedException(String message, Throwable cause) {
|
public VoteFailedException(String message, Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
|
@ -17,14 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.lock.vote;
|
package org.apache.gossip.lock.vote;
|
||||||
|
|
||||||
import org.apache.gossip.crdt.Crdt;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import org.apache.gossip.crdt.Crdt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CRDT which used for distribute a votes for a given key.
|
* CRDT which used for distribute a votes for a given key.
|
||||||
|
@ -22,9 +22,7 @@ import java.util.List;
|
|||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/** VoteSelector implementation which randomly select a voting node. */
|
||||||
* VoteSelector implementation which randomly select a voting node.
|
|
||||||
*/
|
|
||||||
public class RandomVoteSelector implements VoteSelector {
|
public class RandomVoteSelector implements VoteSelector {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,9 +25,9 @@ import java.util.List;
|
|||||||
public class Vote {
|
public class Vote {
|
||||||
private final String votingNode;
|
private final String votingNode;
|
||||||
private final Boolean voteValue; // TODO: 7/16/17 weight?
|
private final Boolean voteValue; // TODO: 7/16/17 weight?
|
||||||
private Boolean voteExchange;
|
|
||||||
private final List<String> liveMembers;
|
private final List<String> liveMembers;
|
||||||
private final List<String> deadMembers;
|
private final List<String> deadMembers;
|
||||||
|
private Boolean voteExchange;
|
||||||
|
|
||||||
public Vote(String votingNode, Boolean voteValue, Boolean voteExchange, List<String> liveMembers,
|
public Vote(String votingNode, Boolean voteValue, Boolean voteExchange, List<String> liveMembers,
|
||||||
List<String> deadMembers) {
|
List<String> deadMembers) {
|
||||||
|
@ -20,9 +20,7 @@ package org.apache.gossip.lock.vote;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/** Stores the vote candidate details and its votes. */
|
||||||
* Stores the vote candidate details and its votes.
|
|
||||||
*/
|
|
||||||
public class VoteCandidate {
|
public class VoteCandidate {
|
||||||
|
|
||||||
private final String candidateNodeId;
|
private final String candidateNodeId;
|
||||||
@ -59,13 +57,11 @@ public class VoteCandidate {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (!(obj instanceof VoteCandidate))
|
if (!(obj instanceof VoteCandidate)) return false;
|
||||||
return false;
|
if (obj == this) return true;
|
||||||
if (obj == this)
|
|
||||||
return true;
|
|
||||||
VoteCandidate other = (VoteCandidate) obj;
|
VoteCandidate other = (VoteCandidate) obj;
|
||||||
return this.candidateNodeId.equals(other.candidateNodeId) && this.votingKey
|
return this.candidateNodeId.equals(other.candidateNodeId)
|
||||||
.equals(other.votingKey);
|
&& this.votingKey.equals(other.votingKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,12 +19,11 @@ package org.apache.gossip.lock.vote;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/** This interface defines vote selection algorithm for the vote based locking. */
|
||||||
* This interface defines vote selection algorithm for the vote based locking.
|
|
||||||
*/
|
|
||||||
public interface VoteSelector {
|
public interface VoteSelector {
|
||||||
/**
|
/**
|
||||||
* This method get call by the lock manager of a node to decide which candidate need to be choose for voting.
|
* This method get call by the lock manager of a node to decide which candidate need to be choose
|
||||||
|
* for voting.
|
||||||
*
|
*
|
||||||
* @param voteCandidateIds node id set for the vote candidates
|
* @param voteCandidateIds node id set for the vote candidates
|
||||||
* @return selected node id to vote from the given vote candidate set.
|
* @return selected node id to vote from the given vote candidate set.
|
||||||
|
@ -17,33 +17,32 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.manager;
|
package org.apache.gossip.manager;
|
||||||
|
|
||||||
import java.util.Map.Entry;
|
import static com.codahale.metrics.MetricRegistry.name;
|
||||||
|
|
||||||
|
import com.codahale.metrics.Histogram;
|
||||||
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import com.codahale.metrics.Histogram;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
|
||||||
import org.apache.gossip.GossipSettings;
|
import org.apache.gossip.GossipSettings;
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
import org.apache.gossip.model.ActiveGossipOk;
|
import org.apache.gossip.model.ActiveGossipOk;
|
||||||
import org.apache.gossip.model.PerNodeDataMessage;
|
|
||||||
import org.apache.gossip.model.Member;
|
import org.apache.gossip.model.Member;
|
||||||
|
import org.apache.gossip.model.PerNodeDataMessage;
|
||||||
import org.apache.gossip.model.Response;
|
import org.apache.gossip.model.Response;
|
||||||
import org.apache.gossip.model.SharedDataMessage;
|
import org.apache.gossip.model.SharedDataMessage;
|
||||||
import org.apache.gossip.model.ShutdownMessage;
|
import org.apache.gossip.model.ShutdownMessage;
|
||||||
import org.apache.gossip.udp.*;
|
import org.apache.gossip.udp.*;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import static com.codahale.metrics.MetricRegistry.name;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ActiveGossipThread sends information. Pick a random partner and send the membership list to that partner
|
* The ActiveGossipThread sends information. Pick a random partner and send the membership list to that partner
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public abstract class AbstractActiveGossiper {
|
public abstract class AbstractActiveGossiper {
|
||||||
|
|
||||||
protected static final Logger LOGGER = Logger.getLogger(AbstractActiveGossiper.class);
|
|
||||||
|
|
||||||
protected final GossipManager gossipManager;
|
protected final GossipManager gossipManager;
|
||||||
protected final GossipCore gossipCore;
|
protected final GossipCore gossipCore;
|
||||||
private final Histogram sharedDataHistogram;
|
private final Histogram sharedDataHistogram;
|
||||||
@ -128,7 +127,7 @@ public abstract class AbstractActiveGossiper {
|
|||||||
udpMessage.setUriFrom(me.getId());
|
udpMessage.setUriFrom(me.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (udpMessage.getMessages().size() > 0) {
|
if (!udpMessage.getMessages().isEmpty()) {
|
||||||
gossipCore.sendOneWay(udpMessage, member.getUri());
|
gossipCore.sendOneWay(udpMessage, member.getUri());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,7 +228,7 @@ public abstract class AbstractActiveGossiper {
|
|||||||
if (r instanceof ActiveGossipOk){
|
if (r instanceof ActiveGossipOk){
|
||||||
//maybe count metrics here
|
//maybe count metrics here
|
||||||
} else {
|
} else {
|
||||||
LOGGER.debug("Message " + message + " generated response " + r);
|
log.debug("Message " + message + " generated response " + r);
|
||||||
}
|
}
|
||||||
sendMembershipHistogram.update(System.currentTimeMillis() - startTime);
|
sendMembershipHistogram.update(System.currentTimeMillis() - startTime);
|
||||||
}
|
}
|
||||||
@ -252,7 +251,7 @@ public abstract class AbstractActiveGossiper {
|
|||||||
*/
|
*/
|
||||||
protected LocalMember selectPartner(List<LocalMember> memberList) {
|
protected LocalMember selectPartner(List<LocalMember> memberList) {
|
||||||
LocalMember member = null;
|
LocalMember member = null;
|
||||||
if (memberList.size() > 0) {
|
if (!memberList.isEmpty()) {
|
||||||
int randomNeighborIndex = random.nextInt(memberList.size());
|
int randomNeighborIndex = random.nextInt(memberList.size());
|
||||||
member = memberList.get(randomNeighborIndex);
|
member = memberList.get(randomNeighborIndex);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,6 @@ package org.apache.gossip.manager;
|
|||||||
public interface Clock {
|
public interface Clock {
|
||||||
|
|
||||||
long currentTimeMillis();
|
long currentTimeMillis();
|
||||||
|
|
||||||
long nanoTime();
|
long nanoTime();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.gossip.model.PerNodeDataMessage;
|
import org.apache.gossip.model.PerNodeDataMessage;
|
||||||
import org.apache.gossip.model.SharedDataMessage;
|
import org.apache.gossip.model.SharedDataMessage;
|
||||||
|
|
||||||
|
@ -17,20 +17,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.manager;
|
package org.apache.gossip.manager;
|
||||||
|
|
||||||
import java.util.List;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends gossip traffic at different rates to other racks and data-centers.
|
* Sends gossip traffic at different rates to other racks and data-centers.
|
||||||
* This implementation controls the rate at which gossip traffic is shared.
|
* This implementation controls the rate at which gossip traffic is shared.
|
||||||
@ -38,18 +37,17 @@ import com.codahale.metrics.MetricRegistry;
|
|||||||
* in the rack than in the the datacenter. We can adjust the rate at which we send messages to each group.
|
* in the rack than in the the datacenter. We can adjust the rate at which we send messages to each group.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class DatacenterRackAwareActiveGossiper extends AbstractActiveGossiper {
|
public class DatacenterRackAwareActiveGossiper extends AbstractActiveGossiper {
|
||||||
|
|
||||||
public static final String DATACENTER = "datacenter";
|
public static final String DATACENTER = "datacenter";
|
||||||
public static final String RACK = "rack";
|
public static final String RACK = "rack";
|
||||||
|
private final BlockingQueue<Runnable> workQueue;
|
||||||
private int sameRackGossipIntervalMs = 100;
|
private int sameRackGossipIntervalMs = 100;
|
||||||
private int sameDcGossipIntervalMs = 500;
|
private int sameDcGossipIntervalMs = 500;
|
||||||
private int differentDatacenterGossipIntervalMs = 1000;
|
private int differentDatacenterGossipIntervalMs = 1000;
|
||||||
private int randomDeadMemberSendIntervalMs = 250;
|
private int randomDeadMemberSendIntervalMs = 250;
|
||||||
|
|
||||||
private ScheduledExecutorService scheduledExecutorService;
|
private ScheduledExecutorService scheduledExecutorService;
|
||||||
private final BlockingQueue<Runnable> workQueue;
|
|
||||||
private ThreadPoolExecutor threadService;
|
private ThreadPoolExecutor threadService;
|
||||||
|
|
||||||
public DatacenterRackAwareActiveGossiper(GossipManager gossipManager, GossipCore gossipCore,
|
public DatacenterRackAwareActiveGossiper(GossipManager gossipManager, GossipCore gossipCore,
|
||||||
@ -220,14 +218,14 @@ public class DatacenterRackAwareActiveGossiper extends AbstractActiveGossiper {
|
|||||||
try {
|
try {
|
||||||
scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
|
scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.debug("Issue during shutdown", e);
|
log.debug("Issue during shutdown", e);
|
||||||
}
|
}
|
||||||
sendShutdownMessage();
|
sendShutdownMessage();
|
||||||
threadService.shutdown();
|
threadService.shutdown();
|
||||||
try {
|
try {
|
||||||
threadService.awaitTermination(5, TimeUnit.SECONDS);
|
threadService.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.debug("Issue during shutdown", e);
|
log.debug("Issue during shutdown", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,13 @@ package org.apache.gossip.manager;
|
|||||||
import com.codahale.metrics.Gauge;
|
import com.codahale.metrics.Gauge;
|
||||||
import com.codahale.metrics.Meter;
|
import com.codahale.metrics.Meter;
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
import org.apache.gossip.Member;
|
import org.apache.gossip.Member;
|
||||||
import org.apache.gossip.RemoteMember;
|
import org.apache.gossip.RemoteMember;
|
||||||
@ -33,35 +40,20 @@ import org.apache.gossip.model.PerNodeDataMessage;
|
|||||||
import org.apache.gossip.model.Response;
|
import org.apache.gossip.model.Response;
|
||||||
import org.apache.gossip.model.SharedDataMessage;
|
import org.apache.gossip.model.SharedDataMessage;
|
||||||
import org.apache.gossip.udp.Trackable;
|
import org.apache.gossip.udp.Trackable;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class GossipCore implements GossipCoreConstants {
|
public class GossipCore implements GossipCoreConstants {
|
||||||
|
|
||||||
class LatchAndBase {
|
|
||||||
private final CountDownLatch latch;
|
|
||||||
private volatile Base base;
|
|
||||||
|
|
||||||
LatchAndBase(){
|
|
||||||
latch = new CountDownLatch(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
public static final Logger LOGGER = Logger.getLogger(GossipCore.class);
|
|
||||||
private final GossipManager gossipManager;
|
private final GossipManager gossipManager;
|
||||||
private ConcurrentHashMap<String, LatchAndBase> requests;
|
@Getter
|
||||||
private final ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> perNodeData;
|
private final ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> perNodeData;
|
||||||
|
@Getter
|
||||||
private final ConcurrentHashMap<String, SharedDataMessage> sharedData;
|
private final ConcurrentHashMap<String, SharedDataMessage> sharedData;
|
||||||
private final Meter messageSerdeException;
|
private final Meter messageSerdeException;
|
||||||
private final Meter transmissionException;
|
private final Meter transmissionException;
|
||||||
private final Meter transmissionSuccess;
|
private final Meter transmissionSuccess;
|
||||||
private final DataEventManager eventManager;
|
private final DataEventManager eventManager;
|
||||||
|
private ConcurrentHashMap<String, LatchAndBase> requests;
|
||||||
public GossipCore(GossipManager manager, MetricRegistry metrics){
|
public GossipCore(GossipManager manager, MetricRegistry metrics){
|
||||||
this.gossipManager = manager;
|
this.gossipManager = manager;
|
||||||
requests = new ConcurrentHashMap<>();
|
requests = new ConcurrentHashMap<>();
|
||||||
@ -75,7 +67,7 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
transmissionException = metrics.meter(MESSAGE_TRANSMISSION_EXCEPTION);
|
transmissionException = metrics.meter(MESSAGE_TRANSMISSION_EXCEPTION);
|
||||||
transmissionSuccess = metrics.meter(MESSAGE_TRANSMISSION_SUCCESS);
|
transmissionSuccess = metrics.meter(MESSAGE_TRANSMISSION_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public void addSharedData(SharedDataMessage message) {
|
public void addSharedData(SharedDataMessage message) {
|
||||||
while (true){
|
while (true){
|
||||||
@ -135,20 +127,12 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> getPerNodeData(){
|
|
||||||
return perNodeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<String, SharedDataMessage> getSharedData() {
|
|
||||||
return sharedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shutdown(){
|
public void shutdown(){
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receive(Base base) {
|
public void receive(Base base) {
|
||||||
if (!gossipManager.getMessageHandler().invoke(this, gossipManager, base)) {
|
if (!gossipManager.getMessageHandler().invoke(this, gossipManager, base)) {
|
||||||
LOGGER.warn("received message can not be handled");
|
log.warn("received message can not be handled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,10 +161,8 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Response send(Base message, URI uri){
|
public Response send(Base message, URI uri){
|
||||||
if (LOGGER.isDebugEnabled()){
|
log.debug("Sending " + message);
|
||||||
LOGGER.debug("Sending " + message);
|
log.debug("Current request queue " + requests);
|
||||||
LOGGER.debug("Current request queue " + requests);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Trackable t;
|
final Trackable t;
|
||||||
LatchAndBase latchAndBase = null;
|
LatchAndBase latchAndBase = null;
|
||||||
@ -195,7 +177,7 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
if (latchAndBase == null){
|
if (latchAndBase == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
boolean complete = latchAndBase.latch.await(1, TimeUnit.SECONDS);
|
boolean complete = latchAndBase.latch.await(1, TimeUnit.SECONDS);
|
||||||
if (complete){
|
if (complete){
|
||||||
@ -206,9 +188,7 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
if (latchAndBase != null){
|
|
||||||
requests.remove(t.getUuid() + "/" + t.getUriFrom());
|
requests.remove(t.getUuid() + "/" + t.getUriFrom());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +202,7 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
try {
|
try {
|
||||||
sendInternal(message, u);
|
sendInternal(message, u);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
LOGGER.debug("Send one way failed", ex);
|
log.debug("Send one way failed", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,12 +220,12 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void mergeLists(RemoteMember senderMember, List<Member> remoteList) {
|
public void mergeLists(RemoteMember senderMember, List<Member> remoteList) {
|
||||||
if (LOGGER.isDebugEnabled()){
|
if (log.isDebugEnabled()){
|
||||||
debugState(senderMember, remoteList);
|
debugState(senderMember, remoteList);
|
||||||
}
|
}
|
||||||
for (LocalMember i : gossipManager.getDeadMembers()) {
|
for (LocalMember i : gossipManager.getDeadMembers()) {
|
||||||
if (i.getId().equals(senderMember.getId())) {
|
if (i.getId().equals(senderMember.getId())) {
|
||||||
LOGGER.debug(gossipManager.getMyself() + " contacted by dead member " + senderMember.getUri());
|
log.debug(gossipManager.getMyself() + " contacted by dead member " + senderMember.getUri());
|
||||||
i.recordHeartbeat(senderMember.getHeartbeat());
|
i.recordHeartbeat(senderMember.getHeartbeat());
|
||||||
i.setHeartbeat(senderMember.getHeartbeat());
|
i.setHeartbeat(senderMember.getHeartbeat());
|
||||||
//TODO consider forcing an UP here
|
//TODO consider forcing an UP here
|
||||||
@ -275,14 +255,14 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOGGER.isDebugEnabled()){
|
if (log.isDebugEnabled()){
|
||||||
debugState(senderMember, remoteList);
|
debugState(senderMember, remoteList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void debugState(RemoteMember senderMember,
|
private void debugState(RemoteMember senderMember,
|
||||||
List<Member> remoteList){
|
List<Member> remoteList){
|
||||||
LOGGER.warn(
|
log.warn(
|
||||||
"-----------------------\n" +
|
"-----------------------\n" +
|
||||||
"Me " + gossipManager.getMyself() + "\n" +
|
"Me " + gossipManager.getMyself() + "\n" +
|
||||||
"Sender " + senderMember + "\n" +
|
"Sender " + senderMember + "\n" +
|
||||||
@ -313,7 +293,7 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerPerNodeDataSubscriber(UpdateNodeDataEventHandler handler){
|
void registerPerNodeDataSubscriber(UpdateNodeDataEventHandler handler){
|
||||||
eventManager.registerPerNodeDataSubscriber(handler);
|
eventManager.registerPerNodeDataSubscriber(handler);
|
||||||
}
|
}
|
||||||
@ -329,4 +309,14 @@ public class GossipCore implements GossipCoreConstants {
|
|||||||
void unregisterSharedDataSubscriber(UpdateSharedDataEventHandler handler){
|
void unregisterSharedDataSubscriber(UpdateSharedDataEventHandler handler){
|
||||||
eventManager.unregisterSharedDataSubscriber(handler);
|
eventManager.unregisterSharedDataSubscriber(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LatchAndBase {
|
||||||
|
private final CountDownLatch latch;
|
||||||
|
private volatile Base base;
|
||||||
|
|
||||||
|
LatchAndBase(){
|
||||||
|
latch = new CountDownLatch(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
package org.apache.gossip.manager;
|
package org.apache.gossip.manager;
|
||||||
|
|
||||||
public interface GossipCoreConstants {
|
public interface GossipCoreConstants {
|
||||||
String PER_NODE_DATA_SIZE = "gossip.core.pernodedata.size";
|
String PER_NODE_DATA_SIZE = "gossip.core.pernodedata.size";
|
||||||
String SHARED_DATA_SIZE = "gossip.core.shareddata.size";
|
String SHARED_DATA_SIZE = "gossip.core.shareddata.size";
|
||||||
String REQUEST_SIZE = "gossip.core.requests.size";
|
String REQUEST_SIZE = "gossip.core.requests.size";
|
||||||
String THREADPOOL_ACTIVE = "gossip.core.threadpool.active";
|
String THREADPOOL_ACTIVE = "gossip.core.threadpool.active";
|
||||||
|
@ -20,6 +20,22 @@ package org.apache.gossip.manager;
|
|||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentSkipListMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.GossipSettings;
|
import org.apache.gossip.GossipSettings;
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
import org.apache.gossip.Member;
|
import org.apache.gossip.Member;
|
||||||
@ -36,29 +52,14 @@ import org.apache.gossip.model.SharedDataMessage;
|
|||||||
import org.apache.gossip.protocol.ProtocolManager;
|
import org.apache.gossip.protocol.ProtocolManager;
|
||||||
import org.apache.gossip.transport.TransportManager;
|
import org.apache.gossip.transport.TransportManager;
|
||||||
import org.apache.gossip.utils.ReflectionUtils;
|
import org.apache.gossip.utils.ReflectionUtils;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import java.io.File;
|
@Slf4j
|
||||||
import java.net.URI;
|
public class GossipManager {
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public abstract class GossipManager {
|
|
||||||
|
|
||||||
public static final Logger LOGGER = Logger.getLogger(GossipManager.class);
|
|
||||||
|
|
||||||
// this mapper is used for ring and user-data persistence only. NOT messages.
|
// this mapper is used for ring and user-data persistence only. NOT messages.
|
||||||
public static final ObjectMapper metdataObjectMapper = new ObjectMapper() {
|
public static final ObjectMapper metdataObjectMapper = new ObjectMapper() {
|
||||||
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
{
|
{
|
||||||
enableDefaultTyping();
|
enableDefaultTyping();
|
||||||
@ -69,10 +70,6 @@ public abstract class GossipManager {
|
|||||||
private final LocalMember me;
|
private final LocalMember me;
|
||||||
private final GossipSettings settings;
|
private final GossipSettings settings;
|
||||||
private final AtomicBoolean gossipServiceRunning;
|
private final AtomicBoolean gossipServiceRunning;
|
||||||
|
|
||||||
private TransportManager transportManager;
|
|
||||||
private ProtocolManager protocolManager;
|
|
||||||
|
|
||||||
private final GossipCore gossipCore;
|
private final GossipCore gossipCore;
|
||||||
private final DataReaper dataReaper;
|
private final DataReaper dataReaper;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
@ -81,9 +78,10 @@ public abstract class GossipManager {
|
|||||||
private final RingStatePersister ringState;
|
private final RingStatePersister ringState;
|
||||||
private final UserDataPersister userDataState;
|
private final UserDataPersister userDataState;
|
||||||
private final GossipMemberStateRefresher memberStateRefresher;
|
private final GossipMemberStateRefresher memberStateRefresher;
|
||||||
|
|
||||||
private final MessageHandler messageHandler;
|
private final MessageHandler messageHandler;
|
||||||
private final LockManager lockManager;
|
private final LockManager lockManager;
|
||||||
|
private TransportManager transportManager;
|
||||||
|
private ProtocolManager protocolManager;
|
||||||
|
|
||||||
public GossipManager(String cluster,
|
public GossipManager(String cluster,
|
||||||
URI uri, String id, Map<String, String> properties, GossipSettings settings,
|
URI uri, String id, Map<String, String> properties, GossipSettings settings,
|
||||||
@ -122,6 +120,21 @@ public abstract class GossipManager {
|
|||||||
readSavedDataState();
|
readSavedDataState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static File buildRingStatePath(GossipManager manager) {
|
||||||
|
return new File(manager.getSettings().getPathToRingState(), "ringstate." + manager.getMyself().getClusterName() + "."
|
||||||
|
+ manager.getMyself().getId() + ".json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File buildSharedDataPath(GossipManager manager){
|
||||||
|
return new File(manager.getSettings().getPathToDataState(), "shareddata."
|
||||||
|
+ manager.getMyself().getClusterName() + "." + manager.getMyself().getId() + ".json");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File buildPerNodeDataPath(GossipManager manager) {
|
||||||
|
return new File(manager.getSettings().getPathToDataState(), "pernodedata."
|
||||||
|
+ manager.getMyself().getClusterName() + "." + manager.getMyself().getId() + ".json");
|
||||||
|
}
|
||||||
|
|
||||||
public MessageHandler getMessageHandler() {
|
public MessageHandler getMessageHandler() {
|
||||||
return messageHandler;
|
return messageHandler;
|
||||||
}
|
}
|
||||||
@ -144,7 +157,7 @@ public abstract class GossipManager {
|
|||||||
.filter(entry -> GossipState.DOWN.equals(entry.getValue()))
|
.filter(entry -> GossipState.DOWN.equals(entry.getValue()))
|
||||||
.map(Entry::getKey).collect(Collectors.toList()));
|
.map(Entry::getKey).collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return a read only list of members found in the UP state
|
* @return a read only list of members found in the UP state
|
||||||
@ -166,26 +179,26 @@ public abstract class GossipManager {
|
|||||||
* thread and start the receiver thread.
|
* thread and start the receiver thread.
|
||||||
*/
|
*/
|
||||||
public void init() {
|
public void init() {
|
||||||
|
|
||||||
// protocol manager and transport managers are specified in settings.
|
// protocol manager and transport managers are specified in settings.
|
||||||
// construct them here via reflection.
|
// construct them here via reflection.
|
||||||
|
|
||||||
protocolManager = ReflectionUtils.constructWithReflection(
|
protocolManager = ReflectionUtils.constructWithReflection(
|
||||||
settings.getProtocolManagerClass(),
|
settings.getProtocolManagerClass(),
|
||||||
new Class<?>[] { GossipSettings.class, String.class, MetricRegistry.class },
|
new Class<?>[] { GossipSettings.class, String.class, MetricRegistry.class },
|
||||||
new Object[] { settings, me.getId(), this.getRegistry() }
|
new Object[] { settings, me.getId(), this.getRegistry() }
|
||||||
);
|
);
|
||||||
|
|
||||||
transportManager = ReflectionUtils.constructWithReflection(
|
transportManager = ReflectionUtils.constructWithReflection(
|
||||||
settings.getTransportManagerClass(),
|
settings.getTransportManagerClass(),
|
||||||
new Class<?>[] { GossipManager.class, GossipCore.class},
|
new Class<?>[] { GossipManager.class, GossipCore.class},
|
||||||
new Object[] { this, gossipCore }
|
new Object[] { this, gossipCore }
|
||||||
);
|
);
|
||||||
|
|
||||||
// start processing gossip messages.
|
// start processing gossip messages.
|
||||||
transportManager.startEndpoint();
|
transportManager.startEndpoint();
|
||||||
transportManager.startActiveGossiper();
|
transportManager.startActiveGossiper();
|
||||||
|
|
||||||
dataReaper.init();
|
dataReaper.init();
|
||||||
if (settings.isPersistRingState()) {
|
if (settings.isPersistRingState()) {
|
||||||
scheduledServiced.scheduleAtFixedRate(ringState, 60, 60, TimeUnit.SECONDS);
|
scheduledServiced.scheduleAtFixedRate(ringState, 60, 60, TimeUnit.SECONDS);
|
||||||
@ -194,9 +207,9 @@ public abstract class GossipManager {
|
|||||||
scheduledServiced.scheduleAtFixedRate(userDataState, 60, 60, TimeUnit.SECONDS);
|
scheduledServiced.scheduleAtFixedRate(userDataState, 60, 60, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
memberStateRefresher.init();
|
memberStateRefresher.init();
|
||||||
LOGGER.debug("The GossipManager is started.");
|
log.debug("The GossipManager is started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readSavedRingState() {
|
private void readSavedRingState() {
|
||||||
if (settings.isPersistRingState()) {
|
if (settings.isPersistRingState()) {
|
||||||
for (LocalMember l : ringState.readFromDisk()) {
|
for (LocalMember l : ringState.readFromDisk()) {
|
||||||
@ -238,7 +251,7 @@ public abstract class GossipManager {
|
|||||||
try {
|
try {
|
||||||
scheduledServiced.awaitTermination(1, TimeUnit.SECONDS);
|
scheduledServiced.awaitTermination(1, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.error(e);
|
log.error("Error!", e);
|
||||||
}
|
}
|
||||||
scheduledServiced.shutdownNow();
|
scheduledServiced.shutdownNow();
|
||||||
}
|
}
|
||||||
@ -331,34 +344,19 @@ public abstract class GossipManager {
|
|||||||
public Clock getClock() {
|
public Clock getClock() {
|
||||||
return clock;
|
return clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetricRegistry getRegistry() {
|
|
||||||
return registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ProtocolManager getProtocolManager() {
|
|
||||||
return protocolManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TransportManager getTransportManager() {
|
|
||||||
return transportManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: consider making these path methods part of GossipSettings
|
// todo: consider making these path methods part of GossipSettings
|
||||||
|
|
||||||
public static File buildRingStatePath(GossipManager manager) {
|
public MetricRegistry getRegistry() {
|
||||||
return new File(manager.getSettings().getPathToRingState(), "ringstate." + manager.getMyself().getClusterName() + "."
|
return registry;
|
||||||
+ manager.getMyself().getId() + ".json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File buildSharedDataPath(GossipManager manager){
|
public ProtocolManager getProtocolManager() {
|
||||||
return new File(manager.getSettings().getPathToDataState(), "shareddata."
|
return protocolManager;
|
||||||
+ manager.getMyself().getClusterName() + "." + manager.getMyself().getId() + ".json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static File buildPerNodeDataPath(GossipManager manager) {
|
public TransportManager getTransportManager() {
|
||||||
return new File(manager.getSettings().getPathToDataState(), "pernodedata."
|
return transportManager;
|
||||||
+ manager.getMyself().getClusterName() + "." + manager.getMyself().getId() + ".json");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerPerNodeDataSubscriber(UpdateNodeDataEventHandler handler){
|
public void registerPerNodeDataSubscriber(UpdateNodeDataEventHandler handler){
|
||||||
|
@ -46,7 +46,7 @@ public class GossipManagerBuilder {
|
|||||||
private List<Member> gossipMembers;
|
private List<Member> gossipMembers;
|
||||||
private GossipListener listener;
|
private GossipListener listener;
|
||||||
private MetricRegistry registry;
|
private MetricRegistry registry;
|
||||||
private Map<String,String> properties;
|
private Map<String, String> properties;
|
||||||
private MessageHandler messageHandler;
|
private MessageHandler messageHandler;
|
||||||
|
|
||||||
private ManagerBuilder() {}
|
private ManagerBuilder() {}
|
||||||
@ -61,8 +61,8 @@ public class GossipManagerBuilder {
|
|||||||
this.cluster = cluster;
|
this.cluster = cluster;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManagerBuilder properties(Map<String,String> properties) {
|
public ManagerBuilder properties(Map<String, String> properties) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ public class GossipManagerBuilder {
|
|||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManagerBuilder startupSettings(StartupSettings startupSettings) {
|
public ManagerBuilder startupSettings(StartupSettings startupSettings) {
|
||||||
this.cluster = startupSettings.getCluster();
|
this.cluster = startupSettings.getCluster();
|
||||||
this.id = startupSettings.getId();
|
this.id = startupSettings.getId();
|
||||||
@ -95,13 +95,13 @@ public class GossipManagerBuilder {
|
|||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManagerBuilder registry(MetricRegistry registry) {
|
public ManagerBuilder registry(MetricRegistry registry) {
|
||||||
this.registry = registry;
|
this.registry = registry;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ManagerBuilder uri(URI uri){
|
public ManagerBuilder uri(URI uri) {
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -116,24 +116,32 @@ public class GossipManagerBuilder {
|
|||||||
checkArgument(cluster != null, "You must specify a cluster name");
|
checkArgument(cluster != null, "You must specify a cluster name");
|
||||||
checkArgument(settings != null, "You must specify gossip settings");
|
checkArgument(settings != null, "You must specify gossip settings");
|
||||||
checkArgument(uri != null, "You must specify a uri");
|
checkArgument(uri != null, "You must specify a uri");
|
||||||
if (registry == null){
|
if (registry == null) {
|
||||||
registry = new MetricRegistry();
|
registry = new MetricRegistry();
|
||||||
}
|
}
|
||||||
if (properties == null){
|
if (properties == null) {
|
||||||
properties = new HashMap<String,String>();
|
properties = new HashMap<String, String>();
|
||||||
}
|
}
|
||||||
if (listener == null){
|
if (listener == null) {
|
||||||
listener((a,b) -> {});
|
listener((a, b) -> {});
|
||||||
}
|
}
|
||||||
if (gossipMembers == null) {
|
if (gossipMembers == null) {
|
||||||
gossipMembers = new ArrayList<>();
|
gossipMembers = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageHandler == null) {
|
if (messageHandler == null) {
|
||||||
messageHandler = MessageHandlerFactory.defaultHandler();
|
messageHandler = MessageHandlerFactory.defaultHandler();
|
||||||
}
|
}
|
||||||
return new GossipManager(cluster, uri, id, properties, settings, gossipMembers, listener, registry, messageHandler) {} ;
|
return new GossipManager(
|
||||||
|
cluster,
|
||||||
|
uri,
|
||||||
|
id,
|
||||||
|
properties,
|
||||||
|
settings,
|
||||||
|
gossipMembers,
|
||||||
|
listener,
|
||||||
|
registry,
|
||||||
|
messageHandler) {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,22 +18,21 @@
|
|||||||
|
|
||||||
package org.apache.gossip.manager;
|
package org.apache.gossip.manager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.GossipSettings;
|
import org.apache.gossip.GossipSettings;
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
import org.apache.gossip.event.GossipListener;
|
import org.apache.gossip.event.GossipListener;
|
||||||
import org.apache.gossip.event.GossipState;
|
import org.apache.gossip.event.GossipState;
|
||||||
import org.apache.gossip.model.PerNodeDataMessage;
|
import org.apache.gossip.model.PerNodeDataMessage;
|
||||||
import org.apache.gossip.model.ShutdownMessage;
|
import org.apache.gossip.model.ShutdownMessage;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class GossipMemberStateRefresher {
|
public class GossipMemberStateRefresher {
|
||||||
public static final Logger LOGGER = Logger.getLogger(GossipMemberStateRefresher.class);
|
|
||||||
|
|
||||||
private final Map<LocalMember, GossipState> members;
|
private final Map<LocalMember, GossipState> members;
|
||||||
private final GossipSettings settings;
|
private final GossipSettings settings;
|
||||||
@ -66,7 +65,7 @@ public class GossipMemberStateRefresher {
|
|||||||
try {
|
try {
|
||||||
runOnce();
|
runOnce();
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
LOGGER.warn("scheduled state had exception", ex);
|
log.warn("scheduled state had exception", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,13 +143,13 @@ public class GossipMemberStateRefresher {
|
|||||||
try {
|
try {
|
||||||
scheduledExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
scheduledExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.debug("Issue during shutdown", e);
|
log.debug("Issue during shutdown", e);
|
||||||
}
|
}
|
||||||
listenerExecutor.shutdown();
|
listenerExecutor.shutdown();
|
||||||
try {
|
try {
|
||||||
listenerExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
listenerExecutor.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.debug("Issue during shutdown", e);
|
log.debug("Issue during shutdown", e);
|
||||||
}
|
}
|
||||||
listenerExecutor.shutdownNow();
|
listenerExecutor.shutdownNow();
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.manager;
|
package org.apache.gossip.manager;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -24,14 +25,12 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class RingStatePersister implements Runnable {
|
public class RingStatePersister implements Runnable {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(RingStatePersister.class);
|
|
||||||
private final File path;
|
private final File path;
|
||||||
// NOTE: this is a different instance than what gets used for message marshalling.
|
// NOTE: this is a different instance than what gets used for message marshalling.
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
@ -53,7 +52,7 @@ public class RingStatePersister implements Runnable {
|
|||||||
try (FileOutputStream fos = new FileOutputStream(path)){
|
try (FileOutputStream fos = new FileOutputStream(path)){
|
||||||
objectMapper.writeValue(fos, i);
|
objectMapper.writeValue(fos, i);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.debug(e);
|
log.error("Error!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +64,7 @@ public class RingStatePersister implements Runnable {
|
|||||||
try (FileInputStream fos = new FileInputStream(path)){
|
try (FileInputStream fos = new FileInputStream(path)){
|
||||||
return objectMapper.readValue(fos, ArrayList.class);
|
return objectMapper.readValue(fos, ArrayList.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.debug(e);
|
log.error("Error", e);
|
||||||
}
|
}
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -25,50 +25,60 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.LocalMember;
|
import org.apache.gossip.LocalMember;
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
|
||||||
/**
|
/** Base implementation gossips randomly to live nodes periodically gossips to dead ones */
|
||||||
* Base implementation gossips randomly to live nodes periodically gossips to dead ones
|
@Slf4j
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class SimpleActiveGossiper extends AbstractActiveGossiper {
|
public class SimpleActiveGossiper extends AbstractActiveGossiper {
|
||||||
|
|
||||||
private ScheduledExecutorService scheduledExecutorService;
|
|
||||||
private final BlockingQueue<Runnable> workQueue;
|
private final BlockingQueue<Runnable> workQueue;
|
||||||
|
private ScheduledExecutorService scheduledExecutorService;
|
||||||
private ThreadPoolExecutor threadService;
|
private ThreadPoolExecutor threadService;
|
||||||
|
|
||||||
public SimpleActiveGossiper(GossipManager gossipManager, GossipCore gossipCore,
|
public SimpleActiveGossiper(
|
||||||
MetricRegistry registry) {
|
GossipManager gossipManager, GossipCore gossipCore, MetricRegistry registry) {
|
||||||
super(gossipManager, gossipCore, registry);
|
super(gossipManager, gossipCore, registry);
|
||||||
scheduledExecutorService = Executors.newScheduledThreadPool(2);
|
scheduledExecutorService = Executors.newScheduledThreadPool(2);
|
||||||
workQueue = new ArrayBlockingQueue<Runnable>(1024);
|
workQueue = new ArrayBlockingQueue<Runnable>(1024);
|
||||||
threadService = new ThreadPoolExecutor(1, 30, 1, TimeUnit.SECONDS, workQueue,
|
threadService =
|
||||||
new ThreadPoolExecutor.DiscardOldestPolicy());
|
new ThreadPoolExecutor(
|
||||||
|
1, 30, 1, TimeUnit.SECONDS, workQueue, new ThreadPoolExecutor.DiscardOldestPolicy());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
super.init();
|
super.init();
|
||||||
scheduledExecutorService.scheduleAtFixedRate(() -> {
|
|
||||||
threadService.execute(() -> {
|
|
||||||
sendToALiveMember();
|
|
||||||
});
|
|
||||||
}, 0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
|
|
||||||
scheduledExecutorService.scheduleAtFixedRate(() -> {
|
|
||||||
sendToDeadMember();
|
|
||||||
}, 0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
|
|
||||||
scheduledExecutorService.scheduleAtFixedRate(
|
scheduledExecutorService.scheduleAtFixedRate(
|
||||||
() -> sendPerNodeData(gossipManager.getMyself(),
|
() -> {
|
||||||
selectPartner(gossipManager.getLiveMembers())),
|
threadService.execute(this::sendToALiveMember);
|
||||||
0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
|
},
|
||||||
|
0,
|
||||||
|
gossipManager.getSettings().getGossipInterval(),
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
scheduledExecutorService.scheduleAtFixedRate(
|
scheduledExecutorService.scheduleAtFixedRate(
|
||||||
() -> sendSharedData(gossipManager.getMyself(),
|
this::sendToDeadMember,
|
||||||
selectPartner(gossipManager.getLiveMembers())),
|
0,
|
||||||
0, gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
|
gossipManager.getSettings().getGossipInterval(),
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
|
scheduledExecutorService.scheduleAtFixedRate(
|
||||||
|
() ->
|
||||||
|
sendPerNodeData(
|
||||||
|
gossipManager.getMyself(), selectPartner(gossipManager.getLiveMembers())),
|
||||||
|
0,
|
||||||
|
gossipManager.getSettings().getGossipInterval(),
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
|
scheduledExecutorService.scheduleAtFixedRate(
|
||||||
|
() ->
|
||||||
|
sendSharedData(
|
||||||
|
gossipManager.getMyself(), selectPartner(gossipManager.getLiveMembers())),
|
||||||
|
0,
|
||||||
|
gossipManager.getSettings().getGossipInterval(),
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
super.shutdown();
|
super.shutdown();
|
||||||
@ -76,31 +86,29 @@ public class SimpleActiveGossiper extends AbstractActiveGossiper {
|
|||||||
try {
|
try {
|
||||||
scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
|
scheduledExecutorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.debug("Issue during shutdown", e);
|
log.debug("Issue during shutdown", e);
|
||||||
}
|
}
|
||||||
sendShutdownMessage();
|
sendShutdownMessage();
|
||||||
threadService.shutdown();
|
threadService.shutdown();
|
||||||
try {
|
try {
|
||||||
threadService.awaitTermination(5, TimeUnit.SECONDS);
|
threadService.awaitTermination(5, TimeUnit.SECONDS);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.debug("Issue during shutdown", e);
|
log.debug("Issue during shutdown", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendToALiveMember(){
|
protected void sendToALiveMember() {
|
||||||
LocalMember member = selectPartner(gossipManager.getLiveMembers());
|
LocalMember member = selectPartner(gossipManager.getLiveMembers());
|
||||||
sendMembershipList(gossipManager.getMyself(), member);
|
sendMembershipList(gossipManager.getMyself(), member);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendToDeadMember(){
|
protected void sendToDeadMember() {
|
||||||
LocalMember member = selectPartner(gossipManager.getDeadMembers());
|
LocalMember member = selectPartner(gossipManager.getDeadMembers());
|
||||||
sendMembershipList(gossipManager.getMyself(), member);
|
sendMembershipList(gossipManager.getMyself(), member);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** sends an optimistic shutdown message to several clusters nodes */
|
||||||
* sends an optimistic shutdown message to several clusters nodes
|
protected void sendShutdownMessage() {
|
||||||
*/
|
|
||||||
protected void sendShutdownMessage(){
|
|
||||||
List<LocalMember> l = gossipManager.getLiveMembers();
|
List<LocalMember> l = gossipManager.getLiveMembers();
|
||||||
int sendTo = l.size() < 3 ? 1 : l.size() / 2;
|
int sendTo = l.size() < 3 ? 1 : l.size() / 2;
|
||||||
for (int i = 0; i < sendTo; i++) {
|
for (int i = 0; i < sendTo; i++) {
|
||||||
|
@ -28,5 +28,4 @@ public class SystemClock implements Clock {
|
|||||||
public long nanoTime() {
|
public long nanoTime() {
|
||||||
return System.nanoTime();
|
return System.nanoTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.gossip.manager;
|
package org.apache.gossip.manager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -24,71 +24,70 @@ import java.io.IOException;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.java.Log;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.model.PerNodeDataMessage;
|
import org.apache.gossip.model.PerNodeDataMessage;
|
||||||
import org.apache.gossip.model.SharedDataMessage;
|
import org.apache.gossip.model.SharedDataMessage;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
public class UserDataPersister implements Runnable {
|
public class UserDataPersister implements Runnable {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(UserDataPersister.class);
|
private final GossipCore gossipCore;
|
||||||
private final GossipCore gossipCore;
|
|
||||||
|
|
||||||
private final File perNodePath;
|
private final File perNodePath;
|
||||||
private final File sharedPath;
|
private final File sharedPath;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
UserDataPersister(GossipCore gossipCore, File perNodePath, File sharedPath) {
|
UserDataPersister(GossipCore gossipCore, File perNodePath, File sharedPath) {
|
||||||
this.gossipCore = gossipCore;
|
this.gossipCore = gossipCore;
|
||||||
this.objectMapper = GossipManager.metdataObjectMapper;
|
this.objectMapper = GossipManager.metdataObjectMapper;
|
||||||
this.perNodePath = perNodePath;
|
this.perNodePath = perNodePath;
|
||||||
this.sharedPath = sharedPath;
|
this.sharedPath = sharedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> readPerNodeFromDisk(){
|
ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>> readPerNodeFromDisk() {
|
||||||
if (!perNodePath.exists()) {
|
if (!perNodePath.exists()) {
|
||||||
return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
|
return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
|
||||||
}
|
}
|
||||||
try (FileInputStream fos = new FileInputStream(perNodePath)){
|
try (FileInputStream fos = new FileInputStream(perNodePath)) {
|
||||||
return objectMapper.readValue(fos, ConcurrentHashMap.class);
|
return objectMapper.readValue(fos, ConcurrentHashMap.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.debug(e);
|
log.error("Error!", e);
|
||||||
}
|
}
|
||||||
return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
|
return new ConcurrentHashMap<String, ConcurrentHashMap<String, PerNodeDataMessage>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writePerNodeToDisk(){
|
void writePerNodeToDisk() {
|
||||||
try (FileOutputStream fos = new FileOutputStream(perNodePath)){
|
try (FileOutputStream fos = new FileOutputStream(perNodePath)) {
|
||||||
objectMapper.writeValue(fos, gossipCore.getPerNodeData());
|
objectMapper.writeValue(fos, gossipCore.getPerNodeData());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.warn(e);
|
log.error("Error!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeSharedToDisk(){
|
void writeSharedToDisk() {
|
||||||
try (FileOutputStream fos = new FileOutputStream(sharedPath)){
|
try (FileOutputStream fos = new FileOutputStream(sharedPath)) {
|
||||||
objectMapper.writeValue(fos, gossipCore.getSharedData());
|
objectMapper.writeValue(fos, gossipCore.getSharedData());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.warn(e);
|
log.error("Error!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ConcurrentHashMap<String, SharedDataMessage> readSharedDataFromDisk(){
|
ConcurrentHashMap<String, SharedDataMessage> readSharedDataFromDisk() {
|
||||||
if (!sharedPath.exists()) {
|
if (!sharedPath.exists()) {
|
||||||
return new ConcurrentHashMap<>();
|
return new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
try (FileInputStream fos = new FileInputStream(sharedPath)){
|
try (FileInputStream fos = new FileInputStream(sharedPath)) {
|
||||||
return objectMapper.readValue(fos, ConcurrentHashMap.class);
|
return objectMapper.readValue(fos, ConcurrentHashMap.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.debug(e);
|
log.error("Error!", e);
|
||||||
}
|
}
|
||||||
return new ConcurrentHashMap<String, SharedDataMessage>();
|
return new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Writes all pernode and shared data to disk */
|
||||||
* Writes all pernode and shared data to disk
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
writePerNodeToDisk();
|
writePerNodeToDisk();
|
||||||
|
@ -17,6 +17,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.manager.handlers;
|
package org.apache.gossip.manager.handlers;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.Member;
|
import org.apache.gossip.Member;
|
||||||
import org.apache.gossip.RemoteMember;
|
import org.apache.gossip.RemoteMember;
|
||||||
import org.apache.gossip.manager.GossipCore;
|
import org.apache.gossip.manager.GossipCore;
|
||||||
@ -26,11 +31,7 @@ import org.apache.gossip.udp.UdpActiveGossipMessage;
|
|||||||
import org.apache.gossip.udp.UdpActiveGossipOk;
|
import org.apache.gossip.udp.UdpActiveGossipOk;
|
||||||
import org.apache.gossip.udp.UdpNotAMemberFault;
|
import org.apache.gossip.udp.UdpNotAMemberFault;
|
||||||
|
|
||||||
import java.net.URI;
|
@Slf4j
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ActiveGossipMessageHandler implements MessageHandler {
|
public class ActiveGossipMessageHandler implements MessageHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,7 +50,7 @@ public class ActiveGossipMessageHandler implements MessageHandler {
|
|||||||
try {
|
try {
|
||||||
u = new URI(activeGossipMessage.getMembers().get(i).getUri());
|
u = new URI(activeGossipMessage.getMembers().get(i).getUri());
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
GossipCore.LOGGER.debug("Gossip message with faulty URI", e);
|
log.debug("Gossip message with faulty URI", e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RemoteMember member = new RemoteMember(
|
RemoteMember member = new RemoteMember(
|
||||||
@ -66,7 +67,7 @@ public class ActiveGossipMessageHandler implements MessageHandler {
|
|||||||
f.setException("Not a member of this cluster " + i);
|
f.setException("Not a member of this cluster " + i);
|
||||||
f.setUriFrom(activeGossipMessage.getUriFrom());
|
f.setUriFrom(activeGossipMessage.getUriFrom());
|
||||||
f.setUuid(activeGossipMessage.getUuid());
|
f.setUuid(activeGossipMessage.getUuid());
|
||||||
GossipCore.LOGGER.warn(f);
|
log.warn("Warn", f);
|
||||||
gossipCore.sendOneWay(f, member.getUri());
|
gossipCore.sendOneWay(f, member.getUri());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -29,4 +29,4 @@ public interface MessageHandler {
|
|||||||
* @return boolean indicating success.
|
* @return boolean indicating success.
|
||||||
*/
|
*/
|
||||||
boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base);
|
boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base);
|
||||||
}
|
}
|
||||||
|
@ -18,40 +18,35 @@
|
|||||||
|
|
||||||
package org.apache.gossip.manager.handlers;
|
package org.apache.gossip.manager.handlers;
|
||||||
|
|
||||||
import org.apache.gossip.manager.GossipCore;
|
|
||||||
import org.apache.gossip.manager.GossipManager;
|
|
||||||
import org.apache.gossip.model.*;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.gossip.model.*;
|
||||||
|
|
||||||
public class MessageHandlerFactory {
|
public class MessageHandlerFactory {
|
||||||
|
|
||||||
public static MessageHandler defaultHandler() {
|
public static MessageHandler defaultHandler() {
|
||||||
return concurrentHandler(
|
return concurrentHandler(
|
||||||
new TypedMessageHandler(Response.class, new ResponseHandler()),
|
new TypedMessageHandlerWrapper(Response.class, new ResponseHandler()),
|
||||||
new TypedMessageHandler(ShutdownMessage.class, new ShutdownMessageHandler()),
|
new TypedMessageHandlerWrapper(ShutdownMessage.class, new ShutdownMessageHandler()),
|
||||||
new TypedMessageHandler(PerNodeDataMessage.class, new PerNodeDataMessageHandler()),
|
new TypedMessageHandlerWrapper(PerNodeDataMessage.class, new PerNodeDataMessageHandler()),
|
||||||
new TypedMessageHandler(SharedDataMessage.class, new SharedDataMessageHandler()),
|
new TypedMessageHandlerWrapper(SharedDataMessage.class, new SharedDataMessageHandler()),
|
||||||
new TypedMessageHandler(ActiveGossipMessage.class, new ActiveGossipMessageHandler()),
|
new TypedMessageHandlerWrapper(ActiveGossipMessage.class, new ActiveGossipMessageHandler()),
|
||||||
new TypedMessageHandler(PerNodeDataBulkMessage.class, new PerNodeDataBulkMessageHandler()),
|
new TypedMessageHandlerWrapper(
|
||||||
new TypedMessageHandler(SharedDataBulkMessage.class, new SharedDataBulkMessageHandler())
|
PerNodeDataBulkMessage.class, new PerNodeDataBulkMessageHandler()),
|
||||||
);
|
new TypedMessageHandlerWrapper(
|
||||||
|
SharedDataBulkMessage.class, new SharedDataBulkMessageHandler()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MessageHandler concurrentHandler(MessageHandler... handlers) {
|
public static MessageHandler concurrentHandler(MessageHandler... handlers) {
|
||||||
if (handlers == null)
|
if (handlers == null) throw new NullPointerException("handlers cannot be null");
|
||||||
throw new NullPointerException("handlers cannot be null");
|
if (Arrays.stream(handlers).filter(Objects::nonNull).count() != handlers.length) {
|
||||||
if (Arrays.asList(handlers).stream().filter(i -> i != null).count() != handlers.length) {
|
|
||||||
throw new NullPointerException("found at least one null handler");
|
throw new NullPointerException("found at least one null handler");
|
||||||
}
|
}
|
||||||
return new MessageHandler() {
|
return (gossipCore, gossipManager, base) -> {
|
||||||
@Override public boolean invoke(GossipCore gossipCore, GossipManager gossipManager,
|
// return true if at least one of the component handlers return true.
|
||||||
Base base) {
|
return Stream.of(handlers).filter((mi) -> mi.invoke(gossipCore, gossipManager, base)).count()
|
||||||
// return true if at least one of the component handlers return true.
|
> 0;
|
||||||
return Arrays.asList(handlers).stream()
|
|
||||||
.filter((mi) -> mi.invoke(gossipCore, gossipManager, base)).count() > 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import org.apache.gossip.model.PerNodeDataMessage;
|
|||||||
import org.apache.gossip.udp.UdpPerNodeDataBulkMessage;
|
import org.apache.gossip.udp.UdpPerNodeDataBulkMessage;
|
||||||
|
|
||||||
public class PerNodeDataBulkMessageHandler implements MessageHandler {
|
public class PerNodeDataBulkMessageHandler implements MessageHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param gossipCore context.
|
* @param gossipCore context.
|
||||||
* @param gossipManager context.
|
* @param gossipManager context.
|
||||||
@ -34,8 +34,7 @@ public class PerNodeDataBulkMessageHandler implements MessageHandler {
|
|||||||
@Override
|
@Override
|
||||||
public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
|
public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
|
||||||
UdpPerNodeDataBulkMessage udpMessage = (UdpPerNodeDataBulkMessage) base;
|
UdpPerNodeDataBulkMessage udpMessage = (UdpPerNodeDataBulkMessage) base;
|
||||||
for (PerNodeDataMessage dataMsg: udpMessage.getMessages())
|
for (PerNodeDataMessage dataMsg : udpMessage.getMessages()) gossipCore.addPerNodeData(dataMsg);
|
||||||
gossipCore.addPerNodeData(dataMsg);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import org.apache.gossip.model.Base;
|
|||||||
import org.apache.gossip.udp.Trackable;
|
import org.apache.gossip.udp.Trackable;
|
||||||
|
|
||||||
public class ResponseHandler implements MessageHandler {
|
public class ResponseHandler implements MessageHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param gossipCore context.
|
* @param gossipCore context.
|
||||||
* @param gossipManager context.
|
* @param gossipManager context.
|
||||||
|
@ -23,8 +23,8 @@ import org.apache.gossip.model.Base;
|
|||||||
import org.apache.gossip.model.SharedDataMessage;
|
import org.apache.gossip.model.SharedDataMessage;
|
||||||
import org.apache.gossip.udp.UdpSharedDataBulkMessage;
|
import org.apache.gossip.udp.UdpSharedDataBulkMessage;
|
||||||
|
|
||||||
public class SharedDataBulkMessageHandler implements MessageHandler{
|
public class SharedDataBulkMessageHandler implements MessageHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param gossipCore context.
|
* @param gossipCore context.
|
||||||
* @param gossipManager context.
|
* @param gossipManager context.
|
||||||
@ -34,8 +34,7 @@ public class SharedDataBulkMessageHandler implements MessageHandler{
|
|||||||
@Override
|
@Override
|
||||||
public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
|
public boolean invoke(GossipCore gossipCore, GossipManager gossipManager, Base base) {
|
||||||
UdpSharedDataBulkMessage udpMessage = (UdpSharedDataBulkMessage) base;
|
UdpSharedDataBulkMessage udpMessage = (UdpSharedDataBulkMessage) base;
|
||||||
for (SharedDataMessage dataMsg: udpMessage.getMessages())
|
for (SharedDataMessage dataMsg : udpMessage.getMessages()) gossipCore.addSharedData(dataMsg);
|
||||||
gossipCore.addSharedData(dataMsg);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ import org.apache.gossip.manager.GossipManager;
|
|||||||
import org.apache.gossip.model.Base;
|
import org.apache.gossip.model.Base;
|
||||||
import org.apache.gossip.udp.UdpSharedDataMessage;
|
import org.apache.gossip.udp.UdpSharedDataMessage;
|
||||||
|
|
||||||
public class SharedDataMessageHandler implements MessageHandler{
|
public class SharedDataMessageHandler implements MessageHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param gossipCore context.
|
* @param gossipCore context.
|
||||||
* @param gossipManager context.
|
* @param gossipManager context.
|
||||||
|
@ -24,7 +24,7 @@ import org.apache.gossip.model.PerNodeDataMessage;
|
|||||||
import org.apache.gossip.model.ShutdownMessage;
|
import org.apache.gossip.model.ShutdownMessage;
|
||||||
|
|
||||||
public class ShutdownMessageHandler implements MessageHandler {
|
public class ShutdownMessageHandler implements MessageHandler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param gossipCore context.
|
* @param gossipCore context.
|
||||||
* @param gossipManager context.
|
* @param gossipManager context.
|
||||||
|
@ -21,11 +21,11 @@ import org.apache.gossip.manager.GossipCore;
|
|||||||
import org.apache.gossip.manager.GossipManager;
|
import org.apache.gossip.manager.GossipManager;
|
||||||
import org.apache.gossip.model.Base;
|
import org.apache.gossip.model.Base;
|
||||||
|
|
||||||
public class TypedMessageHandler implements MessageHandler {
|
public class TypedMessageHandlerWrapper implements MessageHandler {
|
||||||
final private Class<?> messageClass;
|
private final Class<?> messageClass;
|
||||||
final private MessageHandler messageHandler;
|
private final MessageHandler messageHandler;
|
||||||
|
|
||||||
public TypedMessageHandler(Class<?> messageClass, MessageHandler messageHandler) {
|
public TypedMessageHandlerWrapper(Class<?> messageClass, MessageHandler messageHandler) {
|
||||||
if (messageClass == null || messageHandler == null) {
|
if (messageClass == null || messageHandler == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
@ -23,10 +23,8 @@ import java.util.List;
|
|||||||
public class ActiveGossipMessage extends Base {
|
public class ActiveGossipMessage extends Base {
|
||||||
|
|
||||||
private List<Member> members = new ArrayList<>();
|
private List<Member> members = new ArrayList<>();
|
||||||
|
|
||||||
public ActiveGossipMessage(){
|
public ActiveGossipMessage() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Member> getMembers() {
|
public List<Member> getMembers() {
|
||||||
return members;
|
return members;
|
||||||
@ -35,5 +33,4 @@ public class ActiveGossipMessage extends Base {
|
|||||||
public void setMembers(List<Member> members) {
|
public void setMembers(List<Member> members) {
|
||||||
this.members = members;
|
this.members = members;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,4 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.model;
|
package org.apache.gossip.model;
|
||||||
|
|
||||||
public class ActiveGossipOk extends Response {
|
public class ActiveGossipOk extends Response {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -17,16 +17,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.model;
|
package org.apache.gossip.model;
|
||||||
|
|
||||||
import org.apache.gossip.udp.UdpActiveGossipMessage;
|
|
||||||
import org.apache.gossip.udp.UdpActiveGossipOk;
|
|
||||||
import org.apache.gossip.udp.UdpPerNodeDataBulkMessage;
|
|
||||||
import org.apache.gossip.udp.UdpNotAMemberFault;
|
|
||||||
import org.apache.gossip.udp.UdpSharedDataBulkMessage;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
import org.apache.gossip.udp.UdpActiveGossipMessage;
|
||||||
|
import org.apache.gossip.udp.UdpActiveGossipOk;
|
||||||
|
import org.apache.gossip.udp.UdpNotAMemberFault;
|
||||||
|
import org.apache.gossip.udp.UdpPerNodeDataBulkMessage;
|
||||||
|
import org.apache.gossip.udp.UdpSharedDataBulkMessage;
|
||||||
|
|
||||||
@JsonTypeInfo(
|
@JsonTypeInfo(
|
||||||
use = JsonTypeInfo.Id.CLASS,
|
use = JsonTypeInfo.Id.CLASS,
|
||||||
|
@ -21,7 +21,7 @@ public abstract class Fault extends Response {
|
|||||||
|
|
||||||
private String exception;
|
private String exception;
|
||||||
|
|
||||||
public Fault(){}
|
public Fault() {}
|
||||||
|
|
||||||
public String getException() {
|
public String getException() {
|
||||||
return exception;
|
return exception;
|
||||||
@ -35,6 +35,4 @@ public abstract class Fault extends Response {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "Fault [exception=" + exception + "]";
|
return "Fault [exception=" + exception + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,13 +25,11 @@ public class Member {
|
|||||||
private String uri;
|
private String uri;
|
||||||
private String id;
|
private String id;
|
||||||
private Long heartbeat;
|
private Long heartbeat;
|
||||||
private Map<String,String> properties;
|
private Map<String, String> properties;
|
||||||
|
|
||||||
public Member(){
|
public Member() {}
|
||||||
|
|
||||||
}
|
public Member(String cluster, String uri, String id, Long heartbeat) {
|
||||||
|
|
||||||
public Member(String cluster, String uri, String id, Long heartbeat){
|
|
||||||
this.cluster = cluster;
|
this.cluster = cluster;
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -80,8 +78,16 @@ public class Member {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Member [cluster=" + cluster + ", uri=" + uri + ", id=" + id + ", heartbeat="
|
return "Member [cluster="
|
||||||
+ heartbeat + ", properties=" + properties + "]";
|
+ cluster
|
||||||
|
+ ", uri="
|
||||||
|
+ uri
|
||||||
|
+ ", id="
|
||||||
|
+ id
|
||||||
|
+ ", heartbeat="
|
||||||
|
+ heartbeat
|
||||||
|
+ ", properties="
|
||||||
|
+ properties
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,4 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.model;
|
package org.apache.gossip.model;
|
||||||
|
|
||||||
public class Message extends Base {
|
public class Message extends Base {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -19,11 +19,9 @@ package org.apache.gossip.model;
|
|||||||
|
|
||||||
public class NotAMemberFault extends Fault {
|
public class NotAMemberFault extends Fault {
|
||||||
|
|
||||||
public NotAMemberFault(){
|
public NotAMemberFault() {}
|
||||||
|
|
||||||
}
|
public NotAMemberFault(String message) {
|
||||||
|
|
||||||
public NotAMemberFault(String message){
|
|
||||||
this.setException(message);
|
this.setException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,10 @@ public class PerNodeDataBulkMessage extends Base {
|
|||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override
|
||||||
return "GossipDataBulkMessage[" + messages.stream().map(Object::toString)
|
public String toString() {
|
||||||
.collect(Collectors.joining(",")) + "]";
|
return "GossipDataBulkMessage["
|
||||||
|
+ messages.stream().map(Object::toString).collect(Collectors.joining(","))
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,30 +31,39 @@ public class PerNodeDataMessage extends Base {
|
|||||||
public String getNodeId() {
|
public String getNodeId() {
|
||||||
return nodeId;
|
return nodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeId(String nodeId) {
|
public void setNodeId(String nodeId) {
|
||||||
this.nodeId = nodeId;
|
this.nodeId = nodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKey(String key) {
|
public void setKey(String key) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getPayload() {
|
public Object getPayload() {
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPayload(Object payload) {
|
public void setPayload(Object payload) {
|
||||||
this.payload = payload;
|
this.payload = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getTimestamp() {
|
public Long getTimestamp() {
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTimestamp(Long timestamp) {
|
public void setTimestamp(Long timestamp) {
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getExpireAt() {
|
public Long getExpireAt() {
|
||||||
return expireAt;
|
return expireAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExpireAt(Long expireAt) {
|
public void setExpireAt(Long expireAt) {
|
||||||
this.expireAt = expireAt;
|
this.expireAt = expireAt;
|
||||||
}
|
}
|
||||||
@ -69,11 +78,18 @@ public class PerNodeDataMessage extends Base {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "GossipDataMessage [nodeId=" + nodeId + ", key=" + key + ", payload=" + payload
|
return "GossipDataMessage [nodeId="
|
||||||
+ ", timestamp=" + timestamp + ", expireAt=" + expireAt
|
+ nodeId
|
||||||
+ ", replicable=" + replicable + "]";
|
+ ", key="
|
||||||
|
+ key
|
||||||
|
+ ", payload="
|
||||||
|
+ payload
|
||||||
|
+ ", timestamp="
|
||||||
|
+ timestamp
|
||||||
|
+ ", expireAt="
|
||||||
|
+ expireAt
|
||||||
|
+ ", replicable="
|
||||||
|
+ replicable
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,4 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.model;
|
package org.apache.gossip.model;
|
||||||
|
|
||||||
public abstract class Response extends Base {
|
public abstract class Response extends Base {}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -32,8 +32,10 @@ public class SharedDataBulkMessage extends Base {
|
|||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String toString() {
|
@Override
|
||||||
return "SharedGossipDataBulkMessage[" + messages.stream().map(Object::toString)
|
public String toString() {
|
||||||
.collect(Collectors.joining(",")) + "]";
|
return "SharedGossipDataBulkMessage["
|
||||||
|
+ messages.stream().map(Object::toString).collect(Collectors.joining(","))
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.model;
|
package org.apache.gossip.model;
|
||||||
|
|
||||||
import org.apache.gossip.replication.AllReplicable;
|
|
||||||
import org.apache.gossip.replication.Replicable;
|
import org.apache.gossip.replication.Replicable;
|
||||||
|
|
||||||
public class SharedDataMessage extends Base {
|
public class SharedDataMessage extends Base {
|
||||||
|
@ -22,10 +22,8 @@ public class ShutdownMessage extends Message {
|
|||||||
public static final String PER_NODE_KEY = "gossipcore.shutdowmessage";
|
public static final String PER_NODE_KEY = "gossipcore.shutdowmessage";
|
||||||
private long shutdownAtNanos;
|
private long shutdownAtNanos;
|
||||||
private String nodeId;
|
private String nodeId;
|
||||||
|
|
||||||
public ShutdownMessage(){
|
public ShutdownMessage() {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNodeId() {
|
public String getNodeId() {
|
||||||
return nodeId;
|
return nodeId;
|
||||||
@ -47,5 +45,4 @@ public class ShutdownMessage extends Message {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "ShutdownMessage [shutdownAtNanos=" + shutdownAtNanos + ", nodeId=" + nodeId + "]";
|
return "ShutdownMessage [shutdownAtNanos=" + shutdownAtNanos + ", nodeId=" + nodeId + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,20 +17,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.model;
|
package org.apache.gossip.model;
|
||||||
|
|
||||||
public class SignedPayload extends Base{
|
public class SignedPayload extends Base {
|
||||||
private byte [] data;
|
private byte[] data;
|
||||||
private byte [] signature;
|
private byte[] signature;
|
||||||
|
|
||||||
public byte[] getData() {
|
public byte[] getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(byte[] data) {
|
public void setData(byte[] data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getSignature() {
|
public byte[] getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSignature(byte[] signature) {
|
public void setSignature(byte[] signature) {
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.protocol;
|
package org.apache.gossip.protocol;
|
||||||
|
|
||||||
import org.apache.gossip.model.Base;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.apache.gossip.model.Base;
|
||||||
|
|
||||||
/** interface for managing message marshaling. */
|
/** interface for managing message marshaling. */
|
||||||
public interface ProtocolManager {
|
public interface ProtocolManager {
|
||||||
|
@ -28,7 +28,7 @@ import org.apache.gossip.model.Base;
|
|||||||
* @see Replicable
|
* @see Replicable
|
||||||
*/
|
*/
|
||||||
public class AllReplicable<T extends Base> implements Replicable<T> {
|
public class AllReplicable<T extends Base> implements Replicable<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldReplicate(LocalMember me, LocalMember destination, T message) {
|
public boolean shouldReplicate(LocalMember me, LocalMember destination, T message) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -30,9 +30,9 @@ import java.util.List;
|
|||||||
* @see Replicable
|
* @see Replicable
|
||||||
*/
|
*/
|
||||||
public class BlackListReplicable<T extends Base> implements Replicable<T> {
|
public class BlackListReplicable<T extends Base> implements Replicable<T> {
|
||||||
|
|
||||||
private final List<LocalMember> blackListMembers;
|
private final List<LocalMember> blackListMembers;
|
||||||
|
|
||||||
public BlackListReplicable(List<LocalMember> blackListMembers) {
|
public BlackListReplicable(List<LocalMember> blackListMembers) {
|
||||||
if (blackListMembers == null) {
|
if (blackListMembers == null) {
|
||||||
this.blackListMembers = new ArrayList<>();
|
this.blackListMembers = new ArrayList<>();
|
||||||
|
@ -28,19 +28,21 @@ import org.apache.gossip.model.Base;
|
|||||||
* @see Replicable
|
* @see Replicable
|
||||||
*/
|
*/
|
||||||
public class DataCenterReplicable<T extends Base> implements Replicable<T> {
|
public class DataCenterReplicable<T extends Base> implements Replicable<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldReplicate(LocalMember me, LocalMember destination, T message) {
|
public boolean shouldReplicate(LocalMember me, LocalMember destination, T message) {
|
||||||
if (!me.getProperties().containsKey(DatacenterRackAwareActiveGossiper.DATACENTER)) {
|
if (!me.getProperties().containsKey(DatacenterRackAwareActiveGossiper.DATACENTER)) {
|
||||||
// replicate to others if I am not belong to any data center
|
// replicate to others if I am not belong to any data center
|
||||||
return true;
|
return true;
|
||||||
} else if (!destination.getProperties()
|
} else if (!destination
|
||||||
.containsKey(DatacenterRackAwareActiveGossiper.DATACENTER)) {
|
.getProperties()
|
||||||
|
.containsKey(DatacenterRackAwareActiveGossiper.DATACENTER)) {
|
||||||
// Do not replicate if the destination data center is not defined
|
// Do not replicate if the destination data center is not defined
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return me.getProperties().get(DatacenterRackAwareActiveGossiper.DATACENTER)
|
return me.getProperties()
|
||||||
.equals(destination.getProperties().get(DatacenterRackAwareActiveGossiper.DATACENTER));
|
.get(DatacenterRackAwareActiveGossiper.DATACENTER)
|
||||||
|
.equals(destination.getProperties().get(DatacenterRackAwareActiveGossiper.DATACENTER));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import org.apache.gossip.model.Base;
|
|||||||
* @see Replicable
|
* @see Replicable
|
||||||
*/
|
*/
|
||||||
public class NotReplicable<T extends Base> implements Replicable<T> {
|
public class NotReplicable<T extends Base> implements Replicable<T> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldReplicate(LocalMember me, LocalMember destination, T message) {
|
public boolean shouldReplicate(LocalMember me, LocalMember destination, T message) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -21,14 +21,15 @@ import org.apache.gossip.LocalMember;
|
|||||||
import org.apache.gossip.model.Base;
|
import org.apache.gossip.model.Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface is used to determine whether a data item needs to be replicated to
|
* This interface is used to determine whether a data item needs to be replicated to another gossip
|
||||||
* another gossip member.
|
* member.
|
||||||
*
|
*
|
||||||
* @param <T> A subtype of the class {@link org.apache.gossip.model.Base} which uses this interface
|
* @param <T> A subtype of the class {@link org.apache.gossip.model.Base} which uses this interface
|
||||||
*/
|
*/
|
||||||
public interface Replicable<T extends Base> {
|
public interface Replicable<T extends Base> {
|
||||||
/**
|
/**
|
||||||
* Test for a given data item needs to be replicated.
|
* Test for a given data item needs to be replicated.
|
||||||
|
*
|
||||||
* @param me node that the data item is going to transmit from.
|
* @param me node that the data item is going to transmit from.
|
||||||
* @param destination target node to replicate.
|
* @param destination target node to replicate.
|
||||||
* @param message this parameter is currently ignored
|
* @param message this parameter is currently ignored
|
||||||
|
@ -17,11 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.replication;
|
package org.apache.gossip.replication;
|
||||||
|
|
||||||
import org.apache.gossip.LocalMember;
|
|
||||||
import org.apache.gossip.model.Base;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.apache.gossip.LocalMember;
|
||||||
|
import org.apache.gossip.model.Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replicable implementation which replicates data to given set of nodes.
|
* Replicable implementation which replicates data to given set of nodes.
|
||||||
|
@ -30,8 +30,8 @@ import java.security.SecureRandom;
|
|||||||
|
|
||||||
public class KeyTool {
|
public class KeyTool {
|
||||||
|
|
||||||
public static void generatePubandPrivateKeyFiles(String path, String id)
|
public static void generatePubandPrivateKeyFiles(String path, String id)
|
||||||
throws NoSuchAlgorithmException, NoSuchProviderException, IOException{
|
throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
|
||||||
SecureRandom r = new SecureRandom();
|
SecureRandom r = new SecureRandom();
|
||||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
|
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
|
||||||
keyGen.initialize(1024, r);
|
keyGen.initialize(1024, r);
|
||||||
@ -49,9 +49,9 @@ public class KeyTool {
|
|||||||
sigfos.close();
|
sigfos.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main (String [] args) throws
|
public static void main(String[] args)
|
||||||
NoSuchAlgorithmException, NoSuchProviderException, IOException{
|
throws NoSuchAlgorithmException, NoSuchProviderException, IOException {
|
||||||
generatePubandPrivateKeyFiles(args[0], args[1]);
|
generatePubandPrivateKeyFiles(args[0], args[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,27 +18,25 @@
|
|||||||
package org.apache.gossip.transport;
|
package org.apache.gossip.transport;
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry;
|
import com.codahale.metrics.MetricRegistry;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.gossip.manager.AbstractActiveGossiper;
|
import org.apache.gossip.manager.AbstractActiveGossiper;
|
||||||
import org.apache.gossip.manager.GossipCore;
|
import org.apache.gossip.manager.GossipCore;
|
||||||
import org.apache.gossip.manager.GossipManager;
|
import org.apache.gossip.manager.GossipManager;
|
||||||
import org.apache.gossip.utils.ReflectionUtils;
|
import org.apache.gossip.utils.ReflectionUtils;
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage the protcol threads (active and passive gossipers).
|
* Manage the protcol threads (active and passive gossipers).
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public abstract class AbstractTransportManager implements TransportManager {
|
public abstract class AbstractTransportManager implements TransportManager {
|
||||||
|
|
||||||
public static final Logger LOGGER = Logger.getLogger(AbstractTransportManager.class);
|
|
||||||
|
|
||||||
private final ExecutorService gossipThreadExecutor;
|
|
||||||
private final AbstractActiveGossiper activeGossipThread;
|
|
||||||
protected final GossipManager gossipManager;
|
protected final GossipManager gossipManager;
|
||||||
protected final GossipCore gossipCore;
|
protected final GossipCore gossipCore;
|
||||||
|
private final ExecutorService gossipThreadExecutor;
|
||||||
|
private final AbstractActiveGossiper activeGossipThread;
|
||||||
|
|
||||||
public AbstractTransportManager(GossipManager gossipManager, GossipCore gossipCore) {
|
public AbstractTransportManager(GossipManager gossipManager, GossipCore gossipCore) {
|
||||||
this.gossipManager = gossipManager;
|
this.gossipManager = gossipManager;
|
||||||
@ -65,10 +63,10 @@ public abstract class AbstractTransportManager implements TransportManager {
|
|||||||
boolean result = gossipThreadExecutor.awaitTermination(10, TimeUnit.MILLISECONDS);
|
boolean result = gossipThreadExecutor.awaitTermination(10, TimeUnit.MILLISECONDS);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
// common when blocking patterns are used to read data from a socket.
|
// common when blocking patterns are used to read data from a socket.
|
||||||
LOGGER.warn("executor shutdown timed out");
|
log.warn("executor shutdown timed out");
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOGGER.error(e);
|
log.error("Error!", e);
|
||||||
}
|
}
|
||||||
gossipThreadExecutor.shutdownNow();
|
gossipThreadExecutor.shutdownNow();
|
||||||
}
|
}
|
||||||
|
@ -22,19 +22,25 @@ import java.net.URI;
|
|||||||
|
|
||||||
/** interface for manager that sends and receives messages that have already been serialized. */
|
/** interface for manager that sends and receives messages that have already been serialized. */
|
||||||
public interface TransportManager {
|
public interface TransportManager {
|
||||||
|
|
||||||
/** starts the active gossip thread responsible for reaching out to remote nodes. Not related to `startEndpoint()` */
|
/**
|
||||||
|
* starts the active gossip thread responsible for reaching out to remote nodes. Not related to
|
||||||
|
* `startEndpoint()`
|
||||||
|
*/
|
||||||
void startActiveGossiper();
|
void startActiveGossiper();
|
||||||
|
|
||||||
/** starts the passive gossip thread that receives messages from remote nodes. Not related to `startActiveGossiper()` */
|
/**
|
||||||
|
* starts the passive gossip thread that receives messages from remote nodes. Not related to
|
||||||
|
* `startActiveGossiper()`
|
||||||
|
*/
|
||||||
void startEndpoint();
|
void startEndpoint();
|
||||||
|
|
||||||
/** attempts to shutdown all threads. */
|
/** attempts to shutdown all threads. */
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
/** sends a payload to an endpoint. */
|
/** sends a payload to an endpoint. */
|
||||||
void send(URI endpoint, byte[] buf) throws IOException;
|
void send(URI endpoint, byte[] buf) throws IOException;
|
||||||
|
|
||||||
/** gets the next payload being sent to this node */
|
/** gets the next payload being sent to this node */
|
||||||
byte[] read() throws IOException;
|
byte[] read() throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,10 @@ package org.apache.gossip.udp;
|
|||||||
public interface Trackable {
|
public interface Trackable {
|
||||||
|
|
||||||
String getUriFrom();
|
String getUriFrom();
|
||||||
|
|
||||||
void setUriFrom(String uriFrom);
|
void setUriFrom(String uriFrom);
|
||||||
|
|
||||||
String getUuid();
|
String getUuid();
|
||||||
|
|
||||||
void setUuid(String uuid);
|
void setUuid(String uuid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,27 +23,31 @@ public class UdpActiveGossipMessage extends ActiveGossipMessage implements Track
|
|||||||
|
|
||||||
private String uriFrom;
|
private String uriFrom;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
public String getUriFrom() {
|
public String getUriFrom() {
|
||||||
return uriFrom;
|
return uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUriFrom(String uriFrom) {
|
public void setUriFrom(String uriFrom) {
|
||||||
this.uriFrom = uriFrom;
|
this.uriFrom = uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
public void setUuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "UdpActiveGossipMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + ", getMembers()="
|
return "UdpActiveGossipMessage [uriFrom="
|
||||||
+ getMembers() + "]";
|
+ uriFrom
|
||||||
|
+ ", uuid="
|
||||||
|
+ uuid
|
||||||
|
+ ", getMembers()="
|
||||||
|
+ getMembers()
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,24 +21,22 @@ import org.apache.gossip.model.ActiveGossipOk;
|
|||||||
|
|
||||||
public class UdpActiveGossipOk extends ActiveGossipOk implements Trackable {
|
public class UdpActiveGossipOk extends ActiveGossipOk implements Trackable {
|
||||||
|
|
||||||
|
|
||||||
private String uriFrom;
|
private String uriFrom;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
public String getUriFrom() {
|
public String getUriFrom() {
|
||||||
return uriFrom;
|
return uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUriFrom(String uriFrom) {
|
public void setUriFrom(String uriFrom) {
|
||||||
this.uriFrom = uriFrom;
|
this.uriFrom = uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
public void setUuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,28 +19,25 @@ package org.apache.gossip.udp;
|
|||||||
|
|
||||||
import org.apache.gossip.model.NotAMemberFault;
|
import org.apache.gossip.model.NotAMemberFault;
|
||||||
|
|
||||||
public class UdpNotAMemberFault extends NotAMemberFault implements Trackable{
|
public class UdpNotAMemberFault extends NotAMemberFault implements Trackable {
|
||||||
|
|
||||||
public UdpNotAMemberFault(){
|
|
||||||
|
|
||||||
}
|
|
||||||
private String uriFrom;
|
private String uriFrom;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
public UdpNotAMemberFault() {}
|
||||||
|
|
||||||
public String getUriFrom() {
|
public String getUriFrom() {
|
||||||
return uriFrom;
|
return uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUriFrom(String uriFrom) {
|
public void setUriFrom(String uriFrom) {
|
||||||
this.uriFrom = uriFrom;
|
this.uriFrom = uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
public void setUuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,27 +23,31 @@ public class UdpPerNodeDataBulkMessage extends PerNodeDataBulkMessage implements
|
|||||||
|
|
||||||
private String uriFrom;
|
private String uriFrom;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
public String getUriFrom() {
|
public String getUriFrom() {
|
||||||
return uriFrom;
|
return uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUriFrom(String uriFrom) {
|
public void setUriFrom(String uriFrom) {
|
||||||
this.uriFrom = uriFrom;
|
this.uriFrom = uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
public void setUuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "UdpGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid
|
return "UdpGossipDataMessage [uriFrom="
|
||||||
+ ", messages=[" + super.toString() + "] ]";
|
+ uriFrom
|
||||||
|
+ ", uuid="
|
||||||
|
+ uuid
|
||||||
|
+ ", messages=["
|
||||||
|
+ super.toString()
|
||||||
|
+ "] ]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,27 +23,31 @@ public class UdpPerNodeDataMessage extends PerNodeDataMessage implements Trackab
|
|||||||
|
|
||||||
private String uriFrom;
|
private String uriFrom;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
public String getUriFrom() {
|
public String getUriFrom() {
|
||||||
return uriFrom;
|
return uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUriFrom(String uriFrom) {
|
public void setUriFrom(String uriFrom) {
|
||||||
this.uriFrom = uriFrom;
|
this.uriFrom = uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
public void setUuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "UdpGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid
|
return "UdpGossipDataMessage [uriFrom="
|
||||||
+ ", getReplicable()=" + getReplicable() + "]";
|
+ uriFrom
|
||||||
|
+ ", uuid="
|
||||||
|
+ uuid
|
||||||
|
+ ", getReplicable()="
|
||||||
|
+ getReplicable()
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,27 +23,32 @@ public class UdpSharedDataBulkMessage extends SharedDataBulkMessage implements T
|
|||||||
|
|
||||||
private String uriFrom;
|
private String uriFrom;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
public String getUriFrom() {
|
public String getUriFrom() {
|
||||||
return uriFrom;
|
return uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUriFrom(String uriFrom) {
|
public void setUriFrom(String uriFrom) {
|
||||||
this.uriFrom = uriFrom;
|
this.uriFrom = uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
public void setUuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "UdpSharedGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + ", getNodeId()="
|
return "UdpSharedGossipDataMessage [uriFrom="
|
||||||
+ ", messages=[" + super.toString() + "] ]";
|
+ uriFrom
|
||||||
|
+ ", uuid="
|
||||||
|
+ uuid
|
||||||
|
+ ", getNodeId()="
|
||||||
|
+ ", messages=["
|
||||||
|
+ super.toString()
|
||||||
|
+ "] ]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,29 +23,41 @@ public class UdpSharedDataMessage extends SharedDataMessage implements Trackable
|
|||||||
|
|
||||||
private String uriFrom;
|
private String uriFrom;
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
public String getUriFrom() {
|
public String getUriFrom() {
|
||||||
return uriFrom;
|
return uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUriFrom(String uriFrom) {
|
public void setUriFrom(String uriFrom) {
|
||||||
this.uriFrom = uriFrom;
|
this.uriFrom = uriFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUuid(String uuid) {
|
public void setUuid(String uuid) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "UdpSharedGossipDataMessage [uriFrom=" + uriFrom + ", uuid=" + uuid + ", getNodeId()="
|
return "UdpSharedGossipDataMessage [uriFrom="
|
||||||
+ getNodeId() + ", getKey()=" + getKey() + ", getPayload()=" + getPayload()
|
+ uriFrom
|
||||||
+ ", getTimestamp()=" + getTimestamp() + ", getExpireAt()=" + getExpireAt()
|
+ ", uuid="
|
||||||
+ ", getReplicable()=" + getReplicable() + "]";
|
+ uuid
|
||||||
|
+ ", getNodeId()="
|
||||||
|
+ getNodeId()
|
||||||
|
+ ", getKey()="
|
||||||
|
+ getKey()
|
||||||
|
+ ", getPayload()="
|
||||||
|
+ getPayload()
|
||||||
|
+ ", getTimestamp()="
|
||||||
|
+ getTimestamp()
|
||||||
|
+ ", getExpireAt()="
|
||||||
|
+ getExpireAt()
|
||||||
|
+ ", getReplicable()="
|
||||||
|
+ getReplicable()
|
||||||
|
+ "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,9 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
public class ReflectionUtils {
|
public class ReflectionUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a thing. This method essentially makes code more readable by handing the various exception
|
* Create an instance of a thing. This method essentially makes code more readable by handing the
|
||||||
* trapping.
|
* various exception trapping.
|
||||||
|
*
|
||||||
* @param className
|
* @param className
|
||||||
* @param constructorTypes
|
* @param constructorTypes
|
||||||
* @param constructorArgs
|
* @param constructorArgs
|
||||||
@ -32,20 +33,23 @@ public class ReflectionUtils {
|
|||||||
* @return constructed instance of a thing.
|
* @return constructed instance of a thing.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> T constructWithReflection(String className, Class<?>[] constructorTypes, Object[] constructorArgs) {
|
public static <T> T constructWithReflection(
|
||||||
|
String className, Class<?>[] constructorTypes, Object[] constructorArgs) {
|
||||||
try {
|
try {
|
||||||
Constructor<?> c = Class.forName(className).getConstructor(constructorTypes);
|
Constructor<?> c = Class.forName(className).getConstructor(constructorTypes);
|
||||||
c.setAccessible(true);
|
c.setAccessible(true);
|
||||||
return (T) c.newInstance(constructorArgs);
|
return (T) c.newInstance(constructorArgs);
|
||||||
} catch (InvocationTargetException e) {
|
} catch (InvocationTargetException e) {
|
||||||
// catch ITE and throw the target if it is a RTE.
|
// catch ITE and throw the target if it is a RTE.
|
||||||
if (e.getTargetException() != null && RuntimeException.class.isAssignableFrom(e.getTargetException().getClass())) {
|
if (e.getTargetException() != null
|
||||||
|
&& RuntimeException.class.isAssignableFrom(e.getTargetException().getClass())) {
|
||||||
throw (RuntimeException) e.getTargetException();
|
throw (RuntimeException) e.getTargetException();
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
} catch (ReflectiveOperationException others) {
|
} catch (ReflectiveOperationException others) {
|
||||||
// Note: No class in the above list should be a descendent of RuntimeException. Otherwise, we're just wrapping
|
// Note: No class in the above list should be a descendent of RuntimeException. Otherwise,
|
||||||
|
// we're just wrapping
|
||||||
// and making stack traces confusing.
|
// and making stack traces confusing.
|
||||||
throw new RuntimeException(others);
|
throw new RuntimeException(others);
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,9 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
log4j.rootLogger=INFO,stdout
|
log4j.rootLogger=INFO,stdout
|
||||||
|
|
||||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||||
log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
|
log4j.appender.stdout.layout.ConversionPattern=%5p %d{HH:mm:ss,SSS} %m%n
|
||||||
|
|
||||||
log4j.logger.io.teknek=DEBUG
|
log4j.logger.io.teknek=DEBUG
|
||||||
log4j.logger.com.google.code.gossip=INFO
|
log4j.logger.com.google.code.gossip=INFO
|
||||||
|
@ -31,14 +31,14 @@ import org.junit.Before;
|
|||||||
|
|
||||||
public abstract class AbstractIntegrationBase {
|
public abstract class AbstractIntegrationBase {
|
||||||
|
|
||||||
List <GossipManager> nodes = new ArrayList<>();
|
List<GossipManager> nodes = new ArrayList<>();
|
||||||
|
|
||||||
public void register(GossipManager manager){
|
public void register(GossipManager manager) {
|
||||||
nodes.add(manager);
|
nodes.add(manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateStandardNodes(final int memberCount) throws URISyntaxException {
|
public void generateStandardNodes(final int memberCount) throws URISyntaxException {
|
||||||
if(nodes.size() > 0){
|
if (nodes.size() > 0) {
|
||||||
after();
|
after();
|
||||||
nodes.clear();
|
nodes.clear();
|
||||||
}
|
}
|
||||||
@ -55,24 +55,30 @@ public abstract class AbstractIntegrationBase {
|
|||||||
|
|
||||||
for (int i = 1; i < memberCount + 1; ++i) {
|
for (int i = 1; i < memberCount + 1; ++i) {
|
||||||
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
|
URI uri = new URI("udp://" + "127.0.0.1" + ":" + (50000 + i));
|
||||||
GossipManager gossipService = GossipManagerBuilder.newBuilder().cluster(cluster).uri(uri)
|
GossipManager gossipService =
|
||||||
.id(i + "").gossipMembers(startupMembers).gossipSettings(settings).build();
|
GossipManagerBuilder.newBuilder()
|
||||||
|
.cluster(cluster)
|
||||||
|
.uri(uri)
|
||||||
|
.id(i + "")
|
||||||
|
.gossipMembers(startupMembers)
|
||||||
|
.gossipSettings(settings)
|
||||||
|
.build();
|
||||||
gossipService.init();
|
gossipService.init();
|
||||||
register(gossipService);
|
register(gossipService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void before(){
|
public void before() {
|
||||||
nodes = new ArrayList<>();
|
nodes = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void after(){
|
public void after() {
|
||||||
for (GossipManager node: nodes){
|
for (GossipManager node : nodes) {
|
||||||
if (node !=null){
|
if (node != null) {
|
||||||
node.shutdown();
|
node.shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,21 +20,31 @@ package org.apache.gossip;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.platform.runner.JUnitPlatform;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
@RunWith(JUnitPlatform.class)
|
|
||||||
public class MemberTest {
|
public class MemberTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHashCodeFromGossip40() throws URISyntaxException {
|
public void testHashCodeFromGossip40() throws URISyntaxException {
|
||||||
Assert.assertNotEquals(
|
Assertions.assertNotEquals(new LocalMember(
|
||||||
new LocalMember("mycluster", new URI("udp://4.4.4.4:1000"), "myid", 1, new HashMap<String,String>(), 10, 5, "exponential")
|
"mycluster",
|
||||||
.hashCode(),
|
new URI("udp://4.4.4.4:1000"),
|
||||||
new LocalMember("mycluster", new URI("udp://4.4.4.5:1005"), "yourid", 11, new HashMap<String,String>(), 11, 6, "exponential")
|
"myid",
|
||||||
.hashCode());
|
1,
|
||||||
|
new HashMap<>(),
|
||||||
|
10,
|
||||||
|
5,
|
||||||
|
"exponential")
|
||||||
|
.hashCode(), new LocalMember(
|
||||||
|
"mycluster",
|
||||||
|
new URI("udp://4.4.4.5:1005"),
|
||||||
|
"yourid",
|
||||||
|
11,
|
||||||
|
new HashMap<>(),
|
||||||
|
11,
|
||||||
|
6,
|
||||||
|
"exponential")
|
||||||
|
.hashCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,24 +17,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.accrual;
|
package org.apache.gossip.accrual;
|
||||||
|
|
||||||
import org.apache.gossip.GossipSettings;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.junit.platform.runner.JUnitPlatform;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import org.apache.gossip.GossipSettings;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@RunWith(JUnitPlatform.class)
|
|
||||||
public class FailureDetectorTest {
|
public class FailureDetectorTest {
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
interface TriConsumer<A, B, C> {
|
|
||||||
void accept(A a, B b, C c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static final Double failureThreshold = new GossipSettings().getConvictThreshold();
|
static final Double failureThreshold = new GossipSettings().getConvictThreshold();
|
||||||
|
|
||||||
List<Integer> generateTimeList(int begin, int end, int step) {
|
List<Integer> generateTimeList(int begin, int end, int step) {
|
||||||
@ -52,8 +43,8 @@ public class FailureDetectorTest {
|
|||||||
public void normalDistribution() {
|
public void normalDistribution() {
|
||||||
FailureDetector fd = new FailureDetector(1, 1000, "normal");
|
FailureDetector fd = new FailureDetector(1, 1000, "normal");
|
||||||
List<Integer> values = generateTimeList(0, 10000, 100);
|
List<Integer> values = generateTimeList(0, 10000, 100);
|
||||||
Double deltaSum = 0.0;
|
double deltaSum = 0.0;
|
||||||
Integer deltaCount = 0;
|
int deltaCount = 0;
|
||||||
for (int i = 0; i < values.size() - 1; i++) {
|
for (int i = 0; i < values.size() - 1; i++) {
|
||||||
fd.recordHeartbeat(values.get(i));
|
fd.recordHeartbeat(values.get(i));
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
@ -64,21 +55,23 @@ public class FailureDetectorTest {
|
|||||||
Integer lastRecorded = values.get(values.size() - 2);
|
Integer lastRecorded = values.get(values.size() - 2);
|
||||||
|
|
||||||
//after "step" delay we need to be considered UP
|
//after "step" delay we need to be considered UP
|
||||||
Assert.assertTrue(fd.computePhiMeasure(values.get(values.size() - 1)) < failureThreshold);
|
Assertions.assertTrue(fd.computePhiMeasure(values.get(values.size() - 1)) < failureThreshold);
|
||||||
|
|
||||||
//if we check phi-measure after mean delay we get value for 0.5 probability(normal distribution)
|
//if we check phi-measure after mean delay we get value for 0.5 probability(normal distribution)
|
||||||
Assert.assertEquals(fd.computePhiMeasure(lastRecorded + Math.round(deltaSum / deltaCount)), -Math.log10(0.5), 0.1);
|
Assertions.assertEquals(fd.computePhiMeasure(lastRecorded + Math.round(deltaSum / deltaCount)),
|
||||||
|
-Math.log10(0.5),
|
||||||
|
0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void checkMinimumSamples() {
|
public void checkMinimumSamples() {
|
||||||
Integer minimumSamples = 5;
|
int minimumSamples = 5;
|
||||||
FailureDetector fd = new FailureDetector(minimumSamples, 1000, "normal");
|
FailureDetector fd = new FailureDetector(minimumSamples, 1000, "normal");
|
||||||
for (int i = 0; i < minimumSamples + 1; i++) { // +1 because we don't place first heartbeat into structure
|
for (int i = 0; i < minimumSamples + 1; i++) { // +1 because we don't place first heartbeat into structure
|
||||||
Assert.assertNull(fd.computePhiMeasure(100));
|
Assertions.assertNull(fd.computePhiMeasure(100));
|
||||||
fd.recordHeartbeat(i);
|
fd.recordHeartbeat(i);
|
||||||
}
|
}
|
||||||
Assert.assertNotNull(fd.computePhiMeasure(100));
|
Assertions.assertNotNull(fd.computePhiMeasure(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -86,28 +79,33 @@ public class FailureDetectorTest {
|
|||||||
final FailureDetector fd = new FailureDetector(5, 1000, "normal");
|
final FailureDetector fd = new FailureDetector(5, 1000, "normal");
|
||||||
TriConsumer<Integer, Integer, Integer> checkAlive = (begin, end, step) -> {
|
TriConsumer<Integer, Integer, Integer> checkAlive = (begin, end, step) -> {
|
||||||
List<Integer> times = generateTimeList(begin, end, step);
|
List<Integer> times = generateTimeList(begin, end, step);
|
||||||
for (int i = 0; i < times.size(); i++) {
|
for (Integer time : times) {
|
||||||
Double current = fd.computePhiMeasure(times.get(i));
|
Double current = fd.computePhiMeasure(time);
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
Assert.assertTrue(current < failureThreshold);
|
Assertions.assertTrue(current < failureThreshold);
|
||||||
|
}
|
||||||
|
fd.recordHeartbeat(time);
|
||||||
}
|
}
|
||||||
fd.recordHeartbeat(times.get(i));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TriConsumer<Integer, Integer, Integer> checkDeadMonotonic = (begin, end, step) -> {
|
TriConsumer<Integer, Integer, Integer> checkDeadMonotonic = (begin, end, step) -> {
|
||||||
List<Integer> times = generateTimeList(begin, end, step);
|
List<Integer> times = generateTimeList(begin, end, step);
|
||||||
Double prev = null;
|
Double prev = null;
|
||||||
for (int i = 0; i < times.size(); i++) {
|
for (Integer time : times) {
|
||||||
Double current = fd.computePhiMeasure(times.get(i));
|
Double current = fd.computePhiMeasure(time);
|
||||||
if (current != null && prev != null) {
|
if (current != null && prev != null) {
|
||||||
Assert.assertTrue(current >= prev);
|
Assertions.assertTrue(current >= prev);
|
||||||
|
}
|
||||||
|
prev = current;
|
||||||
}
|
}
|
||||||
prev = current;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
checkAlive.accept(0, 20000, 100);
|
checkAlive.accept(0, 20000, 100);
|
||||||
checkDeadMonotonic.accept(20000, 20500, 5);
|
checkDeadMonotonic.accept(20000, 20500, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
interface TriConsumer<A, B, C> {
|
||||||
|
void accept(A a, B b, C c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,16 +39,17 @@ import java.util.stream.Stream;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
public abstract class AddRemoveStringSetTest<SetType extends CrdtAddRemoveSet<String, Set<String>, SetType>> {
|
public abstract class AddRemoveStringSetTest<
|
||||||
|
SetType extends CrdtAddRemoveSet<String, Set<String>, SetType>> {
|
||||||
|
|
||||||
|
private Set<String> sampleSet;
|
||||||
|
|
||||||
abstract SetType construct(Set<String> set);
|
abstract SetType construct(Set<String> set);
|
||||||
|
|
||||||
abstract SetType construct();
|
abstract SetType construct();
|
||||||
|
|
||||||
private Set<String> sampleSet;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup(){
|
public void setup() {
|
||||||
sampleSet = new HashSet<>();
|
sampleSet = new HashSet<>();
|
||||||
sampleSet.add("4");
|
sampleSet.add("4");
|
||||||
sampleSet.add("5");
|
sampleSet.add("5");
|
||||||
@ -56,24 +57,25 @@ public abstract class AddRemoveStringSetTest<SetType extends CrdtAddRemoveSet<St
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void abstractSetConstructorTest(){
|
public void abstractSetConstructorTest() {
|
||||||
Assert.assertEquals(construct(sampleSet).value(), sampleSet);
|
Assert.assertEquals(construct(sampleSet).value(), sampleSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void abstractStressWithSetTest(){
|
public void abstractStressWithSetTest() {
|
||||||
Set<String> hashSet = new HashSet<>();
|
Set<String> hashSet = new HashSet<>();
|
||||||
SetType set = construct();
|
SetType set = construct();
|
||||||
for (int it = 0; it < 40; it++){
|
for (int it = 0; it < 40; it++) {
|
||||||
SetType newSet;
|
SetType newSet;
|
||||||
if (it % 5 == 1){
|
if (it % 5 == 1) {
|
||||||
//deleting existing
|
// deleting existing
|
||||||
String forDelete = hashSet.stream().skip((long) (hashSet.size() * Math.random())).findFirst().get();
|
String forDelete =
|
||||||
|
hashSet.stream().skip((long) (hashSet.size() * Math.random())).findFirst().get();
|
||||||
newSet = set.remove(forDelete);
|
newSet = set.remove(forDelete);
|
||||||
Assert.assertEquals(set.value(), hashSet); // check old version is immutable
|
Assert.assertEquals(set.value(), hashSet); // check old version is immutable
|
||||||
hashSet.remove(forDelete);
|
hashSet.remove(forDelete);
|
||||||
} else {
|
} else {
|
||||||
//adding
|
// adding
|
||||||
String forAdd = String.valueOf((int) (10000 * Math.random()));
|
String forAdd = String.valueOf((int) (10000 * Math.random()));
|
||||||
newSet = set.add(forAdd);
|
newSet = set.add(forAdd);
|
||||||
Assert.assertEquals(set.value(), hashSet); // check old version is immutable
|
Assert.assertEquals(set.value(), hashSet); // check old version is immutable
|
||||||
@ -85,7 +87,7 @@ public abstract class AddRemoveStringSetTest<SetType extends CrdtAddRemoveSet<St
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void abstractEqualsTest(){
|
public void abstractEqualsTest() {
|
||||||
SetType set = construct(sampleSet);
|
SetType set = construct(sampleSet);
|
||||||
Assert.assertFalse(set.equals(sampleSet));
|
Assert.assertFalse(set.equals(sampleSet));
|
||||||
SetType newSet = set.add("25");
|
SetType newSet = set.add("25");
|
||||||
@ -95,7 +97,7 @@ public abstract class AddRemoveStringSetTest<SetType extends CrdtAddRemoveSet<St
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void abstractRemoveMissingTest(){
|
public void abstractRemoveMissingTest() {
|
||||||
SetType set = construct(sampleSet);
|
SetType set = construct(sampleSet);
|
||||||
set = set.add("25");
|
set = set.add("25");
|
||||||
set = set.remove("25");
|
set = set.remove("25");
|
||||||
@ -107,15 +109,16 @@ public abstract class AddRemoveStringSetTest<SetType extends CrdtAddRemoveSet<St
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void abstractStressMergeTest(){
|
public void abstractStressMergeTest() {
|
||||||
// in one-process context, add, remove and merge operations of lww are equal to operations of Set
|
// in one-process context, add, remove and merge operations of lww are equal to operations of
|
||||||
|
// Set
|
||||||
// we've already checked it. Now just check merge
|
// we've already checked it. Now just check merge
|
||||||
Set<String> hashSet1 = new HashSet<>(), hashSet2 = new HashSet<>();
|
Set<String> hashSet1 = new HashSet<>(), hashSet2 = new HashSet<>();
|
||||||
SetType set1 = construct(), set2 = construct();
|
SetType set1 = construct(), set2 = construct();
|
||||||
|
|
||||||
for (int it = 0; it < 100; it++){
|
for (int it = 0; it < 100; it++) {
|
||||||
String forAdd = String.valueOf((int) (10000 * Math.random()));
|
String forAdd = String.valueOf((int) (10000 * Math.random()));
|
||||||
if (it % 2 == 0){
|
if (it % 2 == 0) {
|
||||||
hashSet1.add(forAdd);
|
hashSet1.add(forAdd);
|
||||||
set1 = set1.add(forAdd);
|
set1 = set1.add(forAdd);
|
||||||
} else {
|
} else {
|
||||||
@ -125,12 +128,13 @@ public abstract class AddRemoveStringSetTest<SetType extends CrdtAddRemoveSet<St
|
|||||||
}
|
}
|
||||||
Assert.assertEquals(set1.value(), hashSet1);
|
Assert.assertEquals(set1.value(), hashSet1);
|
||||||
Assert.assertEquals(set2.value(), hashSet2);
|
Assert.assertEquals(set2.value(), hashSet2);
|
||||||
Set<String> mergedSet = Stream.concat(hashSet1.stream(), hashSet2.stream()).collect(Collectors.toSet());
|
Set<String> mergedSet =
|
||||||
|
Stream.concat(hashSet1.stream(), hashSet2.stream()).collect(Collectors.toSet());
|
||||||
Assert.assertEquals(set1.merge(set2).value(), mergedSet);
|
Assert.assertEquals(set1.merge(set2).value(), mergedSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void abstractOptimizeTest(){
|
public void abstractOptimizeTest() {
|
||||||
Assert.assertEquals(construct(sampleSet).value(), sampleSet);
|
Assert.assertEquals(construct(sampleSet).value(), sampleSet);
|
||||||
Assert.assertEquals(construct(sampleSet).optimize().value(), sampleSet);
|
Assert.assertEquals(construct(sampleSet).optimize().value(), sampleSet);
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class GrowOnlyCounterTest {
|
public class GrowOnlyCounterTest {
|
||||||
|
|
||||||
|
@ -27,12 +27,13 @@ public class GrowOnlySetTest {
|
|||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Test
|
@Test
|
||||||
public void mergeTest(){
|
public void mergeTest() {
|
||||||
ConcurrentHashMap<String, Crdt> a = new ConcurrentHashMap<>();
|
ConcurrentHashMap<String, Crdt> a = new ConcurrentHashMap<>();
|
||||||
GrowOnlySet<String> gset = new GrowOnlySet<>(Arrays.asList("a", "b"));
|
GrowOnlySet<String> gset = new GrowOnlySet<>(Arrays.asList("a", "b"));
|
||||||
Assert.assertEquals(gset, a.merge("a", gset, new CrdtBiFunctionMerge()));
|
Assert.assertEquals(gset, a.merge("a", gset, new CrdtBiFunctionMerge()));
|
||||||
GrowOnlySet<String> over = new GrowOnlySet<>(Arrays.asList("b", "d"));
|
GrowOnlySet<String> over = new GrowOnlySet<>(Arrays.asList("b", "d"));
|
||||||
Assert.assertEquals(new GrowOnlySet<>(Arrays.asList("a", "b", "d")),
|
Assert.assertEquals(
|
||||||
a.merge("a", over, CrdtBiFunctionMerge::applyStatic));
|
new GrowOnlySet<>(Arrays.asList("a", "b", "d")),
|
||||||
|
a.merge("a", over, CrdtBiFunctionMerge::applyStatic));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,18 +28,18 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class LwwSetTest extends AddRemoveStringSetTest<LwwSet<String>> {
|
public class LwwSetTest extends AddRemoveStringSetTest<LwwSet<String>> {
|
||||||
static private Clock clock = new SystemClock();
|
private static Clock clock = new SystemClock();
|
||||||
|
|
||||||
LwwSet<String> construct(Set<String> set){
|
LwwSet<String> construct(Set<String> set) {
|
||||||
return new LwwSet<>(set);
|
return new LwwSet<>(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
LwwSet<String> construct(){
|
LwwSet<String> construct() {
|
||||||
return new LwwSet<>();
|
return new LwwSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void valueTest(){
|
public void valueTest() {
|
||||||
Map<Character, LwwSet.Timestamps> map = new HashMap<>();
|
Map<Character, LwwSet.Timestamps> map = new HashMap<>();
|
||||||
map.put('a', new LwwSet.Timestamps(1, 0));
|
map.put('a', new LwwSet.Timestamps(1, 0));
|
||||||
map.put('b', new LwwSet.Timestamps(1, 2));
|
map.put('b', new LwwSet.Timestamps(1, 2));
|
||||||
@ -52,14 +52,15 @@ public class LwwSetTest extends AddRemoveStringSetTest<LwwSet<String>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fakeTimeMergeTest(){
|
public void fakeTimeMergeTest() {
|
||||||
// try to create LWWSet with time from future (simulate other process with its own clock) and validate result
|
// try to create LWWSet with time from future (simulate other process with its own clock) and
|
||||||
|
// validate result
|
||||||
// check remove from the future
|
// check remove from the future
|
||||||
Map<Integer, LwwSet.Timestamps> map = new HashMap<>();
|
Map<Integer, LwwSet.Timestamps> map = new HashMap<>();
|
||||||
map.put(25, new LwwSet.Timestamps(clock.nanoTime(), Long.MAX_VALUE));
|
map.put(25, new LwwSet.Timestamps(clock.nanoTime(), Long.MAX_VALUE));
|
||||||
LwwSet<Integer> lww = new LwwSet<>(map);
|
LwwSet<Integer> lww = new LwwSet<>(map);
|
||||||
Assert.assertEquals(lww, new LwwSet<Integer>());
|
Assert.assertEquals(lww, new LwwSet<Integer>());
|
||||||
//create new LWWSet with element 25, and merge with other LWW which has remove in future
|
// create new LWWSet with element 25, and merge with other LWW which has remove in future
|
||||||
Assert.assertEquals(new LwwSet<>(25).merge(lww), new LwwSet<Integer>());
|
Assert.assertEquals(new LwwSet<>(25).merge(lww), new LwwSet<Integer>());
|
||||||
|
|
||||||
// add in future
|
// add in future
|
||||||
|
@ -17,13 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class MaxChangeSetTest extends AddRemoveStringSetTest<MaxChangeSet<String>> {
|
public class MaxChangeSetTest extends AddRemoveStringSetTest<MaxChangeSet<String>> {
|
||||||
MaxChangeSet<String> construct(Set<String> set){
|
MaxChangeSet<String> construct(Set<String> set){
|
||||||
|
@ -17,13 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.gossip.crdt;
|
package org.apache.gossip.crdt;
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
public class OrSetTest extends AddRemoveStringSetTest<OrSet<String>> {
|
public class OrSetTest extends AddRemoveStringSetTest<OrSet<String>> {
|
||||||
OrSet<String> construct(){
|
OrSet<String> construct(){
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user