diff --git a/Dream2/.classpath b/Dream2/.classpath index d085f01..03be8b6 100644 --- a/Dream2/.classpath +++ b/Dream2/.classpath @@ -12,6 +12,7 @@ + diff --git a/Dream2/.project b/Dream2/.project index efc6b2e..0722981 100644 --- a/Dream2/.project +++ b/Dream2/.project @@ -15,10 +15,16 @@ + + com.stateofflow.eclipse.metrics.MetricsBuilder + + + org.eclipse.ajdt.ui.ajnature org.eclipse.jdt.core.javanature org.eclipse.m2e.core.maven2Nature + com.stateofflow.eclipse.metrics.MetricsNature diff --git a/Dream2/.settings/org.eclipse.jdt.core.prefs b/Dream2/.settings/org.eclipse.jdt.core.prefs index 714351a..0d59eef 100644 --- a/Dream2/.settings/org.eclipse.jdt.core.prefs +++ b/Dream2/.settings/org.eclipse.jdt.core.prefs @@ -3,3 +3,288 @@ org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.compliance=1.8 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/Dream2/.settings/org.eclipse.jdt.ui.prefs b/Dream2/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..07ccfe5 --- /dev/null +++ b/Dream2/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_Dream +formatter_settings_version=12 +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=false +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=true +sp_cleanup.remove_trailing_whitespaces=false +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=true +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/Dream2/.settings/org.eclipse.ltk.core.refactoring.prefs b/Dream2/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 0000000..b196c64 --- /dev/null +++ b/Dream2/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/Dream2/src/examples/java/dream/examples/LineCount.txt b/Dream2/src/examples/java/dream/examples/LineCount.txt new file mode 100644 index 0000000..dc926e5 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/LineCount.txt @@ -0,0 +1,20 @@ +Distributed Form + Single-source glitch freedom with DREAM: 297 + Single-source glitch freedom without DREAM: 343 + Complete glitch freedom with DREAM: 314 + Complete glitch freedom without DREAM: 607 + + +Management application + causal consistency with DREAM: XXX + causal consistency without DREAM: YYY + + +Scrum board + atomic consistency with Dream: 155 + atomic consistency without Dream: 213 + + +Chat application + fifo consistency with Dream: 516 + fifo consistency without Dream: 798 \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/StartLockManager.java b/Dream2/src/examples/java/dream/examples/StartLockManager.java index 0396296..62dc661 100755 --- a/Dream2/src/examples/java/dream/examples/StartLockManager.java +++ b/Dream2/src/examples/java/dream/examples/StartLockManager.java @@ -3,8 +3,8 @@ import dream.locking.LockManagerLauncher; public class StartLockManager { - public static void main(String[] args) { - LockManagerLauncher.start(); - } + public static void main(String[] args) { + LockManagerLauncher.start(); + } } diff --git a/Dream2/src/examples/java/dream/examples/StartServer.java b/Dream2/src/examples/java/dream/examples/StartServer.java index ed7cbad..056fbf9 100755 --- a/Dream2/src/examples/java/dream/examples/StartServer.java +++ b/Dream2/src/examples/java/dream/examples/StartServer.java @@ -4,8 +4,8 @@ public class StartServer { - public static void main(String[] args) { - ServerLauncher.start(); - } + public static void main(String[] args) { + ServerLauncher.start(); + } } diff --git a/Dream2/src/examples/java/dream/examples/biginer/AppEntryPoint.java b/Dream2/src/examples/java/dream/examples/biginer/AppEntryPoint.java new file mode 100644 index 0000000..e3265ab --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/biginer/AppEntryPoint.java @@ -0,0 +1,49 @@ +/** + * + */ +package dream.examples.biginer; + +import dream.examples.util.NewJvmHelper; + +/** + * @author Ram + * + */ +public class AppEntryPoint { + public static void main(String args[]) { + Process infra = null; + Process producer = null; + Process consumer = null; + try { + // Init the infra + infra = new NewJvmHelper().startNewJVM(StartInfra.class); + + // Start Producer + producer = new NewJvmHelper().startNewJVM(ProducerApp.class); + + // Start Consumer + consumer = new NewJvmHelper().startNewJVM(ConsumerApp.class); + + Thread.sleep(5000); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + /** + * All of the JVMs should be closed before exit + */ + finally { + if (infra != null) { + infra.destroyForcibly(); + } + if (producer != null) { + producer.destroyForcibly(); + } + if (consumer != null) { + consumer.destroyForcibly(); + } + } + + } +} diff --git a/Dream2/src/examples/java/dream/examples/biginer/ConsumerApp.java b/Dream2/src/examples/java/dream/examples/biginer/ConsumerApp.java new file mode 100644 index 0000000..e490ae4 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/biginer/ConsumerApp.java @@ -0,0 +1,40 @@ +package dream.examples.biginer; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.common.Consts; + +/** + * An application which consumes the variables + */ +public class ConsumerApp { + + public ConsumerApp() throws Exception { + // App will be running on host different from the producer + Consts.hostName = "Host2"; + + // Register a Subscription + RemoteVar rv = new RemoteVar("Host1", "exVar"); + System.out.println("Consumer has started\n Please wait..initial communication may take upto 10 seconds"); + // On every change in remote variable rv create a signal which could + // trigger appropriate action + Signal s = new Signal("s", () -> { + return rv.get() + "ABC"; + } , rv); + + // Register a handler which will be executed upon receiving the signal + s.change().addHandler((oldVal, val) -> System.out.println("Signal1: " + val)); + } + + public static void main(String args[]) { + try { + // Start Consumer + new ConsumerApp(); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } +} diff --git a/Dream2/src/examples/java/dream/examples/biginer/ProducerApp.java b/Dream2/src/examples/java/dream/examples/biginer/ProducerApp.java new file mode 100644 index 0000000..16f743d --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/biginer/ProducerApp.java @@ -0,0 +1,43 @@ +package dream.examples.biginer; + +import dream.client.Var; +import dream.common.Consts; + +/** + * An app which produces the variables + */ +public class ProducerApp { + + public ProducerApp() throws Exception { + // Mention the host(node) which is producing the value + Consts.hostName = "Host1"; + + // myVar is created and registered as exVar for remote consumption. + // exVar is initialized to AAA + Var myVar = new Var("exVar", "AAA"); + System.out.println("Producer has started\n Please wait..initial communication may take upto 10 seconds"); + int iteration = 10; + Thread.sleep(3000); + while (iteration > 0) { + Thread.sleep(100); + // change value of exVar + myVar.set("Value-" + (10 - iteration) + ""); + System.out.println("Changed myvar " + myVar.get()); + iteration--; + } + } + + public static void main(String args[]) { + try { + + // Start Producer + new ProducerApp(); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + +} diff --git a/Dream2/src/examples/java/dream/examples/biginer/StartInfra.java b/Dream2/src/examples/java/dream/examples/biginer/StartInfra.java new file mode 100644 index 0000000..d5fc712 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/biginer/StartInfra.java @@ -0,0 +1,19 @@ +package dream.examples.biginer; + +import dream.locking.LockManagerLauncher; +import dream.server.ServerLauncher; + +public class StartInfra { + + public static void main(String args[]) { + try { + // Start the Server + ServerLauncher.start(); + // Start the LockManager + LockManagerLauncher.start(); + } catch (Exception e) { + // TODO Auto-generated catch block + + } + } +} diff --git a/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.dot b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.dot new file mode 100644 index 0000000..6e68b34 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.dot @@ -0,0 +1,14 @@ +digraph G { +"incoming_messages@Bob" -> "display@Bob" +"chat_message@Bob" -> "incomingBob@Bob" +"chat_message@Alice" -> "incomingAlice@Bob" +"incomingAlice@Bob" -> "incoming_messages@Bob" +"incomingBob@Bob" -> "incoming_messages@Bob" +"incoming_messages@Alice" -> "display@Alice" +"chat_message@Bob" -> "incomingBob@Alice" +"chat_message@Alice" -> "incomingAlice@Alice" +"incomingAlice@Alice" -> "incoming_messages@Alice" +"incomingBob@Alice" -> "incoming_messages@Alice" +"server_RegisteredClients@ChatServer" -> "setup@Bob" +"server_RegisteredClients@ChatServer" -> "setup@Alice" +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.png b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.png new file mode 100644 index 0000000..1ba7ada Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/chat/DependencyGraph.png differ diff --git a/Dream2/src/examples/java/dream/examples/chat/Starter.java b/Dream2/src/examples/java/dream/examples/chat/Starter.java new file mode 100644 index 0000000..3360b41 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/Starter.java @@ -0,0 +1,46 @@ +package dream.examples.chat; + +import dream.examples.chat.core.Chat; +import dream.examples.chat.core.ChatServer; +import dream.examples.util.MultipleStarter; + +/** + * Convenience class to start ChatServer and x Chats (x = CHAT_COUNT), each in + * its own VM. + * + * To exit all processes just close one chat window. + */ +public class Starter { + + public static final int CHAT_COUNT = 4; + + public static void main(String[] args) { + new Starter().start(); + } + + private static final String[] names = { "Alice", "Bob", "Chris", "David", "Eve", "Fred", "Georg", "Hans", "Igor" }; + int xStep = 450; + int yStep = 175; + + private void start() { + MultipleStarter.addStartQueue(ChatServer.class); + int x = 0; + int y = 0; + for (int i = 0; i < CHAT_COUNT; i++) { + MultipleStarter.addStartQueue(Chat.class, getName(i), Integer.toString(x), Integer.toString(y)); + x += xStep; + if (x >= 3 * xStep) { + x = 0; + y += yStep; + } + } + MultipleStarter.start(); + } + + private String getName(int i) { + if (i < names.length) + return names[i]; + else + return names[i % names.length] + "" + i; + } +} diff --git a/Dream2/src/examples/java/dream/examples/chat/core/Chat.java b/Dream2/src/examples/java/dream/examples/chat/core/Chat.java new file mode 100644 index 0000000..c80227e --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/core/Chat.java @@ -0,0 +1,230 @@ +package dream.examples.chat.core; + +import java.awt.EventQueue; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import dream.client.DreamClient; +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.examples.util.Client; +import dream.examples.util.DependencyVisualization; + +public class Chat extends Client { + + private ChatGUI gui; + + private final Signal> onlineList; + private List lastOnline; + + private Var toServer; + + private Map> rooms = new HashMap<>(); + private Map roomNames = new HashMap<>(); + + private int posX; + private int posY; + + public Chat(String username, int window_x, int window_y) { + super(username); + this.posX = window_x; + this.posY = window_y; + + // Establish new session with server + RemoteVar> registeredClients = new RemoteVar>(ChatServer.NAME, + ChatServer.SERVER_REGISTERED_CLIENTS); + onlineList = new Signal>("onlineList", () -> { + if (registeredClients.get() == null) + return new ArrayList(); + else + return registeredClients.get(); + }, registeredClients); + onlineList.change().addHandler((o, n) -> { + if (n.contains("toServerVar@" + username) && gui == null) + setup(); + + List names = n.stream().map(x -> x.split("@")[1]).collect(Collectors.toList()); + setOnline(names); + }); + + toServer = new Var("toServerVar", ""); + logger.fine("Setup: Waiting for Registration to Server ..."); + } + + private void setOnline(List online) { + if (lastOnline != null) { + for (String s : lastOnline) { + if (!online.contains(s)) { + String msg = s + " has left the Chat."; + // gui.displayMessage(0, msg); + } + } + for (String s : online) { + if (!lastOnline.contains(s)) { + String msg = s + " has joined."; + // gui.displayMessage(0, msg); + } + } + } + lastOnline = online; + gui.setOnline(online); + } + + private void setup() { + logger.fine("Setup: Var successfully registered to Server"); + // Var for messages from server + String serverVar = ChatServer.getRandom(); + sendServerMessage(serverVar); + // while (!DreamClient.instance.listVariables().contains(serverVar + "@" + // + ChatServer.NAME)) { + logger.fine(DreamClient.instance.listVariables().toString()); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // } + RemoteVar remote = new RemoteVar(ChatServer.NAME, serverVar); + Signal fromServer = new Signal<>("fromServer", () -> { + if (remote.get() != null) + return remote.get(); + else + return ""; + }, remote); + fromServer.change().addHandler((oldValue, newValue) -> receivedServerMessage(newValue)); + + logger.fine("Setup: Starting GUI"); + gui = new ChatGUI(getHostName(), posX, posY); + gui.setListener(this); + + // main room: + // newRoom("Main", "*"); + } + + protected void receivedChatMessage(int roomNumber, String sender, String message) { + gui.displayMessage(roomNumber, sender + ": " + message); + } + + protected void receivedServerMessage(String message) { + logger.fine("Received message from server: " + message); + String[] temp = message.split(" ", 2); + String command = temp[0]; + String rest = temp.length > 1 ? temp[1] : ""; + if (command.equalsIgnoreCase("room")) { + // room ... + String[] t = rest.split(" ", 2); + String roomName = t[0]; + String otherClients = t[1]; + logger.finer("Server requested a Var for room " + roomName + " with " + otherClients); + + String roomVar = newRoom(roomName); + sendServerMessage("roomVar " + roomName + " " + roomVar); + } else if (command.equalsIgnoreCase("roomVar")) { + // roomVar = = + String[] t = rest.split(" ", 2); + String roomName = t[0]; + String[] pairs = t[1].split(" "); + for (String p : pairs) { + String[] t2 = p.split("=", 2); + String clientName = t2[0]; + String clientVar = t2[1]; + int roomNumber = roomNames.get(roomName); + createConnection(roomNumber, roomName, clientName, clientVar); + } + } + } + + protected void sendChatMessage(int roomNumber, String message) { + rooms.get(roomNumber).set(message); + } + + protected void sendServerMessage(String message) { + toServer.set(message); + } + + private String newRoom(String roomName) { + int roomNumber = gui.newChat(roomName); + return newRoom(roomName, roomNumber); + } + + protected String newRoom(String roomName, int roomNumber) { + String roomVar = "room" + roomNumber; + Var room = new Var(roomVar, ""); + rooms.put(roomNumber, room); + roomNames.put(roomName, roomNumber); + logger.fine("Room: Creating new Room(" + roomNumber + ")"); + return roomVar; + } + + private void createConnection(int roomNumber, String roomName, String clientName, String clientVar) { + if (clientName.equals(getHostName())) + return; + RemoteVar r = new RemoteVar<>(clientName, clientVar); + Signal s = new Signal<>(roomName + "_" + clientName, () -> { + if (r.get() != null) + return r.get(); + else + return ""; + }, r); + s.change().addHandler((oldValue, newValue) -> receivedChatMessage(roomNumber, clientName, newValue)); + } + + protected void typedMessage(String text) { + if (!text.startsWith("/")) { + // normal message + int room = gui.getSelectedChat(); + gui.displayMessage(room, "You: " + text); + sendChatMessage(room, text); + logger.fine("Send Message to Room" + room + ": " + text); + } else { + // message to server + processCommand(text.substring(1, text.length())); + } + } + + private void processCommand(String text) { + String[] temp = text.split(" ", 2); + String command = temp[0]; + String rest = temp.length > 1 ? temp[1] : ""; + if (command.equalsIgnoreCase("room")) { + String[] temp1 = rest.split(" ", 2); + String name = temp1[0]; + initiateNewRoom(name, temp1[1]); + } else if (command.equalsIgnoreCase("graph")) { + DependencyVisualization.show(); + } else if (command.equalsIgnoreCase("sgraph")) { + sendServerMessage("graph"); + } + logger.fine("Processed Command: " + text); + } + + private void initiateNewRoom(String name, String recipients) { + String roomVar = newRoom(name); + // room command: room ... + logger.finer("Room: Sending to Server: " + "room " + name + " " + roomVar + " " + recipients); + sendServerMessage("room " + name + " " + roomVar + " " + recipients); + } + + public static void main(String[] args) { + if (args.length < 1) { + Logger.getGlobal().severe("username missing"); + return; + } + int x, y; + if (args.length < 3) + y = -1; + else + y = Integer.parseInt(args[2]); + + if (args.length < 2) + x = -1; + else + x = Integer.parseInt(args[1]); + EventQueue.invokeLater(() -> new Chat(args[0], x, y)); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/chat/core/ChatGUI.java b/Dream2/src/examples/java/dream/examples/chat/core/ChatGUI.java new file mode 100644 index 0000000..94e5d63 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/core/ChatGUI.java @@ -0,0 +1,264 @@ +package dream.examples.chat.core; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.io.File; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.ListSelectionModel; +import javax.swing.SpringLayout; +import javax.swing.SwingUtilities; + +public class ChatGUI extends JFrame implements WindowListener { + + private static final long serialVersionUID = 4659984914364067514L; + private JTabbedPane jtp; + private List msgs; + private JTextField sendText; + private JList statusList; + private DefaultListModel listModel; + + private Chat listener; + + public ChatGUI(String userName, int posX, int posY) { + this.addWindowListener(this); + initUI(userName); + if (posX >= 0 && posY >= 0) + this.setLocation(posX, posY); + } + + public void setListener(Chat c) { + listener = c; + } + + public String getTypedText() { + return sendText.getText(); + } + + public void resetTypedText() { + sendText.setText(""); + } + + public int getSelectedChat() { + return jtp.getSelectedIndex(); + } + + public int newChat(String name) { + msgs.add(new JTextArea(5, 27)); + int r = msgs.size() - 1; + msgs.get(r).setEditable(false); + JScrollPane sp = new JScrollPane(msgs.get(r)); + sp.setAutoscrolls(true); + jtp.add(name, sp); + pack(); + return r; + } + + public void closeChat(int index) { + Component t = jtp.getComponentAt(index); + jtp.remove(t); + } + + public void displayMessage(int room, String text) { + if (msgs.get(room).getText().isEmpty()) + msgs.get(room).append(text); + else + msgs.get(room).append(System.lineSeparator() + text); + } + + public void setOnline(List online) { + List offlineList = new ArrayList(); + for (int i = 0; i < listModel.size(); i++) { + if (!online.contains(listModel.get(i))) + offlineList.add(listModel.get(i)); + } + SwingUtilities.invokeLater(() -> { + listModel.clear(); + for (String e : online) { + listModel.addElement(e); + } + for (String e : offlineList) + listModel.addElement(e); + statusList.setSelectionInterval(0, online.size() - 1); + }); + + } + + public void removeOnline(String name) { + listModel.removeElement(name); + } + + private void sendText() { + listener.typedMessage(getTypedText()); + this.resetTypedText(); + } + + private void initUI(String userName) { + sendText = new JTextField(20); + sendText.addKeyListener(new KeyListener() { + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + sendText(); + } + }); + JButton sendButton = new JButton("Send"); + sendButton.addActionListener((e) -> sendText()); + jtp = new JTabbedPane(JTabbedPane.TOP); + jtp.setPreferredSize(new Dimension(400, 100)); + msgs = new ArrayList<>(); + // newChat("Main"); + + listModel = new DefaultListModel(); + statusList = new JList(listModel); + statusList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + statusList.setEnabled(false); + statusList.setLayoutOrientation(JList.HORIZONTAL_WRAP); + statusList.setVisibleRowCount(-1); + // statusList.setSelectionBackground(Color.GREEN); + // statusList.setSelectionForeground(Color.BLACK); + // statusList.setForeground(Color.BLACK); + // statusList.setBackground(Color.WHITE); + // statusList.setCellRenderer(new DefaultListCellRenderer()); + + statusList.setCellRenderer(new DefaultListCellRenderer() { + + private static final long serialVersionUID = 9019815674349211344L; + private JLabel label = new JLabel(); + private Color textSelectionColor = Color.BLACK; + private Color backgroundSelectionColor = Color.CYAN; + private Color textNonSelectionColor = Color.BLACK; + private Color backgroundNonSelectionColor = Color.WHITE; + + @Override + public java.awt.Component getListCellRendererComponent(javax.swing.JList list, Object value, int index, + boolean isSelected, boolean cellHasFocus) { + + String name = (String) value; + label.setText(name); + + if (isSelected) { + label.setBackground(backgroundSelectionColor); + label.setForeground(textSelectionColor); + label.setIcon(createImageIcon("status-online.png", "Online")); + } else { + label.setBackground(backgroundNonSelectionColor); + label.setForeground(textNonSelectionColor); + label.setIcon(createImageIcon("status-offline.png", "Offline")); + } + + return label; + }; + + }); + + SpringLayout layout = new SpringLayout(); + + // put messages on (5,5) + layout.putConstraint(SpringLayout.WEST, jtp, 5, SpringLayout.WEST, getContentPane()); + layout.putConstraint(SpringLayout.NORTH, jtp, 5, SpringLayout.NORTH, getContentPane()); + + // put textfield below messages + layout.putConstraint(SpringLayout.NORTH, sendText, 5, SpringLayout.SOUTH, jtp); + layout.putConstraint(SpringLayout.WEST, sendText, 5, SpringLayout.WEST, getContentPane()); + + // put button next to the textfield + layout.putConstraint(SpringLayout.NORTH, sendButton, 5, SpringLayout.SOUTH, jtp); + layout.putConstraint(SpringLayout.WEST, sendButton, 5, SpringLayout.EAST, sendText); + + // make the frame big enough to fit all in + layout.putConstraint(SpringLayout.EAST, getContentPane(), 10, SpringLayout.EAST, statusList); + layout.putConstraint(SpringLayout.SOUTH, getContentPane(), 10, SpringLayout.SOUTH, sendText); + + layout.putConstraint(SpringLayout.NORTH, statusList, 5, SpringLayout.NORTH, getContentPane()); + layout.putConstraint(SpringLayout.WEST, statusList, 15, SpringLayout.EAST, jtp); + + getContentPane().setLayout(layout); + + getContentPane().add(jtp); + getContentPane().add(sendText); + getContentPane().add(sendButton); + getContentPane().add(statusList); + + setTitle("Chat - " + userName); + // setSize(300, 200); + setLocationRelativeTo(null); + setDefaultCloseOperation(EXIT_ON_CLOSE); + + pack(); + setVisible(true); + } + + /** Returns an ImageIcon, or null if the path was invalid. */ + protected ImageIcon createImageIcon(String path, String description) { + File img = new File("./src/resources/dream/examples/chat/" + path); + try { + java.net.URL imgURL = img.toURI().toURL(); + if (imgURL != null) { + return new ImageIcon(imgURL, description); + } else { + System.err.println("Couldn't find file: " + path); + return null; + } + } catch (MalformedURLException e) { + System.err.println("Couldn't find file: " + path); + return null; + } + } + + @Override + public void windowOpened(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowDeactivated(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + listener.typedMessage("/quit"); + } + + @Override + public void windowClosed(WindowEvent e) { + } + + @Override + public void windowActivated(WindowEvent e) { + } +} diff --git a/Dream2/src/examples/java/dream/examples/chat/core/ChatServer.java b/Dream2/src/examples/java/dream/examples/chat/core/ChatServer.java new file mode 100644 index 0000000..18a61f4 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/core/ChatServer.java @@ -0,0 +1,172 @@ +package dream.examples.chat.core; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import dream.client.DreamClient; +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.examples.util.Client; +import dream.examples.util.DependencyVisualization; +import dream.examples.util.Pair; + +public class ChatServer extends Client { + public static final String NAME = "ChatServer"; + + private final static SecureRandom r = new SecureRandom(); + + private final Var> clients; + private final HashMap> clientVars; + private final HashMap> rooms; + private final Logger logger = Logger.getLogger("ChatServer"); + + public static final String SERVER_PREFIX = "server_"; + public static final String SERVER_REGISTERED_CLIENTS = SERVER_PREFIX + "RegisteredClients"; + + public static void main(String[] args) { + new ChatServer(); + } + + public ChatServer() { + super(NAME); + logger.setLevel(Level.ALL); + logger.addHandler(Logger.getGlobal().getHandlers()[0]); + clientVars = new HashMap<>(); + rooms = new HashMap<>(); + clients = new Var>(SERVER_REGISTERED_CLIENTS, new ArrayList()); + detectNewSession(); + } + + /** + * Look for new clients every 5 seconds + */ + private void detectNewSession() { + Set vars = DreamClient.instance.listVariables(); + vars.stream().map(x -> new Pair(x.split("@")[1], x.split("@")[0])).// Pair(Host,Var) + filter(x -> !clients.get().contains(x.getSecond() + "@" + x.getFirst()) + && x.getSecond().equalsIgnoreCase("toServerVar")) + .// + forEach(x -> createNewSessionFor(x.getFirst(), x.getSecond())); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e); + } + + detectNewSession(); + } + + /** + * Registers a new chat client with its name and the name of the variable it + * is sending messages on + * + * @param clientName + * the name of the client + * @param clientVar + * the name of the variable, must be of type String + */ + private void createNewSessionFor(String clientName, String clientVar) { + logger.fine("Creating new Session for " + clientName + " with Var " + clientVar); + + // add listener to messages from this client + RemoteVar var = new RemoteVar(clientName, clientVar); + Signal sig = new Signal<>(SERVER_PREFIX + "receive_" + clientName, () -> { + if (var.get() != null) + return var.get(); + else + return ""; + }, var); + sig.change().addHandler((oldValue, newValue) -> receivedMessage(clientName, newValue)); + + // add client as registered + clients.modify((old) -> old.add(clientVar + "@" + clientName)); + + // now wait for first message from client + logger.fine("Setup: Waiting for first message from " + clientName); + } + + protected void sendMessage(String clientName, String message) { + clientVars.get(clientName).set(message); + } + + protected void receivedMessage(String clientName, String message) { + logger.fine("Received client message from " + clientName + ": " + message); + if (!clientVars.containsKey(clientName)) { + // first message from client + // setup Var for messages to this client + clientVars.put(clientName, new Var(message, "")); + logger.fine("Setup: new Var for messages to " + clientName); + } else { + String[] temp = message.split(" ", 2); + String command = temp[0]; + String rest = temp.length > 1 ? temp[1] : ""; + + if (command.equalsIgnoreCase("room")) { + // room ... + logger.fine("Room: Received command to create new room (" + message + ")"); + String[] t = rest.split(" ", 3); + String roomName = t[0]; + String otherClients = t[2]; + // Map: clientName -> clientRoomVar + HashMap roomVars = new HashMap<>(); + roomVars.put(clientName, t[1]); + // send message to every recipient to send a Var for that room + if (otherClients.equals("*")) { + for (String client : clients.get()) { + // set Var for c as "not sent" + roomVars.put(client, null); + // and ask c for his Var + logger.finer("Room: Sending Var-Request for " + roomName + " to " + client); + sendMessage(client, "room " + roomName + " " + otherClients.replace(client, clientName)); + } + } else { + for (String client : otherClients.split(" ")) { + // set Var for c as "not sent" + roomVars.put(client, null); + // and ask c for his Var + logger.finer("Room: Sending Var-Request for " + roomName + " to " + client); + sendMessage(client, "room " + roomName + " " + otherClients.replace(client, clientName)); + } + } + rooms.put(roomName, roomVars); + } else if (command.equalsIgnoreCase("roomVar")) { + // roomVar + String[] t = rest.split(" ", 2); + String roomName = t[0]; + String varName = t[1]; + logger.fine("Room: Received a Var (" + varName + ") from " + clientName + " for room " + roomName); + Map roomVars = rooms.get(roomName); + roomVars.put(clientName, varName); + + // check if every room member has sent a Var + if (!roomVars.values().contains(null)) { + String varString = ""; + for (Entry e : roomVars.entrySet()) { + varString += e.getKey() + "=" + e.getValue() + " "; + } + for (String client : roomVars.keySet()) { + sendMessage(client, "roomVar " + roomName + " " + varString); + } + logger.fine("Room: Finished setting up room " + roomName); + } + } else if (command.equalsIgnoreCase("graph")) { + DependencyVisualization.show(); + } + } + } + + /** + * @return random String hashed with SHA-256 + */ + public static String getRandom() { + return new BigInteger(130, r).toString(32); + } +} diff --git a/Dream2/src/examples/java/dream/examples/chat/fifo/Chat.java b/Dream2/src/examples/java/dream/examples/chat/fifo/Chat.java new file mode 100644 index 0000000..a529577 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/fifo/Chat.java @@ -0,0 +1,110 @@ +package dream.examples.chat.fifo; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map.Entry; + +public class Chat extends dream.examples.chat.core.Chat { + + private HashMap roomClocks = new HashMap<>(); + private HashMap> messageCache = new HashMap<>(); + + public Chat(String username, int window_x, int window_y) { + super(username, window_x, window_y); + } + + @Override + protected void sendChatMessage(int roomNumber, String message) { + // increment VectorClock by 1 + VectorClock roomClock = roomClocks.get(roomNumber); + roomClock.incrementClock(getHostName()); + // attach VectorClock to message + String newMessage = roomClock.toString() + "|" + message; + logger.fine("Sending message with VectorClock " + roomClock + ": " + message); + super.sendChatMessage(roomNumber, newMessage); + } + + @Override + protected void receivedChatMessage(int roomNumber, String sender, String message) { + String[] temp = message.split("\\|", 2); + VectorClock messageClock = new VectorClock(temp[0]); + String newMessage = temp[1]; + cacheMessage(messageClock, roomNumber, sender, newMessage); + processCachedMessages(roomNumber); + } + + private void cacheMessage(VectorClock messageClock, int roomNumber, String sender, String message) { + messageCache.get(roomNumber).add(new CachedMessage(messageClock, roomNumber, sender, message)); + } + + private void processCachedMessages(int roomNumber) { + List messages = messageCache.get(roomNumber); + VectorClock roomClock = roomClocks.get(roomNumber); + boolean removed = false; + for (CachedMessage cm : messages) { + if (cm.canSend(roomClock)) { + // increase received messages from the sender + roomClock.incrementClock(cm.getSender()); + // deliver the message + super.receivedChatMessage(cm.getRoom(), cm.getSender(), cm.getMessage()); + // remove message from cache + messages.remove(cm); + } + } + if (removed) + processCachedMessages(roomNumber); + } + + @Override + protected String newRoom(String roomName, int roomNumber) { + roomClocks.put(roomNumber, new VectorClock()); + messageCache.put(roomNumber, new ArrayList<>()); + return super.newRoom(roomName, roomNumber); + } +} + +class CachedMessage { + private VectorClock clock; + private int room; + private String sender; + private String message; + + public CachedMessage(VectorClock messageClock, int roomNumber, String sender, String message) { + this.clock = messageClock; + this.room = roomNumber; + this.sender = sender; + this.message = message; + } + + public boolean canSend(VectorClock roomClock) { + // delivered every message that the sender has sent before this message + boolean senderSent = clock.get(sender) == roomClock.get(sender) + 1; + // delivered every message that the sender has delivered before this + // message + boolean senderDelivered = true; + for (Entry e : clock.entrySet()) { + if (!e.getKey().equals(sender)) { + if (clock.get(e.getKey()) > roomClock.get(e.getKey())) + senderDelivered = false; + } + } + return senderSent && senderDelivered; + } + + public VectorClock getClock() { + return clock; + } + + public int getRoom() { + return room; + } + + public String getSender() { + return sender; + } + + public String getMessage() { + return message; + } +} diff --git a/Dream2/src/examples/java/dream/examples/chat/fifo/VectorClock.java b/Dream2/src/examples/java/dream/examples/chat/fifo/VectorClock.java new file mode 100644 index 0000000..4e5b3e5 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/fifo/VectorClock.java @@ -0,0 +1,252 @@ +package dream.examples.chat.fifo; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; + +/** + * Implements a VectorClock that records the time stamps of all send and receive + * events. It contains functions to compare and merge two VectorClocks. + * + * @author Frits de Nijs + * @author Peter Dijkshoorn + */ +public class VectorClock extends HashMap implements Serializable, Comparator { + // Unique Serial. + private static final long serialVersionUID = 6668164199894268488L; + + public VectorClock() { + + } + + public VectorClock(String initString) { + fromString(this, initString); + } + + /** + * Increases the component of pUnit by 1. + * + * @param pUnit + * - The ID of the vector element being increased. + */ + public void incrementClock(String pUnit) { + // If we have it in the vector, increment. + if (this.containsKey(pUnit)) { + this.put(pUnit, this.get(pUnit).intValue() + 1); + } + // Else, store with value 1 (starts at 0, +1). + else { + this.put(pUnit, 1); + } + } + + /** + * GUI operation, returns the IDs in some neat order. + * + * @return The IDs of the elements in the Clock. + */ + public String[] getOrderedIDs() { + String[] lResult = new String[this.size()]; + + lResult = this.keySet().toArray(lResult); + + Arrays.sort(lResult); + + return lResult; + } + + /** + * GUI operation, returns the values in some neat order. + * + * @return The Values of the elements in the Clock. + */ + public Integer[] getOrderedValues() { + Integer[] lResult = new Integer[this.size()]; + String[] lKeySet = this.getOrderedIDs(); + + int i = 0; + for (String lKey : lKeySet) { + lResult[i] = this.get(lKey); + i++; + } + + return lResult; + } + + @Override + public Integer get(Object key) { + Integer lResult = super.get(key); + + if (lResult == null) + lResult = 0; + + return lResult; + } + + @Override + public VectorClock clone() { + return (VectorClock) super.clone(); + } + + @Override + public String toString() { + return toString(this); + } + + /** + * VectorClock merging operation. Creates a new VectorClock with the maximum + * for each element in either clock. Used in Buffer and Process to + * manipulate clocks. + * + * @param pOne + * - First Clock being merged. + * @param pTwo + * - Second Clock being merged. + * + * @return A new VectorClock with the maximum for each element in either + * clock. + */ + public static VectorClock max(VectorClock pOne, VectorClock pTwo) { + // Create new Clock. + VectorClock lResult = new VectorClock(); + + // Go over all elements in clock One, put them in the new clock. + for (String lEntry : pOne.keySet()) { + lResult.put(lEntry, pOne.get(lEntry)); + } + + // Go over all elements in clock Two, + for (String lEntry : pTwo.keySet()) { + // Insert the Clock Two value if it is not present in One, or if it + // is higher. + if (!lResult.containsKey(lEntry) || lResult.get(lEntry) < pTwo.get(lEntry)) { + lResult.put(lEntry, pTwo.get(lEntry)); + } + } + + // Return the merged clock. + return lResult; + } + + public int compare(VectorClock v1, VectorClock v2) { + switch (order(v1, v2)) { + case GREATER: + return 1; + case SMALLER: + return -1; + default: + return 0; + } + } + + /** + * VectorClock compare operation. Returns one of four possible values + * indicating how clock one relates to clock two: + * + * VectorComparison.GREATER If One > Two. VectorComparison.EQUAL If One = + * Two. VectorComparison.SMALLER If One < Two. VectorComparison.SIMULTANEOUS + * If One <> Two. + * + * @param pOne + * - First Clock being compared. + * @param pTwo + * - Second Clock being compared. + * + * @return VectorComparison value indicating how One relates to Two. + */ + public static VectorComparison order(VectorClock pOne, VectorClock pTwo) { + // Initially we assume it is all possible things. + boolean lEqual = true; + boolean lGreater = true; + boolean lSmaller = true; + + // Go over all elements in Clock one. + for (String lEntry : pOne.keySet()) { + // Compare if also present in clock two. + if (pTwo.containsKey(lEntry)) { + // If there is a difference, it can never be equal. + // Greater / smaller depends on the difference. + if (pOne.get(lEntry) < pTwo.get(lEntry)) { + lEqual = false; + lGreater = false; + } + if (pOne.get(lEntry) > pTwo.get(lEntry)) { + lEqual = false; + lSmaller = false; + } + } + // Else assume zero (default value is 0). + else if (pOne.get(lEntry) != 0) { + lEqual = false; + lSmaller = false; + } + } + + // Go over all elements in Clock two. + for (String lEntry : pTwo.keySet()) { + // Only elements we have not found in One still need to be checked. + if (!pOne.containsKey(lEntry) && (pTwo.get(lEntry) != 0)) { + lEqual = false; + lGreater = false; + } + } + + // Return based on determined information. + if (lEqual) { + return VectorComparison.EQUAL; + } else if (lGreater && !lSmaller) { + return VectorComparison.GREATER; + } else if (lSmaller && !lGreater) { + return VectorComparison.SMALLER; + } else { + return VectorComparison.SIMULTANEOUS; + } + } + + public static String toString(VectorClock clock) { + StringBuilder sb = new StringBuilder(); + String[] lIDs = clock.getOrderedIDs(); + Integer[] lRequests = clock.getOrderedValues(); + sb.append("["); + for (int i = 0; i < lRequests.length; i++) { + sb.append(lIDs[i]).append("=").append(lRequests[i].toString()); + if (i + 1 < lRequests.length) { + sb.append(","); + } + } + sb.append("]"); + return sb.toString(); + } + + public static VectorClock fromString(String clockString) { + return fromString(new VectorClock(), clockString); + } + + private static VectorClock fromString(VectorClock vc, String clockString) { + if (clockString.startsWith("[") && clockString.endsWith("]")) { + clockString = clockString.substring(1, clockString.length() - 1); + String[] pairs = clockString.split(","); + for (int i = 0; i < pairs.length; i++) { + if (pairs[i].length() > 0) { + String[] temp = pairs[i].split("="); + String key = temp[0]; + int value = Integer.valueOf(temp[1]); + vc.put(key, value); + } + } + return vc; + } else + throw new IllegalArgumentException("String is not a VectorClock: " + clockString); + } +} + +/** + * Enumerates the four different outcomes of comparing two VectorClocks. + * + * @author Frits de Nijs + * @author Peter Dijkshoorn + */ +enum VectorComparison { + GREATER, EQUAL, SMALLER, SIMULTANEOUS; +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/chat/line-count.core.txt b/Dream2/src/examples/java/dream/examples/chat/line-count.core.txt new file mode 100644 index 0000000..064384d --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/line-count.core.txt @@ -0,0 +1,8 @@ +http://cloc.sourceforge.net v 1.64 T=0.02 s (145.4 files/s, 32269.1 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 3 95 55 516 +------------------------------------------------------------------------------- +SUM: 3 95 55 516 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/chat/line-count.diff.core.fifo.txt b/Dream2/src/examples/java/dream/examples/chat/line-count.diff.core.fifo.txt new file mode 100644 index 0000000..ca3fd13 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/line-count.diff.core.fifo.txt @@ -0,0 +1,16 @@ +http://cloc.sourceforge.net v 1.64 T=0.08 s (13.1 files/s, 13.1 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java + same 0 0 0 20 + modified 1 0 8 59 + added 1 31 75 153 + removed 2 79 47 437 +------------------------------------------------------------------------------- +SUM: + same 0 0 0 20 + modified 1 0 8 59 + added 1 31 75 153 + removed 2 79 47 437 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/chat/line-count.fifo.txt b/Dream2/src/examples/java/dream/examples/chat/line-count.fifo.txt new file mode 100644 index 0000000..c974ab7 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/line-count.fifo.txt @@ -0,0 +1,8 @@ +http://cloc.sourceforge.net v 1.64 T=0.03 s (57.9 files/s, 10488.8 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 2 47 83 232 +------------------------------------------------------------------------------- +SUM: 2 47 83 232 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/chat/package-info.java b/Dream2/src/examples/java/dream/examples/chat/package-info.java new file mode 100644 index 0000000..cba4f26 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/chat/package-info.java @@ -0,0 +1,10 @@ +/** + * A small example for a Chat Application + * + * Usage: Start {@link javareact.chat.ChatServer ChatServer} first. Then start + * as many instances of {@link dream.examples.chat.core.Chat Chat} as you need + * and supply a user name as the first parameter. + * + * @author Tobias Becker + */ +package dream.examples.chat; diff --git a/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java b/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java index 450dc9c..77823f6 100644 --- a/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java +++ b/Dream2/src/examples/java/dream/examples/financial/FinancialApp.java @@ -1,67 +1,68 @@ package dream.examples.financial; +import java.util.Arrays; +import java.util.List; + +import dream.client.ChangeEventHandler; import dream.client.RemoteVar; import dream.client.Signal; -import dream.client.ValueChangeListener; -import dream.common.Consts; - -public class FinancialApp implements ValueChangeListener { - private Signal f1Signal; - private Signal f2Signal; - private Signal f3Signal; +import dream.examples.util.Client; - private RemoteVar f1; - private RemoteVar f2; - private RemoteVar f3; +public class FinancialApp extends Client implements ChangeEventHandler { - public static void main(String[] args) { - new FinancialApp().start(); - } + public FinancialApp() { + super("Local"); + } - public void start() { - Consts.hostName = "Local"; + private Signal f1Signal; + private Signal f2Signal; + private Signal f3Signal; - try { - Thread.sleep(2000); - } catch (final InterruptedException e) { - e.printStackTrace(); - } + private RemoteVar f1; + private RemoteVar f2; + private RemoteVar f3; - f1 = new RemoteVar<>("f1@Model1"); - f2 = new RemoteVar<>("f2@Model2"); - f3 = new RemoteVar<>("f3@Model3"); + public static void main(String[] args) { + new FinancialApp().start(); + } - final RemoteVar model1 = new RemoteVar<>("Model1", "model1"); + @Override + protected List waitForVars() { + return Arrays.asList("f1@Model1", "f2@Model2", "f3@Model3"); + } - f1Signal = new Signal<>("f1Signal", () -> f1.get(), f1); - f2Signal = new Signal<>("f2Signal", () -> f2.get(), f2); - f3Signal = new Signal<>("f3Signal", () -> f3.get(), f3); + public void start() { + f1 = new RemoteVar<>("Model1", "f1"); + f2 = new RemoteVar<>("Model2", "f2"); + f3 = new RemoteVar<>("Model3", "f3"); - f1Signal.addValueChangeListener(this); - f2Signal.addValueChangeListener(this); - f3Signal.addValueChangeListener(this); + f1Signal = new Signal<>("f1Signal", () -> f1.get(), f1); + f2Signal = new Signal<>("f2Signal", () -> f2.get(), f2); + f3Signal = new Signal<>("f3Signal", () -> f3.get(), f3); - try { - Thread.sleep(2000); - } catch (final InterruptedException e) { - e.printStackTrace(); - } + f1Signal.change().addHandler(this); + f2Signal.change().addHandler(this); + f3Signal.change().addHandler(this); - System.out.println(f1.get()); - System.out.println(f2.get()); - System.out.println(f3.get()); + try { + Thread.sleep(2000); + } catch (final InterruptedException e) { + e.printStackTrace(); + } - System.out.println(model1.get()); - } + System.out.println(f1.get()); + System.out.println(f2.get()); + System.out.println(f3.get()); + } - @Override - public void notifyValueChanged(Integer newValue) { - System.out.println("Value changed"); + @Override + public void handle(Integer oldVal, Integer newVal) { + System.out.println("Value changed"); - if (f1.get() != null && f2.get() != null && f3.get() != null) { - if ((f1.get() + f2.get() + f3.get()) / 3.0 > 150) { - System.out.println("Financial Alert!"); - } - } - } + if (f1.get() != null && f2.get() != null && f3.get() != null) { + if ((f1.get() + f2.get() + f3.get()) / 3.0 > 150) { + System.out.println("Financial Alert!"); + } + } + } } diff --git a/Dream2/src/examples/java/dream/examples/financial/InputModel.java b/Dream2/src/examples/java/dream/examples/financial/InputModel.java index b8b4a67..42f6b90 100644 --- a/Dream2/src/examples/java/dream/examples/financial/InputModel.java +++ b/Dream2/src/examples/java/dream/examples/financial/InputModel.java @@ -3,66 +3,37 @@ import java.util.Random; import dream.client.Var; -import dream.common.Consts; -import dream.locking.LockManagerLauncher; -import dream.server.ServerLauncher; +import dream.examples.util.Client; -public class InputModel { - private boolean serverStarted = false; - private boolean lockManagerStarted = false; +public class InputModel extends Client { - public static void main(String[] args) { - new InputModel().start(); - } + public InputModel() { + super("InputModel"); + } - public void start() { - startServerIfNeeded(); - startLockManagerIfNeeded(); + public static void main(String[] args) { + new InputModel().start(); + } - Consts.hostName = "InputModel"; + public void start() { + final Var marketIndex = new Var<>("marketIndex", 1); + final Var stockOpts = new Var<>("stockOpts", 1); + final Var news = new Var<>("news", 1); - final Var marketIndex = new Var<>("marketIndex", 1); - final Var stockOpts = new Var<>("stockOpts", 1); - final Var news = new Var<>("news", 1); + final Random random = new Random(); - final Random random = new Random(); + while (true) { + marketIndex.set(random.nextInt(100)); + stockOpts.set(random.nextInt(100)); + news.set(random.nextInt(100)); - while (true) { - marketIndex.set(random.nextInt(100)); - stockOpts.set(random.nextInt(100)); - news.set(random.nextInt(100)); + System.out.println("New values: " + marketIndex.get() + ", " + stockOpts.get() + ", " + news.get()); - System.out.println("New values: " + marketIndex.get() + ", " + stockOpts.get() + ", " + news.get()); - - try { - Thread.sleep(1000); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - } - - private final void startServerIfNeeded() { - if (!serverStarted) { - ServerLauncher.start(); - serverStarted = true; - } - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - - private final void startLockManagerIfNeeded() { - if (!lockManagerStarted) { - LockManagerLauncher.start(); - lockManagerStarted = true; - } - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } + try { + Thread.sleep(1000); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + } } diff --git a/Dream2/src/examples/java/dream/examples/financial/Model1.java b/Dream2/src/examples/java/dream/examples/financial/Model1.java index 705b564..3d7e9c9 100644 --- a/Dream2/src/examples/java/dream/examples/financial/Model1.java +++ b/Dream2/src/examples/java/dream/examples/financial/Model1.java @@ -1,34 +1,38 @@ package dream.examples.financial; +import java.util.Arrays; +import java.util.List; + import dream.client.RemoteVar; import dream.client.Signal; -import dream.client.ValueChangeListener; -import dream.common.Consts; - -public class Model1 implements ValueChangeListener { - public void start() { - Consts.hostName = "Model1"; - - final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex"); - final RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts"); - - final Signal f1 = new Signal<>("f1", () -> { - if (marketIndex.get() == null || stockOpts.get() == null) { - return null; - } else { - return marketIndex.get() * 2 + stockOpts.get(); - } - } , marketIndex, stockOpts); - - f1.addValueChangeListener(this); - } - - @Override - public void notifyValueChanged(Integer newValue) { - System.out.println("New value for f1: " + newValue); - } - - public static void main(String[] args) { - new Model1().start(); - } +import dream.examples.util.Client; + +public class Model1 extends Client { + public Model1() { + super("Model1"); + } + + @Override + protected List waitForVars() { + return Arrays.asList("marketIndex@InputModel", "stockOpts@InputModel"); + } + + public void start() { + final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex"); + final RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts"); + + final Signal f1 = new Signal<>("f1", () -> { + if (marketIndex.get() == null || stockOpts.get() == null) { + return null; + } else { + return marketIndex.get() * 2 + stockOpts.get(); + } + } , marketIndex, stockOpts); + + f1.change().addHandler((oldVal, newVal) -> System.out.println("New value for f1: " + newVal)); + } + + public static void main(String[] args) { + new Model1().start(); + } } diff --git a/Dream2/src/examples/java/dream/examples/financial/Model2.java b/Dream2/src/examples/java/dream/examples/financial/Model2.java index 7676696..a63825b 100644 --- a/Dream2/src/examples/java/dream/examples/financial/Model2.java +++ b/Dream2/src/examples/java/dream/examples/financial/Model2.java @@ -1,30 +1,37 @@ package dream.examples.financial; +import java.util.Arrays; +import java.util.List; + import dream.client.RemoteVar; import dream.client.Signal; -import dream.client.ValueChangeListener; -import dream.common.Consts; +import dream.examples.util.Client; + +public class Model2 extends Client { + public Model2() { + super("Model2"); + } + + @Override + protected List waitForVars() { + return Arrays.asList("marketIndex@InputModel", "stockOpts@InputModel"); + } -public class Model2 implements ValueChangeListener { public void start() { - Consts.hostName = "Model2"; + final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex"); + final RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts"); - RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex"); - RemoteVar stockOpts = new RemoteVar<>("InputModel", "stockOpts"); + final Signal f2 = new Signal<>("f2", () -> { + if (marketIndex.get() == null || stockOpts.get() == null) { + return null; + } else { + return marketIndex.get() + stockOpts.get() * 2; + } + } , marketIndex, stockOpts); - Signal f2 = new Signal<>("f2", () -> { - if (marketIndex.get() == null || stockOpts.get() == null) { return null; } - else { return marketIndex.get() + stockOpts.get() * 2; } - }, marketIndex, stockOpts); - - f2.addValueChangeListener(this); + f2.change().addHandler((oldVal, newVal) -> System.out.println("New value for f2: " + newVal)); } - @Override - public void notifyValueChanged(Integer newValue) { - System.out.println("New value for f2: " + newValue); - } - public static void main(String[] args) { new Model2().start(); } diff --git a/Dream2/src/examples/java/dream/examples/financial/Model3.java b/Dream2/src/examples/java/dream/examples/financial/Model3.java index 0151fdf..f85bdce 100644 --- a/Dream2/src/examples/java/dream/examples/financial/Model3.java +++ b/Dream2/src/examples/java/dream/examples/financial/Model3.java @@ -1,30 +1,38 @@ package dream.examples.financial; +import java.util.Arrays; +import java.util.List; + import dream.client.RemoteVar; import dream.client.Signal; -import dream.client.ValueChangeListener; -import dream.common.Consts; +import dream.examples.util.Client; -public class Model3 implements ValueChangeListener { - public void start() { - Consts.hostName = "Model3"; - - RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex"); - RemoteVar news = new RemoteVar<>("InputModel", "news"); - - Signal f3 = new Signal<>("f3", () -> { - if (marketIndex.get() == null || news.get() == null) { return null; } - else { return marketIndex.get() + news.get(); } - }, marketIndex, news); - - f3.addValueChangeListener(this); +public class Model3 extends Client { + + public Model3() { + super("Model3"); } @Override - public void notifyValueChanged(Integer newValue) { - System.out.println("New value for f3: " + newValue); + protected List waitForVars() { + return Arrays.asList("marketIndex@InputModel", "news@InputModel"); } - + + public void start() { + final RemoteVar marketIndex = new RemoteVar<>("InputModel", "marketIndex"); + final RemoteVar news = new RemoteVar<>("InputModel", "news"); + + final Signal f3 = new Signal<>("f3", () -> { + if (marketIndex.get() == null || news.get() == null) { + return null; + } else { + return marketIndex.get() + news.get(); + } + } , marketIndex, news); + + f3.change().addHandler((oldVal, newVal) -> System.out.println("New value for f3: " + newVal)); + } + public static void main(String[] args) { new Model3().start(); } diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Boss.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Boss.java new file mode 100644 index 0000000..d278e17 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Boss.java @@ -0,0 +1,60 @@ +package dream.examples.form.complete_glitchfree; + +import dream.client.Var; +import dream.examples.util.Pair; + +public class Boss extends FormClient { + + public static final String NAME = "Boss"; + public static final String EuroPerHour = "euro_per_hour"; + public static final String RequiredHours = "required_hours"; + + private Var eph; + private Var> rh; + + public Boss() { + super(NAME, "Euro/Hour", "Minimum Hours", "Maximum Hours"); + setInitValues(Double.toString(8.5), Integer.toString(10), Integer.toString(60)); + } + + @Override + protected void init() { + eph = new Var<>(EuroPerHour, 8.5); + rh = new Var<>(RequiredHours, new Pair<>(10, 60)); + } + + @Override + public void typedText(int i, String typedText) { + switch (i) { + case 0: + Double value = Double.valueOf(typedText); + lock(Variable.get(eph)); + eph.set(value); + unlock(); + logger.fine("Set Euro_Per_Hour to " + value); + break; + case 1: + Integer value2 = Integer.valueOf(typedText); + lock(Variable.get(rh)); + rh.set(new Pair<>(value2, rh.get().getSecond())); + unlock(); + logger.fine("Set minimum @ Required_Hours to " + value2); + break; + case 2: + Integer value3 = Integer.valueOf(typedText); + lock(Variable.get(rh)); + rh.set(new Pair<>(rh.get().getFirst(), value3)); + unlock(); + logger.fine("Set maximum @ Required_Hours to " + value3); + break; + default: + break; + } + + } + + public static void main(String[] args) { + new Boss(); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/CompleteGlitchFreeFormServer.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/CompleteGlitchFreeFormServer.java new file mode 100644 index 0000000..df02d5b --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/CompleteGlitchFreeFormServer.java @@ -0,0 +1,52 @@ +package dream.examples.form.complete_glitchfree; + +import dream.client.Signal; + +public class CompleteGlitchFreeFormServer extends FormServer { + + @Override + protected void createDependencies() { + logger.fine("Building Dependencies"); + // TODO implement glitch freedom + final Signal minimumHours = new Signal<>(MinimumHours, () -> { + if (working_hours.get() != null && required_hours.get() != null) + return working_hours.get() > required_hours.get().getFirst(); + else + return false; + }, working_hours, required_hours); + + final Signal maximumHours = new Signal<>(MaximumHours, () -> { + if (working_hours.get() != null && required_hours.get() != null) + return working_hours.get() < required_hours.get().getSecond(); + else + return false; + }, working_hours, required_hours); + + final Signal minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> { + if (euro_per_hour.get() != null) + return euro_per_hour.get() > 10; + else + return false; + }, euro_per_hour); + + new Signal<>(SettingsOkay, () -> { + if (minimumHours.get() != null && maximumHours.get() != null && minimumEuroPerHour.get() != null) + return minimumHours.get() && maximumHours.get() && minimumEuroPerHour.get(); + else + return false; + }, minimumHours, maximumHours, minimumEuroPerHour); + + new Signal<>(Salary, () -> { + if (working_hours.get() != null && euro_per_hour.get() != null) + return working_hours.get() * euro_per_hour.get(); + else + return 0.0; + }, working_hours, euro_per_hour); + + logger.fine("Finished building Dependencies"); + } + + public static void main(String[] args) { + new CompleteGlitchFreeFormServer(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormClient.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormClient.java new file mode 100644 index 0000000..efe026a --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormClient.java @@ -0,0 +1,71 @@ +package dream.examples.form.complete_glitchfree; + +import java.awt.Color; +import java.util.Arrays; +import java.util.List; + +import dream.client.RemoteVar; +import dream.client.Signal; + +public abstract class FormClient extends LockClient { + + private RemoteVar salary; + private RemoteVar settings; + private Signal remoteSalary; + private Signal remoteSettings; + + private FormGUI gui; + private String[] labelText; + private String[] values; + + public FormClient(String name, String... labelText) { + super(name); + this.labelText = labelText; + } + + @Override + protected List waitForVars() { + return Arrays.asList(toVar(FormServer.NAME, FormServer.Salary), + toVar(FormServer.NAME, FormServer.SettingsOkay)); + } + + protected void start() { + gui = new FormGUI(getHostName(), labelText); + gui.setListener(this); + if (values != null) + gui.setInitValues(values); + + salary = new RemoteVar<>(FormServer.NAME, FormServer.Salary); + settings = new RemoteVar<>(FormServer.NAME, FormServer.SettingsOkay); + + remoteSalary = new Signal<>("remoteSalary", () -> { + if (salary.get() != null) + return salary.get(); + else + return 0.0; + }, salary); + + remoteSettings = new Signal<>("remoteSettings", () -> { + if (settings.get() != null) + return settings.get(); + else + return false; + }, settings); + + gui.setText("Salary: "); + gui.setColor(Color.red); + remoteSalary.change().addHandler((o, n) -> gui.setText("Salary: " + n.toString())); + remoteSettings.change().addHandler((o, n) -> gui.setColor((n ? Color.green : Color.red))); + } + + public abstract void typedText(int i, String typedText); + + public void setInitValues(String... values) { + this.values = values; + } + + @Override + protected void setup() { + start(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormGUI.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormGUI.java new file mode 100644 index 0000000..93f96dd --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormGUI.java @@ -0,0 +1,124 @@ +package dream.examples.form.complete_glitchfree; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +public class FormGUI extends JFrame { + + private static final long serialVersionUID = 9205614575242281482L; + private JTextField[] sendText; + private FormClient listener; + private JLabel display; + private String[] labelText; + + public FormGUI(String name, String... labelText) { + setTitle(name); + this.labelText = labelText; + initUI(); + } + + private void initUI() { + getContentPane().setLayout(new BorderLayout()); + JPanel all = new JPanel(); + all.setLayout(new GridLayout(0, 2)); + getContentPane().add(all, BorderLayout.CENTER); + + sendText = new JTextField[labelText.length]; + + for (int i = 0; i < labelText.length; i++) { + sendText[i] = new JTextField(20); + sendText[i].addKeyListener(new MultiListener(i)); + JButton sendButton = new JButton("Set"); + sendButton.addActionListener(new MultiListener(i)); + + JLabel label = new JLabel(labelText[i] + ": "); + + JPanel p = new JPanel(); + p.add(label); + p.add(sendText[i]); + + all.add(p); + all.add(sendButton); + } + + display = new JLabel(""); + display.setPreferredSize(new Dimension(100, 30)); + display.setMinimumSize(new Dimension(100, 30)); + display.setOpaque(true); + getContentPane().add(display, BorderLayout.NORTH); + + // setSize(300, 200); + setLocationRelativeTo(null); + setDefaultCloseOperation(EXIT_ON_CLOSE); + + pack(); + setVisible(true); + } + + public void setInitValues(String... values) { + for (int i = 0; i < values.length; i++) { + if (sendText[i].getText() == null || sendText[i].getText().isEmpty()) { + sendText[i].setText(values[i]); + } + } + } + + private void sendText(int i) { + listener.typedText(i, getTypedText(i)); + } + + public void setListener(FormClient c) { + listener = c; + } + + public String getTypedText(int i) { + return sendText[i].getText(); + } + + public void setText(String text) { + display.setText(text); + } + + public void setColor(Color bg) { + display.setBackground(bg); + } + + class MultiListener implements KeyListener, ActionListener { + private int i; + + public MultiListener(int i) { + this.i = i; + } + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + sendText(i); + } + + @Override + public void actionPerformed(ActionEvent e) { + sendText(i); + } + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormServer.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormServer.java new file mode 100644 index 0000000..3789a9a --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/FormServer.java @@ -0,0 +1,105 @@ +package dream.examples.form.complete_glitchfree; + +import java.util.logging.Level; + +import dream.client.DreamClient; +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.examples.util.Pair; + +public class FormServer extends LockClient { + + protected RemoteVar working_hours; + protected RemoteVar euro_per_hour; + protected RemoteVar> required_hours; + + public static final String NAME = "FormServer"; + public static final String MinimumHours = "minimumHours"; + public static final String MaximumHours = "maximumHours"; + public static final String MinimumEuroPerHour = "minimumEuroPerHour"; + public static final String SettingsOkay = "settingsOkay"; + public static final String Salary = "salary"; + + public FormServer() { + super(NAME); + detectNewSession(); + } + + /** + * Look for new clients every 5 seconds + */ + private void detectNewSession() { + while (euro_per_hour == null || working_hours == null || required_hours == null) { + for (String str : DreamClient.instance.listVariables()) { + String host = str.split("@")[1]; + String var = str.split("@")[0]; + if (working_hours == null && var.equalsIgnoreCase(Secretary.WorkingHours)) { + working_hours = new RemoteVar<>(host, var); + logger.fine("Found Secretary"); + } else if (euro_per_hour == null && var.equalsIgnoreCase(Boss.EuroPerHour)) { + euro_per_hour = new RemoteVar<>(host, var); + logger.fine("Found Boss"); + } else if (required_hours == null && var.equalsIgnoreCase(Boss.RequiredHours)) { + required_hours = new RemoteVar<>(host, var); + logger.fine("Found Boss"); + } + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e); + } + } + createDependencies(); + } + + protected void createDependencies() { + logger.fine("Building Dependencies"); + + final Signal minimumHours = new Signal<>(MinimumHours, () -> { + if (working_hours.get() != null && required_hours.get() != null) + return working_hours.get() > required_hours.get().getFirst(); + else + return false; + }, working_hours, required_hours); + + final Signal maximumHours = new Signal<>(MaximumHours, () -> { + if (working_hours.get() != null && required_hours.get() != null) + return working_hours.get() < required_hours.get().getSecond(); + else + return false; + }, working_hours, required_hours); + + final Signal minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> { + if (euro_per_hour.get() != null) + return euro_per_hour.get() > 10; + else + return false; + }, euro_per_hour); + + new Signal<>(SettingsOkay, () -> { + if (minimumHours.get() != null && maximumHours.get() != null && minimumEuroPerHour.get() != null) + return minimumHours.get() && maximumHours.get() && minimumEuroPerHour.get(); + else + return false; + }, minimumHours, maximumHours, minimumEuroPerHour); + + new Signal<>(Salary, () -> { + if (working_hours.get() != null && euro_per_hour.get() != null) + return working_hours.get() * euro_per_hour.get(); + else + return 0.0; + }, working_hours, euro_per_hour); + + logger.fine("Finished building Dependencies"); + } + + public static void main(String[] args) { + new FormServer(); + } + + @Override + protected void setup() { + } + +} diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockClient.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockClient.java new file mode 100644 index 0000000..7b88796 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockClient.java @@ -0,0 +1,80 @@ +package dream.examples.form.complete_glitchfree; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.examples.util.Client; +import dream.examples.util.Pair; + +public abstract class LockClient extends Client { + private boolean setup = false; + private Var lockRequest; + private List hasLock; + + public LockClient(String name) { + super(name); + + // Establish new session with LockManager + RemoteVar>> registeredClients = new RemoteVar<>(LockManager.NAME, + LockManager.VAR_clients); + Signal>> s = new Signal<>("s", () -> { + if (registeredClients.get() == null) + return new ArrayList>(); + else + return registeredClients.get(); + }, registeredClients); + s.change().addHandler((o, n) -> { + if (n.contains(new Pair<>(this.getHostName(), LockManager.VAR_requestLock)) && setup == false) + lockSetup(); + }); + + hasLock = new ArrayList<>(); + lockRequest = new Var<>(LockManager.VAR_requestLock, null); + logger.fine("Setup: Waiting for Registration to LockManager ..."); + } + + private void lockSetup() { + setup = true; + RemoteVar lock = new RemoteVar<>(LockManager.NAME, LockManager.VAR_lock); + Signal sLock = new Signal<>("lock", () -> { + return lock.get(); + }, lock); + sLock.change().addHandler((oldValue, newValue) -> { + newValue.forEach((var, client) -> { + if (client.equals(getHostName())) + hasLock.add(var); + else + hasLock.remove(var); + }); + synchronized (this) { + this.notify(); + } + }); + + setup(); + } + + protected abstract void setup(); + + public void lock(Variable... vars) { + lockRequest.set(new LockRequest(getHostName(), vars)); + synchronized (this) { + while (!hasLock.containsAll(Arrays.asList(vars))) { + try { + this.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void unlock() { + lockRequest.set(new LockRequest(getHostName())); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockManager.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockManager.java new file mode 100644 index 0000000..d925fd0 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/LockManager.java @@ -0,0 +1,224 @@ +package dream.examples.form.complete_glitchfree; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Level; + +import dream.client.DreamClient; +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.common.utils.DependencyGraph; +import dream.examples.util.Client; +import dream.examples.util.Pair; + +public class LockManager extends Client { + + public static final String VAR_lock = "lock"; + public static final String VAR_requestLock = "requestLock"; + public static final String VAR_clients = "clients"; + public static final String NAME = "LockManager"; + + private Var lock; + private final Var> clients; + private LinkedList lockRequests; + + public LockManager() { + super(NAME); + clients = new Var<>(VAR_clients, new ArrayList<>()); + lock = new Var<>(VAR_lock, new Lock()); + lockRequests = new LinkedList<>(); + detectNewSession(); + } + + private void detectNewSession() { + Set vars = DreamClient.instance.listVariables(); + vars.stream().map(x -> new Variable(x.split("@")[1], x.split("@")[0])).// Pair(Host,Var) + filter(x -> !clients.get().contains(x) && x.getVar().equalsIgnoreCase(VAR_requestLock)).// + forEach(x -> createNewSessionFor(x)); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e); + } + + detectNewSession(); + } + + private void createNewSessionFor(Variable x) { + RemoteVar rv = new RemoteVar<>(x.getHost(), x.getVar()); + Signal s = new Signal<>(x.getHost() + "request", () -> { + if (rv.get() != null) + return rv.get(); + else + return null; + }, rv); + s.change().addHandler((oldValue, newValue) -> { + if (newValue.isLockRequest()) { + // client requesting a lock + if (!lock.get().isLocked(newValue.getVars())) { + lock.set(new Lock(lock.get(), newValue)); + } else { + // already locked, adding to queue + lockRequests.add(newValue); + } + } else { + // client trying to release a lock + lock.set(new Lock(lock.get(), newValue)); + removeLockRequestsFor(x.getHost()); + processNextRequest(); + } + }); + clients.modify(old -> old.add(x)); + } + + private void processNextRequest() { + for (LockRequest req : lockRequests) { + if (!lock.get().isLocked(req.getVars())) { + lock.set(new Lock(lock.get(), req)); + lockRequests.remove(req); + break; + } + } + } + + private void removeLockRequestsFor(String host) { + for (LockRequest req : lockRequests) { + if (req.getClient().equals(host)) { + lockRequests.remove(req); + } + } + } + + public static void main(String[] args) { + new LockManager(); + } +} + +class Variable extends Pair { + private static final long serialVersionUID = 4689891891604406371L; + + public Variable(String host, String var) { + super(host, var); + } + + public String getHost() { + return getFirst(); + } + + public String getVar() { + return getSecond(); + } + + public static Variable get(Var v) { + return new Variable(v.getHost(), v.getObject()); + } + + public static Variable fromDreamString(String s) { + String[] temp = s.split("@", 2); + return new Variable(temp[1], temp[0]); + } + + public String toDreamString() { + return getVar() + "@" + getHost(); + } + + @Override + public String toString() { + return "Var" + super.toString(); + } +} + +class LockRequest implements Serializable { + private static final long serialVersionUID = -7166632148414861582L; + private CopyOnWriteArrayList vars; + private String client; + + public LockRequest(String client, Variable... vars) { + this.vars = new CopyOnWriteArrayList<>(); + this.vars.addAll(Arrays.asList(vars)); + this.client = client; + + computeDependencies(); + } + + private void computeDependencies() { + Map> nodes = new HashMap<>(); + DependencyGraph.instance.getGraph().forEach((v1, v2) -> { + Collection t = new LinkedList<>(); + v2.forEach(x -> t.add(Variable.fromDreamString(x))); + nodes.put(Variable.fromDreamString(v1), t); + }); + for (Variable v : vars) { + computeDependencies(nodes, v); + } + } + + private void computeDependencies(Map> nodes, Variable v) { + nodes.forEach((v1, v2) -> { + if (v2.contains(v) && !vars.contains(v1)) { + // v1 depends on v + this.vars.add(v1); + computeDependencies(nodes, v1); + } + }); + } + + public Variable[] getVars() { + return vars.toArray(new Variable[] {}); + } + + public String getClient() { + return client; + } + + public boolean isLockRequest() { + return vars.size() > 0; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (isLockRequest()) + sb.append("LockRequest(").append(client).append("->").append(vars).append(")"); + else + sb.append("LockRelease()"); + return sb.toString(); + } +} + +class Lock extends HashMap { + private static final long serialVersionUID = -4195570287637533298L; + + public Lock() { + + } + + public Lock(Lock lock, LockRequest req) { + this.putAll(lock); + if (!req.isLockRequest()) { + // lock release + for (Iterator k = keySet().iterator(); k.hasNext();) { + if (get(k.next()).equals(req.getClient())) + k.remove(); + } + } else { + for (int i = 0; i < req.getVars().length; i++) { + put(req.getVars()[i], req.getClient()); + } + } + } + + public boolean isLocked(Variable[] vars) { + return Arrays.asList(vars).stream().anyMatch(x -> containsKey(x)); + } + +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Secretary.java b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Secretary.java new file mode 100644 index 0000000..638968e --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/Secretary.java @@ -0,0 +1,34 @@ +package dream.examples.form.complete_glitchfree; + +import dream.client.Var; + +public class Secretary extends FormClient { + + public static final String NAME = "Secretary"; + public static final String WorkingHours = "working_hours"; + + private Var wh; + + public Secretary() { + super(NAME, "Working Hours"); + setInitValues(Integer.toString(5)); + } + + @Override + protected void init() { + wh = new Var<>(WorkingHours, 5); + } + + @Override + public void typedText(int i, String typedText) { + Integer value = Integer.valueOf(typedText); + lock(Variable.get(wh)); + wh.set(value); + unlock(); + logger.fine("Set Working_Hours to " + value); + } + + public static void main(String[] args) { + new Secretary(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/complete_glitchfree_graph.png b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/complete_glitchfree_graph.png new file mode 100644 index 0000000..2381fa5 Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/form/complete_glitchfree/complete_glitchfree_graph.png differ diff --git a/Dream2/src/examples/java/dream/examples/form/core/FormClient.java b/Dream2/src/examples/java/dream/examples/form/core/FormClient.java new file mode 100644 index 0000000..dd77f4d --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/core/FormClient.java @@ -0,0 +1,67 @@ +package dream.examples.form.core; + +import java.awt.Color; +import java.util.Arrays; +import java.util.List; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.examples.util.Client; + +public abstract class FormClient extends Client { + + private RemoteVar salary; + private RemoteVar settings; + private Signal remoteSalary; + private Signal remoteSettings; + + private FormGUI gui; + private String[] labelText; + private String[] values; + + public FormClient(String name, String... labelText) { + super(name); + this.labelText = labelText; + } + + @Override + protected List waitForVars() { + return Arrays.asList(toVar(FormServer.NAME, FormServer.Salary), + toVar(FormServer.NAME, FormServer.SettingsOkay)); + } + + protected void start() { + gui = new FormGUI(getHostName(), labelText); + gui.setListener(this); + if (values != null) + gui.setInitValues(values); + + salary = new RemoteVar<>(FormServer.NAME, FormServer.Salary); + settings = new RemoteVar<>(FormServer.NAME, FormServer.SettingsOkay); + + remoteSalary = new Signal<>("remoteSalary", () -> { + if (salary.get() != null) + return salary.get(); + else + return 0.0; + }, salary); + + remoteSettings = new Signal<>("remoteSettings", () -> { + if (settings.get() != null) + return settings.get(); + else + return false; + }, settings); + + gui.setText("Salary: "); + gui.setColor(Color.red); + remoteSalary.change().addHandler((o, n) -> gui.setText("Salary: " + n.toString())); + remoteSettings.change().addHandler((o, n) -> gui.setColor((n ? Color.green : Color.red))); + } + + public abstract void typedText(int i, String typedText); + + public void setInitValues(String... values) { + this.values = values; + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/core/FormGUI.java b/Dream2/src/examples/java/dream/examples/form/core/FormGUI.java new file mode 100644 index 0000000..3e91cc7 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/core/FormGUI.java @@ -0,0 +1,124 @@ +package dream.examples.form.core; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +public class FormGUI extends JFrame { + + private static final long serialVersionUID = 9205614575242281482L; + private JTextField[] sendText; + private FormClient listener; + private JLabel display; + private String[] labelText; + + public FormGUI(String name, String... labelText) { + setTitle(name); + this.labelText = labelText; + initUI(); + } + + private void initUI() { + getContentPane().setLayout(new BorderLayout()); + JPanel all = new JPanel(); + all.setLayout(new GridLayout(0, 2)); + getContentPane().add(all, BorderLayout.CENTER); + + sendText = new JTextField[labelText.length]; + + for (int i = 0; i < labelText.length; i++) { + sendText[i] = new JTextField(20); + sendText[i].addKeyListener(new MultiListener(i)); + JButton sendButton = new JButton("Set"); + sendButton.addActionListener(new MultiListener(i)); + + JLabel label = new JLabel(labelText[i] + ": "); + + JPanel p = new JPanel(); + p.add(label); + p.add(sendText[i]); + + all.add(p); + all.add(sendButton); + } + + display = new JLabel(""); + display.setPreferredSize(new Dimension(100, 30)); + display.setMinimumSize(new Dimension(100, 30)); + display.setOpaque(true); + getContentPane().add(display, BorderLayout.NORTH); + + // setSize(300, 200); + setLocationRelativeTo(null); + setDefaultCloseOperation(EXIT_ON_CLOSE); + + pack(); + setVisible(true); + } + + public void setInitValues(String... values) { + for (int i = 0; i < values.length; i++) { + if (sendText[i].getText() == null || sendText[i].getText().isEmpty()) { + sendText[i].setText(values[i]); + } + } + } + + private void sendText(int i) { + listener.typedText(i, getTypedText(i)); + } + + public void setListener(FormClient c) { + listener = c; + } + + public String getTypedText(int i) { + return sendText[i].getText(); + } + + public void setText(String text) { + display.setText(text); + } + + public void setColor(Color bg) { + display.setBackground(bg); + } + + class MultiListener implements KeyListener, ActionListener { + private int i; + + public MultiListener(int i) { + this.i = i; + } + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + sendText(i); + } + + @Override + public void actionPerformed(ActionEvent e) { + sendText(i); + } + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/core/FormServer.java b/Dream2/src/examples/java/dream/examples/form/core/FormServer.java new file mode 100644 index 0000000..ea9795f --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/core/FormServer.java @@ -0,0 +1,25 @@ +package dream.examples.form.core; + +import dream.client.RemoteVar; +import dream.examples.util.Client; + +public class FormServer extends Client { + + public static final String NAME = "FormServer"; + public static final String MinimumHours = "minimumHours"; + public static final String MaximumHours = "maximumHours"; + public static final String MinimumEuroPerHour = "minimumEuroPerHour"; + public static final String SettingsOkay = "settingsOkay"; + public static final String Salary = "salary"; + + protected RemoteVar working_hours; + protected RemoteVar euro_per_hour; + + public FormServer() { + super(NAME); + } + + public static void main(String[] args) { + new FormServer(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/graph2.png b/Dream2/src/examples/java/dream/examples/form/graph2.png new file mode 100644 index 0000000..195cccc Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/form/graph2.png differ diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-advanced-complete-glitch-freedom.txt b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-complete-glitch-freedom.txt new file mode 100644 index 0000000..14deb29 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-complete-glitch-freedom.txt @@ -0,0 +1,17 @@ +complete_glitchfree/Boss.java +complete_glitchfree/Secretary.java +complete_glitchfree/FormClient.java +complete_glitchfree/FormGUI.java +complete_glitchfree/FormServer.java +complete_glitchfree/LockClient.java +complete_glitchfree/CompleteGlitchFreeFormServer.java +complete_glitchfree/LockManager.java + +http://cloc.sourceforge.net v 1.64 T=0.03 s (314.6 files/s, 29496.1 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 8 132 11 607 +------------------------------------------------------------------------------- +SUM: 8 132 11 607 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-advanced-dream.txt b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-dream.txt new file mode 100644 index 0000000..9ba9b2d --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/line-count-advanced-dream.txt @@ -0,0 +1,14 @@ +complete_glitchfree/Boss.java +complete_glitchfree/Secretary.java +complete_glitchfree/FormClient.java +complete_glitchfree/FormGUI.java +complete_glitchfree/FormServer.java + +http://cloc.sourceforge.net v 1.64 T=0.02 s (263.4 files/s, 20755.3 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 5 76 4 314 +------------------------------------------------------------------------------- +SUM: 5 76 4 314 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-simple-dream.txt b/Dream2/src/examples/java/dream/examples/form/line-count-simple-dream.txt new file mode 100644 index 0000000..35c620c --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/line-count-simple-dream.txt @@ -0,0 +1,14 @@ +Counted files: +core +simple/Boss.java +simple/Secretary.java +simple/FormServer.java + +http://cloc.sourceforge.net v 1.64 T=0.02 s (295.7 files/s, 18678.1 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 6 78 4 297 +------------------------------------------------------------------------------- +SUM: 6 78 4 297 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/form/line-count-simple-single-glitch-freedom.txt b/Dream2/src/examples/java/dream/examples/form/line-count-simple-single-glitch-freedom.txt new file mode 100644 index 0000000..47cfd91 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/line-count-simple-single-glitch-freedom.txt @@ -0,0 +1,15 @@ +Counted Files: +core +simple/Boss.java +simple/Secretary.java +simple/FormServer.java +simple/GlitchFreeFormServer.java + +http://cloc.sourceforge.net v 1.64 T=0.03 s (279.9 files/s, 17590.9 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 7 93 4 343 +------------------------------------------------------------------------------- +SUM: 7 93 4 343 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/form/package-info.java b/Dream2/src/examples/java/dream/examples/form/package-info.java new file mode 100644 index 0000000..14f2b0c --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/package-info.java @@ -0,0 +1,21 @@ +/** + * This packages contains two examples:
+ * a) {@link dream.examples.form.simple simple}: uses a simple graph with a + * probable glitch. There are two different solutions to this glitch:
+ * {@link dream.examples.form.simple.FormServer FormServer} depending on Dream's + * single_glitch_free consistency to solve the glitch and
+ * {@link dream.examples.form.simple.GlitchFreeFormServer GlitchFreeFormServer}, + * which ensures itself that no glitch can occur.
+ *
+ * b) {@link dream.examples.form.complete_glitchfree complete} uses a different + * graph, which requires a locking mechanism. + * {@link dream.examples.form.complete_glitchfree.CompleteGlitchFreeFormServer + * CompleteGlitchFreeFormServer}, which ensures complete_glitch_freedom itself + * with a own locking mechanism.
+ *
+ *
+ * Both examples contain an image of their used dependency graph + * + * @author Tobias Becker + */ +package dream.examples.form; \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/form/simple/Boss.java b/Dream2/src/examples/java/dream/examples/form/simple/Boss.java new file mode 100644 index 0000000..c21fd78 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/simple/Boss.java @@ -0,0 +1,41 @@ +package dream.examples.form.simple; + +import dream.client.Var; +import dream.examples.form.core.FormClient; + +public class Boss extends FormClient { + + public static final String NAME = "Boss"; + public static final String EuroPerHour = "euro_per_hour"; + + protected Var eph; + + public Boss() { + super(NAME, "Euro/Hour"); + setInitValues(Double.toString(8.5)); + } + + @Override + protected void init() { + eph = new Var<>(EuroPerHour, 8.5); + } + + @Override + public void typedText(int i, String typedText) { + switch (i) { + case 0: + Double value = Double.valueOf(typedText); + eph.set(value); + logger.fine("Set Euro_Per_Hour to " + value); + break; + default: + break; + } + + } + + public static void main(String[] args) { + Boss b = new Boss(); + b.start(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/simple/FormServer.java b/Dream2/src/examples/java/dream/examples/form/simple/FormServer.java new file mode 100644 index 0000000..3a56c02 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/simple/FormServer.java @@ -0,0 +1,87 @@ +package dream.examples.form.simple; + +import java.util.logging.Level; + +import dream.client.DreamClient; +import dream.client.RemoteVar; +import dream.client.Signal; + +public class FormServer extends dream.examples.form.core.FormServer { + + protected RemoteVar working_hours; + protected RemoteVar euro_per_hour; + + public FormServer() { + detectNewSession(); + } + + /** + * Look for new clients every 5 seconds + */ + private void detectNewSession() { + while (euro_per_hour == null || working_hours == null) { + for (String str : DreamClient.instance.listVariables()) { + String host = str.split("@")[1]; + String var = str.split("@")[0]; + if (working_hours == null && var.equalsIgnoreCase(Secretary.WorkingHours)) { + working_hours = new RemoteVar<>(host, var); + logger.fine("Found Secretary"); + } else if (euro_per_hour == null && var.equalsIgnoreCase(Boss.EuroPerHour)) { + euro_per_hour = new RemoteVar<>(host, var); + logger.fine("Found Boss"); + } + } + try { + Thread.sleep(500); + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e); + } + } + createDependencies(); + } + + protected void createDependencies() { + logger.fine("Building Dependencies"); + + final Signal minimumHours = new Signal<>(MinimumHours, () -> { + if (working_hours.get() != null) + return working_hours.get() > 10; + else + return false; + }, working_hours); + + final Signal maximumHours = new Signal<>(MaximumHours, () -> { + if (working_hours.get() != null) + return working_hours.get() < 60; + else + return false; + }, working_hours); + + final Signal minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> { + if (euro_per_hour.get() != null) + return euro_per_hour.get() > 10; + else + return false; + }, euro_per_hour); + + new Signal<>(SettingsOkay, () -> { + if (minimumHours.get() != null && maximumHours.get() != null && minimumEuroPerHour.get() != null) + return minimumHours.get() && maximumHours.get() && minimumEuroPerHour.get(); + else + return false; + }, minimumHours, maximumHours, minimumEuroPerHour); + + new Signal<>(Salary, () -> { + if (working_hours.get() != null && euro_per_hour.get() != null) + return working_hours.get() * euro_per_hour.get(); + else + return 0.0; + }, working_hours, euro_per_hour); + + logger.fine("Finished building Dependencies"); + } + + public static void main(String[] args) { + new FormServer(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/form/simple/GlitchFreeFormServer.java b/Dream2/src/examples/java/dream/examples/form/simple/GlitchFreeFormServer.java new file mode 100644 index 0000000..d98caab --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/simple/GlitchFreeFormServer.java @@ -0,0 +1,61 @@ +package dream.examples.form.simple; + +import java.util.LinkedList; + +import dream.client.Signal; +import dream.client.Var; + +public class GlitchFreeFormServer extends FormServer { + + final LinkedList minimumQueue = new LinkedList<>(); + final LinkedList maximumQueue = new LinkedList<>(); + final Var settingsOkay = new Var<>(SettingsOkay, false); + Signal minimumEuroPerHour; + + private void updateSettingsOkay() { + if (minimumQueue.size() > 0 && maximumQueue.size() > 0 && minimumEuroPerHour.get() != null) + settingsOkay.set(minimumQueue.pop() && maximumQueue.pop() && minimumEuroPerHour.get()); + } + + @Override + protected void createDependencies() { + logger.fine("Building Dependencies"); + + minimumEuroPerHour = new Signal<>(MinimumEuroPerHour, () -> { + return euro_per_hour.get() > 10; + }, euro_per_hour); + + final Signal minimumHours = new Signal<>(MinimumHours, () -> { + return working_hours.get() > 10; + }, working_hours); + + final Signal maximumHours = new Signal<>(MaximumHours, () -> { + return working_hours.get() < 60; + }, working_hours); + + minimumEuroPerHour.change().addHandler((o, n) -> updateSettingsOkay()); + + minimumHours.change().addHandler((o, n) -> { + minimumQueue.add(n); + updateSettingsOkay(); + }); + + maximumHours.change().addHandler((o, n) -> { + maximumQueue.add(n); + updateSettingsOkay(); + }); + + new Signal<>(Salary, () -> { + if (working_hours.get() != null && euro_per_hour.get() != null) + return working_hours.get() * euro_per_hour.get(); + else + return 0.0; + }, working_hours, euro_per_hour); + + logger.fine("Finished building Dependencies"); + } + + public static void main(String[] args) { + new GlitchFreeFormServer(); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/form/simple/Secretary.java b/Dream2/src/examples/java/dream/examples/form/simple/Secretary.java new file mode 100644 index 0000000..b10e312 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/form/simple/Secretary.java @@ -0,0 +1,35 @@ +package dream.examples.form.simple; + +import dream.client.Var; +import dream.examples.form.core.FormClient; + +public class Secretary extends FormClient { + + public static final String NAME = "Secretary"; + public static final String WorkingHours = "working_hours"; + + private Var wh; + + public Secretary() { + super(NAME, "Working Hours"); + setInitValues(Integer.toString(5)); + } + + @Override + protected void init() { + wh = new Var<>(WorkingHours, 5); + } + + @Override + public void typedText(int i, String typedText) { + Integer value = Integer.valueOf(typedText); + wh.set(value); + logger.fine("Set Working_Hours to " + value); + } + + public static void main(String[] args) { + Secretary s = new Secretary(); + s.start(); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/form/simple/graph.png b/Dream2/src/examples/java/dream/examples/form/simple/graph.png new file mode 100644 index 0000000..c2275dc Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/form/simple/graph.png differ diff --git a/Dream2/src/examples/java/dream/examples/local/Example1.java b/Dream2/src/examples/java/dream/examples/local/Example1.java index 77d7626..03f0632 100755 --- a/Dream2/src/examples/java/dream/examples/local/Example1.java +++ b/Dream2/src/examples/java/dream/examples/local/Example1.java @@ -5,34 +5,41 @@ public class Example1 { - public static void main(String args[]) { - final Var varInt = new Var<>("varInt", 1); - final Var varDouble = new Var<>("varDouble", 1.0); - final Var varBool = new Var<>("varBool", false); - final Var varString1 = new Var<>("varString1", ""); - final Var varString2 = new Var<>("varString2", ""); - - final Signal signalInt = new Signal("signalInt", () -> 10 - 2 + (varInt.get() * 2 + varInt.get()) / 2, varInt); - final Signal signalDouble = new Signal("signalDouble", () -> varDouble.get() + varDouble.get() * 2, varDouble); - final Signal signalBool = new Signal("signalBool", () -> !varBool.get(), varBool); - final Signal signalString = new Signal("signalString", () -> varString1.get() + varString2.get(), varString1, varString2); - - signalInt.addValueChangeListener(val -> System.out.println("signalInt: " + val + " (correct value: 158)")); - signalDouble.addValueChangeListener(val -> System.out.println("signalDouble: " + val + " (correct value: 4.8)")); - signalBool.addValueChangeListener(val -> System.out.println("signalBool: " + val + " (correct value: false)")); - signalString.addValueChangeListener(val -> System.out.println("signalString: " + val + " (correct value: Hello World!)")); - - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - - varInt.set(100); - varDouble.set(1.6); - varBool.set(true); - varString1.set("Hello "); - varString2.set("World!"); - - } + public static void main(String args[]) { + final Var varInt = new Var<>("varInt", 1); + final Var varDouble = new Var<>("varDouble", 1.0); + final Var varBool = new Var<>("varBool", false); + final Var varString1 = new Var<>("varString1", ""); + final Var varString2 = new Var<>("varString2", ""); + + final Signal signalInt = new Signal("signalInt", + () -> 10 - 2 + (varInt.get() * 2 + varInt.get()) / 2, varInt); + final Signal signalDouble = new Signal("signalDouble", + () -> varDouble.get() + varDouble.get() * 2, varDouble); + final Signal signalBool = new Signal("signalBool", () -> !varBool.get(), varBool); + final Signal signalString = new Signal("signalString", + () -> varString1.get() + varString2.get(), varString1, varString2); + + signalInt.change() + .addHandler((oldVal, val) -> System.out.println("signalInt: " + val + " (correct value: 158)")); + signalDouble.change() + .addHandler((oldVal, val) -> System.out.println("signalDouble: " + val + " (correct value: 4.8)")); + signalBool.change() + .addHandler((oldVal, val) -> System.out.println("signalBool: " + val + " (correct value: false)")); + signalString.change().addHandler( + (oldVal, val) -> System.out.println("signalString: " + val + " (correct value: Hello World!)")); + + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + varInt.set(100); + varDouble.set(1.6); + varBool.set(true); + varString1.set("Hello "); + varString2.set("World!"); + + } } diff --git a/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java b/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java index e3ff1f5..22292e2 100644 --- a/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java +++ b/Dream2/src/examples/java/dream/examples/local/ExampleFilter.java @@ -4,32 +4,34 @@ import dream.client.Var; public class ExampleFilter { - public static void main(String args[]) { - - final Var varInt = new Var<>("varInt", 1); - final Signal signalInt = new Signal<>("signalInt", () -> varInt.get() + 1, varInt.filter(val -> val > 10)); - final Signal signalInt2 = new Signal<>("signalInt2", () -> signalInt.get() + 1, signalInt.filter(val -> val > 20)); - - signalInt.addValueChangeListener(val -> System.out.println("SignalInt: " + val)); - signalInt2.addValueChangeListener(val -> System.out.println("SignalInt2: " + val)); - - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - - System.out.println("Expected results:"); - System.out.println("SignalInt: 12"); - System.out.println("SignalInt: 21"); - System.out.println("SignalInt2: 22"); - System.out.println(); - - varInt.set(1); - varInt.set(2); - varInt.set(11); - varInt.set(20); - varInt.set(10); - - } + public static void main(String args[]) { + + final Var varInt = new Var<>("varInt", 1); + final Signal signalInt = new Signal<>("signalInt", () -> varInt.get() + 1, + varInt.filter(val -> val > 10)); + final Signal signalInt2 = new Signal<>("signalInt2", () -> signalInt.get() + 1, + signalInt.filter(val -> val > 20)); + + signalInt.change().addHandler((oldVal, val) -> System.out.println("SignalInt: " + val)); + signalInt2.change().addHandler((oldVal, val) -> System.out.println("SignalInt2: " + val)); + + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + System.out.println("Expected results:"); + System.out.println("SignalInt: 12"); + System.out.println("SignalInt: 21"); + System.out.println("SignalInt2: 22"); + System.out.println(); + + varInt.set(1); + varInt.set(2); + varInt.set(11); + varInt.set(20); + varInt.set(10); + + } } diff --git a/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java b/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java index c050628..70fe13b 100755 --- a/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java +++ b/Dream2/src/examples/java/dream/examples/local/ExampleGlitch.java @@ -5,45 +5,45 @@ public class ExampleGlitch { - public static void main(String args[]) { - final ExampleGlitch example = new ExampleGlitch(); - example.launch(); - } - - public void launch() { - final Var var = new Var<>("var", 1.0); - - final Signal mid1 = new Signal<>("mid1", () -> var.get() * 2, var); - final Signal mid2 = new Signal<>("mid2", () -> var.get() * 3, var); - - final Signal finalResult = new Signal<>("final", () -> mid1.get() + mid2.get(), mid1, mid2); - finalResult.addValueChangeListener(System.out::println); - - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - - final double v1 = 10; - final double v2 = 20; - final double v3 = 30; - - System.out.println("Expected values (with glitch freedom): "); - System.out.println("1) " + (v1 * 2 + v1 * 3)); - System.out.println("2) " + (v2 * 2 + v2 * 3)); - System.out.println("3) " + (v3 * 2 + v3 * 3)); - - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - - var.set(v1); - var.set(v2); - var.set(v3); - - } + public static void main(String args[]) { + final ExampleGlitch example = new ExampleGlitch(); + example.launch(); + } + + public void launch() { + final Var var = new Var<>("var", 1.0); + + final Signal mid1 = new Signal<>("mid1", () -> var.get() * 2, var); + final Signal mid2 = new Signal<>("mid2", () -> var.get() * 3, var); + + final Signal finalResult = new Signal<>("final", () -> mid1.get() + mid2.get(), mid1, mid2); + finalResult.change().addHandler((oldVal, val) -> System.out.println(val)); + + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + final double v1 = 10; + final double v2 = 20; + final double v3 = 30; + + System.out.println("Expected values (with glitch freedom): "); + System.out.println("1) " + (v1 * 2 + v1 * 3)); + System.out.println("2) " + (v2 * 2 + v2 * 3)); + System.out.println("3) " + (v3 * 2 + v3 * 3)); + + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + var.set(v1); + var.set(v2); + var.set(v3); + + } } diff --git a/Dream2/src/examples/java/dream/examples/local/ExampleList.java b/Dream2/src/examples/java/dream/examples/local/ExampleList.java index cd934ed..4e8aa67 100755 --- a/Dream2/src/examples/java/dream/examples/local/ExampleList.java +++ b/Dream2/src/examples/java/dream/examples/local/ExampleList.java @@ -7,32 +7,32 @@ public class ExampleList { - public static void main(String args[]) { - final Var> varList = new Var<>("varList", new ArrayList()); - final Signal signalInt = new Signal("signalInt", () -> 1000 + varList.get().size(), varList); - - signalInt.addValueChangeListener(System.out::println); - - System.out.println("Expected results: "); - System.out.println(1001); - System.out.println(1002); - System.out.println(1003); - System.out.println(1002); - System.out.println(1000); - System.out.println(); - - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - - varList.modify(self -> self.add(10)); - varList.modify(self -> self.add(20)); - varList.modify(self -> self.add(30)); - varList.modify(self -> self.remove(1)); - varList.modify(self -> self.clear()); - - } + public static void main(String args[]) { + final Var> varList = new Var<>("varList", new ArrayList()); + final Signal signalInt = new Signal("signalInt", () -> 1000 + varList.get().size(), varList); + + signalInt.change().addHandler((oldVal, val) -> System.out.println(val)); + + System.out.println("Expected results: "); + System.out.println(1001); + System.out.println(1002); + System.out.println(1003); + System.out.println(1002); + System.out.println(1000); + System.out.println(); + + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + varList.modify(self -> self.add(10)); + varList.modify(self -> self.add(20)); + varList.modify(self -> self.add(30)); + varList.modify(self -> self.remove(1)); + varList.modify(self -> self.clear()); + + } } diff --git a/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java b/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java index 82dbfe4..9d3eeee 100755 --- a/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java +++ b/Dream2/src/examples/java/dream/examples/remote/RemoteSignalExample.java @@ -1,7 +1,7 @@ package dream.examples.remote; +import java.util.ArrayList; import java.util.HashSet; -import java.util.LinkedList; import java.util.Set; import dream.client.DreamClient; @@ -11,38 +11,41 @@ public class RemoteSignalExample { - public static void main(String args[]) { - Consts.hostName = "Signal"; - - final DreamClient client = DreamClient.instance; - client.connect(); - - final Set relevantRemoteVars = new HashSet<>(); - relevantRemoteVars.add("remoteInt@Remote"); - relevantRemoteVars.add("remoteString1@Remote"); - relevantRemoteVars.add("remoteString2@Remote"); - relevantRemoteVars.add("remoteList@Remote"); - while (!client.listVariables().containsAll(relevantRemoteVars)) { - try { - Thread.sleep(100); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - - final RemoteVar remoteInt = new RemoteVar("Remote", "remoteInt"); - final RemoteVar remoteString1 = new RemoteVar("Remote", "remoteString1"); - final RemoteVar remoteString2 = new RemoteVar("Remote", "remoteString2"); - final RemoteVar> remoteList = new RemoteVar<>("Remote", "remoteList"); - - final Signal signal1 = new Signal("signal1", () -> remoteInt.get() + remoteString1.get().length(), remoteInt, remoteString1); - final Signal signal2 = new Signal("signal2", () -> remoteInt.get(), remoteInt); - final Signal signal3 = new Signal("signal3", () -> remoteString1.get() + remoteString2.get(), remoteString1, remoteString2); - final Signal signal4 = new Signal("signal4", () -> remoteString1.get().length() + remoteList.get().size(), remoteString1, remoteList); - - signal1.addValueChangeListener(val -> System.out.println("Signal1: " + val)); - signal2.addValueChangeListener(val -> System.out.println("Signal2: " + val)); - signal3.addValueChangeListener(val -> System.out.println("Signal3: " + val)); - signal4.addValueChangeListener(val -> System.out.println("Signal4: " + val)); - } + public static void main(String args[]) { + Consts.hostName = "Signal"; + + final DreamClient client = DreamClient.instance; + client.connect(); + + final Set relevantRemoteVars = new HashSet<>(); + relevantRemoteVars.add("remoteInt@Remote"); + relevantRemoteVars.add("remoteString1@Remote"); + relevantRemoteVars.add("remoteString2@Remote"); + relevantRemoteVars.add("remoteList@Remote"); + while (!client.listVariables().containsAll(relevantRemoteVars)) { + try { + Thread.sleep(100); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + + final RemoteVar remoteInt = new RemoteVar("Remote", "remoteInt"); + final RemoteVar remoteString1 = new RemoteVar("Remote", "remoteString1"); + final RemoteVar remoteString2 = new RemoteVar("Remote", "remoteString2"); + final RemoteVar> remoteList = new RemoteVar<>("Remote", "remoteList"); + + final Signal signal1 = new Signal("signal1", + () -> remoteInt.get() + remoteString1.get().length(), remoteInt, remoteString1); + final Signal signal2 = new Signal("signal2", () -> remoteInt.get(), remoteInt); + final Signal signal3 = new Signal("signal3", () -> remoteString1.get() + remoteString2.get(), + remoteString1, remoteString2); + final Signal signal4 = new Signal("signal4", + () -> remoteString1.get().length() + remoteList.get().size(), remoteString1, remoteList); + + signal1.change().addHandler((oldVal, val) -> System.out.println("Signal1: " + val)); + signal2.change().addHandler((oldVal, val) -> System.out.println("Signal2: " + val)); + signal3.change().addHandler((oldVal, val) -> System.out.println("Signal3: " + val)); + signal4.change().addHandler((oldVal, val) -> System.out.println("Signal4: " + val)); + } } diff --git a/Dream2/src/examples/java/dream/examples/remote/RemoteVarExample.java b/Dream2/src/examples/java/dream/examples/remote/RemoteVarExample.java index b984be7..2facf23 100755 --- a/Dream2/src/examples/java/dream/examples/remote/RemoteVarExample.java +++ b/Dream2/src/examples/java/dream/examples/remote/RemoteVarExample.java @@ -8,32 +8,32 @@ public class RemoteVarExample { - public static void main(String args[]) { - Consts.hostName = "Remote"; - final Var remoteInt = new Var("remoteInt", 1); - final Var remoteString1 = new Var("remoteString1", "a"); - final Var remoteString2 = new Var("remoteString2", "b"); - final Var> remoteList = new Var>("remoteList", new ArrayList()); - final Random random = new Random(); - - try { - Thread.sleep(5000); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - - while (true) { - remoteInt.set(random.nextInt(1000)); - remoteString1.set(String.valueOf(random.nextInt(10)) + " "); - remoteString2.set(String.valueOf(random.nextInt(10)) + "!"); - remoteList.modify(t -> t.add(random.nextInt(1000))); - try { - Thread.sleep(2000); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - - } + public static void main(String args[]) { + Consts.hostName = "Remote"; + final Var remoteInt = new Var("remoteInt", 1); + final Var remoteString1 = new Var("remoteString1", "a"); + final Var remoteString2 = new Var("remoteString2", "b"); + final Var> remoteList = new Var>("remoteList", new ArrayList()); + final Random random = new Random(); + + try { + Thread.sleep(5000); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + + while (true) { + remoteInt.set(random.nextInt(1000)); + remoteString1.set(String.valueOf(random.nextInt(10)) + " "); + remoteString2.set(String.valueOf(random.nextInt(10)) + "!"); + remoteList.modify(t -> t.add(random.nextInt(1000))); + try { + Thread.sleep(2000); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + + } } diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/Creator.java b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/Creator.java new file mode 100644 index 0000000..8cc9090 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/Creator.java @@ -0,0 +1,45 @@ +package dream.examples.scrumBoard.atomic; + +import java.util.LinkedList; +import java.util.Random; +import java.util.logging.Logger; + +import dream.client.Var; +import dream.examples.scrumBoard.common.Assignment; +import dream.examples.scrumBoard.common.CreatorGUI; + +/** + * Interface to create new Tasks. May be started multiple times! + * + * @author Min Yang + * @author Tobias Becker + */ +public class Creator extends LockClient implements dream.examples.scrumBoard.common.CreatorGUI.Creator { + + public static final String VAR_newAssignment = "newAssign"; + + private Var> assignmentCreator; + + public Creator() { + super("Creator" + new Random().nextInt(1000)); + } + + protected void setup() { + assignmentCreator = new Var<>(VAR_newAssignment, new LinkedList<>()); + new CreatorGUI(this); + } + + public static void main(String[] args) { + new Creator(); + } + + public Logger getLogger() { + return logger; + } + + public void addAssignment(Assignment t) { + lock(); + assignmentCreator.modify((old) -> old.addLast(t)); + unlock(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/InitApp.java b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/InitApp.java new file mode 100644 index 0000000..1bfabc6 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/InitApp.java @@ -0,0 +1,26 @@ +package dream.examples.scrumBoard.atomic; + +import dream.examples.scrumBoard.core.Server; +import dream.examples.util.MultipleStarter; + +/** + * To start this example either:
+ * - run {@link Server}, {@link Creator} and {@link Monitor} in any order
+ * - or run this class.
+ * This class will start all three classes each in a seperate instance of the + * JVM. It will also stop all classes if one of them is stopped normally.
+ * + * @author Min Yang + * @author Tobias Becker + */ +public class InitApp { + + public static void main(String... args) { + MultipleStarter.addStartQueue(LockManager.class); + MultipleStarter.addStartQueue(Server.class); + MultipleStarter.addStartQueue(Creator.class); + MultipleStarter.addStartQueue(Creator.class); + MultipleStarter.addStartQueue(Monitor.class); + MultipleStarter.start(); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/LockClient.java b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/LockClient.java new file mode 100644 index 0000000..7984933 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/LockClient.java @@ -0,0 +1,74 @@ +package dream.examples.scrumBoard.atomic; + +import java.util.ArrayList; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.examples.util.Client; +import dream.examples.util.Pair; + +public abstract class LockClient extends Client { + private boolean setup = false; + private Var lockRequest; + private boolean hasLock; + + public LockClient(String name) { + super(name); + + // Establish new session with LockManager + RemoteVar>> registeredClients = new RemoteVar<>(LockManager.NAME, + LockManager.VAR_clients); + Signal>> s = new Signal<>("s", () -> { + if (registeredClients.get() == null) + return new ArrayList>(); + else + return registeredClients.get(); + }, registeredClients); + s.change().addHandler((o, n) -> { + if (n.contains(new Pair<>(this.getHostName(), LockManager.VAR_requestLock)) && setup == false) + lockSetup(); + }); + + lockRequest = new Var<>(LockManager.VAR_requestLock, false); + logger.fine("Setup: Waiting for Registration to LockManager ..."); + } + + private void lockSetup() { + setup = true; + RemoteVar lock = new RemoteVar<>(LockManager.NAME, LockManager.VAR_lock); + Signal sLock = new Signal<>("lock", () -> { + return lock.get(); + }, lock); + sLock.change().addHandler((oldValue, newValue) -> { + if (newValue.equals(getHostName())) + hasLock = true; + else + hasLock = false; + synchronized (this) { + this.notify(); + } + }); + + setup(); + } + + protected abstract void setup(); + + public void lock() { + lockRequest.set(true); + synchronized (this) { + while (!hasLock) + try { + this.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void unlock() { + lockRequest.set(false); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/LockManager.java b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/LockManager.java new file mode 100644 index 0000000..835ec14 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/LockManager.java @@ -0,0 +1,97 @@ +package dream.examples.scrumBoard.atomic; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Set; +import java.util.logging.Level; + +import dream.client.DreamClient; +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.examples.util.Client; +import dream.examples.util.Pair; + +public class LockManager extends Client { + + public static final String VAR_lock = "lock"; + public static final String VAR_requestLock = "requestLock"; + public static final String VAR_clients = "clients"; + public static final String NAME = "LockManager"; + + /** + * lock:
+ * "" -> no lock
+ * [ClientName] -> graph is locked for this Client + */ + private Var lock; + private final Var>> clients; + private LinkedList lockRequests; + + public LockManager() { + super(NAME); + clients = new Var<>(VAR_clients, new ArrayList<>()); + lock = new Var<>(VAR_lock, ""); + lockRequests = new LinkedList<>(); + detectNewSession(); + } + + private void detectNewSession() { + Set vars = DreamClient.instance.listVariables(); + vars.stream().map(x -> new Pair(x.split("@")[1], x.split("@")[0])).// Pair(Host,Var) + filter(x -> !clients.get().contains(x) && x.getSecond().equalsIgnoreCase(VAR_requestLock)).// + forEach(x -> createNewSessionFor(x)); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Failed to sleep for 0.5 seconds", e); + } + + detectNewSession(); + } + + private void createNewSessionFor(Pair x) { + RemoteVar rv = new RemoteVar<>(x.getFirst(), x.getSecond()); + Signal s = new Signal<>(x.getFirst() + "request", () -> { + if (rv.get() != null) + return rv.get(); + else + return false; + }, rv); + s.change().addHandler((oldValue, newValue) -> { + if (newValue) { + // client requesting a lock + if (lock.get().equals("")) { + // no lock present, granting + lock.set(x.getFirst()); + logger.fine("Currently not locked, granting lock for: " + x.getFirst()); + } else { + // already locked, adding to queue + lockRequests.add(x.getFirst()); + logger.fine("Already locked for \"" + lock.get() + "\". Adding \"" + x.getFirst() + "\"to queue"); + } + } else if (!newValue) { + // client trying to release a lock + if (lock.get().equals(x.getFirst())) { + // client had the lock, releasing + lock.set(""); + logger.fine("Releasing lock for:" + x.getFirst()); + // granting lock request for next client + if (!lockRequests.isEmpty()) { + lock.set(lockRequests.poll()); + logger.fine("Processing next in queue"); + } + } else { + // client didn't have the lock -> withdrawing lock request + lockRequests.remove(x.getFirst()); + logger.fine("\"" + x.getFirst() + "\" withdraw lock request"); + } + } + }); + clients.modify(old -> old.add(x)); + } + + public static void main(String[] args) { + new LockManager(); + } +} diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/Monitor.java b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/Monitor.java new file mode 100644 index 0000000..6deae7f --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/atomic/Monitor.java @@ -0,0 +1,52 @@ +package dream.examples.scrumBoard.atomic; + +import java.util.Arrays; +import java.util.List; + +import dream.client.RemoteVar; +import dream.examples.scrumBoard.common.MonitorGUI; +import dream.examples.scrumBoard.core.Server; + +/** + * Displays both lists, the developers and the tasks. + * + * @author Min Yang + * @author Tobias Becker + */ +public class Monitor extends LockClient implements dream.examples.scrumBoard.common.MonitorGUI.Monitor { + + public static final String NAME = "Monitor"; + + private MonitorGUI gui; + private RemoteVar devs; + private RemoteVar tasks; + + @Override + protected List waitForVars() { + return Arrays.asList(toVar(Server.NAME, Server.VAR_developers), toVar(Server.NAME, Server.VAR_tasks)); + } + + public Monitor() { + super(NAME); + } + + protected void setup() { + gui = new MonitorGUI(this); + + devs = new RemoteVar(Server.NAME, Server.VAR_developers); + tasks = new RemoteVar(Server.NAME, Server.VAR_tasks); + } + + public static void main(String[] args) { + new Monitor(); + } + + public void clickButton() { + lock(); + if (tasks.get() != null) + gui.setTasks(tasks.get()); + if (devs.get() != null) + gui.setDevs(devs.get()); + unlock(); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/common/Assignment.java b/Dream2/src/examples/java/dream/examples/scrumBoard/common/Assignment.java new file mode 100644 index 0000000..5318a76 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/common/Assignment.java @@ -0,0 +1,60 @@ +package dream.examples.scrumBoard.common; + +import java.io.Serializable; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Small serializable class that represents a task assigned to a developer. + * + * @author Min Yang + * @author Tobias Becker + */ +public class Assignment implements Serializable, Comparable { + private static final long serialVersionUID = 8329097603920137211L; + public static String pattern = "D(\\d*):T(\\d*)"; + private int developer; + private int task; + private Date time; + + public Assignment(String input) { + Matcher m = Pattern.compile(pattern).matcher(input); + if (m.matches()) { + developer = Integer.parseInt(m.group(1)); + task = Integer.parseInt(m.group(2)); + time = new Date(); + } else + throw new UnsupportedOperationException("Wrong Input"); + } + + public static boolean isValid(String input) { + return input.matches(pattern); + } + + public int getDeveloper() { + return developer; + } + + public int getTask() { + return task; + } + + public String getDevString() { + return Integer.toString(developer); + } + + public String getTaskString() { + return Integer.toString(task); + } + + public Date getTime() { + return time; + } + + @Override + public int compareTo(Assignment o) { + return time.compareTo(o.time); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/common/CreatorGUI.java b/Dream2/src/examples/java/dream/examples/scrumBoard/common/CreatorGUI.java new file mode 100644 index 0000000..9451e3e --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/common/CreatorGUI.java @@ -0,0 +1,130 @@ +package dream.examples.scrumBoard.common; + +import java.awt.Container; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.util.logging.Logger; + +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JTextField; + +public class CreatorGUI { + public interface Creator { + void addAssignment(Assignment assignment); + + Logger getLogger(); + } + + private JTextField textField1; + private JFrame frame1; + private JButton button1; + private Creator creator; + + public CreatorGUI(Creator t) { + this.creator = t; + initComponents(); + } + + void initComponents() { + frame1 = new JFrame(); + frame1.addWindowListener(new WindowListener() { + @Override + public void windowOpened(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowDeactivated(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + } + + @Override + public void windowClosed(WindowEvent e) { + } + + @Override + public void windowActivated(WindowEvent e) { + } + }); + textField1 = new JTextField(); + textField1.addKeyListener(new KeyListener() { + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + button1.doClick(); + } + }); + button1 = new JButton(); + + // ======== frame1 ======== + { + Container frame1ContentPane = frame1.getContentPane(); + + // ---- button1 ---- + button1.setText("New Task"); + button1.addActionListener(new ButtonListener()); + + GroupLayout frame1ContentPaneLayout = new GroupLayout(frame1ContentPane); + frame1ContentPane.setLayout(frame1ContentPaneLayout); + frame1ContentPaneLayout + .setHorizontalGroup(frame1ContentPaneLayout.createParallelGroup() + .addGroup(frame1ContentPaneLayout.createSequentialGroup().addGap(20, 20, 20) + .addComponent(textField1, GroupLayout.PREFERRED_SIZE, 590, + GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18).addComponent(button1).addContainerGap(34, Short.MAX_VALUE))); + + frame1ContentPaneLayout.setVerticalGroup(frame1ContentPaneLayout.createParallelGroup() + .addGroup(frame1ContentPaneLayout.createSequentialGroup().addGap(19, 19, 19) + .addGroup(frame1ContentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(button1).addComponent(textField1, GroupLayout.PREFERRED_SIZE, + GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addContainerGap(24, Short.MAX_VALUE))); + + frame1.pack(); + frame1.setLocationRelativeTo(frame1.getOwner()); + frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame1.setVisible(true); + } + } + + class ButtonListener implements ActionListener { + @Override + public void actionPerformed(ActionEvent paramActionEvent) { + String toTasks = textField1.getText(); + if (Assignment.isValid(toTasks)) { + creator.addAssignment(new Assignment(toTasks)); + textField1.setText(""); + } else { + textField1.setText(""); + JOptionPane.showMessageDialog(null, "Please input the right pattern of task. (D:T)"); + creator.getLogger().info("Wrong input pattern of tasks"); + } + } + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/common/MonitorGUI.java b/Dream2/src/examples/java/dream/examples/scrumBoard/common/MonitorGUI.java new file mode 100644 index 0000000..0bb5e24 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/common/MonitorGUI.java @@ -0,0 +1,91 @@ +package dream.examples.scrumBoard.common; + +import java.awt.Container; +import java.awt.event.ActionEvent; + +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextArea; +import javax.swing.LayoutStyle; + +public class MonitorGUI { + + public interface Monitor { + void clickButton(); + } + + private JFrame frame1; + private JTextArea textAreaTasks; + private JLabel label1; + private JLabel label2; + private JTextArea textAreaDevs; + private JButton button1; + private Monitor monitor; + + public MonitorGUI(Monitor m) { + this.monitor = m; + frame1 = new JFrame(); + label1 = new JLabel(); + label2 = new JLabel(); + button1 = new JButton(); + textAreaTasks = new JTextArea(); + textAreaDevs = new JTextArea(); + textAreaDevs.setEditable(false); + textAreaTasks.setEditable(false); + + // ======== frame1 ======== + { + Container frame1ContentPane = frame1.getContentPane(); + // ---- label1 ---- + label1.setText("Current devs:"); + + // ---- label2 ---- + label2.setText("Current tasks:"); + + // ---- button1 ---- + button1.setText("Show me tasks"); + button1.addActionListener(e -> button1ActionPerformed(e)); + + GroupLayout frame1ContentPaneLayout = new GroupLayout(frame1ContentPane); + frame1ContentPane.setLayout(frame1ContentPaneLayout); + frame1ContentPaneLayout.setHorizontalGroup(frame1ContentPaneLayout.createParallelGroup() + .addGroup(frame1ContentPaneLayout.createSequentialGroup().addContainerGap() + .addGroup(frame1ContentPaneLayout.createParallelGroup().addComponent(label1).addComponent( + textAreaDevs, GroupLayout.PREFERRED_SIZE, 57, GroupLayout.PREFERRED_SIZE)) + .addGap(30, 30, 30) + .addGroup(frame1ContentPaneLayout.createParallelGroup().addComponent(label2).addComponent( + textAreaTasks, GroupLayout.PREFERRED_SIZE, 57, GroupLayout.PREFERRED_SIZE)) + .addContainerGap(9, Short.MAX_VALUE)) + .addGroup(GroupLayout.Alignment.TRAILING, frame1ContentPaneLayout.createSequentialGroup() + .addContainerGap(11, Short.MAX_VALUE).addComponent(button1).addGap(71, 71, 71))); + frame1ContentPaneLayout.setVerticalGroup(frame1ContentPaneLayout.createParallelGroup() + .addGroup(frame1ContentPaneLayout.createSequentialGroup().addComponent(button1) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) + .addGroup(frame1ContentPaneLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(label2).addComponent(label1)) + .addGap(13, 13, 13) + .addGroup(frame1ContentPaneLayout.createParallelGroup(GroupLayout.Alignment.LEADING, false) + .addComponent(textAreaDevs, GroupLayout.DEFAULT_SIZE, 108, Short.MAX_VALUE) + .addComponent(textAreaTasks, GroupLayout.DEFAULT_SIZE, 108, Short.MAX_VALUE)) + .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + frame1.pack(); + frame1.setLocationRelativeTo(frame1.getOwner()); + frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame1.setVisible(true); + } + } + + private void button1ActionPerformed(ActionEvent e) { + monitor.clickButton(); + } + + public void setDevs(String value) { + textAreaDevs.setText(value.replace(":", "\n")); + } + + public void setTasks(String value) { + textAreaTasks.setText(value.replace(":", "\n")); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/core/Creator.java b/Dream2/src/examples/java/dream/examples/scrumBoard/core/Creator.java new file mode 100644 index 0000000..d6eb040 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/core/Creator.java @@ -0,0 +1,41 @@ +package dream.examples.scrumBoard.core; + +import java.util.LinkedList; +import java.util.Random; +import java.util.logging.Logger; + +import dream.client.Var; +import dream.examples.scrumBoard.common.Assignment; +import dream.examples.scrumBoard.common.CreatorGUI; +import dream.examples.util.Client; + +/** + * Interface to create new Tasks. May be started multiple times! + * + * @author Min Yang + * @author Tobias Becker + */ +public class Creator extends Client implements dream.examples.scrumBoard.common.CreatorGUI.Creator { + + public static final String VAR_newAssignment = "newAssign"; + + private Var> assignmentCreator; + + public Creator() { + super("Creator" + new Random().nextInt(1000)); + assignmentCreator = new Var<>(VAR_newAssignment, new LinkedList<>()); + new CreatorGUI(this); + } + + public static void main(String[] args) { + new Creator(); + } + + public Logger getLogger() { + return logger; + } + + public void addAssignment(Assignment t) { + assignmentCreator.modify((old) -> old.addLast(t)); + } +} diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/core/InitApp.java b/Dream2/src/examples/java/dream/examples/scrumBoard/core/InitApp.java new file mode 100644 index 0000000..6356038 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/core/InitApp.java @@ -0,0 +1,24 @@ +package dream.examples.scrumBoard.core; + +import dream.examples.util.MultipleStarter; + +/** + * To start this example either:
+ * - run {@link Server}, {@link Creator} and {@link Monitor} in any order
+ * - or run this class.
+ * This class will start all three classes each in a seperate instance of the + * JVM. It will also stop all classes if one of them is stopped normally.
+ * + * @author Min Yang + * @author Tobias Becker + */ +public class InitApp { + + public static void main(String... args) { + MultipleStarter.addStartQueue(Server.class); + MultipleStarter.addStartQueue(Creator.class); + MultipleStarter.addStartQueue(Creator.class); + MultipleStarter.addStartQueue(Monitor.class); + MultipleStarter.start(); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/core/Monitor.java b/Dream2/src/examples/java/dream/examples/scrumBoard/core/Monitor.java new file mode 100644 index 0000000..eb8f12c --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/core/Monitor.java @@ -0,0 +1,69 @@ +package dream.examples.scrumBoard.core; + +import java.util.Arrays; +import java.util.List; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.examples.scrumBoard.common.MonitorGUI; +import dream.examples.util.Client; + +/** + * Displays both lists, the developers and the tasks. + * + * @author Min Yang + * @author Tobias Becker + */ +public class Monitor extends Client implements dream.examples.scrumBoard.common.MonitorGUI.Monitor { + + public static final String NAME = "Monitor"; + + private final MonitorGUI gui; + private final RemoteVar devs; + private final RemoteVar tasks; + private final Signal sigDevs; + private final Signal sigTasks; + + @Override + protected List waitForVars() { + return Arrays.asList(toVar(Server.NAME, Server.VAR_developers), toVar(Server.NAME, Server.VAR_tasks)); + } + + public Monitor() { + super(NAME); + gui = new MonitorGUI(this); + + devs = new RemoteVar(Server.NAME, Server.VAR_developers); + sigDevs = new Signal("sigDevs", () -> { + return devs.get(); + }, devs); + + tasks = new RemoteVar(Server.NAME, Server.VAR_tasks); + sigTasks = new Signal("sigTests", () -> { + return tasks.get(); + }, tasks); + + sigDevs.change().addHandler((oldVa, newVal) -> { + System.out.println("newVal devs:" + newVal); + // gui.setDevs(newVal); + }); + + sigTasks.change().addHandler((oldVa, newVal) -> { + System.out.println("newVal tasks:" + newVal); + // gui.setTasks(newVal); + }); + } + + public static void main(String[] args) { + new Monitor(); + } + + public void clickButton() { + readLock(toVar(Server.NAME, Server.VAR_tasks), toVar(Server.NAME, Server.VAR_developers)); + if (tasks.get() != null) + gui.setTasks(tasks.get()); + if (devs.get() != null) + gui.setDevs(devs.get()); + unlock(); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/core/Server.java b/Dream2/src/examples/java/dream/examples/scrumBoard/core/Server.java new file mode 100644 index 0000000..7db4274 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/core/Server.java @@ -0,0 +1,95 @@ +package dream.examples.scrumBoard.core; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.Set; +import java.util.stream.Collectors; + +import dream.client.DreamClient; +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.examples.scrumBoard.common.Assignment; +import dream.examples.util.Client; +import dream.examples.util.Pair; + +/** + * Holds a list of tasks and a list of developers each indicated by a simple + * integer. Searches for new clients (TaskCreater) and registers to their + * "task creation channels" + * + * @author Min Yang + * @author Tobias Becker + */ +public class Server extends Client { + public static final String NAME = "ServerNode"; + public static final String VAR_developers = "developers"; + public static final String VAR_tasks = "tasks"; + + private Pair creator1; + private Pair creator2; + + public static void main(String... args) { + new Server(); + } + + public Server() { + super(NAME); + detectClients(); + } + + private void detectClients() { + Set vars = DreamClient.instance.listVariables(); + vars.stream().map(x -> new Pair(x.split("@")[1], x.split("@")[0])) + .filter(x -> (creator1 == null || !creator1.equals(x)) && (creator2 == null || !creator2.equals(x)) + && x.getSecond().equalsIgnoreCase(Creator.VAR_newAssignment)) + .forEach(x -> foundCreator(x)); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + // stop looking after two creators have been found + if (creator1 == null || creator2 == null) + detectClients(); + } + + private void foundCreator(Pair creator) { + logger.info("found creator instance " + creator); + if (creator1 == null) + creator1 = creator; + else if (creator2 == null) + creator2 = creator; + + if (creator1 != null && creator2 != null) + initDependencies(); + } + + private void initDependencies() { + + RemoteVar> rv1 = new RemoteVar<>(creator1.getFirst(), creator1.getSecond()); + RemoteVar> rv2 = new RemoteVar<>(creator2.getFirst(), creator2.getSecond()); + + Signal developers = new Signal(VAR_developers, () -> { + LinkedList temp = new LinkedList<>(); + if (rv1.get() != null) + temp.addAll(rv1.get()); + if (rv2.get() != null) + temp.addAll(rv2.get()); + Collections.sort(temp); + return temp.stream().map(a -> a.getDevString()).collect(Collectors.joining(":")); + }, rv1, rv2); + + Signal tasks = new Signal(VAR_tasks, () -> { + LinkedList temp = new LinkedList<>(); + if (rv1.get() != null) + temp.addAll(rv1.get()); + if (rv2.get() != null) + temp.addAll(rv2.get()); + Collections.sort(temp); + return temp.stream().map(a -> a.getTaskString()).collect(Collectors.joining(":")); + }, rv1, rv2); + + } + +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/core/graph.png b/Dream2/src/examples/java/dream/examples/scrumBoard/core/graph.png new file mode 100644 index 0000000..2d2f07b Binary files /dev/null and b/Dream2/src/examples/java/dream/examples/scrumBoard/core/graph.png differ diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.atomic.txt b/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.atomic.txt new file mode 100644 index 0000000..9fb4c61 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.atomic.txt @@ -0,0 +1,8 @@ +http://cloc.sourceforge.net v 1.64 T=0.25 s (20.1 files/s, 1183.5 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 5 46 35 213 +------------------------------------------------------------------------------- +SUM: 5 46 35 213 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.core.txt b/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.core.txt new file mode 100644 index 0000000..10501c8 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.core.txt @@ -0,0 +1,8 @@ +http://cloc.sourceforge.net v 1.64 T=0.09 s (46.2 files/s, 2643.9 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java 4 41 33 155 +------------------------------------------------------------------------------- +SUM: 4 41 33 155 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.diff.core.atomic.txt b/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.diff.core.atomic.txt new file mode 100644 index 0000000..ab54d76 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/scrumBoard/line-count.diff.core.atomic.txt @@ -0,0 +1,16 @@ +http://cloc.sourceforge.net v 1.64 T=0.28 s (3.5 files/s, 3.5 lines/s) +------------------------------------------------------------------------------- +Language files blank comment code +------------------------------------------------------------------------------- +Java + same 0 0 22 59 + modified 3 0 0 10 + added 2 23 13 144 + removed 1 18 11 86 +------------------------------------------------------------------------------- +SUM: + same 0 0 22 59 + modified 3 0 0 10 + added 2 23 13 144 + removed 1 18 11 86 +------------------------------------------------------------------------------- diff --git a/Dream2/src/examples/java/dream/examples/tasks/DeligatProcess.java b/Dream2/src/examples/java/dream/examples/tasks/DeligatProcess.java new file mode 100644 index 0000000..ddab317 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/DeligatProcess.java @@ -0,0 +1,88 @@ +/** + * + */ +package dream.examples.tasks; + +import java.util.HashMap; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.common.Consts; +import dream.examples.util.VectorClock; + +/** + * @author Ram + * + */ +public class DeligatProcess { + + static int i; + int clock; + VectorClock localClock = new VectorClock("p2"); + /** + * @param args + */ + private String processName; + + /** + * @return the processName + */ + public String getProcessName() { + return processName; + } + + /** + * @param processName + * the processName to set + */ + public void setProcessName(String processName) { + this.processName = processName; + } + + public DeligatProcess(String processName, String host) { + this.setProcessName(processName); + } + + public DeligatProcess() { + // TODO Auto-generated constructor stub + } + + private void init() { + Consts.hostName = "Host2"; + RemoteVar rv = new RemoteVar("Host1", "TASK"); + Var myVar = new Var("TASK_ASSIGNED", null); + + Signal s = new Signal("s", () -> { + return rv.get(); + } , rv); + + // Register a handler which will be executed upon receiving the signal + s.change().addHandler((oldVal, val) -> { + + localClock.updateClock(); + HashMap messageClock = val.getClock(); + if (localClock.isNew(messageClock)) { + localClock.updateClock(messageClock); + } + try { + Thread.sleep(1000); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + val.getTask().setAssignee(i++ % 10 + ""); + val.setId("p2"); + localClock.updateClock(); + val.setClock(localClock.getLocalClock()); + myVar.set(val); + + }); + } + + public static void main(String[] args) { + new DeligatProcess().init(); + + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/MasterProcess.java b/Dream2/src/examples/java/dream/examples/tasks/MasterProcess.java new file mode 100644 index 0000000..d6b3c98 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/MasterProcess.java @@ -0,0 +1,69 @@ +/** + * + */ +package dream.examples.tasks; + +import dream.client.Var; +import dream.common.Consts; +import dream.examples.util.VectorClock; + +/** + * @author Ram + * + */ +public class MasterProcess { + + private void init() { + Consts.hostName = "Host1"; + + VectorClock vectorClock = new VectorClock("p1"); + Var initTask = new Var("TASK", null); + Var initTask2 = new Var("TASK2", null); + try { + + int i = 1; + while (true) { + // Create a message to be distributed + Message message = new Message(); + message.setId("p1"); + Thread.sleep(5000); + + // Add task to a message + Task task = new Task("Task" + i); + + // Set id for the task + task.setId(1000 + i); + + message.setTask(task); + // increment local clock + vectorClock.updateClock(); + + // set clock for the task + message.setClock(vectorClock.getLocalClock()); + + // Add description to task + task.setDescription("This is " + i + "th task"); + + // Send task to Deligator + initTask.set(message); + + // link latency + Thread.sleep(5000); + // Send task to worker + initTask2.set(message); + i++; + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * @param args + */ + public static void main(String[] args) { + new MasterProcess().init(); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/Message.java b/Dream2/src/examples/java/dream/examples/tasks/Message.java new file mode 100644 index 0000000..b745cb9 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/Message.java @@ -0,0 +1,67 @@ +/** + * + */ +package dream.examples.tasks; + +import java.io.Serializable; +import java.util.HashMap; + +/** + * Message format used for communication between different nodes + * + * @author Ram + * + */ +public class Message implements Serializable { + + private static final long serialVersionUID = -9119849212879479791L; + private Task task; + private HashMap clock; + private String id; + + /** + * @return the id + */ + public String getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return the task + */ + public Task getTask() { + return task; + } + + /** + * @param task + * the task to set + */ + public void setTask(Task task) { + this.task = task; + } + + /** + * @return the clock + */ + public HashMap getClock() { + return clock; + } + + /** + * @param clock + * the clock to set + */ + public void setClock(HashMap clock) { + this.clock = clock; + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/Relation.java b/Dream2/src/examples/java/dream/examples/tasks/Relation.java new file mode 100644 index 0000000..df76c92 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/Relation.java @@ -0,0 +1,16 @@ +/** + * + */ +package dream.examples.tasks; + +/** + * @author Ram + * + */ +public enum Relation { + FOLLOWEDBY, OR, AND +} + +enum Clock { + EQUAL, OLD, NEW, QUEUE +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/tasks/Task.java b/Dream2/src/examples/java/dream/examples/tasks/Task.java new file mode 100644 index 0000000..b8ee020 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/Task.java @@ -0,0 +1,103 @@ +/** + * + */ +package dream.examples.tasks; + +import java.util.ArrayList; + +/** + * @author Ram + * + */ +public class Task extends ArrayList { + /** + * + */ + private static final long serialVersionUID = 7635579009380741902L; + private String name; + private String assignee; + private int id; + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the clock + */ + public int getClock() { + return clock; + } + + /** + * @param clock + * the clock to set + */ + public void setClock(int clock) { + this.clock = clock; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description + * the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + private int clock; + private String description; + + public Task(String name) { + this.setName(name); + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name + * the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the assignee + */ + public String getAssignee() { + return assignee; + } + + /** + * @param assignee + * the assignee to set + */ + public void setAssignee(String assignee) { + this.assignee = assignee; + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/UiUpdatesListner.java b/Dream2/src/examples/java/dream/examples/tasks/UiUpdatesListner.java new file mode 100644 index 0000000..c5ee2d0 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/UiUpdatesListner.java @@ -0,0 +1,15 @@ +/** + * + */ +package dream.examples.tasks; + +/** + * @author Ram + * + */ +public interface UiUpdatesListner { + + void updateTasks(String task, boolean accepted); + + void updateClockinUi(String string); +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/VectorClockHelper.java b/Dream2/src/examples/java/dream/examples/tasks/VectorClockHelper.java new file mode 100644 index 0000000..19867b4 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/VectorClockHelper.java @@ -0,0 +1,150 @@ +/** + * + */ +package dream.examples.tasks; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; + +/** + * @author Ram + * + */ +public class VectorClockHelper implements Runnable { + + HashMap localClock; + String processId; + private WorkerHelper helper; + + public VectorClockHelper(String processId, WorkerHelper helper) { + this.processId = processId; + this.helper = helper; + } + + /** + * @return the localClock + */ + public HashMap getLocalClock() { + checkNull(); + return localClock; + } + + void checkNull() { + if (localClock == null) { + localClock = new HashMap<>(); + localClock.put(processId, 0); + } + } + + java.util.List queue1 = Collections.synchronizedList(new ArrayList()); + java.util.List queue2 = Collections.synchronizedList(new ArrayList()); + + synchronized void checkEvent(Message msg) { + + if (newEvent(msg) == Clock.NEW && msg.getId().equals("p1")) { + updateClock(msg.getId(), msg.getClock().get(msg.getId())); + helper.updateClock(); + queueEvent(msg, true); + + } + if (newEvent(msg) == Clock.QUEUE && msg.getId().equals("p2")) { + updateClock(msg.getId(), msg.getClock().get(msg.getId())); + helper.updateClock(); + queueEvent(msg, false); + } + + } + + private synchronized void queueEvent(Message msg, boolean newEvent) { + + if (newEvent) { + helper.listner.updateTasks( + "ENQUEUE to Q2 " + msg.getTask().getId() + " Message is from process " + msg.getId(), false); + queue2.add(msg); + } else { + helper.listner.updateTasks( + "ENQUEUE to Q1 " + msg.getTask().getId() + " Message is from process " + msg.getId(), false); + queue1.add(msg); + } + } + + private synchronized void composeEvent(Message msg) { + + } + + void updateClock() { + checkNull(); + int clock = localClock.get(processId); + clock++; + updateClock(processId, clock); + + } + + private void updateClock(String id, int clock) { + + localClock.put(id, clock); + + } + + private Clock newEvent(Message msg) { + int flag = 0; + checkNull(); + for (String key : localClock.keySet()) { + if (msg.getClock().keySet().contains(key)) { + if (localClock.get(key) <= msg.getClock().get(key) && !key.equals(msg.getId())) { + return Clock.QUEUE; + } + if (localClock.get(key) >= msg.getClock().get(key) && !key.equals(msg.getId())) { + flag = 1; + } + } else { + return Clock.NEW; + } + } + if (flag == 1 && localClock.keySet().contains(msg.getId()) + && localClock.get(msg.getId()) < msg.getClock().get(msg.getId())) { + return Clock.NEW; + } + return Clock.QUEUE; + } + + @Override + public void run() { + while (true) { + helper.updateClock(); + int flag = 0; + Iterator iterator2 = queue2.iterator(); + while (iterator2.hasNext()) { + Message msg = iterator2.next(); + Iterator iterator = queue1.iterator(); + while (iterator.hasNext()) { + Message qMsg = iterator.next(); + if (msg.getId().equals("p1") && qMsg.getId().equals("p2") + && msg.getClock().get(msg.getId()).equals(qMsg.getClock().get(msg.getId()))) { + helper.handleEvent(msg, qMsg); + helper.listner.updateTasks("Event detected with timestamp :" + msg.getClock().get(msg.getId()), + false); + flag = 1; + helper.listner.updateTasks("DQUEUE msg :" + qMsg.getTask().getId(), false); + iterator.remove(); + + } + + } + if (flag == 0) { + queue1.add(msg); + updateClock(msg.getId(), msg.getClock().get(msg.getId())); + } + } + try { + Thread.sleep(1000); + } catch (Exception e) { + e.printStackTrace(); + } + } + + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/WorkerHelper.java b/Dream2/src/examples/java/dream/examples/tasks/WorkerHelper.java new file mode 100644 index 0000000..3d6d2de --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/WorkerHelper.java @@ -0,0 +1,103 @@ +/** + * + */ +package dream.examples.tasks; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.common.Consts; + +/** + * @author Ram + * + */ +public class WorkerHelper implements Runnable { + static int i = 0; + UiUpdatesListner listner; + VectorClockHelper localClock;// = new VectorClock("p3"); + Var complexEvent = new Var("COMPEVENT", null); + /** + * @param args + */ + private String processName; + + /** + * @return the processName + */ + public String getProcessName() { + return processName; + } + + /** + * @param processName + * the processName to set + */ + public void setProcessName(String processName) { + this.processName = processName; + } + + public WorkerHelper() { + this.setProcessName(processName); + + } + + public void handleEvent(Message p1, Message p2) { + // update clock on receiving new message + Task task = p1.getTask(); + updateClock(); + listner.updateTasks("\nTask Name: " + task.getName() + "\n" + "Task Discription: " + task.getDescription() + + "\n" + "Assignee ID: " + p2.getTask().getAssignee(), true); + + } + + void updateClock() { + listner.updateClockinUi(localClock.getLocalClock().toString()); + } + + public void isEvent(String val) { + updateClock(); + listner.updateTasks(val, false); + + } + + public void run() { + localClock = new VectorClockHelper("p3", this); + Consts.hostName = "Host3"; + Thread t = new Thread(localClock); + t.start(); + RemoteVar task = new RemoteVar("Host1", "TASK2"); + RemoteVar taskDeligated = new RemoteVar("Host2", "TASK_ASSIGNED"); + + Signal signalFromMaster = new Signal("s", () -> { + return task.get(); + } , task); + Signal signalFromDeligator = new Signal("s1", () -> { + return taskDeligated.get(); + } , taskDeligated); + + // Register a handler which will be executed upon receiving the signal + // from master process + signalFromMaster.change().addHandler((oldVal, val) -> { + if (val != null) { + localClock.updateClock(); + localClock.checkEvent(val); + } + }); + + // Register a handler which will be executed upon receiving the signal + // from delegate process + signalFromDeligator.change().addHandler((oldVal, val) -> { + if (val != null) { + localClock.updateClock(); + localClock.checkEvent(val); + } + }); + + } + + public void addListners(WorkerProcess dsUi) { + this.listner = dsUi; + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/WorkerProcess.java b/Dream2/src/examples/java/dream/examples/tasks/WorkerProcess.java new file mode 100644 index 0000000..3faf971 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/WorkerProcess.java @@ -0,0 +1,222 @@ +/** + * + */ +package dream.examples.tasks; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author Ram + */ +public class WorkerProcess extends javax.swing.JFrame implements UiUpdatesListner { + + /** + * + */ + private static final long serialVersionUID = 1L; + /** + * Creates new form TaskWindow + */ + WorkerHelper manager; + + public WorkerProcess(WorkerHelper manager2) { + this.manager = manager2; + this.manager.addListners(this); + initComponents(); + + } + + @Override + public void updateTasks(String task, boolean accepted) { + if (accepted) { + jTextArea1.append("\n" + task); + jTextArea1.append("\n**************************************************************"); + } else { + jTextArea2.append("\n" + task); + jTextArea2.append("\n**************************************************************"); + } + + this.repaint(); + this.revalidate(); + } + + public static void main(String args[]) { + WorkerHelper manager = new WorkerHelper(); + WorkerProcess snapshotUi = new WorkerProcess(manager); + snapshotUi.initUi(); + Thread S = new Thread(manager); + S.start(); + } + + void initUi() { + + try { + for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + javax.swing.UIManager.setLookAndFeel(info.getClassName()); + this.setVisible(true); + break; + } + } + } catch (ClassNotFoundException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } catch (InstantiationException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } catch (IllegalAccessException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } catch (javax.swing.UnsupportedLookAndFeelException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } + } + + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jPanel2 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + jScrollPane2 = new javax.swing.JScrollPane(); + jTextArea2 = new javax.swing.JTextArea(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jButton1 = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + + jLabel1.setText("Local Clock"); + + jTextField1.setEditable(false); + jTextField1.setText("Local clock will be displayed here"); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup().addGap(67, 67, 67).addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addComponent(jTextField1) + .addContainerGap())); + jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1).addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 8, Short.MAX_VALUE))); + + jTextArea1.setEditable(false); + jTextArea1.setColumns(20); + jTextArea1.setRows(50); + jScrollPane1.setViewportView(jTextArea1); + + jTextArea2.setEditable(false); + jTextArea2.setColumns(20); + jTextArea2.setRows(50); + jScrollPane2.setViewportView(jTextArea2); + + jLabel2.setText("Accepted Events"); + + jLabel3.setText("Log"); + + jButton1.setText("Clear"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup().addGap(22, 22, 22).addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 345, + Short.MAX_VALUE) + .addGap(18, 18, 18))) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, + jPanel2Layout.createSequentialGroup().addComponent(jLabel3).addGap(106, 106, + 106)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, + jPanel2Layout.createSequentialGroup() + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 335, + javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE).addComponent(jButton1).addGap(297, 297, 297))); + jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, + jPanel2Layout.createSequentialGroup().addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3).addComponent(jLabel2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 360, + javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jButton1))); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup().addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap())); + layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup().addContainerGap() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap())); + + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButton1ActionPerformed + this.jTextArea1.setText(""); + this.jTextArea2.setText(""); + }// GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextArea jTextArea2; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables + + @Override + public void updateClockinUi(String clock) { + this.jTextField1.setText(clock); + this.repaint(); + this.revalidate(); + + } + +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/tasks/inconsistent/DeligatProcess.java b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/DeligatProcess.java new file mode 100644 index 0000000..a2c7610 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/DeligatProcess.java @@ -0,0 +1,88 @@ +/** + * + */ +package dream.examples.tasks.inconsistent; + +import java.util.HashMap; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.common.Consts; +import dream.examples.util.VectorClock; + +/** + * @author Ram + * + */ +public class DeligatProcess { + + static int i; + int clock; + VectorClock localClock = new VectorClock("p2"); + /** + * @param args + */ + private String processName; + + /** + * @return the processName + */ + public String getProcessName() { + return processName; + } + + /** + * @param processName + * the processName to set + */ + public void setProcessName(String processName) { + this.processName = processName; + } + + public DeligatProcess(String processName, String host) { + this.setProcessName(processName); + } + + public DeligatProcess() { + // TODO Auto-generated constructor stub + } + + private void init() { + Consts.hostName = "Host2"; + RemoteVar rv = new RemoteVar("Host1", "TASK"); + Var myVar = new Var("TASK_ASSIGNED", null); + + Signal s = new Signal("s", () -> { + return rv.get(); + } , rv); + + // Register a handler which will be executed upon receiving the signal + s.change().addHandler((oldVal, val) -> { + + localClock.updateClock(); + HashMap messageClock = val.getClock(); + if (localClock.isNew(messageClock)) { + localClock.updateClock(messageClock); + } + try { + Thread.sleep(1000); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + val.getTask().setAssignee(i++ % 10 + ""); + val.setId("p2"); + localClock.updateClock(); + val.setClock(localClock.getLocalClock()); + myVar.set(val); + + }); + } + + public static void main(String[] args) { + new DeligatProcess().init(); + + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/inconsistent/MasterProcess.java b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/MasterProcess.java new file mode 100644 index 0000000..3988855 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/MasterProcess.java @@ -0,0 +1,69 @@ +/** + * + */ +package dream.examples.tasks.inconsistent; + +import dream.client.Var; +import dream.common.Consts; +import dream.examples.util.VectorClock; + +/** + * @author Ram + * + */ +public class MasterProcess { + + private void init() { + Consts.hostName = "Host1"; + + VectorClock vectorClock = new VectorClock("p1"); + Var initTask = new Var("TASK", null); + Var initTask2 = new Var("TASK2", null); + try { + + int i = 1; + while (true) { + // Create a message to be distributed + Message message = new Message(); + message.setId("p1"); + Thread.sleep(5000); + + // Add task to a message + Task task = new Task("Task" + i); + + // Set id for the task + task.setId(1000 + i); + + message.setTask(task); + // increment local clock + vectorClock.updateClock(); + + // set clock for the task + message.setClock(vectorClock.getLocalClock()); + + // Add description to task + task.setDescription("This is " + i + "th task"); + + // Send task to Deligator + initTask.set(message); + + // link latency + Thread.sleep(5000); + // Send task to worker + initTask2.set(message); + i++; + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * @param args + */ + public static void main(String[] args) { + new MasterProcess().init(); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/inconsistent/Message.java b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/Message.java new file mode 100644 index 0000000..30f9896 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/Message.java @@ -0,0 +1,67 @@ +/** + * + */ +package dream.examples.tasks.inconsistent; + +import java.io.Serializable; +import java.util.HashMap; + +/** + * Message format used for communication between different nodes + * + * @author Ram + * + */ +public class Message implements Serializable { + + private static final long serialVersionUID = -9119849212879479791L; + private Task task; + private HashMap clock; + private String id; + + /** + * @return the id + */ + public String getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * @return the task + */ + public Task getTask() { + return task; + } + + /** + * @param task + * the task to set + */ + public void setTask(Task task) { + this.task = task; + } + + /** + * @return the clock + */ + public HashMap getClock() { + return clock; + } + + /** + * @param clock + * the clock to set + */ + public void setClock(HashMap clock) { + this.clock = clock; + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/inconsistent/Task.java b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/Task.java new file mode 100644 index 0000000..f388d0a --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/Task.java @@ -0,0 +1,103 @@ +/** + * + */ +package dream.examples.tasks.inconsistent; + +import java.util.ArrayList; + +/** + * @author Ram + * + */ +public class Task extends ArrayList { + /** + * + */ + private static final long serialVersionUID = 7635579009380741902L; + private String name; + private String assignee; + private int id; + + /** + * @return the id + */ + public int getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(int id) { + this.id = id; + } + + /** + * @return the clock + */ + public int getClock() { + return clock; + } + + /** + * @param clock + * the clock to set + */ + public void setClock(int clock) { + this.clock = clock; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description + * the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + private int clock; + private String description; + + public Task(String name) { + this.setName(name); + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name + * the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the assignee + */ + public String getAssignee() { + return assignee; + } + + /** + * @param assignee + * the assignee to set + */ + public void setAssignee(String assignee) { + this.assignee = assignee; + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/inconsistent/UiUpdatesListner.java b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/UiUpdatesListner.java new file mode 100644 index 0000000..cdc0002 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/UiUpdatesListner.java @@ -0,0 +1,15 @@ +/** + * + */ +package dream.examples.tasks.inconsistent; + +/** + * @author Ram + * + */ +public interface UiUpdatesListner { + + void updateTasks(String task, boolean accepted); + + void updateClockinUi(String string); +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/inconsistent/WorkerHelper.java b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/WorkerHelper.java new file mode 100644 index 0000000..b78a7a2 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/WorkerHelper.java @@ -0,0 +1,93 @@ +/** + * + */ +package dream.examples.tasks.inconsistent; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.client.Var; +import dream.common.Consts; + +/** + * @author Ram + * + */ +public class WorkerHelper implements Runnable { + static int i = 0; + UiUpdatesListner listner; + Var complexEvent = new Var("COMPEVENT", null); + /** + * @param args + */ + private String processName; + + /** + * @return the processName + */ + public String getProcessName() { + return processName; + } + + /** + * @param processName + * the processName to set + */ + public void setProcessName(String processName) { + this.processName = processName; + } + + public WorkerHelper() { + this.setProcessName(processName); + + } + + public void handleEvent(Message p1, Message p2) { + // update clock on receiving new message + Task task = p1.getTask(); + listner.updateTasks("\nTask Name: " + task.getName() + "\n" + "Task Discription: " + task.getDescription() + + "\n" + "Assignee ID: " + p1.getTask().getAssignee(), true); + + } + + public void isEvent(String val) { + listner.updateTasks(val, false); + + } + + public void run() { + + Consts.hostName = "Host3"; + + RemoteVar task = new RemoteVar("Host1", "TASK2"); + RemoteVar taskDeligated = new RemoteVar("Host2", "TASK_ASSIGNED"); + + Signal signalFromMaster = new Signal("s", () -> { + return task.get(); + } , task); + Signal signalFromDeligator = new Signal("s1", () -> { + return taskDeligated.get(); + } , taskDeligated); + + // Register a handler which will be executed upon receiving the signal + // from master process + signalFromMaster.change().addHandler((oldVal, val) -> { + if (val != null) { + handleEvent(val, null); + } + }); + + // Register a handler which will be executed upon receiving the signal + // from delegate process + signalFromDeligator.change().addHandler((oldVal, val) -> { + if (val != null) { + handleEvent(val, null); + } + }); + + } + + public void addListners(WorkerProcess dsUi) { + this.listner = dsUi; + } + +} diff --git a/Dream2/src/examples/java/dream/examples/tasks/inconsistent/WorkerProcess.java b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/WorkerProcess.java new file mode 100644 index 0000000..2783d3b --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/tasks/inconsistent/WorkerProcess.java @@ -0,0 +1,222 @@ +/** + * + */ +package dream.examples.tasks.inconsistent; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author Ram + */ +public class WorkerProcess extends javax.swing.JFrame implements UiUpdatesListner { + + /** + * + */ + private static final long serialVersionUID = 1L; + /** + * Creates new form TaskWindow + */ + WorkerHelper manager; + + public WorkerProcess(WorkerHelper manager2) { + this.manager = manager2; + this.manager.addListners(this); + initComponents(); + + } + + @Override + public void updateTasks(String task, boolean accepted) { + if (accepted) { + jTextArea1.append("\n" + task); + jTextArea1.append("\n**************************************************************"); + } else { + jTextArea2.append("\n" + task); + jTextArea2.append("\n**************************************************************"); + } + + this.repaint(); + this.revalidate(); + } + + public static void main(String args[]) { + WorkerHelper manager = new WorkerHelper(); + WorkerProcess snapshotUi = new WorkerProcess(manager); + snapshotUi.initUi(); + Thread S = new Thread(manager); + S.start(); + } + + void initUi() { + + try { + for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + javax.swing.UIManager.setLookAndFeel(info.getClassName()); + this.setVisible(true); + break; + } + } + } catch (ClassNotFoundException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } catch (InstantiationException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } catch (IllegalAccessException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } catch (javax.swing.UnsupportedLookAndFeelException ex) { + java.util.logging.Logger.getLogger(WorkerProcess.class.getName()).log(java.util.logging.Level.SEVERE, null, + ex); + } + } + + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jPanel2 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + jTextArea1 = new javax.swing.JTextArea(); + jScrollPane2 = new javax.swing.JScrollPane(); + jTextArea2 = new javax.swing.JTextArea(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jButton1 = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); + + jLabel1.setText("Local Clock"); + + jTextField1.setEditable(false); + jTextField1.setText("Local clock will be displayed here"); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup().addGap(67, 67, 67).addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addComponent(jTextField1) + .addContainerGap())); + jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel1).addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 8, Short.MAX_VALUE))); + + jTextArea1.setEditable(false); + jTextArea1.setColumns(20); + jTextArea1.setRows(50); + jScrollPane1.setViewportView(jTextArea1); + + jTextArea2.setEditable(false); + jTextArea2.setColumns(20); + jTextArea2.setRows(50); + jScrollPane2.setViewportView(jTextArea2); + + jLabel2.setText("Accepted Events"); + + jLabel3.setText("Log"); + + jButton1.setText("Clear"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup().addGap(22, 22, 22).addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 345, + Short.MAX_VALUE) + .addGap(18, 18, 18))) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, + jPanel2Layout.createSequentialGroup().addComponent(jLabel3).addGap(106, 106, + 106)) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, + jPanel2Layout.createSequentialGroup() + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 335, + javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE).addComponent(jButton1).addGap(297, 297, 297))); + jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, + jPanel2Layout.createSequentialGroup().addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel3).addComponent(jLabel2)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 360, + javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, Short.MAX_VALUE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jButton1))); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup().addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap())); + layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup().addContainerGap() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, + javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap())); + + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButton1ActionPerformed + this.jTextArea1.setText(""); + this.jTextArea2.setText(""); + }// GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JScrollPane jScrollPane2; + private javax.swing.JTextArea jTextArea1; + private javax.swing.JTextArea jTextArea2; + private javax.swing.JTextField jTextField1; + // End of variables declaration//GEN-END:variables + + @Override + public void updateClockinUi(String clock) { + this.jTextField1.setText(clock); + this.repaint(); + this.revalidate(); + + } + +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/util/Client.java b/Dream2/src/examples/java/dream/examples/util/Client.java new file mode 100644 index 0000000..4dfcb4d --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/Client.java @@ -0,0 +1,163 @@ +package dream.examples.util; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import dream.client.DreamClient; +import dream.client.LockToken; +import dream.common.Consts; +import dream.locking.LockManagerLauncher; +import dream.server.ServerLauncher; +import polimi.reds.broker.overlay.TCPTransport; + +/** + * A helper class for client implementations that ensures that a instance of the + * Dream Server and LockManager are running, as well as setting up basic + * infrastructure for clients. + * + * @author Tobias Becker + */ +public abstract class Client { + + private static boolean lockManagerStarted; + private static boolean serverStarted; + protected Logger logger; + + public Client(String name) { + // set up a logger + logger = Logger.getLogger(name); + + // make sure a DreamServer is running + startDream(); + + // set hostName + Consts.hostName = name; + + // connect to the dependency graph + DreamClient.instance.connect(); + + init(); + + // wait for vars needed by the client + try { + if (!waitForVars().isEmpty()) + logger.fine("Waiting for Vars: " + waitForVars()); + while (!allVarsAvailable()) { + Thread.sleep(500); + } + if (!waitForVars().isEmpty()) + logger.fine("Vars are now all available."); + logger.fine("Client initialization finished."); + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private boolean allVarsAvailable() { + for (String var : waitForVars()) { + if (!DreamClient.instance.listVariables().contains(var)) + return false; + } + return true; + } + + /** + * Override this method if you need certain variables to be available before + * your computation can start. The constructor will block until they are on + * the dependency graph. + * + * @return a list of variables to be available before continuing + */ + protected List waitForVars() { + return new ArrayList(); + } + + /** + * Override this method if you want to initialize something before waiting + * for the vars in {@link waitForVars()}. + * + */ + protected void init() { + + } + + private void startDream() { + try { + TCPTransport test = new TCPTransport(Consts.serverPort); + test.start(); + test.stop(); + } catch (IOException e) { + serverStarted = true; + logger.fine("Server already running"); + } + try { + TCPTransport test = new TCPTransport(Consts.lockManagerPort); + test.start(); + test.stop(); + } catch (IOException e) { + lockManagerStarted = true; + logger.fine("LockManager already running"); + } + try { + startServer(); + startLockManager(); + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Failed to sleep", e); + } + } + + private static final void startServer() throws InterruptedException { + if (!serverStarted) { + ServerLauncher.start(); + serverStarted = true; + } + Thread.sleep(100); + } + + private static final void startLockManager() throws InterruptedException { + if (!lockManagerStarted) { + LockManagerLauncher.start(); + lockManagerStarted = true; + } + Thread.sleep(100); + } + + public String getHostName() { + return Consts.hostName; + } + + private LinkedList lockQueue = new LinkedList<>(); + + public LockToken readLock(String... vars) { + Set temp = new HashSet<>(); + Collections.addAll(temp, vars); + lockQueue.addLast(DreamClient.instance.readLock(temp)); + return lockQueue.getLast(); + } + + public void unlock(LockToken lock) { + lockQueue.remove(lock); + DreamClient.instance.unlock(lock); + } + + public void unlock() { + DreamClient.instance.unlock(lockQueue.poll()); + } + + public String toVar(String host, String var) { + return var + "@" + host; + } + + public String toVar(Pair var) { + return toVar(var.getFirst(), var.getSecond()); + } + +} diff --git a/Dream2/src/examples/java/dream/examples/util/DependencyVisualization.java b/Dream2/src/examples/java/dream/examples/util/DependencyVisualization.java new file mode 100644 index 0000000..92f90b2 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/DependencyVisualization.java @@ -0,0 +1,74 @@ +package dream.examples.util; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +public class DependencyVisualization { + + private static File writeAndOpen(String data, String filenamePrefix, String filenameSuffix) { + File file = null; + try { + file = File.createTempFile(filenamePrefix, filenameSuffix); + + FileOutputStream fos = new java.io.FileOutputStream(file); + fos.write(data.getBytes("UTF-8")); + fos.close(); + java.awt.Desktop.getDesktop().open(file); + } catch (IOException e) { + e.printStackTrace(); + } + return file; + } + + private static String toDot(Map> nodes) { + return toDot(nodes, "forward", "1.0"); + } + + private static Map> addHostVar(Map> map, String hv) { + String[] temp = hv.split("@", 2); + String var = temp[0]; + String host = temp[1]; + if (!map.containsKey(host)) + map.put(host, new HashSet()); + map.get(host).add(var); + return map; + } + + private static String toDot(Map> nodes, String dir, String ranksep) { + String s = "digraph G {\n\tdir=" + dir + ";\n\tranksep=" + ranksep + ";\n"; + Map> hostVars = new HashMap<>(); + for (String str : nodes.keySet()) { + addHostVar(hostVars, str); + for (String str2 : nodes.get(str)) { + addHostVar(hostVars, str2); + } + } + for (String host : hostVars.keySet()) { + s += "subgraph cluster_" + host + " {\n\tnode [style=filled];\n"; + for (String var : hostVars.get(host)) { + s += "\t\"" + var + "@" + host + "\";\n"; + } + s += "\tlabel = \"" + host + "\";\n\tcolor=blue\n}\n\n"; + } + for (Entry> e : nodes.entrySet()) { + for (String e2 : e.getValue()) { + s += "\t\"" + e.getKey() + "\" -> \"" + e2 + "\" [dir=" + dir + "];\n"; + } + } + s += "}"; + return s; + } + + public static void show() { + Map> graph = dream.common.utils.DependencyGraph.instance.getGraph(); + System.out.println(graph); + writeAndOpen(toDot(graph), "temp", ".dot"); + } +} diff --git a/Dream2/src/examples/java/dream/examples/util/MultipleStarter.java b/Dream2/src/examples/java/dream/examples/util/MultipleStarter.java new file mode 100644 index 0000000..3f4ff00 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/MultipleStarter.java @@ -0,0 +1,96 @@ +package dream.examples.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Base64; +import java.util.LinkedList; +import java.util.List; + +/** + * Utility class to start multiple classes in their own vm and ensure that all + * are closed properly afterwards. + * + * @author Tobias Becker + */ +public class MultipleStarter { + + private static final LinkedList, String[]>> queue = new LinkedList<>(); + private static List processes; + + public static void main(String[] args) { + if (args.length < 1) + throw new UnsupportedOperationException("You are not supposed to run this Class directly"); + LinkedList, String[]>> q = queueFromString(args[0]); + processes = new ArrayList<>(); + for (Pair, String[]> p : q) { + processes.add(NewJvmHelper.startNewJVM(p.getFirst(), p.getSecond())); + } + sleep(-1); + } + + public static void addStartQueue(Class c, String... args) { + queue.add(new Pair<>(c, args)); + } + + public static void start() { + NewJvmHelper.startNewJVM(MultipleStarter.class, queueToString()); + } + + private static void sleep(int time) { + do { + try { + Thread.sleep(time == -1 ? 1000 : time); + checkExit(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } while (time == -1); + + } + + private static void checkExit() { + for (Process p : processes) { + if (!p.isAlive()) { + System.out.println(p.getClass().getSimpleName() + " closed ... exiting!"); + destr(); + System.exit(0); + } + } + } + + private static void destr() { + for (Process p : processes) { + p.destroyForcibly(); + } + } + + private static String queueToString() { + String s = ""; + try { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + ObjectOutputStream so = new ObjectOutputStream(bo); + so.writeObject(queue); + so.flush(); + s = new String(Base64.getEncoder().encode(bo.toByteArray())); + } catch (Exception e) { + System.err.println(e); + } + return s; + } + + private static LinkedList, String[]>> queueFromString(String s) { + try { + byte b[] = Base64.getDecoder().decode(s.getBytes()); + ByteArrayInputStream bi = new ByteArrayInputStream(b); + ObjectInputStream si = new ObjectInputStream(bi); + LinkedList, String[]>> obj = (LinkedList, String[]>>) si.readObject(); + return obj; + } catch (Exception e) { + System.err.println(e); + return null; + } + } +} diff --git a/Dream2/src/examples/java/dream/examples/util/NewJvmHelper.java b/Dream2/src/examples/java/dream/examples/util/NewJvmHelper.java new file mode 100644 index 0000000..f1473a1 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/NewJvmHelper.java @@ -0,0 +1,54 @@ +/** + * + */ +package dream.examples.util; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +/** + * @author Ram + * + */ +public class NewJvmHelper { + + private static Logger logger = Logger.getGlobal(); + + /** + * + * @param c + * class name which needs to be executed in new JVM + * @param args + * arguments which needs to be passed as a run time argument to + * the JVM + * @return process, which needs to be cleaned by the class which initializes + * the new JVM. + */ + public static Process startNewJVM(Class c, String... args) { + logger.fine("Starting " + c.getName() + " ..."); + String separator = System.getProperty("file.separator"); + String classpath = System.getProperty("java.class.path"); + String path = System.getProperty("java.home") + separator + "bin" + separator + "java"; + String[] arguments = new String[args.length + 4]; + arguments[0] = path; + arguments[1] = "-cp"; + arguments[2] = classpath; + arguments[3] = c.getName(); + for (int i = 0; i < args.length; i++) { + arguments[i + 4] = args[i]; + } + ProcessBuilder processBuilder = new ProcessBuilder(arguments).inheritIO(); + Process process = null; + try { + process = processBuilder.start(); + process.waitFor(1, TimeUnit.SECONDS); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + logger.fine(c.getName() + " started!"); + return process; + } +} diff --git a/Dream2/src/examples/java/dream/examples/util/Pair.java b/Dream2/src/examples/java/dream/examples/util/Pair.java new file mode 100644 index 0000000..6ec0c8c --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/Pair.java @@ -0,0 +1,35 @@ +package dream.examples.util; + +import java.io.Serializable; + +public class Pair implements Serializable { + private static final long serialVersionUID = 8685298368867903814L; + private final S first; + private final T second; + + public Pair(S a, T b) { + this.first = a; + this.second = b; + } + + public S getFirst() { + return first; + } + + public T getSecond() { + return second; + } + + @Override + public String toString() { + return "(" + first + ", " + second + ")"; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Pair)) + return false; + Pair p2 = (Pair) obj; + return first.equals(p2.first) && second.equals(p2.second); + } +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/util/Relation.java b/Dream2/src/examples/java/dream/examples/util/Relation.java new file mode 100644 index 0000000..529d52e --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/Relation.java @@ -0,0 +1,16 @@ +/** + * + */ +package dream.examples.util; + +/** + * @author Ram + * + */ +public enum Relation { + FOLLOWEDBY, OR, AND +} + +enum Clock { + EQUAL, OLD, NEW +} \ No newline at end of file diff --git a/Dream2/src/examples/java/dream/examples/util/StartInfra.java b/Dream2/src/examples/java/dream/examples/util/StartInfra.java new file mode 100644 index 0000000..104e727 --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/StartInfra.java @@ -0,0 +1,19 @@ +package dream.examples.util; + +import dream.locking.LockManagerLauncher; +import dream.server.ServerLauncher; + +public class StartInfra { + + public static void main(String args[]) { + try { + // Start the Server + ServerLauncher.start(); + // Start the LockManager + LockManagerLauncher.start(); + } catch (Exception e) { + // TODO Auto-generated catch block + + } + } +} diff --git a/Dream2/src/examples/java/dream/examples/util/StringToList.java b/Dream2/src/examples/java/dream/examples/util/StringToList.java new file mode 100644 index 0000000..1fa962e --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/StringToList.java @@ -0,0 +1,38 @@ +/** + * + */ +package dream.examples.util; + +import java.util.HashMap; + +/** + * @author Ram + * + */ +public class StringToList { + + /** + * @param args + */ + public static void main(String[] args) { + String input = "p1:2@p2:3"; + String seperator = "@"; + StringToList.getClockFromString(input, seperator); + + } + + public static HashMap getClockFromString(String inputString, String seperator) { + HashMap clock = new HashMap<>(); + + String[] tokens = inputString.split(seperator); + int tokenCount = tokens.length; + for (int j = 0; j < tokenCount; j++) { + String kString = tokens[j].substring(0, tokens[j].indexOf(':')); + Integer value = new Integer( + Integer.parseInt(tokens[j].substring(tokens[j].indexOf(':') + 1, tokens[j].length()))); + System.out.println(tokens[j] + " " + kString + " " + value); + } + return clock; + + } +} diff --git a/Dream2/src/examples/java/dream/examples/util/VectorClock.java b/Dream2/src/examples/java/dream/examples/util/VectorClock.java new file mode 100644 index 0000000..37d58ed --- /dev/null +++ b/Dream2/src/examples/java/dream/examples/util/VectorClock.java @@ -0,0 +1,136 @@ +/** + * + */ +package dream.examples.util; + +import java.util.HashMap; +import java.util.Set; + +/** + * @author Ram + * + */ +public class VectorClock { + + HashMap localClock; + String processId; + + public VectorClock(String processId) { + this.processId = processId; + } + + /** + * @return the localClock + */ + public HashMap getLocalClock() { + checkNull(); + return localClock; + } + + void checkNull() { + if (localClock == null) { + localClock = new HashMap<>(); + localClock.put(processId, 0); + } + } + + /** + * Method to be used to compare two clock vectors, true will be returned if + * both clocks have same keyset and have same values for individual keys. + * Usually used to compare if the arrived message is older than the local + * state. + * + * @param localClock + * @param messageClock + * @return + */ + public Clock compareClock(HashMap messageClock) { + checkNull(); + if (localClock.keySet().containsAll(messageClock.keySet()) + && localClock.keySet().size() == messageClock.keySet().size()) { + for (String key : localClock.keySet()) { + if (!localClock.get(key).equals(messageClock.get(key)) && localClock.get(key) > messageClock.get(key)) { + return Clock.OLD; + } + if (!localClock.get(key).equals(messageClock.get(key)) && localClock.get(key) < messageClock.get(key)) { + return Clock.NEW; + } + } + return Clock.EQUAL; + + } else if (localClock.keySet().containsAll(messageClock.keySet()) + && localClock.keySet().size() > messageClock.keySet().size()) { + for (String key : messageClock.keySet()) { + if (!localClock.get(key).equals(messageClock.get(key)) && localClock.get(key) > messageClock.get(key)) { + return Clock.NEW; + } + if (!localClock.get(key).equals(messageClock.get(key)) && localClock.get(key) < messageClock.get(key)) { + return Clock.OLD; + } + } + return Clock.EQUAL; + + } + + return null; + + } + + public boolean isNew(HashMap messageClock) { + checkNull(); + Set localKeyList = localClock.keySet(); + for (String key : messageClock.keySet()) { + + if (localKeyList.contains(key)) { + if (messageClock.get(key) > localClock.get(key)) { + return true; + } + } else { + return true; + } + } + return false; + } + + /** + * Method invoked by local process to update the clock after execution of an + * instruction which has global effect Ex: Sending of message or receiving + * of message. processId should be provided as an input key and local clock + * vector is provided as localClock. + * + * @param localClock + * @param key + * @return + */ + + public HashMap updateClock() { + checkNull(); + localClock.put(processId, localClock.get(processId) + 1); + return localClock; + + } + + /** + * @param localClock + * @param messageClock + * @return + */ + public void updateClock(HashMap messageClock) { + checkNull(); + Set localKeyList = localClock.keySet(); + for (String key : messageClock.keySet()) { + if (localKeyList.contains(key)) { + if (messageClock.get(key) > localClock.get(key)) { + localClock.put(key, messageClock.get(key)); + } + } else { + localClock.put(key, messageClock.get(key)); + } + } + } + + public Integer getTimeStamp() { + checkNull(); + return localClock.get(processId); + } +} diff --git a/Dream2/src/main/java/dream/client/ChangeEvent.java b/Dream2/src/main/java/dream/client/ChangeEvent.java new file mode 100644 index 0000000..e7f646e --- /dev/null +++ b/Dream2/src/main/java/dream/client/ChangeEvent.java @@ -0,0 +1,44 @@ +package dream.client; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +import dream.common.packets.EventPacket; + +public class ChangeEvent implements UpdateConsumer { + + private T latest; + private UUID latestId; + + private Set> handlers = new HashSet>(); + + public ChangeEvent(UpdateProducer p) { + p.registerUpdateConsumer(this, p.getConstraints()); + } + + public void addHandler(ChangeEventHandler handler) { + handlers.add(handler); + } + + public void removeHandler(ChangeEventHandler handler) { + handlers.remove(handler); + } + + private void notifyHandler(T oldValue) { + handlers.forEach(h -> h.handle(oldValue, this.latest)); + } + + @Override + public void updateFromProducer(EventPacket packet, UpdateProducer producer) { + T newVal = (T) packet.getEvent().getVal(); + if (latest == null || !packet.getId().equals(latestId)) { + T old = latest; + latestId = packet.getId(); + this.latest = newVal; + notifyHandler(old); + } + producer.notifyUpdateFinished(); + } + +} \ No newline at end of file diff --git a/Dream2/src/main/java/dream/client/ChangeEventHandler.java b/Dream2/src/main/java/dream/client/ChangeEventHandler.java new file mode 100644 index 0000000..b3e54e2 --- /dev/null +++ b/Dream2/src/main/java/dream/client/ChangeEventHandler.java @@ -0,0 +1,6 @@ +package dream.client; + +@FunctionalInterface +public interface ChangeEventHandler { + public void handle(T oldVal, T newVal); +} diff --git a/Dream2/src/main/java/dream/client/ClientEventForwarder.java b/Dream2/src/main/java/dream/client/ClientEventForwarder.java index 185826d..8ab0cfd 100755 --- a/Dream2/src/main/java/dream/client/ClientEventForwarder.java +++ b/Dream2/src/main/java/dream/client/ClientEventForwarder.java @@ -33,294 +33,293 @@ import polimi.reds.broker.routing.PacketForwarder; class ClientEventForwarder implements PacketForwarder { - private static ClientEventForwarder self = null; - - private final ConnectionManager connectionManager; - private final ClientSubscriptionTable subTable; - - // Dependency graph - private final DependencyGraph dependencyGraph = DependencyGraph.instance; - - // Dependency detectors - private final IntraSourceDependencyDetector intraDepDetector = IntraSourceDependencyDetector.instance; - private final InterSourceDependencyDetector interDepDetector = // - Consts.consistencyType == ConsistencyType.ATOMIC // - ? new AtomicDependencyDetector() // - : new CompleteGlitchFreeDependencyDetector(); - private final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - // Lock applicants waiting for a grant - private final Map lockApplicants = new HashMap<>(); - - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - static final ClientEventForwarder get() { - if (self == null) { - self = new ClientEventForwarder(); - } - return self; - } - - static final void stop() { - if (self != null) { - self.stopClient(); - self = null; - } - } - - private final void stopClient() { - connectionManager.stop(); - } - - private ClientEventForwarder() { - connectionManager = new ConnectionManager(); - subTable = new ClientSubscriptionTable(); - connectionManager.registerForwarder(this, AdvertisementPacket.subject); - connectionManager.registerForwarder(this, SubscriptionPacket.subject); - connectionManager.registerForwarder(this, EventPacket.subject); - connectionManager.registerForwarder(this, LockGrantPacket.subject); - } - - @Override - public Collection forwardPacket(String subject, NodeDescriptor sender, Serializable packet, Collection neighbors, Outbox outbox) { - final Collection result = new ArrayList(); - if (subject.equals(AdvertisementPacket.subject)) { - assert packet instanceof AdvertisementPacket; - logger.finer("Received an advertisement packet " + packet); - processAdvertisementFromServer((AdvertisementPacket) packet); - } else if (subject.equals(SubscriptionPacket.subject)) { - assert packet instanceof SubscriptionPacket; - logger.fine("Received a subscription packet " + packet); - processSubscriptionFromServer((SubscriptionPacket) packet); - } else if (subject.equals(EventPacket.subject)) { - assert packet instanceof EventPacket; - logger.finer("Received an event packet " + packet); - processEventFromServer((EventPacket) packet); - } else if (subject.equals(LockGrantPacket.subject)) { - assert packet instanceof LockGrantPacket; - logger.finer("Received lock grant packet " + packet); - processLockGrant((LockGrantPacket) packet); - } else { - assert false : subject; - } - return result; - } - - final void sendEvent(UUID id, Event ev, String initialVar) { - logger.finer("Sending an event " + ev); - Set lockReleaseNodes; - switch (Consts.consistencyType) { - case COMPLETE_GLITCH_FREE: - lockReleaseNodes = interDepDetector.getNodesToLockFor(initialVar); - break; - case ATOMIC: - lockReleaseNodes = finalNodesDetector.getFinalNodesFor(initialVar); - break; - default: - lockReleaseNodes = new HashSet<>(); - } - - if (subTable.needsToDeliverToServer(ev)) { - connectionManager.sendEvent(id, ev, initialVar, lockReleaseNodes); - } - } - - /** - * Return false if the lock request is not needed - */ - final void sendReadOnlyLockRequest(String node, LockApplicant applicant) { - if (Consts.consistencyType != ConsistencyType.ATOMIC) { - assert false : Consts.consistencyType; - logger.warning("Invoked sendReadOnlyLockRequest() even if the consistency level does not require it."); - return; - } - - logger.finer("Invoked sendReadOnlyLockRequest for node " + node); - final Set nodesToLock = new HashSet<>(); - nodesToLock.add(node); - - final LockRequestPacket reqPkt = new LockRequestPacket(connectionManager.getNodeDescriptor(), nodesToLock, nodesToLock, LockType.READ_ONLY); - final UUID lockId = reqPkt.getLockID(); - lockApplicants.put(lockId, applicant); - - connectionManager.sendLockRequest(reqPkt); - } - - /** - * Return false if the lock request is not needed - */ - final boolean sendReadWriteLockRequest(String source, LockApplicant applicant) { - if (Consts.consistencyType != ConsistencyType.COMPLETE_GLITCH_FREE && // - Consts.consistencyType != ConsistencyType.ATOMIC) { - assert false : Consts.consistencyType; - logger.warning("Invoked sendReadWriteLockRequest() even if the consistency level does not require it."); - return false; - } - - logger.finer("Invoked sendReadWriteLockRequest for source " + source); - final Set nodesToLock = interDepDetector.getNodesToLockFor(source); - final Set releaseNodes = getLockReleaseNodesFor(source); - - if (nodesToLock.isEmpty()) { - return false; - } - - final LockRequestPacket reqPkt = new LockRequestPacket(connectionManager.getNodeDescriptor(), nodesToLock, releaseNodes, LockType.READ_WRITE); - final UUID lockId = reqPkt.getLockID(); - lockApplicants.put(lockId, applicant); - - connectionManager.sendLockRequest(reqPkt); - return true; - } - - final Set getLockReleaseNodesFor(String source) { - switch (Consts.consistencyType) { - case COMPLETE_GLITCH_FREE: - return interDepDetector.getNodesToLockFor(source); - case ATOMIC: - return finalNodesDetector.getFinalNodesFor(source); - default: - return new HashSet<>(); - } - } - - final void sendLockRelease(UUID lockID) { - if (Consts.consistencyType != ConsistencyType.COMPLETE_GLITCH_FREE && // - Consts.consistencyType != ConsistencyType.ATOMIC) { - assert false : Consts.consistencyType; - logger.warning("Invoked sendLockRelease() even if the consistency level does not require it."); - return; - } - - connectionManager.sendLockRelease(new LockReleasePacket(lockID)); - } - - final void advertise(Advertisement adv, boolean isPublic) { - logger.fine("Sending advertisement " + adv); - if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - dependencyGraph.processAdv(adv); - updateDetectors(); - } - connectionManager.sendAdvertisement(adv, isPublic); - } - - final void unadvertise(Advertisement adv, boolean isPublic) { - logger.fine("Sending unadvertisement " + adv); - if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - dependencyGraph.processUnAdv(adv); - updateDetectors(); - } - connectionManager.sendUnadvertisement(adv, isPublic); - } - - final void advertise(Advertisement adv, Set> subs, boolean isPublic) { - logger.fine("Sending advertisement " + adv + " with subscriptions " + subs); - if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - dependencyGraph.processAdv(adv, subs); - updateDetectors(); - } - connectionManager.sendAdvertisement(adv, subs, isPublic); - } - - final void unadvertise(Advertisement adv, Set> subs, boolean isPublic) { - logger.fine("Sending unadvertisement " + adv + " with subscriptions " + subs); - if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - dependencyGraph.processUnAdv(adv, subs); - updateDetectors(); - } - connectionManager.sendUnadvertisement(adv, isPublic); - } - - final void addSubscription(Subscriber subscriber, Subscription subscription) { - logger.fine("Adding subscription " + subscription); - subTable.addSubscription(subscriber, subscription); - if (needToSendToServer(subscription)) { - connectionManager.sendSubscription(subscription); - } - } - - final void removeSubscription(Subscriber subscriber, Subscription subscription) { - logger.fine("Removing subscription " + subscription); - subTable.addSubscription(subscriber, subscription); - if (needToSendToServer(subscription)) { - connectionManager.sendSubscription(subscription); - } - } - - private final boolean needToSendToServer(Subscription sub) { - return !isLocal(sub); - } - - private final boolean isLocal(Subscription sub) { - return sub.getHostId().equals(Consts.hostName); - } - - private final void processEventFromServer(EventPacket evPkt) { - subTable.getMatchingSubscribers(evPkt.getEvent()).forEach(sub -> sub.notifyEventReceived(evPkt)); - if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - subTable.getSignatureOnlyMatchingSubscribers(evPkt.getEvent()).forEach(sub -> sub.notifyEventReceived(evPkt)); - } - } - - private final void processAdvertisementFromServer(AdvertisementPacket advPkt) { - if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - final Set> subs = advPkt.getSubscriptions(); - switch (advPkt.getAdvType()) { - case ADV: - if (subs.isEmpty()) { - dependencyGraph.processAdv(advPkt.getAdvertisement()); - } else { - dependencyGraph.processAdv(advPkt.getAdvertisement(), subs); - } - break; - case UNADV: - if (subs.isEmpty()) { - dependencyGraph.processUnAdv(advPkt.getAdvertisement()); - } else { - dependencyGraph.processUnAdv(advPkt.getAdvertisement(), subs); - } - break; - } - updateDetectors(); - } - } - - private final void processSubscriptionFromServer(SubscriptionPacket subPkt) { - switch (subPkt.getSubType()) { - case SUB: - subTable.addServerSubscription(subPkt.getSubscription()); - break; - case UNSUB: - subTable.removeServerSubscription(subPkt.getSubscription()); - break; - default: - assert false : subPkt.getSubType(); - } - } - - private final void processLockGrant(LockGrantPacket lockGrant) { - final UUID lockID = lockGrant.getLockID(); - assert lockApplicants.containsKey(lockID); - final LockApplicant applicant = lockApplicants.remove(lockID); - applicant.notifyLockGranted(lockGrant); - } - - private final void updateDetectors() { - finalNodesDetector.consolidate(); - intraDepDetector.consolidate(); - interDepDetector.consolidate(); - } + private static ClientEventForwarder self = null; + + private final ConnectionManager connectionManager; + private final ClientSubscriptionTable subTable; + + // Dependency graph + private final DependencyGraph dependencyGraph = DependencyGraph.instance; + + // Dependency detectors + private final IntraSourceDependencyDetector intraDepDetector = IntraSourceDependencyDetector.instance; + private final InterSourceDependencyDetector interDepDetector = // + Consts.consistencyType == ConsistencyType.ATOMIC // + ? new AtomicDependencyDetector() // + : new CompleteGlitchFreeDependencyDetector(); + private final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + // Lock applicants waiting for a grant + private final Map lockApplicants = new HashMap<>(); + + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + static final ClientEventForwarder get() { + if (self == null) { + self = new ClientEventForwarder(); + } + return self; + } + + static final void stop() { + if (self != null) { + self.stopClient(); + self = null; + } + } + + private final void stopClient() { + connectionManager.stop(); + } + + private ClientEventForwarder() { + connectionManager = new ConnectionManager(); + subTable = new ClientSubscriptionTable(); + connectionManager.registerForwarder(this, AdvertisementPacket.subject); + connectionManager.registerForwarder(this, SubscriptionPacket.subject); + connectionManager.registerForwarder(this, EventPacket.subject); + connectionManager.registerForwarder(this, LockGrantPacket.subject); + } + + @Override + public synchronized Collection forwardPacket(String subject, NodeDescriptor sender, + Serializable packet, Collection neighbors, Outbox outbox) { + final Collection result = new ArrayList(); + if (subject.equals(AdvertisementPacket.subject)) { + assert packet instanceof AdvertisementPacket; + logger.finer("Received an advertisement packet " + packet); + processAdvertisementFromServer((AdvertisementPacket) packet); + } else if (subject.equals(SubscriptionPacket.subject)) { + assert packet instanceof SubscriptionPacket; + logger.fine("Received a subscription packet " + packet); + processSubscriptionFromServer((SubscriptionPacket) packet); + } else if (subject.equals(EventPacket.subject)) { + assert packet instanceof EventPacket; + logger.finer("Received an event packet " + packet); + processEventFromServer((EventPacket) packet); + } else if (subject.equals(LockGrantPacket.subject)) { + assert packet instanceof LockGrantPacket; + logger.finer("Received lock grant packet " + packet); + processLockGrant((LockGrantPacket) packet); + } else { + assert false : subject; + } + return result; + } + + final synchronized void sendEvent(UUID id, Event ev, String initialVar) { + logger.finer("Sending an event " + ev); + Set lockReleaseNodes; + switch (Consts.consistencyType) { + case COMPLETE_GLITCH_FREE: + lockReleaseNodes = interDepDetector.getNodesToLockFor(initialVar); + break; + case ATOMIC: + lockReleaseNodes = finalNodesDetector.getFinalNodesFor(initialVar); + break; + default: + lockReleaseNodes = new HashSet<>(); + } + + if (subTable.needsToDeliverToServer(ev)) { + connectionManager.sendEvent(id, ev, initialVar, lockReleaseNodes); + } + } + + final synchronized void sendReadOnlyLockRequest(Set nodesToLock, LockApplicant applicant) { + if (Consts.consistencyType != ConsistencyType.ATOMIC) { + assert false : Consts.consistencyType; + logger.warning("Invoked sendReadOnlyLockRequest() even if the consistency level does not require it."); + return; + } + + logger.finer("Invoked sendReadOnlyLockRequest for nodes " + nodesToLock); + + final LockRequestPacket reqPkt = new LockRequestPacket(connectionManager.getNodeDescriptor(), nodesToLock, + nodesToLock, LockType.READ_ONLY); + final UUID lockId = reqPkt.getLockID(); + lockApplicants.put(lockId, applicant); + + connectionManager.sendLockRequest(reqPkt); + } + + /** + * Return false if the lock request is not needed + */ + final synchronized boolean sendReadWriteLockRequest(String source, LockApplicant applicant) { + if (Consts.consistencyType != ConsistencyType.COMPLETE_GLITCH_FREE && // + Consts.consistencyType != ConsistencyType.ATOMIC) { + assert false : Consts.consistencyType; + logger.warning("Invoked sendReadWriteLockRequest() even if the consistency level does not require it."); + return false; + } + + logger.finer("Invoked sendReadWriteLockRequest for source " + source); + final Set nodesToLock = interDepDetector.getNodesToLockFor(source); + final Set releaseNodes = getLockReleaseNodesFor(source); + + if (nodesToLock.isEmpty()) { + return false; + } + + final LockRequestPacket reqPkt = new LockRequestPacket(connectionManager.getNodeDescriptor(), nodesToLock, + releaseNodes, LockType.READ_WRITE); + final UUID lockId = reqPkt.getLockID(); + lockApplicants.put(lockId, applicant); + + connectionManager.sendLockRequest(reqPkt); + return true; + } + + final synchronized Set getLockReleaseNodesFor(String source) { + switch (Consts.consistencyType) { + case COMPLETE_GLITCH_FREE: + return interDepDetector.getNodesToLockFor(source); + case ATOMIC: + return finalNodesDetector.getFinalNodesFor(source); + default: + return new HashSet<>(); + } + } + + final synchronized void sendLockRelease(UUID lockID) { + if (Consts.consistencyType != ConsistencyType.COMPLETE_GLITCH_FREE && // + Consts.consistencyType != ConsistencyType.ATOMIC) { + assert false : Consts.consistencyType; + logger.warning("Invoked sendLockRelease() even if the consistency level does not require it."); + return; + } + + connectionManager.sendLockRelease(new LockReleasePacket(lockID)); + } + + final synchronized void advertise(Advertisement adv, boolean isPublic) { + logger.fine("Sending advertisement " + adv); + if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + dependencyGraph.processAdv(adv); + updateDetectors(); + } + connectionManager.sendAdvertisement(adv, isPublic); + } + + final synchronized void unadvertise(Advertisement adv, boolean isPublic) { + logger.fine("Sending unadvertisement " + adv); + if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + dependencyGraph.processUnAdv(adv); + updateDetectors(); + } + connectionManager.sendUnadvertisement(adv, isPublic); + } + + final synchronized void advertise(Advertisement adv, Set> subs, boolean isPublic) { + logger.fine("Sending advertisement " + adv + " with subscriptions " + subs); + if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + dependencyGraph.processAdv(adv, subs); + updateDetectors(); + } + connectionManager.sendAdvertisement(adv, subs, isPublic); + } + + final synchronized void unadvertise(Advertisement adv, Set> subs, boolean isPublic) { + logger.fine("Sending unadvertisement " + adv + " with subscriptions " + subs); + if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + dependencyGraph.processUnAdv(adv, subs); + updateDetectors(); + } + connectionManager.sendUnadvertisement(adv, isPublic); + } + + final synchronized void addSubscription(Subscriber subscriber, Subscription subscription) { + logger.fine("Adding subscription " + subscription); + subTable.addSubscription(subscriber, subscription); + if (needToSendToServer(subscription)) { + connectionManager.sendSubscription(subscription); + } + } + + final synchronized void removeSubscription(Subscriber subscriber, Subscription subscription) { + logger.fine("Removing subscription " + subscription); + subTable.addSubscription(subscriber, subscription); + if (needToSendToServer(subscription)) { + connectionManager.sendSubscription(subscription); + } + } + + private final boolean needToSendToServer(Subscription sub) { + return !isLocal(sub); + } + + private final boolean isLocal(Subscription sub) { + return sub.getHostId().equals(Consts.hostName); + } + + private final void processEventFromServer(EventPacket evPkt) { + subTable.getMatchingSubscribers(evPkt.getEvent()).forEach(sub -> sub.notifyEventReceived(evPkt)); + if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + subTable.getSignatureOnlyMatchingSubscribers(evPkt.getEvent()) + .forEach(sub -> sub.notifyEventReceived(evPkt)); + } + } + + private final void processAdvertisementFromServer(AdvertisementPacket advPkt) { + if (Consts.consistencyType == ConsistencyType.SINGLE_SOURCE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + final Set> subs = advPkt.getSubscriptions(); + switch (advPkt.getAdvType()) { + case ADV: + if (subs.isEmpty()) { + dependencyGraph.processAdv(advPkt.getAdvertisement()); + } else { + dependencyGraph.processAdv(advPkt.getAdvertisement(), subs); + } + break; + case UNADV: + if (subs.isEmpty()) { + dependencyGraph.processUnAdv(advPkt.getAdvertisement()); + } else { + dependencyGraph.processUnAdv(advPkt.getAdvertisement(), subs); + } + break; + } + updateDetectors(); + } + } + + private final void processSubscriptionFromServer(SubscriptionPacket subPkt) { + switch (subPkt.getSubType()) { + case SUB: + subTable.addServerSubscription(subPkt.getSubscription()); + break; + case UNSUB: + subTable.removeServerSubscription(subPkt.getSubscription()); + break; + default: + assert false : subPkt.getSubType(); + } + } + + private final void processLockGrant(LockGrantPacket lockGrant) { + final UUID lockID = lockGrant.getLockID(); + assert lockApplicants.containsKey(lockID); + final LockApplicant applicant = lockApplicants.remove(lockID); + applicant.notifyLockGranted(lockGrant); + } + + private final void updateDetectors() { + finalNodesDetector.consolidate(); + intraDepDetector.consolidate(); + interDepDetector.consolidate(); + } } diff --git a/Dream2/src/main/java/dream/client/ClientSubscriptionTable.java b/Dream2/src/main/java/dream/client/ClientSubscriptionTable.java index fd23fb9..8bf044c 100755 --- a/Dream2/src/main/java/dream/client/ClientSubscriptionTable.java +++ b/Dream2/src/main/java/dream/client/ClientSubscriptionTable.java @@ -12,65 +12,67 @@ import dream.common.packets.content.Subscription; final class ClientSubscriptionTable { - private final Map>> subs = new HashMap>>(); - private final Collection> serverSubscriptions = new ArrayList>(); + private final Map>> subs = new HashMap>>(); + private final Collection> serverSubscriptions = new ArrayList>(); - final void addSubscription(Subscriber subscriber, Subscription sub) { - Collection> subsList = subs.get(subscriber); - if (subsList == null) { - subsList = new ArrayList>(); - subs.put(subscriber, subsList); - } - subsList.add(sub); - } + final void addSubscription(Subscriber subscriber, Subscription sub) { + Collection> subsList = subs.get(subscriber); + if (subsList == null) { + subsList = new ArrayList>(); + subs.put(subscriber, subsList); + } + subsList.add(sub); + } - final void addSubscriptions(Subscriber subscriber, Collection> subs) { - subs.forEach(sub -> addSubscription(subscriber, sub)); - } + final void addSubscriptions(Subscriber subscriber, Collection> subs) { + subs.forEach(sub -> addSubscription(subscriber, sub)); + } - final void addServerSubscription(Subscription sub) { - serverSubscriptions.add(sub); - } + final void addServerSubscription(Subscription sub) { + serverSubscriptions.add(sub); + } - final void removeSubscription(Subscriber subscriber, Subscription sub) { - final Collection> subscriptions = subs.get(subscriber); - if (subscriptions == null) { - return; - } - subscriptions.remove(sub); - if (subscriptions.isEmpty()) { - subs.remove(subscriber); - } - } + final void removeSubscription(Subscriber subscriber, Subscription sub) { + final Collection> subscriptions = subs.get(subscriber); + if (subscriptions == null) { + return; + } + subscriptions.remove(sub); + if (subscriptions.isEmpty()) { + subs.remove(subscriber); + } + } - final void removeSubscriptions(Subscriber subscriber, Collection> subs) { - subs.forEach(sub -> removeSubscription(subscriber, sub)); - } + final void removeSubscriptions(Subscriber subscriber, Collection> subs) { + subs.forEach(sub -> removeSubscription(subscriber, sub)); + } - final void removeServerSubscription(Subscription sub) { - serverSubscriptions.remove(sub); - } + final void removeServerSubscription(Subscription sub) { + serverSubscriptions.remove(sub); + } - final Set getMatchingSubscribers(Event ev) { - return getSubscribersWithAnySubscriptionMatching(sub -> sub.isSatisfiedBy(ev)); - } + final Set getMatchingSubscribers(Event ev) { + return getSubscribersWithAnySubscriptionMatching(sub -> sub.isSatisfiedBy(ev)); + } - final Set getSignatureOnlyMatchingSubscribers(Event ev) { - return getSubscribersWithAnySubscriptionMatching(sub -> sub.matchesOnlySignatureOf(ev) && !sub.isSatisfiedBy(ev)); - } + final Set getSignatureOnlyMatchingSubscribers(Event ev) { + return getSubscribersWithAnySubscriptionMatching( + sub -> sub.matchesOnlySignatureOf(ev) && !sub.isSatisfiedBy(ev)); + } - private final Set getSubscribersWithAnySubscriptionMatching(Predicate> predicate) { - final Predicate hasSubscriptionMatchingOnlySignature = subscriber -> subs.get(subscriber).stream().anyMatch(predicate); - return subs.keySet().stream().filter(hasSubscriptionMatchingOnlySignature).collect(Collectors.toSet()); - } + private final Set getSubscribersWithAnySubscriptionMatching(Predicate> predicate) { + final Predicate hasSubscriptionMatchingOnlySignature = subscriber -> subs.get(subscriber).stream() + .anyMatch(predicate); + return subs.keySet().stream().filter(hasSubscriptionMatchingOnlySignature).collect(Collectors.toSet()); + } - final boolean needsToDeliverToServer(Event ev) { - return serverSubscriptions.stream().anyMatch(sub -> sub.isSatisfiedBy(ev)); - } + final boolean needsToDeliverToServer(Event ev) { + return serverSubscriptions.stream().anyMatch(sub -> sub.isSatisfiedBy(ev)); + } - @Override - public String toString() { - return "ClientSubscriptionTable [\n subs=" + subs + "\n serverSubscriptions=" + serverSubscriptions + "\n]"; - } + @Override + public String toString() { + return "ClientSubscriptionTable [\n subs=" + subs + "\n serverSubscriptions=" + serverSubscriptions + "\n]"; + } } diff --git a/Dream2/src/main/java/dream/client/ConnectionManager.java b/Dream2/src/main/java/dream/client/ConnectionManager.java index e2a9d04..a237bb4 100755 --- a/Dream2/src/main/java/dream/client/ConnectionManager.java +++ b/Dream2/src/main/java/dream/client/ConnectionManager.java @@ -39,158 +39,162 @@ import polimi.reds.broker.routing.PacketForwarder; class ConnectionManager implements PacketForwarder { - private final Overlay overlay; - private final GenericRouter router; - - private NodeDescriptor server = null; - private NodeDescriptor lockManager = null; - - private final Queue serverQueue = new LinkedList<>(); - private final Queue lockManagerQueue = new LinkedList<>(); - - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - ConnectionManager() { - Transport tr = null; - try { - tr = new TCPTransport(); - } catch (final IOException e) { - e.printStackTrace(); - } - final TopologyManager tm = new SimpleTopologyManager(); - overlay = new GenericOverlay(tm, tr, false); - router = new GenericRouter(overlay); - router.setPacketForwarder(ServerHelloPacket.subject, this); - router.setPacketForwarder(LockManagerHelloPacket.subject, this); - overlay.start(); - try { - overlay.addNeighbor(Consts.serverAddr); - if (Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - overlay.addNeighbor(Consts.lockManagerAddr); - } - } catch (ConnectException | MalformedURLException | NotRunningException e) { - e.printStackTrace(); - } - } - - final NodeDescriptor getNodeDescriptor() { - return overlay.getNodeDescriptor(); - } - - final void sendEvent(UUID id, Event event, String initialVar, Set lockReleaseNodes) { - final EventPacket pkt = new EventPacket(event, id, initialVar); - pkt.setLockReleaseNodes(lockReleaseNodes); - sendToServer(EventPacket.subject, pkt); - } - - final void sendSubscription(Subscription sub) { - final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.SUB); - sendToServer(SubscriptionPacket.subject, pkt); - } - - final void sendUnsubscription(Subscription sub) { - final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.UNSUB); - sendToServer(SubscriptionPacket.subject, pkt); - } - - final void sendAdvertisement(Advertisement adv, boolean isPublic) { - sendAdvertisement(adv, AdvType.ADV, null, isPublic); - } - - final void sendAdvertisement(Advertisement adv, Set> subs, boolean isPublic) { - sendAdvertisement(adv, AdvType.ADV, subs, isPublic); - } - - final void sendUnadvertisement(Advertisement adv, boolean isPublic) { - sendAdvertisement(adv, AdvType.UNADV, null, isPublic); - } - - final void sendUnadvertisement(Advertisement adv, Set> subs, boolean isPublic) { - sendAdvertisement(adv, AdvType.UNADV, subs, isPublic); - } - - final void sendLockRequest(LockRequestPacket req) { - sendToLockManager(LockRequestPacket.subject, req); - } - - final void sendLockRelease(LockReleasePacket rel) { - sendToLockManager(LockReleasePacket.subject, rel); - } - - private final void sendAdvertisement(Advertisement adv, AdvType advType, Set> subs, boolean isPublic) { - final AdvertisementPacket pkt = subs != null ? new AdvertisementPacket(adv, advType, subs, isPublic) : new AdvertisementPacket(adv, advType, isPublic); - sendToServer(AdvertisementPacket.subject, pkt); - } - - final void registerForwarder(PacketForwarder forwarder, String subject) { - router.setPacketForwarder(subject, forwarder); - } - - final void stop() { - overlay.stop(); - } - - private final void sendToServer(String subject, Serializable packet) { - if (server == null) { - serverQueue.add(new PacketSubjectPair(subject, packet)); - } else { - try { - overlay.send(subject, packet, server); - } catch (IOException | NotRunningException e) { - e.printStackTrace(); - } - } - } - - private final void sendToLockManager(String subject, Serializable packet) { - if (lockManager == null) { - lockManagerQueue.add(new PacketSubjectPair(subject, packet)); - } else { - try { - overlay.send(subject, packet, lockManager); - } catch (IOException | NotRunningException e) { - e.printStackTrace(); - } - } - } - - @Override - public final Collection forwardPacket(String subject, NodeDescriptor sender, Serializable packet, Collection neighbors, Outbox outbox) { - if (subject.equals(ServerHelloPacket.subject)) { - logger.info("Received server hello packet"); - assert packet instanceof ServerHelloPacket; - server = sender; - serverQueue.forEach(p -> sendToServer(p.getSubject(), p.getPacket())); - } else if (subject.equals(LockManagerHelloPacket.subject)) { - logger.info("Received lock manager hello packet"); - assert packet instanceof LockManagerHelloPacket; - lockManager = sender; - lockManagerQueue.forEach(p -> sendToLockManager(p.getSubject(), p.getPacket())); - } else { - assert false : subject; - } - return new ArrayList<>(); - } - - private class PacketSubjectPair { - private final String subject; - private final Serializable packet; - - public PacketSubjectPair(String subject, Serializable packet) { - super(); - this.subject = subject; - this.packet = packet; - } - - final String getSubject() { - return subject; - } - - final Serializable getPacket() { - return packet; - } - - } + private final Overlay overlay; + private final GenericRouter router; + + private NodeDescriptor server = null; + private NodeDescriptor lockManager = null; + + private final Queue serverQueue = new LinkedList<>(); + private final Queue lockManagerQueue = new LinkedList<>(); + + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + ConnectionManager() { + Transport tr = null; + try { + tr = new TCPTransport(); + } catch (final IOException e) { + e.printStackTrace(); + } + final TopologyManager tm = new SimpleTopologyManager(); + overlay = new GenericOverlay(tm, tr, false); + router = new GenericRouter(overlay); + router.setPacketForwarder(ServerHelloPacket.subject, this); + router.setPacketForwarder(LockManagerHelloPacket.subject, this); + overlay.start(); + try { + overlay.addNeighbor(Consts.serverAddr); + if (Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + overlay.addNeighbor(Consts.lockManagerAddr); + } + } catch (ConnectException | MalformedURLException | NotRunningException e) { + e.printStackTrace(); + } + } + + final NodeDescriptor getNodeDescriptor() { + return overlay.getNodeDescriptor(); + } + + final void sendEvent(UUID id, Event event, String initialVar, + Set lockReleaseNodes) { + final EventPacket pkt = new EventPacket(event, id, initialVar); + pkt.setLockReleaseNodes(lockReleaseNodes); + sendToServer(EventPacket.subject, pkt); + } + + final void sendSubscription(Subscription sub) { + final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.SUB); + sendToServer(SubscriptionPacket.subject, pkt); + } + + final void sendUnsubscription(Subscription sub) { + final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.UNSUB); + sendToServer(SubscriptionPacket.subject, pkt); + } + + final void sendAdvertisement(Advertisement adv, boolean isPublic) { + sendAdvertisement(adv, AdvType.ADV, null, isPublic); + } + + final void sendAdvertisement(Advertisement adv, Set> subs, boolean isPublic) { + sendAdvertisement(adv, AdvType.ADV, subs, isPublic); + } + + final void sendUnadvertisement(Advertisement adv, boolean isPublic) { + sendAdvertisement(adv, AdvType.UNADV, null, isPublic); + } + + final void sendUnadvertisement(Advertisement adv, Set> subs, boolean isPublic) { + sendAdvertisement(adv, AdvType.UNADV, subs, isPublic); + } + + final void sendLockRequest(LockRequestPacket req) { + sendToLockManager(LockRequestPacket.subject, req); + } + + final void sendLockRelease(LockReleasePacket rel) { + sendToLockManager(LockReleasePacket.subject, rel); + } + + private final void sendAdvertisement(Advertisement adv, AdvType advType, Set> subs, + boolean isPublic) { + final AdvertisementPacket pkt = subs != null ? new AdvertisementPacket(adv, advType, subs, isPublic) + : new AdvertisementPacket(adv, advType, isPublic); + sendToServer(AdvertisementPacket.subject, pkt); + } + + final void registerForwarder(PacketForwarder forwarder, String subject) { + router.setPacketForwarder(subject, forwarder); + } + + final void stop() { + overlay.stop(); + } + + private final void sendToServer(String subject, Serializable packet) { + if (server == null) { + serverQueue.add(new PacketSubjectPair(subject, packet)); + } else { + try { + overlay.send(subject, packet, server); + } catch (IOException | NotRunningException e) { + e.printStackTrace(); + } + } + } + + private final void sendToLockManager(String subject, Serializable packet) { + if (lockManager == null) { + lockManagerQueue.add(new PacketSubjectPair(subject, packet)); + } else { + try { + overlay.send(subject, packet, lockManager); + } catch (IOException | NotRunningException e) { + e.printStackTrace(); + } + } + } + + @Override + public final Collection forwardPacket(String subject, NodeDescriptor sender, Serializable packet, + Collection neighbors, Outbox outbox) { + if (subject.equals(ServerHelloPacket.subject)) { + logger.info("Received server hello packet"); + assert packet instanceof ServerHelloPacket; + server = sender; + serverQueue.forEach(p -> sendToServer(p.getSubject(), p.getPacket())); + } else if (subject.equals(LockManagerHelloPacket.subject)) { + logger.info("Received lock manager hello packet"); + assert packet instanceof LockManagerHelloPacket; + lockManager = sender; + lockManagerQueue.forEach(p -> sendToLockManager(p.getSubject(), p.getPacket())); + } else { + assert false : subject; + } + return new ArrayList<>(); + } + + private class PacketSubjectPair { + private final String subject; + private final Serializable packet; + + public PacketSubjectPair(String subject, Serializable packet) { + super(); + this.subject = subject; + this.packet = packet; + } + + final String getSubject() { + return subject; + } + + final Serializable getPacket() { + return packet; + } + + } } diff --git a/Dream2/src/main/java/dream/client/DreamClient.java b/Dream2/src/main/java/dream/client/DreamClient.java index 83a9b14..fe8536f 100644 --- a/Dream2/src/main/java/dream/client/DreamClient.java +++ b/Dream2/src/main/java/dream/client/DreamClient.java @@ -10,19 +10,60 @@ * to obtain information about the dependency graph. */ public enum DreamClient { - instance; + instance; - private final DependencyGraph depGraph = DependencyGraph.instance; + private final DependencyGraph depGraph = DependencyGraph.instance; + private ClientEventForwarder eventForwarder; - public final void connect() { - ClientEventForwarder.get(); - } + public final void connect() { + eventForwarder = ClientEventForwarder.get(); + } - public final Set listVariables() { - final Set result = new HashSet<>(); - result.addAll(depGraph.getGraph().keySet()); - result.addAll(depGraph.getSources()); - return result; - } + public final Set listVariables() { + final Set result = new HashSet<>(); + result.addAll(depGraph.getGraph().keySet()); + result.addAll(depGraph.getSources()); + return result; + } + + public final LockToken readLock(Set varsToLock) { + LockToken token = new LockToken(varsToLock.size()); + Lock lock = new Lock(); + eventForwarder.sendReadOnlyLockRequest(varsToLock, grant -> { + synchronized (lock) { + lock.unlock(); + token.setLockId(grant.getLockID()); + lock.notifyAll(); + } + }); + synchronized (lock) { + while (!lock.isUnlocked()) { + try { + lock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + return token; + } + + public final void unlock(LockToken token) { + for (int i = 0; i < token.getNumLocks(); i++) { + eventForwarder.sendLockRelease(token.getLockId()); + } + } + + private class Lock { + private boolean unlocked = false; + + final void unlock() { + unlocked = true; + } + + final boolean isUnlocked() { + return unlocked; + } + } } diff --git a/Dream2/src/main/java/dream/client/EventProducerPair.java b/Dream2/src/main/java/dream/client/EventProducerPair.java index 7ee7728..6fe0e13 100755 --- a/Dream2/src/main/java/dream/client/EventProducerPair.java +++ b/Dream2/src/main/java/dream/client/EventProducerPair.java @@ -3,26 +3,26 @@ import dream.common.packets.EventPacket; public class EventProducerPair { - private final EventPacket eventPacket; - private final UpdateProducer producer; + private final EventPacket eventPacket; + private final UpdateProducer producer; - public EventProducerPair(EventPacket eventPacket, UpdateProducer producer) { - super(); - this.eventPacket = eventPacket; - this.producer = producer; - } + public EventProducerPair(EventPacket eventPacket, UpdateProducer producer) { + super(); + this.eventPacket = eventPacket; + this.producer = producer; + } - public final EventPacket getEventPacket() { - return eventPacket; - } + public final EventPacket getEventPacket() { + return eventPacket; + } - public final UpdateProducer getUpdateProducer() { - return producer; - } + public final UpdateProducer getUpdateProducer() { + return producer; + } - @Override - public String toString() { - return "ComputationHandler [eventPacket=" + eventPacket + ", producer=" + producer + "]"; - } + @Override + public String toString() { + return "ComputationHandler [eventPacket=" + eventPacket + ", producer=" + producer + "]"; + } } diff --git a/Dream2/src/main/java/dream/client/FilteredUpdateProducer.java b/Dream2/src/main/java/dream/client/FilteredUpdateProducer.java index a28eb1a..dbc8626 100644 --- a/Dream2/src/main/java/dream/client/FilteredUpdateProducer.java +++ b/Dream2/src/main/java/dream/client/FilteredUpdateProducer.java @@ -6,49 +6,49 @@ class FilteredUpdateProducer implements UpdateProducer { - private final UpdateProducer producer; - private final List> constraints; - - public FilteredUpdateProducer(UpdateProducer producer, List> constraints) { - super(); - this.producer = producer; - this.constraints = constraints; - } - - @Override - public void notifyUpdateFinished() { - producer.notifyUpdateFinished(); - } - - @Override - public void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { - producer.registerUpdateConsumer(consumer, constraints); - } - - @Override - public void unregisterUpdateConsumer(UpdateConsumer consumer) { - producer.unregisterUpdateConsumer(consumer); - } - - @Override - public UpdateProducer filter(SerializablePredicate constraint) { - constraints.add(constraint); - return this; - } - - @Override - public String getHost() { - return producer.getHost(); - } - - @Override - public String getObject() { - return producer.getObject(); - } - - @Override - public List> getConstraints() { - return constraints; - } + private final UpdateProducer producer; + private final List> constraints; + + public FilteredUpdateProducer(UpdateProducer producer, List> constraints) { + super(); + this.producer = producer; + this.constraints = constraints; + } + + @Override + public void notifyUpdateFinished() { + producer.notifyUpdateFinished(); + } + + @Override + public void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { + producer.registerUpdateConsumer(consumer, constraints); + } + + @Override + public void unregisterUpdateConsumer(UpdateConsumer consumer) { + producer.unregisterUpdateConsumer(consumer); + } + + @Override + public UpdateProducer filter(SerializablePredicate constraint) { + constraints.add(constraint); + return this; + } + + @Override + public String getHost() { + return producer.getHost(); + } + + @Override + public String getObject() { + return producer.getObject(); + } + + @Override + public List> getConstraints() { + return constraints; + } } diff --git a/Dream2/src/main/java/dream/client/LockApplicant.java b/Dream2/src/main/java/dream/client/LockApplicant.java index d891785..9651a59 100644 --- a/Dream2/src/main/java/dream/client/LockApplicant.java +++ b/Dream2/src/main/java/dream/client/LockApplicant.java @@ -7,12 +7,12 @@ */ interface LockApplicant { - /** - * Method invoked when a lock is granted. - * - * @param lockGrant - * the granted lock. - */ - void notifyLockGranted(LockGrantPacket lockGrant); + /** + * Method invoked when a lock is granted. + * + * @param lockGrant + * the granted lock. + */ + void notifyLockGranted(LockGrantPacket lockGrant); } diff --git a/Dream2/src/main/java/dream/client/LockToken.java b/Dream2/src/main/java/dream/client/LockToken.java new file mode 100644 index 0000000..2bd1063 --- /dev/null +++ b/Dream2/src/main/java/dream/client/LockToken.java @@ -0,0 +1,25 @@ +package dream.client; + +import java.util.UUID; + +public class LockToken { + private UUID lockId; + private final int numLocks; + + LockToken(int numLocks) { + this.numLocks = numLocks; + } + + final void setLockId(UUID lockId) { + this.lockId = lockId; + } + + final UUID getLockId() { + return lockId; + } + + final int getNumLocks() { + return numLocks; + } + +} diff --git a/Dream2/src/main/java/dream/client/QueueManager.java b/Dream2/src/main/java/dream/client/QueueManager.java index 4d87a2a..6b5f947 100755 --- a/Dream2/src/main/java/dream/client/QueueManager.java +++ b/Dream2/src/main/java/dream/client/QueueManager.java @@ -18,77 +18,79 @@ * to make sure that no glitch can occur. */ class QueueManager { - // WaitingElements, partitioned by id - private final Map waitingElements = new HashMap(); - // Candidate results to deliver (they can be effectively delivered only there - // are no waiting elements). - private final Set pendingResults = new HashSet<>(); + // WaitingElements, partitioned by id + private final Map waitingElements = new HashMap(); + // Candidate results to deliver (they can be effectively delivered only + // there + // are no waiting elements). + private final Set pendingResults = new HashSet<>(); - final List processEventPacket(EventProducerPair event, String expression) { - final EventPacket evPkt = event.getEventPacket(); - final UUID id = evPkt.getId(); - final Set waitingRecommendations = // - IntraSourceDependencyDetector.instance.// - getWaitRecommendations(evPkt.getEvent(), evPkt.getSource()).// - stream().filter(wr -> wr.getExpression().equals(expression)).// - collect(Collectors.toSet()); + final List processEventPacket(EventProducerPair event, String expression) { + final EventPacket evPkt = event.getEventPacket(); + final UUID id = evPkt.getId(); + final Set waitingRecommendations = // + IntraSourceDependencyDetector.instance.// + getWaitRecommendations(evPkt.getEvent(), evPkt.getSource()).// + stream().filter(wr -> wr.getExpression().equals(expression)).// + collect(Collectors.toSet()); - if (waitingElements.containsKey(id)) { - final WaitingElement elem = waitingElements.get(id); - elem.processEvent(event); - if (elem.hasFinishedWaiting()) { - elem.getReceivedEvents().forEach(pendingResults::add); - waitingElements.remove(id); - } - } else { - final Set expressionsToWaitFrom = getExpressionsToWaitFrom(waitingRecommendations); - if (!expressionsToWaitFrom.isEmpty()) { - final WaitingElement elem = new WaitingElement(expressionsToWaitFrom, event); - waitingElements.put(id, elem); - } else { - pendingResults.add(event); - } - } + if (waitingElements.containsKey(id)) { + final WaitingElement elem = waitingElements.get(id); + elem.processEvent(event); + if (elem.hasFinishedWaiting()) { + elem.getReceivedEvents().forEach(pendingResults::add); + waitingElements.remove(id); + } + } else { + final Set expressionsToWaitFrom = getExpressionsToWaitFrom(waitingRecommendations); + if (!expressionsToWaitFrom.isEmpty()) { + final WaitingElement elem = new WaitingElement(expressionsToWaitFrom, event); + waitingElements.put(id, elem); + } else { + pendingResults.add(event); + } + } - final List result = new ArrayList<>(); - if (!waitingElements.containsKey(id)) { - result.addAll(pendingResults); - pendingResults.clear(); - } - return result; - } + final List result = new ArrayList<>(); + if (!waitingElements.containsKey(id)) { + result.addAll(pendingResults); + pendingResults.clear(); + } + return result; + } - private final Set getExpressionsToWaitFrom(Set recommendations) { - return recommendations.stream().// - map(wr -> wr.getRecommendations()).// - collect(HashSet::new, HashSet::addAll, HashSet::addAll); - } + private final Set getExpressionsToWaitFrom(Set recommendations) { + return recommendations.stream().// + map(wr -> wr.getRecommendations()).// + collect(HashSet::new, HashSet::addAll, HashSet::addAll); + } - private class WaitingElement { - // Set of expressions we are waiting for before delivering the events with - // the given id - private final Set waitingFor = new HashSet<>(); - // Set of events received with the given id - private final Set receivedEvents = new HashSet<>(); + private class WaitingElement { + // Set of expressions we are waiting for before delivering the events + // with + // the given id + private final Set waitingFor = new HashSet<>(); + // Set of events received with the given id + private final Set receivedEvents = new HashSet<>(); - WaitingElement(Set waitingFor, EventProducerPair event) { - this.waitingFor.addAll(waitingFor); - receivedEvents.add(event); - } + WaitingElement(Set waitingFor, EventProducerPair event) { + this.waitingFor.addAll(waitingFor); + receivedEvents.add(event); + } - final void processEvent(EventProducerPair event) { - final String signature = event.getEventPacket().getEvent().getSignature(); - assert waitingFor.contains(signature); - waitingFor.remove(signature); - receivedEvents.add(event); - } + final void processEvent(EventProducerPair event) { + final String signature = event.getEventPacket().getEvent().getSignature(); + assert waitingFor.contains(signature); + waitingFor.remove(signature); + receivedEvents.add(event); + } - final boolean hasFinishedWaiting() { - return waitingFor.isEmpty(); - } + final boolean hasFinishedWaiting() { + return waitingFor.isEmpty(); + } - final Set getReceivedEvents() { - return receivedEvents; - } - } + final Set getReceivedEvents() { + return receivedEvents; + } + } } diff --git a/Dream2/src/main/java/dream/client/RemoteVar.java b/Dream2/src/main/java/dream/client/RemoteVar.java index 63ece5c..6e87851 100755 --- a/Dream2/src/main/java/dream/client/RemoteVar.java +++ b/Dream2/src/main/java/dream/client/RemoteVar.java @@ -17,115 +17,115 @@ import dream.common.packets.content.Subscription; public class RemoteVar implements Subscriber, UpdateProducer { - private T val; - - private final ClientEventForwarder forwarder; - private final Map>> consumers = new HashMap<>(); - - private final Queue eventsQueue = new ArrayDeque<>(); - private int pendingAcks = 0; - - private final List> constraints = new ArrayList<>(); - - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - private final String host; - private final String object; - - public RemoteVar(String host, String object, List> constraints) { - this.host = host; - this.object = object; - - final Subscription sub = new Subscription(host, object, constraints); - forwarder = ClientEventForwarder.get(); - forwarder.addSubscription(this, sub); - } - - public RemoteVar(String object, List> constraints) { - this(Consts.hostName, object, constraints); - } - - public RemoteVar(String host, String object) { - this(host, object, new ArrayList>()); - } - - public RemoteVar(String object) { - this(Consts.hostName, object); - } - - public final synchronized T get() { - return val; - } - - @Override - public synchronized void notifyEventReceived(EventPacket evPkt) { - eventsQueue.add(evPkt); - logger.finest("Received event packet " + evPkt + ". Added to the queue."); - if (eventsQueue.size() == 1) { - logger.finest("The element is the only one in the queue. Let's process it."); - processNextEvent(); - } - } - - @Override - public final synchronized void notifyUpdateFinished() { - pendingAcks--; - processNextEvent(); - } - - @SuppressWarnings("unchecked") - private void processNextEvent() { - if (pendingAcks == 0 && !eventsQueue.isEmpty()) { - final EventPacket nextPkt = eventsQueue.poll(); - val = (T) nextPkt.getEvent().getVal(); - sendEventPacketToListeners(nextPkt); - } - } - - private final void sendEventPacketToListeners(EventPacket evPkt) { - if (!consumers.isEmpty()) { - final Set satConsumers = // - consumers.entrySet().stream().filter(e -> e.getValue().stream().allMatch(constr -> constr.test(val)))// - .map(e -> e.getKey())// - .collect(Collectors.toSet()); - - pendingAcks = satConsumers.size(); - satConsumers.forEach(c -> c.updateFromProducer(evPkt, this)); - } else { - processNextEvent(); - } - } - - @Override - public final String getHost() { - return host; - } - - @Override - public final String getObject() { - return object; - } - - @Override - public final List> getConstraints() { - return constraints; - } - - @Override - public final void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { - consumers.put(consumer, constraints); - } - - @Override - public final void unregisterUpdateConsumer(UpdateConsumer consumer) { - consumers.remove(consumer); - } - - @Override - public UpdateProducer filter(SerializablePredicate constraint) { - final List> constrList = new ArrayList<>(); - constrList.add(constraint); - return new FilteredUpdateProducer<>(this, constrList); - } + private T val; + + private final ClientEventForwarder forwarder; + private final Map>> consumers = new HashMap<>(); + + private final Queue eventsQueue = new ArrayDeque<>(); + private int pendingAcks = 0; + + private final List> constraints = new ArrayList<>(); + + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + private final String host; + private final String object; + + public RemoteVar(String host, String object, List> constraints) { + this.host = host; + this.object = object; + + final Subscription sub = new Subscription(host, object, constraints); + forwarder = ClientEventForwarder.get(); + forwarder.addSubscription(this, sub); + } + + public RemoteVar(String object, List> constraints) { + this(Consts.hostName, object, constraints); + } + + public RemoteVar(String host, String object) { + this(host, object, new ArrayList>()); + } + + public RemoteVar(String object) { + this(Consts.hostName, object); + } + + public final synchronized T get() { + return val; + } + + @Override + public synchronized void notifyEventReceived(EventPacket evPkt) { + eventsQueue.add(evPkt); + logger.finest("Received event packet " + evPkt + ". Added to the queue1."); + if (eventsQueue.size() == 1) { + logger.finest("The element is the only one in the queue1. Let's process it."); + processNextEvent(); + } + } + + @Override + public final synchronized void notifyUpdateFinished() { + pendingAcks--; + processNextEvent(); + } + + @SuppressWarnings("unchecked") + private void processNextEvent() { + if (pendingAcks == 0 && !eventsQueue.isEmpty()) { + final EventPacket nextPkt = eventsQueue.poll(); + val = (T) nextPkt.getEvent().getVal(); + sendEventPacketToListeners(nextPkt); + } + } + + private final void sendEventPacketToListeners(EventPacket evPkt) { + if (!consumers.isEmpty()) { + final Set satConsumers = // + consumers.entrySet().stream().filter(e -> e.getValue().stream().allMatch(constr -> constr.test(val)))// + .map(e -> e.getKey())// + .collect(Collectors.toSet()); + + pendingAcks = satConsumers.size(); + satConsumers.forEach(c -> c.updateFromProducer(evPkt, this)); + } else { + processNextEvent(); + } + } + + @Override + public final String getHost() { + return host; + } + + @Override + public final String getObject() { + return object; + } + + @Override + public final List> getConstraints() { + return constraints; + } + + @Override + public final void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { + consumers.put(consumer, constraints); + } + + @Override + public final void unregisterUpdateConsumer(UpdateConsumer consumer) { + consumers.remove(consumer); + } + + @Override + public UpdateProducer filter(SerializablePredicate constraint) { + final List> constrList = new ArrayList<>(); + constrList.add(constraint); + return new FilteredUpdateProducer<>(this, constrList); + } } diff --git a/Dream2/src/main/java/dream/client/Signal.java b/Dream2/src/main/java/dream/client/Signal.java index bca44dc..02f7618 100755 --- a/Dream2/src/main/java/dream/client/Signal.java +++ b/Dream2/src/main/java/dream/client/Signal.java @@ -9,8 +9,8 @@ import java.util.Map; import java.util.Queue; import java.util.Set; -import java.util.UUID; import java.util.function.Supplier; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -21,230 +21,183 @@ import dream.common.packets.content.Advertisement; import dream.common.packets.content.Event; import dream.common.packets.content.Subscription; -import dream.common.packets.locking.LockGrantPacket; - -public class Signal implements TimeChangingValue, UpdateProducer, UpdateConsumer, LockApplicant { - private final Set> valueChangeListeners = new HashSet<>(); - - // Management of local subscribers - private final Map>> consumers = new HashMap<>(); - private final Queue eventQueue = new ArrayDeque<>(); - private int pendingAcks = 0; - private final Set> waitingProducers = new HashSet<>(); - - private final ClientEventForwarder clientEventForwarder; - private final QueueManager queueManager = new QueueManager(); - - private final String host; - private final String object; - private final List> constraints = new ArrayList<>(); - - private final Supplier evaluation; - - private UUID lockID = null; - - private T val; - - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public Signal(String object, Supplier evaluation, UpdateProducer... prods) { - this.host = Consts.hostName; - this.object = object; - this.evaluation = evaluation; - - final Set> subs = new HashSet<>(); - for (final UpdateProducer prod : prods) { - prod.registerUpdateConsumer(this, prod.getConstraints()); - subs.add(new Subscription(prod.getHost(), prod.getObject(), prod.getConstraints())); - } - - clientEventForwarder = ClientEventForwarder.get(); - clientEventForwarder.advertise(new Advertisement(Consts.hostName, object), subs, true); - } - - private final synchronized void processNextUpdate() { - if (pendingAcks == 0) { - // Notify that the previous update has finished - if (!waitingProducers.isEmpty()) { - waitingProducers.forEach(prod -> prod.notifyUpdateFinished()); - waitingProducers.clear(); - } - // Process the next packet, if any - if (!eventQueue.isEmpty()) { - processUpdate(eventQueue.poll()); - } - } - } - - private final void processUpdate(EventProducerPair update) { - logger.finest("processTask method invoked with " + update); - final List pairs = queueManager.processEventPacket(update, object + "@" + Consts.hostName); - logger.finest("The queueManager returned the following pairs " + pairs); - - if (!pairs.isEmpty()) { - logger.finest("Actual update"); - // Extract information from any of the packets - final EventPacket anyPkt = pairs.stream().findAny().get().getEventPacket(); - - // Compute the new value - try { - val = evaluate(); - logger.finest("New value computed for the reactive object: " + val); - } catch (final Exception e) { - logger.info("Exception during the evaluation of the expression. Acknowledging the producers, releasing the locks, and returning."); - pairs.forEach(pair -> pair.getUpdateProducer().notifyUpdateFinished()); - // Release locks, if needed - if ((Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) && // - anyPkt.getLockReleaseNodes().contains(object + "@" + host)) { - clientEventForwarder.sendLockRelease(anyPkt.getId()); - } - return; - } - - // Notify value change listeners - logger.finest("Notifying registered listeners of the change."); - valueChangeListeners.forEach(l -> l.notifyValueChanged(val)); - - // Notify local and remote dependent objects - logger.finest("Sending event to dependent objects."); - final Event event = new Event(Consts.hostName, object, val); - // Notify remote subscribers - clientEventForwarder.sendEvent(anyPkt.getId(), event, anyPkt.getSource()); - - final Set satConsumers = // - consumers.entrySet().stream().filter(e -> e.getValue().stream().allMatch(constr -> constr.test(val)))// - .map(e -> e.getKey())// - .collect(Collectors.toSet()); - // Notify local subscribers - if (!satConsumers.isEmpty()) { - pairs.forEach(pair -> waitingProducers.add(pair.getUpdateProducer())); - final EventPacket newEvPkt = new EventPacket(event, anyPkt.getId(), anyPkt.getSource()); - newEvPkt.setLockReleaseNodes(anyPkt.getLockReleaseNodes()); - pendingAcks = satConsumers.size(); - satConsumers.forEach(c -> c.updateFromProducer(newEvPkt, this)); - } else { - // Acknowledge the producers if there are no pending acks - logger.finest("Acknowledging the producers."); - pairs.forEach(pair -> pair.getUpdateProducer().notifyUpdateFinished()); - } - - // Release locks, if needed - if ((Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) && // - anyPkt.getLockReleaseNodes().contains(object + "@" + host)) { - clientEventForwarder.sendLockRelease(anyPkt.getId()); - } - - } else { - logger.finest(object + ": update call but waiting: " + update); - } - } - - @Override - public void addValueChangeListener(ValueChangeListener listener) { - valueChangeListeners.add(listener); - } - - @Override - public void removeValueChangeListener(ValueChangeListener listener) { - valueChangeListeners.remove(listener); - } - - @Override - public final synchronized T evaluate() { - return evaluation.get(); - } - - public T get() { - return val; - } - - public T atomicGet() { - acquireLock(); - // TODO: this should actually be a copy of the object - final T currentVal = val; - releaseLock(); - return currentVal; - } - - private final synchronized void acquireLock() { - if (Consts.consistencyType != ConsistencyType.ATOMIC) { - return; - } - clientEventForwarder.sendReadOnlyLockRequest(object + "@" + host, this); - while (lockID == null) { - try { - wait(); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - } - - private final synchronized void releaseLock() { - if (Consts.consistencyType != ConsistencyType.ATOMIC) { - return; - } - clientEventForwarder.sendLockRelease(lockID); - lockID = null; - } - - @Override - public UpdateProducer filter(SerializablePredicate constraint) { - final List> constrList = new ArrayList<>(); - constrList.add(constraint); - return new FilteredUpdateProducer<>(this, constrList); - } - - @Override - public final synchronized void updateFromProducer(EventPacket packet, UpdateProducer producer) { - final EventProducerPair pair = new EventProducerPair(packet, producer); - eventQueue.add(pair); - logger.finest("Method update called for event " + pair + ". Added to the queue."); - if (eventQueue.size() == 1) { - logger.finest("The element is the only one in the queue. Let's process it."); - processNextUpdate(); - } - - } - - @Override - public final synchronized void notifyUpdateFinished() { - pendingAcks--; - processNextUpdate(); - } - - @Override - public void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { - consumers.put(consumer, constraints); - } - - @Override - public void unregisterUpdateConsumer(UpdateConsumer consumer) { - consumers.remove(consumer); - } - - @Override - public String getHost() { - return host; - } - - @Override - public String getObject() { - return object; - } - - @Override - public List> getConstraints() { - return constraints; - } - - @Override - public final synchronized void notifyLockGranted(LockGrantPacket lockGrant) { - lockID = lockGrant.getLockID(); - notifyAll(); - } + +public class Signal implements TimeChangingValue, UpdateProducer, UpdateConsumer { + + // Management of local subscribers + private final Map>> consumers = new HashMap<>(); + private final Queue eventQueue = new ArrayDeque<>(); + private int pendingAcks = 0; + private final Set> waitingProducers = new HashSet<>(); + + private final ClientEventForwarder clientEventForwarder; + private final QueueManager queueManager = new QueueManager(); + + private final String host; + private final String object; + private final List> constraints = new ArrayList<>(); + + private final Supplier evaluation; + + private T val; + + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Signal(String object, Supplier evaluation, UpdateProducer... prods) { + this.host = Consts.hostName; + this.object = object; + this.evaluation = evaluation; + + final Set> subs = new HashSet<>(); + for (final UpdateProducer prod : prods) { + prod.registerUpdateConsumer(this, prod.getConstraints()); + subs.add(new Subscription(prod.getHost(), prod.getObject(), prod.getConstraints())); + } + + clientEventForwarder = ClientEventForwarder.get(); + clientEventForwarder.advertise(new Advertisement(Consts.hostName, object), subs, true); + } + + private final synchronized void processNextUpdate() { + if (pendingAcks == 0) { + // Notify that the previous update has finished + if (!waitingProducers.isEmpty()) { + waitingProducers.forEach(prod -> prod.notifyUpdateFinished()); + waitingProducers.clear(); + } + // Process the next packet, if any + if (!eventQueue.isEmpty()) { + processUpdate(eventQueue.poll()); + } + } + } + + private final void processUpdate(EventProducerPair update) { + logger.finest("processTask method invoked with " + update); + final List pairs = queueManager.processEventPacket(update, object + "@" + Consts.hostName); + logger.finest("The queueManager returned the following pairs " + pairs); + + if (!pairs.isEmpty()) { + logger.finest("Actual update"); + // Extract information from any of the packets + final EventPacket anyPkt = pairs.stream().findAny().get().getEventPacket(); + + // Compute the new value + try { + val = evaluate(); + logger.finest("New value computed for the reactive object: " + val); + } catch (final Exception e) { + logger.log(Level.INFO, + "Exception during the evaluation of the expression. Acknowledging the producers, releasing the locks, and returning.", + e); + pairs.forEach(pair -> pair.getUpdateProducer().notifyUpdateFinished()); + // Release locks, if needed + if ((Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) && // + anyPkt.getLockReleaseNodes().contains(object + "@" + host)) { + clientEventForwarder.sendLockRelease(anyPkt.getId()); + } + return; + } + + // Notify local and remote dependent objects + logger.finest("Sending event to dependent objects."); + final Event event = new Event(Consts.hostName, object, val); + // Notify remote subscribers + clientEventForwarder.sendEvent(anyPkt.getId(), event, anyPkt.getSource()); + + final Set satConsumers = // + consumers.entrySet().stream() + .filter(e -> e.getValue().stream().allMatch(constr -> constr.test(val)))// + .map(e -> e.getKey())// + .collect(Collectors.toSet()); + // Notify local subscribers + if (!satConsumers.isEmpty()) { + pairs.forEach(pair -> waitingProducers.add(pair.getUpdateProducer())); + final EventPacket newEvPkt = new EventPacket(event, anyPkt.getId(), anyPkt.getSource()); + newEvPkt.setLockReleaseNodes(anyPkt.getLockReleaseNodes()); + pendingAcks = satConsumers.size(); + satConsumers.forEach(c -> c.updateFromProducer(newEvPkt, this)); + } else { + // Acknowledge the producers if there are no pending acks + logger.finest("Acknowledging the producers."); + pairs.forEach(pair -> pair.getUpdateProducer().notifyUpdateFinished()); + } + + // Release locks, if needed + if ((Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) && // + anyPkt.getLockReleaseNodes().contains(object + "@" + host)) { + clientEventForwarder.sendLockRelease(anyPkt.getId()); + } + + } else { + logger.finest(object + ": update call but waiting: " + update); + } + } + + @Override + public final synchronized T evaluate() { + return evaluation.get(); + } + + public T get() { + return val; + } + + @Override + public UpdateProducer filter(SerializablePredicate constraint) { + final List> constrList = new ArrayList<>(); + constrList.add(constraint); + return new FilteredUpdateProducer<>(this, constrList); + } + + @Override + public final synchronized void updateFromProducer(EventPacket packet, UpdateProducer producer) { + final EventProducerPair pair = new EventProducerPair(packet, producer); + eventQueue.add(pair); + logger.finest("Method update called for event " + pair + ". Added to the queue1."); + if (eventQueue.size() == 1) { + logger.finest("The element is the only one in the queue1. Let's process it."); + processNextUpdate(); + } + } + + @Override + public final synchronized void notifyUpdateFinished() { + pendingAcks--; + processNextUpdate(); + } + + @Override + public void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { + consumers.put(consumer, constraints); + } + + @Override + public void unregisterUpdateConsumer(UpdateConsumer consumer) { + consumers.remove(consumer); + } + + @Override + public String getHost() { + return host; + } + + @Override + public String getObject() { + return object; + } + + @Override + public List> getConstraints() { + return constraints; + } + + @Override + public ChangeEvent change() { + return new ChangeEvent(this); + } } diff --git a/Dream2/src/main/java/dream/client/Subscriber.java b/Dream2/src/main/java/dream/client/Subscriber.java index b2ce0f7..ffa88d8 100755 --- a/Dream2/src/main/java/dream/client/Subscriber.java +++ b/Dream2/src/main/java/dream/client/Subscriber.java @@ -8,12 +8,12 @@ */ public interface Subscriber { - /** - * Notifies the subscriber that the given event has occurred. - * - * @param event - * the occurred event. - */ - public void notifyEventReceived(EventPacket event); + /** + * Notifies the subscriber that the given event has occurred. + * + * @param event + * the occurred event. + */ + public void notifyEventReceived(EventPacket event); } diff --git a/Dream2/src/main/java/dream/client/TimeChangingValue.java b/Dream2/src/main/java/dream/client/TimeChangingValue.java index dc8fe1c..2bdedca 100755 --- a/Dream2/src/main/java/dream/client/TimeChangingValue.java +++ b/Dream2/src/main/java/dream/client/TimeChangingValue.java @@ -11,26 +11,18 @@ */ interface TimeChangingValue { - /** - * The evaluate method is automatically invoked whenever one of the values - * this object depends on changes. - */ - public T evaluate(); - - /** - * Register a new ValueChangeListener. - * - * @param listener - * the listener to add. - */ - public void addValueChangeListener(ValueChangeListener listener); - - /** - * Unregister a ValueChangeListener. - * - * @param listener - * the listener to remove. - */ - public void removeValueChangeListener(ValueChangeListener listener); + /** + * The evaluate method is automatically invoked whenever one of the values + * this object depends on changes. + */ + public T evaluate(); + /** + * Create an event that fires every time the TimeChangingValue changes. It + * fires the tuple (oldVal, newVal) for the change. The first tuple is + * (null, newVal) + * + * @return a new ChangeEvent + */ + public ChangeEvent change(); } diff --git a/Dream2/src/main/java/dream/client/UpdateConsumer.java b/Dream2/src/main/java/dream/client/UpdateConsumer.java index 7e78d6e..fce5aea 100644 --- a/Dream2/src/main/java/dream/client/UpdateConsumer.java +++ b/Dream2/src/main/java/dream/client/UpdateConsumer.java @@ -7,13 +7,13 @@ */ public interface UpdateConsumer { - /** - * Notifies a local update coming from the given signal. - * - * @param packet - * the packet containing the update. - * @param producer - * the producer that generated the update. - */ - void updateFromProducer(EventPacket packet, UpdateProducer producer); + /** + * Notifies a local update coming from the given signal. + * + * @param packet + * the packet containing the update. + * @param producer + * the producer that generated the update. + */ + void updateFromProducer(EventPacket packet, UpdateProducer producer); } diff --git a/Dream2/src/main/java/dream/client/UpdateProducer.java b/Dream2/src/main/java/dream/client/UpdateProducer.java index 03fb335..2936882 100644 --- a/Dream2/src/main/java/dream/client/UpdateProducer.java +++ b/Dream2/src/main/java/dream/client/UpdateProducer.java @@ -10,58 +10,58 @@ */ public interface UpdateProducer { - /** - * The method is invoked when an update procedure finishes. - */ - void notifyUpdateFinished(); + /** + * The method is invoked when an update procedure finishes. + */ + void notifyUpdateFinished(); - /** - * Register a new consumer for the updates of this producer. The consumer is - * notified only if the given constraints are satisfied. - * - * @param consumer - * the consumer. - * @param constraints - * the constraints. - */ - void registerUpdateConsumer(UpdateConsumer consumer, List> constraints); + /** + * Register a new consumer for the updates of this producer. The consumer is + * notified only if the given constraints are satisfied. + * + * @param consumer + * the consumer. + * @param constraints + * the constraints. + */ + void registerUpdateConsumer(UpdateConsumer consumer, List> constraints); - /** - * Unregister the consumer from the updates of this producer. - * - * @param consumer - * the consumer. - */ - void unregisterUpdateConsumer(UpdateConsumer consumer); + /** + * Unregister the consumer from the updates of this producer. + * + * @param consumer + * the consumer. + */ + void unregisterUpdateConsumer(UpdateConsumer consumer); - /** - * Return an UpdateProducer with the given filter. - * - * @param constraint - * the constraint used to filter. - * @return an UpdateProducer for the filtered object. - */ - public UpdateProducer filter(SerializablePredicate constraint); + /** + * Return an UpdateProducer with the given filter. + * + * @param constraint + * the constraint used to filter. + * @return an UpdateProducer for the filtered object. + */ + public UpdateProducer filter(SerializablePredicate constraint); - /** - * Return the host of the object the producer refers to. - * - * @return the host of the object. - */ - String getHost(); + /** + * Return the host of the object the producer refers to. + * + * @return the host of the object. + */ + String getHost(); - /** - * Return the name of the object the producer refers to. - * - * @return the name of the object. - */ - String getObject(); + /** + * Return the name of the object the producer refers to. + * + * @return the name of the object. + */ + String getObject(); - /** - * Returns the constraints of the producer. - * - * @return the constraints of the producer. - */ - List> getConstraints(); + /** + * Returns the constraints of the producer. + * + * @return the constraints of the producer. + */ + List> getConstraints(); } diff --git a/Dream2/src/main/java/dream/client/ValueChangeListener.java b/Dream2/src/main/java/dream/client/ValueChangeListener.java deleted file mode 100755 index c1452f2..0000000 --- a/Dream2/src/main/java/dream/client/ValueChangeListener.java +++ /dev/null @@ -1,11 +0,0 @@ -package dream.client; - -/** - * A ValueChangeListener can register to a time changing object O and gets - * notified whenever the value of O changes. - */ -public interface ValueChangeListener { - - public void notifyValueChanged(T newValue); - -} diff --git a/Dream2/src/main/java/dream/client/Var.java b/Dream2/src/main/java/dream/client/Var.java index 30d8cf5..7f840d7 100755 --- a/Dream2/src/main/java/dream/client/Var.java +++ b/Dream2/src/main/java/dream/client/Var.java @@ -22,135 +22,135 @@ import dream.common.packets.locking.LockGrantPacket; public class Var implements UpdateProducer, LockApplicant { - private final ClientEventForwarder forwarder; - - private final String host; - private final String object; - private final List> constraints = new ArrayList<>(); - - private final Map>> consumers = new HashMap<>(); - private final Queue waitingModifications = new ArrayDeque<>(); - private int pendingAcks = 0; - - private T val; - - public Var(String object, T val) { - this.forwarder = ClientEventForwarder.get(); - this.host = Consts.hostName; - this.object = object; - this.val = val; - forwarder.advertise(new Advertisement(Consts.hostName, object), true); - } - - public final synchronized void set(T val) { - final Supplier supplier = () -> val; - waitingModifications.add(supplier); - if (waitingModifications.size() == 1) { - tryToProcessNextUpdate(); - } - } - - public final synchronized void modify(Consumer modification) { - waitingModifications.add(modification); - if (waitingModifications.size() == 1) { - tryToProcessNextUpdate(); - } - } - - public final synchronized T get() { - assert val != null; - return val; - } - - private final void tryToProcessNextUpdate() { - if (pendingAcks == 0 && !waitingModifications.isEmpty()) { - // In the case of complete glitch freedom or atomic consistency, we - // possibly need to acquire a lock before processing the update - if (Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // - Consts.consistencyType == ConsistencyType.ATOMIC) { - final boolean lockRequired = forwarder.sendReadWriteLockRequest(object + "@" + host, this); - if (!lockRequired) { - processNextUpdate(UUID.randomUUID()); - } - } - // Otherwise the update can be immediately processed - else { - processNextUpdate(UUID.randomUUID()); - } - } - } - - private final void processNextUpdate(UUID eventId) { - final Object mod = waitingModifications.poll(); - // Apply modification - if (mod instanceof Consumer) { - @SuppressWarnings("unchecked") - final Consumer consumer = (Consumer) mod; - consumer.accept(val); - } else if (mod instanceof Supplier) { - @SuppressWarnings("unchecked") - final Supplier supplier = (Supplier) mod; - val = supplier.get(); - } - - // Propagate modification to local and remote subscribers - final Event ev = new Event<>(Consts.hostName, object, val); - final String source = ev.getSignature(); - final EventPacket packet = new EventPacket(ev, eventId, source); - packet.setLockReleaseNodes(forwarder.getLockReleaseNodesFor(source)); - - final Set satConsumers = // - consumers.entrySet().stream().filter(e -> e.getValue().stream().allMatch(constr -> constr.test(val)))// - .map(e -> e.getKey())// - .collect(Collectors.toSet()); - - pendingAcks = satConsumers.size(); - satConsumers.forEach(c -> c.updateFromProducer(packet, this)); - - forwarder.sendEvent(eventId, ev, ev.getSignature()); - } - - @Override - public UpdateProducer filter(SerializablePredicate constraint) { - final List> constrList = new ArrayList<>(); - constrList.add(constraint); - return new FilteredUpdateProducer(this, constrList); - } - - @Override - public final void notifyUpdateFinished() { - pendingAcks--; - tryToProcessNextUpdate(); - } - - @Override - public void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { - consumers.put(consumer, constraints); - } - - @Override - public void unregisterUpdateConsumer(UpdateConsumer consumer) { - consumers.remove(consumer); - } - - @Override - public String getHost() { - return host; - } - - @Override - public String getObject() { - return object; - } - - @Override - public List> getConstraints() { - return constraints; - } - - @Override - public void notifyLockGranted(LockGrantPacket lockGrant) { - processNextUpdate(lockGrant.getLockID()); - } + private final ClientEventForwarder forwarder; + + private final String host; + private final String object; + private final List> constraints = new ArrayList<>(); + + private final Map>> consumers = new HashMap<>(); + private final Queue waitingModifications = new ArrayDeque<>(); + private int pendingAcks = 0; + + private T val; + + public Var(String object, T val) { + this.forwarder = ClientEventForwarder.get(); + this.host = Consts.hostName; + this.object = object; + this.val = val; + forwarder.advertise(new Advertisement(Consts.hostName, object), true); + } + + public final synchronized void set(T val) { + final Supplier supplier = () -> val; + waitingModifications.add(supplier); + if (waitingModifications.size() == 1) { + tryToProcessNextUpdate(); + } + } + + public final synchronized void modify(Consumer modification) { + waitingModifications.add(modification); + if (waitingModifications.size() == 1) { + tryToProcessNextUpdate(); + } + } + + public final synchronized T get() { + assert val != null; + return val; + } + + private final void tryToProcessNextUpdate() { + if (pendingAcks == 0 && !waitingModifications.isEmpty()) { + // In the case of complete glitch freedom or atomic consistency, we + // possibly need to acquire a lock before processing the update + if (Consts.consistencyType == ConsistencyType.COMPLETE_GLITCH_FREE || // + Consts.consistencyType == ConsistencyType.ATOMIC) { + final boolean lockRequired = forwarder.sendReadWriteLockRequest(object + "@" + host, this); + if (!lockRequired) { + processNextUpdate(UUID.randomUUID()); + } + } + // Otherwise the update can be immediately processed + else { + processNextUpdate(UUID.randomUUID()); + } + } + } + + private final void processNextUpdate(UUID eventId) { + final Object mod = waitingModifications.poll(); + // Apply modification + if (mod instanceof Consumer) { + @SuppressWarnings("unchecked") + final Consumer consumer = (Consumer) mod; + consumer.accept(val); + } else if (mod instanceof Supplier) { + @SuppressWarnings("unchecked") + final Supplier supplier = (Supplier) mod; + val = supplier.get(); + } + + // Propagate modification to local and remote subscribers + final Event ev = new Event<>(Consts.hostName, object, val); + final String source = ev.getSignature(); + final EventPacket packet = new EventPacket(ev, eventId, source); + packet.setLockReleaseNodes(forwarder.getLockReleaseNodesFor(source)); + + final Set satConsumers = // + consumers.entrySet().stream().filter(e -> e.getValue().stream().allMatch(constr -> constr.test(val)))// + .map(e -> e.getKey())// + .collect(Collectors.toSet()); + + pendingAcks = satConsumers.size(); + satConsumers.forEach(c -> c.updateFromProducer(packet, this)); + + forwarder.sendEvent(eventId, ev, ev.getSignature()); + } + + @Override + public UpdateProducer filter(SerializablePredicate constraint) { + final List> constrList = new ArrayList<>(); + constrList.add(constraint); + return new FilteredUpdateProducer(this, constrList); + } + + @Override + public final void notifyUpdateFinished() { + pendingAcks--; + tryToProcessNextUpdate(); + } + + @Override + public void registerUpdateConsumer(UpdateConsumer consumer, List> constraints) { + consumers.put(consumer, constraints); + } + + @Override + public void unregisterUpdateConsumer(UpdateConsumer consumer) { + consumers.remove(consumer); + } + + @Override + public String getHost() { + return host; + } + + @Override + public String getObject() { + return object; + } + + @Override + public List> getConstraints() { + return constraints; + } + + @Override + public void notifyLockGranted(LockGrantPacket lockGrant) { + processNextUpdate(lockGrant.getLockID()); + } } diff --git a/Dream2/src/main/java/dream/common/ConsistencyType.java b/Dream2/src/main/java/dream/common/ConsistencyType.java index 1dbfa5e..470691d 100755 --- a/Dream2/src/main/java/dream/common/ConsistencyType.java +++ b/Dream2/src/main/java/dream/common/ConsistencyType.java @@ -1,28 +1,28 @@ package dream.common; public enum ConsistencyType { - CAUSAL { - @Override - public final String toString() { - return "Causal"; - } - }, - SINGLE_SOURCE_GLITCH_FREE { - @Override - public final String toString() { - return "Single source glitch free"; - } - }, - COMPLETE_GLITCH_FREE { - @Override - public final String toString() { - return "Complete glitch free"; - } - }, - ATOMIC { - @Override - public final String toString() { - return "Atomic"; - } - } + CAUSAL { + @Override + public final String toString() { + return "Causal"; + } + }, + SINGLE_SOURCE_GLITCH_FREE { + @Override + public final String toString() { + return "Single source glitch free"; + } + }, + COMPLETE_GLITCH_FREE { + @Override + public final String toString() { + return "Complete glitch free"; + } + }, + ATOMIC { + @Override + public final String toString() { + return "Atomic"; + } + } } diff --git a/Dream2/src/main/java/dream/common/Consts.java b/Dream2/src/main/java/dream/common/Consts.java index 3a85ad8..dd81aef 100755 --- a/Dream2/src/main/java/dream/common/Consts.java +++ b/Dream2/src/main/java/dream/common/Consts.java @@ -9,68 +9,69 @@ import java.util.logging.Logger; public final class Consts { - private static final Properties properties = new Properties(); - private static final String LOGGING_PROPERTIES_FILE_NAME = "logging.properties"; + private static final Properties properties = new Properties(); + private static final String LOGGING_PROPERTIES_FILE_NAME = "logging.properties"; - public static final String serverAddr; - public static final String lockManagerAddr; + public static final String serverAddr; + public static final String lockManagerAddr; - public static final int serverPort; - public static final int lockManagerPort; + public static final int serverPort; + public static final int lockManagerPort; - public static ConsistencyType consistencyType; - public static String hostName; + public static ConsistencyType consistencyType; + public static String hostName; - static { - /** - * Read logging properties - */ - final LogManager manager = LogManager.getLogManager(); - try { - manager.readConfiguration(new FileInputStream(new File(LOGGING_PROPERTIES_FILE_NAME))); - } catch (SecurityException | IOException e) { - e.printStackTrace(); - } - final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - final ConsoleHandler consoleHandler = new ConsoleHandler(); - logger.addHandler(consoleHandler); + static { + /** + * Read logging properties + */ + final LogManager manager = LogManager.getLogManager(); + try { + manager.readConfiguration(new FileInputStream(new File(LOGGING_PROPERTIES_FILE_NAME))); + } catch (SecurityException | IOException e) { + e.printStackTrace(); + } + final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + final ConsoleHandler consoleHandler = new ConsoleHandler(); + logger.addHandler(consoleHandler); - /** - * Load properties - */ - try { - final FileInputStream input = new FileInputStream("dream.properties"); - properties.load(input); - input.close(); - } catch (final IOException e) { - e.printStackTrace(); - } + /** + * Load properties + */ + try { + final FileInputStream input = new FileInputStream("dream.properties"); + properties.load(input); + input.close(); + } catch (final IOException e) { + e.printStackTrace(); + } - final String serverAddrProperty = properties.getProperty("serverAddr", "localhost"); - final String serverPortProperty = properties.getProperty("serverPort", "9000"); - serverPort = Integer.parseInt(serverPortProperty); - serverAddr = "reds-tcp:" + serverAddrProperty + ":" + serverPort; + final String serverAddrProperty = properties.getProperty("serverAddr", "localhost"); + final String serverPortProperty = properties.getProperty("serverPort", "9000"); + serverPort = Integer.parseInt(serverPortProperty); + serverAddr = "reds-tcp:" + serverAddrProperty + ":" + serverPort; - final String lockManagerAddrProperty = properties.getProperty("lockManagerAddr", "localhost"); - final String lockManagerPortProperty = properties.getProperty("serverManagerPort", "9999"); - lockManagerPort = Integer.parseInt(lockManagerPortProperty); - lockManagerAddr = "reds-tcp:" + lockManagerAddrProperty + ":" + lockManagerPort; + final String lockManagerAddrProperty = properties.getProperty("lockManagerAddr", "localhost"); + final String lockManagerPortProperty = properties.getProperty("serverManagerPort", "9999"); + lockManagerPort = Integer.parseInt(lockManagerPortProperty); + lockManagerAddr = "reds-tcp:" + lockManagerAddrProperty + ":" + lockManagerPort; - final String hostNameProperty = properties.getProperty("hostName", "local"); - hostName = hostNameProperty; + final String hostNameProperty = properties.getProperty("hostName", "local"); + hostName = hostNameProperty; - final String consistencyTypeProperty = properties.getProperty("consistencyType", "single_glitch_free").toLowerCase(); - if (consistencyTypeProperty.equals("causal")) { - consistencyType = ConsistencyType.CAUSAL; - } else if (consistencyTypeProperty.equals("single_glitch_free")) { - consistencyType = ConsistencyType.SINGLE_SOURCE_GLITCH_FREE; - } else if (consistencyTypeProperty.equals("complete_glitch_free")) { - consistencyType = ConsistencyType.COMPLETE_GLITCH_FREE; - } else if (consistencyTypeProperty.equals("atomic")) { - consistencyType = ConsistencyType.ATOMIC; - } else { - logger.warning("Unknown consistency type. Using single source glitch free as default."); - } + final String consistencyTypeProperty = properties.getProperty("consistencyType", "single_glitch_free") + .toLowerCase(); + if (consistencyTypeProperty.equals("causal")) { + consistencyType = ConsistencyType.CAUSAL; + } else if (consistencyTypeProperty.equals("single_glitch_free")) { + consistencyType = ConsistencyType.SINGLE_SOURCE_GLITCH_FREE; + } else if (consistencyTypeProperty.equals("complete_glitch_free")) { + consistencyType = ConsistencyType.COMPLETE_GLITCH_FREE; + } else if (consistencyTypeProperty.equals("atomic")) { + consistencyType = ConsistencyType.ATOMIC; + } else { + logger.warning("Unknown consistency type. Using single source glitch free as default."); + } - } + } } diff --git a/Dream2/src/main/java/dream/common/packets/AdvertisementPacket.java b/Dream2/src/main/java/dream/common/packets/AdvertisementPacket.java index b2cce7b..c34b6e2 100755 --- a/Dream2/src/main/java/dream/common/packets/AdvertisementPacket.java +++ b/Dream2/src/main/java/dream/common/packets/AdvertisementPacket.java @@ -15,90 +15,91 @@ * includes the set of subscriptions that define such dependencies. */ public class AdvertisementPacket implements Serializable { - private static final long serialVersionUID = 5219175796450319466L; - public static final String subject = "__DREAM_ADVERTISEMENT_PACKET_SUBJECT"; + private static final long serialVersionUID = 5219175796450319466L; + public static final String subject = "__DREAM_ADVERTISEMENT_PACKET_SUBJECT"; - private final Advertisement advertisement; - private final AdvType advType; - private final Set> subscriptions = new HashSet<>(); - private final boolean isPublic; + private final Advertisement advertisement; + private final AdvType advType; + private final Set> subscriptions = new HashSet<>(); + private final boolean isPublic; - public AdvertisementPacket(Advertisement advertisement, AdvType advType, Set> subscriptions, boolean isPublic) { - this(advertisement, advType, isPublic); - this.subscriptions.addAll(subscriptions); - } + public AdvertisementPacket(Advertisement advertisement, AdvType advType, Set> subscriptions, + boolean isPublic) { + this(advertisement, advType, isPublic); + this.subscriptions.addAll(subscriptions); + } - public AdvertisementPacket(Advertisement advertisement, AdvType advType, boolean isPublic) { - this.advertisement = advertisement; - this.advType = advType; - this.isPublic = isPublic; - } + public AdvertisementPacket(Advertisement advertisement, AdvType advType, boolean isPublic) { + this.advertisement = advertisement; + this.advType = advType; + this.isPublic = isPublic; + } - public Advertisement getAdvertisement() { - return advertisement; - } + public Advertisement getAdvertisement() { + return advertisement; + } - public AdvType getAdvType() { - return advType; - } + public AdvType getAdvType() { + return advType; + } - public final Set> getSubscriptions() { - return subscriptions; - } + public final Set> getSubscriptions() { + return subscriptions; + } - public final boolean isPublic() { - return isPublic; - } + public final boolean isPublic() { + return isPublic; + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (advType == null ? 0 : advType.hashCode()); - result = prime * result + (advertisement == null ? 0 : advertisement.hashCode()); - result = prime * result + (subscriptions == null ? 0 : subscriptions.hashCode()); - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (advType == null ? 0 : advType.hashCode()); + result = prime * result + (advertisement == null ? 0 : advertisement.hashCode()); + result = prime * result + (subscriptions == null ? 0 : subscriptions.hashCode()); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof AdvertisementPacket)) { - return false; - } - final AdvertisementPacket other = (AdvertisementPacket) obj; - if (advType != other.advType) { - return false; - } - if (advertisement == null) { - if (other.advertisement != null) { - return false; - } - } else if (!advertisement.equals(other.advertisement)) { - return false; - } - if (subscriptions == null) { - if (other.subscriptions != null) { - return false; - } - } else if (!subscriptions.equals(other.subscriptions)) { - return false; - } - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof AdvertisementPacket)) { + return false; + } + final AdvertisementPacket other = (AdvertisementPacket) obj; + if (advType != other.advType) { + return false; + } + if (advertisement == null) { + if (other.advertisement != null) { + return false; + } + } else if (!advertisement.equals(other.advertisement)) { + return false; + } + if (subscriptions == null) { + if (other.subscriptions != null) { + return false; + } + } else if (!subscriptions.equals(other.subscriptions)) { + return false; + } + return true; + } - @Override - public String toString() { - if (subscriptions != null) { - return advType + ": " + advertisement.toString() + " - Depending on: " + subscriptions; - } else { - return advType + ": " + advertisement.toString(); - } - } + @Override + public String toString() { + if (subscriptions != null) { + return advType + ": " + advertisement.toString() + " - Depending on: " + subscriptions; + } else { + return advType + ": " + advertisement.toString(); + } + } } diff --git a/Dream2/src/main/java/dream/common/packets/EventPacket.java b/Dream2/src/main/java/dream/common/packets/EventPacket.java index 85297d6..6a13a02 100755 --- a/Dream2/src/main/java/dream/common/packets/EventPacket.java +++ b/Dream2/src/main/java/dream/common/packets/EventPacket.java @@ -11,51 +11,53 @@ * Packet used to deliver events, which notify about some state change. */ public class EventPacket implements Serializable { - private static final long serialVersionUID = 8208653909787190211L; - public static final String subject = "__DREAM_PUBLICATION_PACKET_SUBJECT"; - - private final Event event; - - // Uniquely identifies a propagation. In the case of complete glitch free and - // atomic consistency, it is identical to the id of the read lock associated - // to the propagation. - private final UUID id; - - // Original source of the change - private final String source; - - // Nodes that should release the lock for the propagation, if any - private final Set lockReleaseNodes = new HashSet<>(); - - public EventPacket(Event event, UUID id, String source) { - this.event = event; - this.id = id; - this.source = source; - } - - public final Event getEvent() { - return event; - } - - public final UUID getId() { - return id; - } - - public final String getSource() { - return source; - } - - public final void setLockReleaseNodes(Set lockReleaseNodes) { - this.lockReleaseNodes.addAll(lockReleaseNodes); - } - - public final Set getLockReleaseNodes() { - return lockReleaseNodes; - } - - @Override - public String toString() { - return "EventPacket [event=" + event + ", id=" + id + ", source=" + source + ", lockReleaseNodes=" + lockReleaseNodes + "]"; - } + private static final long serialVersionUID = 8208653909787190211L; + public static final String subject = "__DREAM_PUBLICATION_PACKET_SUBJECT"; + + private final Event event; + + // Uniquely identifies a propagation. In the case of complete glitch free + // and + // atomic consistency, it is identical to the id of the read lock associated + // to the propagation. + private final UUID id; + + // Original source of the change + private final String source; + + // Nodes that should release the lock for the propagation, if any + private final Set lockReleaseNodes = new HashSet<>(); + + public EventPacket(Event event, UUID id, String source) { + this.event = event; + this.id = id; + this.source = source; + } + + public final Event getEvent() { + return event; + } + + public final UUID getId() { + return id; + } + + public final String getSource() { + return source; + } + + public final void setLockReleaseNodes(Set lockReleaseNodes) { + this.lockReleaseNodes.addAll(lockReleaseNodes); + } + + public final Set getLockReleaseNodes() { + return lockReleaseNodes; + } + + @Override + public String toString() { + return "EventPacket [event=" + event + ", id=" + id + ", source=" + source + ", lockReleaseNodes=" + + lockReleaseNodes + "]"; + } } diff --git a/Dream2/src/main/java/dream/common/packets/SubscriptionPacket.java b/Dream2/src/main/java/dream/common/packets/SubscriptionPacket.java index 9a906f4..945047b 100755 --- a/Dream2/src/main/java/dream/common/packets/SubscriptionPacket.java +++ b/Dream2/src/main/java/dream/common/packets/SubscriptionPacket.java @@ -10,62 +10,62 @@ * specific events. */ public class SubscriptionPacket implements Serializable { - private static final long serialVersionUID = -9026500933220636540L; - public static final String subject = "__DREAM_SUBSCRIPTION_PACKET_SUBJECT"; + private static final long serialVersionUID = -9026500933220636540L; + public static final String subject = "__DREAM_SUBSCRIPTION_PACKET_SUBJECT"; - private final Subscription subscription; - private final SubType subType; + private final Subscription subscription; + private final SubType subType; - public SubscriptionPacket(Subscription subscription, SubType subType) { - this.subscription = subscription; - this.subType = subType; - } + public SubscriptionPacket(Subscription subscription, SubType subType) { + this.subscription = subscription; + this.subType = subType; + } - public final SubType getSubType() { - return subType; - } + public final SubType getSubType() { + return subType; + } - public final Subscription getSubscription() { - return subscription; - } + public final Subscription getSubscription() { + return subscription; + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + (subType == null ? 0 : subType.hashCode()); - result = prime * result + (subscription == null ? 0 : subscription.hashCode()); - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (subType == null ? 0 : subType.hashCode()); + result = prime * result + (subscription == null ? 0 : subscription.hashCode()); + return result; + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof SubscriptionPacket)) { - return false; - } - final SubscriptionPacket other = (SubscriptionPacket) obj; - if (subType != other.subType) { - return false; - } - if (subscription == null) { - if (other.subscription != null) { - return false; - } - } else if (!subscription.equals(other.subscription)) { - return false; - } - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof SubscriptionPacket)) { + return false; + } + final SubscriptionPacket other = (SubscriptionPacket) obj; + if (subType != other.subType) { + return false; + } + if (subscription == null) { + if (other.subscription != null) { + return false; + } + } else if (!subscription.equals(other.subscription)) { + return false; + } + return true; + } - @Override - public String toString() { - return subType + " " + subscription.toString(); - } + @Override + public String toString() { + return subType + " " + subscription.toString(); + } } diff --git a/Dream2/src/main/java/dream/common/packets/content/AdvType.java b/Dream2/src/main/java/dream/common/packets/content/AdvType.java index 3aa2541..a6653f2 100755 --- a/Dream2/src/main/java/dream/common/packets/content/AdvType.java +++ b/Dream2/src/main/java/dream/common/packets/content/AdvType.java @@ -1,5 +1,5 @@ package dream.common.packets.content; public enum AdvType { - ADV, UNADV + ADV, UNADV } diff --git a/Dream2/src/main/java/dream/common/packets/content/Advertisement.java b/Dream2/src/main/java/dream/common/packets/content/Advertisement.java index 516662e..1dda1ce 100755 --- a/Dream2/src/main/java/dream/common/packets/content/Advertisement.java +++ b/Dream2/src/main/java/dream/common/packets/content/Advertisement.java @@ -3,35 +3,35 @@ import java.io.Serializable; public class Advertisement implements Serializable { - private static final long serialVersionUID = -6636280874981657399L; + private static final long serialVersionUID = -6636280874981657399L; - private final String hostId; - private final String objectId; + private final String hostId; + private final String objectId; - public Advertisement(String hostId, String objectId) { - this.hostId = hostId; - this.objectId = objectId; - } + public Advertisement(String hostId, String objectId) { + this.hostId = hostId; + this.objectId = objectId; + } - public boolean isSatisfiedBy(Subscription sub) { - return hostId.equals(sub.getHostId()) && objectId.equals(sub.getObjectId()); - } + public boolean isSatisfiedBy(Subscription sub) { + return hostId.equals(sub.getHostId()) && objectId.equals(sub.getObjectId()); + } - public final String getObjectId() { - return objectId; - } + public final String getObjectId() { + return objectId; + } - public final String getHostId() { - return hostId; - } + public final String getHostId() { + return hostId; + } - public final String getSignature() { - return objectId + "@" + hostId; - } + public final String getSignature() { + return objectId + "@" + hostId; + } - @Override - public String toString() { - return "Advertisement [" + objectId + "@" + hostId + "]"; - } + @Override + public String toString() { + return "Advertisement [" + objectId + "@" + hostId + "]"; + } } diff --git a/Dream2/src/main/java/dream/common/packets/content/Event.java b/Dream2/src/main/java/dream/common/packets/content/Event.java index e437575..535def1 100755 --- a/Dream2/src/main/java/dream/common/packets/content/Event.java +++ b/Dream2/src/main/java/dream/common/packets/content/Event.java @@ -3,37 +3,37 @@ import java.io.Serializable; public class Event implements Serializable { - private static final long serialVersionUID = 831217881290695190L; - - private final String objectId; - private final String hostId; - private final T val; - - public Event(String hostId, String objectId, T val) { - this.hostId = hostId; - this.objectId = objectId; - this.val = val; - } - - public final String getObjectId() { - return objectId; - } - - public final String getHostId() { - return hostId; - } - - public final T getVal() { - return val; - } - - public final String getSignature() { - return objectId + "@" + hostId; - } - - @Override - public String toString() { - return objectId + "@" + hostId + "(val = " + val.toString() + ")"; - } + private static final long serialVersionUID = 831217881290695190L; + + private final String objectId; + private final String hostId; + private final T val; + + public Event(String hostId, String objectId, T val) { + this.hostId = hostId; + this.objectId = objectId; + this.val = val; + } + + public final String getObjectId() { + return objectId; + } + + public final String getHostId() { + return hostId; + } + + public final T getVal() { + return val; + } + + public final String getSignature() { + return objectId + "@" + hostId; + } + + @Override + public String toString() { + return objectId + "@" + hostId + "(val = " + (val == null ? "null" : val.toString()) + ")"; + } } diff --git a/Dream2/src/main/java/dream/common/packets/content/SubType.java b/Dream2/src/main/java/dream/common/packets/content/SubType.java index a328524..53fa264 100755 --- a/Dream2/src/main/java/dream/common/packets/content/SubType.java +++ b/Dream2/src/main/java/dream/common/packets/content/SubType.java @@ -1,5 +1,5 @@ package dream.common.packets.content; public enum SubType { - SUB, UNSUB + SUB, UNSUB } diff --git a/Dream2/src/main/java/dream/common/packets/content/Subscription.java b/Dream2/src/main/java/dream/common/packets/content/Subscription.java index 9f5dcd9..f0c3e51 100755 --- a/Dream2/src/main/java/dream/common/packets/content/Subscription.java +++ b/Dream2/src/main/java/dream/common/packets/content/Subscription.java @@ -8,60 +8,60 @@ import dream.common.SerializablePredicate; public class Subscription implements Serializable { - private static final long serialVersionUID = -3452847781395458670L; + private static final long serialVersionUID = -3452847781395458670L; - private final String objectId; - private final String hostId; - private final UUID subId; - private final List> constraints = new ArrayList>(); + private final String objectId; + private final String hostId; + private final UUID subId; + private final List> constraints = new ArrayList>(); - public Subscription(String hostId, String objectId) { - this.hostId = hostId; - this.objectId = objectId; - this.subId = UUID.randomUUID(); - this.constraints.addAll(constraints); - } + public Subscription(String hostId, String objectId) { + this.hostId = hostId; + this.objectId = objectId; + this.subId = UUID.randomUUID(); + this.constraints.addAll(constraints); + } - public Subscription(String hostId, String objectId, List> constraints) { - this(hostId, objectId); - this.constraints.addAll(constraints); - } + public Subscription(String hostId, String objectId, List> constraints) { + this(hostId, objectId); + this.constraints.addAll(constraints); + } - public final boolean isSatisfiedBy(Event ev) { - @SuppressWarnings("unchecked") - final T val = (T) ev.getVal(); - return hostId.equals(ev.getHostId()) && // - objectId.equals(ev.getObjectId()) && // - constraints.stream().allMatch(c -> c.test(val)); - } + public final boolean isSatisfiedBy(Event ev) { + @SuppressWarnings("unchecked") + final T val = (T) ev.getVal(); + return hostId.equals(ev.getHostId()) && // + objectId.equals(ev.getObjectId()) && // + constraints.stream().allMatch(c -> c.test(val)); + } - public final boolean matchesOnlySignatureOf(Event ev) { - @SuppressWarnings("unchecked") - final T val = (T) ev.getVal(); - return hostId.equals(ev.getHostId()) && // - objectId.equals(ev.getObjectId()) && // - constraints.stream().anyMatch(c -> !c.test(val)); - } + public final boolean matchesOnlySignatureOf(Event ev) { + @SuppressWarnings("unchecked") + final T val = (T) ev.getVal(); + return hostId.equals(ev.getHostId()) && // + objectId.equals(ev.getObjectId()) && // + constraints.stream().anyMatch(c -> !c.test(val)); + } - public final String getObjectId() { - return objectId; - } + public final String getObjectId() { + return objectId; + } - public final String getHostId() { - return hostId; - } + public final String getHostId() { + return hostId; + } - public final UUID getSubId() { - return subId; - } + public final UUID getSubId() { + return subId; + } - public final String getSignature() { - return objectId + "@" + hostId; - } + public final String getSignature() { + return objectId + "@" + hostId; + } - @Override - public String toString() { - return objectId + "@" + hostId + "(" + constraints + ")"; - } + @Override + public String toString() { + return objectId + "@" + hostId + "(" + constraints + ")"; + } } diff --git a/Dream2/src/main/java/dream/common/packets/discovery/LockManagerHelloPacket.java b/Dream2/src/main/java/dream/common/packets/discovery/LockManagerHelloPacket.java index 1f3cd04..9c94dd1 100644 --- a/Dream2/src/main/java/dream/common/packets/discovery/LockManagerHelloPacket.java +++ b/Dream2/src/main/java/dream/common/packets/discovery/LockManagerHelloPacket.java @@ -7,7 +7,7 @@ * connects to it. */ public class LockManagerHelloPacket implements Serializable { - private static final long serialVersionUID = -7563002622651694641L; + private static final long serialVersionUID = -7563002622651694641L; - public static final String subject = "__DREAM_LOCK_MANAGER_HELLO_PACKET_SUBJECT"; + public static final String subject = "__DREAM_LOCK_MANAGER_HELLO_PACKET_SUBJECT"; } diff --git a/Dream2/src/main/java/dream/common/packets/discovery/ServerHelloPacket.java b/Dream2/src/main/java/dream/common/packets/discovery/ServerHelloPacket.java index 6e6b227..35f98f0 100644 --- a/Dream2/src/main/java/dream/common/packets/discovery/ServerHelloPacket.java +++ b/Dream2/src/main/java/dream/common/packets/discovery/ServerHelloPacket.java @@ -7,7 +7,7 @@ * connects to it. */ public class ServerHelloPacket implements Serializable { - private static final long serialVersionUID = 3429557416466895040L; + private static final long serialVersionUID = 3429557416466895040L; - public static final String subject = "__DREAM_SERVER_HELLO_PACKET_SUBJECT"; + public static final String subject = "__DREAM_SERVER_HELLO_PACKET_SUBJECT"; } diff --git a/Dream2/src/main/java/dream/common/packets/locking/LockGrantPacket.java b/Dream2/src/main/java/dream/common/packets/locking/LockGrantPacket.java index 15f1b42..7a073a6 100644 --- a/Dream2/src/main/java/dream/common/packets/locking/LockGrantPacket.java +++ b/Dream2/src/main/java/dream/common/packets/locking/LockGrantPacket.java @@ -4,22 +4,22 @@ import java.util.UUID; public class LockGrantPacket implements Serializable { - private static final long serialVersionUID = -3499224800050816098L; - public static final String subject = "__DREAM_LOCK_GRANT_PACKET_SUBJECT"; + private static final long serialVersionUID = -3499224800050816098L; + public static final String subject = "__DREAM_LOCK_GRANT_PACKET_SUBJECT"; - private final UUID lockID; + private final UUID lockID; - public LockGrantPacket(LockRequestPacket reqPkt) { - this.lockID = reqPkt.getLockID(); - } + public LockGrantPacket(LockRequestPacket reqPkt) { + this.lockID = reqPkt.getLockID(); + } - public final UUID getLockID() { - return lockID; - } + public final UUID getLockID() { + return lockID; + } - @Override - public String toString() { - return "LockGrantPacket [lockID=" + lockID + "]"; - } + @Override + public String toString() { + return "LockGrantPacket [lockID=" + lockID + "]"; + } } diff --git a/Dream2/src/main/java/dream/common/packets/locking/LockReleasePacket.java b/Dream2/src/main/java/dream/common/packets/locking/LockReleasePacket.java index 811a1be..bd7b207 100644 --- a/Dream2/src/main/java/dream/common/packets/locking/LockReleasePacket.java +++ b/Dream2/src/main/java/dream/common/packets/locking/LockReleasePacket.java @@ -8,22 +8,22 @@ * assumes that requests are sequential (e.g., generated from a single server). */ public class LockReleasePacket implements Serializable { - private static final long serialVersionUID = -1523880233653918696L; - public static final String subject = "__DREAM_LOCK_RELEASE_PACKET_SUBJECT"; + private static final long serialVersionUID = -1523880233653918696L; + public static final String subject = "__DREAM_LOCK_RELEASE_PACKET_SUBJECT"; - private final UUID lockID; + private final UUID lockID; - public LockReleasePacket(UUID lockID) { - this.lockID = lockID; - } + public LockReleasePacket(UUID lockID) { + this.lockID = lockID; + } - public final UUID getLockID() { - return lockID; - } + public final UUID getLockID() { + return lockID; + } - @Override - public String toString() { - return "LockReleasePacket [lockID=" + lockID + "]"; - } + @Override + public String toString() { + return "LockReleasePacket [lockID=" + lockID + "]"; + } } diff --git a/Dream2/src/main/java/dream/common/packets/locking/LockRequestPacket.java b/Dream2/src/main/java/dream/common/packets/locking/LockRequestPacket.java index 764966b..7f42071 100644 --- a/Dream2/src/main/java/dream/common/packets/locking/LockRequestPacket.java +++ b/Dream2/src/main/java/dream/common/packets/locking/LockRequestPacket.java @@ -8,52 +8,52 @@ import polimi.reds.NodeDescriptor; public class LockRequestPacket implements Serializable { - private static final long serialVersionUID = -1523880233653918696L; - public static final String subject = "__DREAM_LOCK_REQUEST_PACKET_SUBJECT"; - - /** - * Node that requests the lock. - */ - private final NodeDescriptor applicant; - - /** - * Nodes to lock. - */ - private final Set lockNodes; - - /** - * Nodes that will sent a lock release. - */ - private final Set unlockNodes; - - private final LockType type; - private final UUID lockID = UUID.randomUUID(); - - public LockRequestPacket(NodeDescriptor applicant, Set lockNodes, Set unlockNodes, LockType type) { - this.applicant = applicant; - this.lockNodes = new HashSet<>(lockNodes); - this.unlockNodes = new HashSet<>(unlockNodes); - this.type = type; - } - - public final NodeDescriptor getApplicant() { - return applicant; - } - - public final Set getLockNodes() { - return lockNodes; - } - - public final Set getUnlockNodes() { - return unlockNodes; - } - - public final LockType getType() { - return type; - } - - public final UUID getLockID() { - return lockID; - } + private static final long serialVersionUID = -1523880233653918696L; + public static final String subject = "__DREAM_LOCK_REQUEST_PACKET_SUBJECT"; + + /** + * Node that requests the lock. + */ + private final NodeDescriptor applicant; + + /** + * Nodes to lock. + */ + private final Set lockNodes; + + /** + * Nodes that will sent a lock release. + */ + private final Set unlockNodes; + + private final LockType type; + private final UUID lockID = UUID.randomUUID(); + + public LockRequestPacket(NodeDescriptor applicant, Set lockNodes, Set unlockNodes, LockType type) { + this.applicant = applicant; + this.lockNodes = new HashSet<>(lockNodes); + this.unlockNodes = new HashSet<>(unlockNodes); + this.type = type; + } + + public final NodeDescriptor getApplicant() { + return applicant; + } + + public final Set getLockNodes() { + return lockNodes; + } + + public final Set getUnlockNodes() { + return unlockNodes; + } + + public final LockType getType() { + return type; + } + + public final UUID getLockID() { + return lockID; + } } diff --git a/Dream2/src/main/java/dream/common/packets/locking/LockType.java b/Dream2/src/main/java/dream/common/packets/locking/LockType.java index b5b785d..bc07cdb 100644 --- a/Dream2/src/main/java/dream/common/packets/locking/LockType.java +++ b/Dream2/src/main/java/dream/common/packets/locking/LockType.java @@ -1,5 +1,5 @@ package dream.common.packets.locking; public enum LockType { - READ_WRITE, READ_ONLY + READ_WRITE, READ_ONLY } diff --git a/Dream2/src/main/java/dream/common/utils/AtomicDependencyDetector.java b/Dream2/src/main/java/dream/common/utils/AtomicDependencyDetector.java index e1d56e4..3b1f59e 100644 --- a/Dream2/src/main/java/dream/common/utils/AtomicDependencyDetector.java +++ b/Dream2/src/main/java/dream/common/utils/AtomicDependencyDetector.java @@ -4,14 +4,14 @@ public class AtomicDependencyDetector extends InterSourceDependencyDetector { - @Override - protected void computeDataStructs() { - // Nothing to do - } + @Override + protected void computeDataStructs() { + // Nothing to do + } - @Override - public Set getNodesToLockFor(String source) { - return dependencyClosure.get(source); - } + @Override + public Set getNodesToLockFor(String source) { + return dependencyClosure.get(source); + } } diff --git a/Dream2/src/main/java/dream/common/utils/CompleteGlitchFreeDependencyDetector.java b/Dream2/src/main/java/dream/common/utils/CompleteGlitchFreeDependencyDetector.java index 30023ca..db1eb7e 100644 --- a/Dream2/src/main/java/dream/common/utils/CompleteGlitchFreeDependencyDetector.java +++ b/Dream2/src/main/java/dream/common/utils/CompleteGlitchFreeDependencyDetector.java @@ -17,48 +17,48 @@ * depends on both s and s'. */ public class CompleteGlitchFreeDependencyDetector extends InterSourceDependencyDetector { - private final Map> sharedExpressions = new HashMap<>(); + private final Map> sharedExpressions = new HashMap<>(); - @Override - public final void computeDataStructs() { - computeSharedExpressions(); - } + @Override + public final void computeDataStructs() { + computeSharedExpressions(); + } - @Override - public final synchronized Set getNodesToLockFor(String source) { - return sharedExpressions.containsKey(source) ? // - sharedExpressions.get(source) - : // - new HashSet<>(); - } + @Override + public final synchronized Set getNodesToLockFor(String source) { + return sharedExpressions.containsKey(source) ? // + sharedExpressions.get(source) + : // + new HashSet<>(); + } - private final void computeSharedExpressions() { - graph.getSources().// - forEach(initExp -> sharedExpressions.put(initExp, computeSharedExpressionsFor(initExp))); - } + private final void computeSharedExpressions() { + graph.getSources().// + forEach(initExp -> sharedExpressions.put(initExp, computeSharedExpressionsFor(initExp))); + } - private final Set computeSharedExpressionsFor(String initialDependency) { - final Set result = new HashSet<>(); - final Set depNodes = dependencyClosure.get(initialDependency); - if (depNodes.size() < 2) { - return result; - } - for (final Entry> entry : dependencyClosure.entrySet()) { - if (entry.getKey().equals(initialDependency)) { - continue; - } - final Set intersect = intersect(depNodes, entry.getValue()); - if (intersect.size() >= 2) { - result.addAll(intersect); - } - } - return result; - } + private final Set computeSharedExpressionsFor(String initialDependency) { + final Set result = new HashSet<>(); + final Set depNodes = dependencyClosure.get(initialDependency); + if (depNodes.size() < 2) { + return result; + } + for (final Entry> entry : dependencyClosure.entrySet()) { + if (entry.getKey().equals(initialDependency)) { + continue; + } + final Set intersect = intersect(depNodes, entry.getValue()); + if (intersect.size() >= 2) { + result.addAll(intersect); + } + } + return result; + } - private final Set intersect(Set set1, Set set2) { - return set1.stream().// - filter(elem -> set2.contains(elem)).// - collect(Collectors.toSet()); - } + private final Set intersect(Set set1, Set set2) { + return set1.stream().// + filter(elem -> set2.contains(elem)).// + collect(Collectors.toSet()); + } } diff --git a/Dream2/src/main/java/dream/common/utils/DependencyDetector.java b/Dream2/src/main/java/dream/common/utils/DependencyDetector.java index ddf25af..c95614e 100644 --- a/Dream2/src/main/java/dream/common/utils/DependencyDetector.java +++ b/Dream2/src/main/java/dream/common/utils/DependencyDetector.java @@ -9,10 +9,10 @@ */ public interface DependencyDetector { - /** - * Compute the accessory data structures required to speed-up the query - * process. It needs to be invoked when the dependency graph changes. - */ - public void consolidate(); + /** + * Compute the accessory data structures required to speed-up the query + * process. It needs to be invoked when the dependency graph changes. + */ + public void consolidate(); } diff --git a/Dream2/src/main/java/dream/common/utils/DependencyGraph.java b/Dream2/src/main/java/dream/common/utils/DependencyGraph.java index 418f80b..3c76115 100644 --- a/Dream2/src/main/java/dream/common/utils/DependencyGraph.java +++ b/Dream2/src/main/java/dream/common/utils/DependencyGraph.java @@ -11,46 +11,46 @@ import dream.common.packets.content.Subscription; public enum DependencyGraph { - instance; - - // Node -> set of nodes it directly depends on - private final Map> graph = new HashMap<>(); - // Sources - private final Set sources = new HashSet<>(); - - public synchronized final void clear() { - graph.clear(); - sources.clear(); - } - - public synchronized final void processAdv(Advertisement adv) { - final String advSignature = adv.getSignature(); - sources.add(advSignature); - } - - public synchronized final void processAdv(Advertisement adv, Set> subs) { - final String advSignature = adv.getSignature(); - assert !subs.isEmpty(); - final Set subSignatures = subs.stream().// - map(sub -> sub.getSignature()).// - collect(Collectors.toSet()); - graph.put(advSignature, subSignatures); - } - - public synchronized final void processUnAdv(Advertisement adv) { - // TODO manage unadvertisements - } - - public synchronized final void processUnAdv(Advertisement adv, Set> subs) { - // TODO manage unadvertisements - } - - public synchronized final Map> getGraph() { - return graph; - } - - public synchronized final Set getSources() { - return sources; - } + instance; + + // Node -> set of nodes it directly depends on + private final Map> graph = new HashMap<>(); + // Sources + private final Set sources = new HashSet<>(); + + public synchronized final void clear() { + graph.clear(); + sources.clear(); + } + + public synchronized final void processAdv(Advertisement adv) { + final String advSignature = adv.getSignature(); + sources.add(advSignature); + } + + public synchronized final void processAdv(Advertisement adv, Set> subs) { + final String advSignature = adv.getSignature(); + assert !subs.isEmpty(); + final Set subSignatures = subs.stream().// + map(sub -> sub.getSignature()).// + collect(Collectors.toSet()); + graph.put(advSignature, subSignatures); + } + + public synchronized final void processUnAdv(Advertisement adv) { + // TODO manage unadvertisements + } + + public synchronized final void processUnAdv(Advertisement adv, Set> subs) { + // TODO manage unadvertisements + } + + public synchronized final Map> getGraph() { + return graph; + } + + public synchronized final Set getSources() { + return sources; + } } diff --git a/Dream2/src/main/java/dream/common/utils/DependencyGraphUtils.java b/Dream2/src/main/java/dream/common/utils/DependencyGraphUtils.java index 72fa660..f655e20 100644 --- a/Dream2/src/main/java/dream/common/utils/DependencyGraphUtils.java +++ b/Dream2/src/main/java/dream/common/utils/DependencyGraphUtils.java @@ -9,111 +9,114 @@ class DependencyGraphUtils { - /** - * Return, for each node, the set of sources it directly or indirectly depends - * on. - * - * @return the set of sources each node directly or indirectly depends on. - */ - static final Map> computeRelevantSources() { - final Map> result = new HashMap<>(); - final DependencyGraph depGraph = DependencyGraph.instance; - depGraph.getSources().forEach(s -> { - final HashSet sources = new HashSet<>(); - sources.add(s); - result.put(s, sources); - }); - depGraph.getGraph().keySet().// - forEach(node -> result.put(node, computeRelevantSourcesFor(node, depGraph))); - return result; - } + /** + * Return, for each node, the set of sources it directly or indirectly + * depends on. + * + * @return the set of sources each node directly or indirectly depends on. + */ + static final Map> computeRelevantSources() { + final Map> result = new HashMap<>(); + final DependencyGraph depGraph = DependencyGraph.instance; + depGraph.getSources().forEach(s -> { + final HashSet sources = new HashSet<>(); + sources.add(s); + result.put(s, sources); + }); + depGraph.getGraph().keySet().// + forEach(node -> result.put(node, computeRelevantSourcesFor(node, depGraph))); + return result; + } - /** - * Return the set of final nodes in the propagation graph, that is to say, all - * the nodes that do not have any other nodes that depends on them. - * - * @return the set of final nodes in the propagation graph. - */ - static final Set computeFinalNodes() { - final Map> graph = DependencyGraph.instance.getGraph(); - final Set sources = DependencyGraph.instance.getSources(); + /** + * Return the set of final nodes in the propagation graph, that is to say, + * all the nodes that do not have any other nodes that depends on them. + * + * @return the set of final nodes in the propagation graph. + */ + static final Set computeFinalNodes() { + final Map> graph = DependencyGraph.instance.getGraph(); + final Set sources = DependencyGraph.instance.getSources(); - final Set allNodes = new HashSet<>(graph.keySet()); - allNodes.addAll(sources); + final Set allNodes = new HashSet<>(graph.keySet()); + allNodes.addAll(sources); - return allNodes.stream()// - .filter(node -> graph.values().stream() // - .allMatch(depNodes -> !depNodes.contains(node))) // - .collect(Collectors.toSet()); - } + return allNodes.stream()// + .filter(node -> graph.values().stream() // + .allMatch(depNodes -> !depNodes.contains(node))) // + .collect(Collectors.toSet()); + } - /** - * Return, for each source, the set of nodes that directly or indirectly - * depend on it. - * - * @return for each source, the set of nodes that directly or indirectly - * depend on it. - */ - static final Map> computeDependencyClosure() { - final Map> result = new HashMap<>(); - final DependencyGraph depGraph = DependencyGraph.instance; - depGraph.getSources().forEach(s -> result.put(s, computeDependencyClosureFor(s, depGraph))); - return result; - } + /** + * Return, for each source, the set of nodes that directly or indirectly + * depend on it. + * + * @return for each source, the set of nodes that directly or indirectly + * depend on it. + */ + static final Map> computeDependencyClosure() { + final Map> result = new HashMap<>(); + final DependencyGraph depGraph = DependencyGraph.instance; + depGraph.getSources().forEach(s -> result.put(s, computeDependencyClosureFor(s, depGraph))); + return result; + } - private static final Set computeDependencyClosureFor(String source, DependencyGraph depGraph) { - final Set result = new HashSet<>(); - final Set newNodes = new HashSet<>(); - result.add(source); - newNodes.add(source); - computeDependencyClosureFor(newNodes, result, depGraph); - return result; - } + private static final Set computeDependencyClosureFor(String source, DependencyGraph depGraph) { + final Set result = new HashSet<>(); + final Set newNodes = new HashSet<>(); + result.add(source); + newNodes.add(source); + computeDependencyClosureFor(newNodes, result, depGraph); + return result; + } - private static final void computeDependencyClosureFor(Set newNodes, Set accumulator, DependencyGraph depGraph) { - final Set newNodesToEvaluate = new HashSet<>(); - newNodes.forEach(n -> { - final Set depNodes = dependentNodesFor(n, depGraph); - depNodes.removeAll(accumulator); - accumulator.addAll(depNodes); - newNodesToEvaluate.addAll(depNodes); - }); - if (!newNodesToEvaluate.isEmpty()) { - computeDependencyClosureFor(newNodesToEvaluate, accumulator, depGraph); - } - } + private static final void computeDependencyClosureFor(Set newNodes, Set accumulator, + DependencyGraph depGraph) { + final Set newNodesToEvaluate = new HashSet<>(); + newNodes.forEach(n -> { + final Set depNodes = dependentNodesFor(n, depGraph); + depNodes.removeAll(accumulator); + accumulator.addAll(depNodes); + newNodesToEvaluate.addAll(depNodes); + }); + if (!newNodesToEvaluate.isEmpty()) { + computeDependencyClosureFor(newNodesToEvaluate, accumulator, depGraph); + } + } - /** - * Return the set of nodes that directly depend on node. - */ - private static Set dependentNodesFor(String node, DependencyGraph depGraph) { - return depGraph.getGraph().entrySet().stream().// - filter(e -> e.getValue().contains(node)).// - map(e -> e.getKey()).// - collect(Collectors.toSet()); - } + /** + * Return the set of nodes that directly depend on node. + */ + private static Set dependentNodesFor(String node, DependencyGraph depGraph) { + return depGraph.getGraph().entrySet().stream().// + filter(e -> e.getValue().contains(node)).// + map(e -> e.getKey()).// + collect(Collectors.toSet()); + } - private static final Set computeRelevantSourcesFor(String node, DependencyGraph depGraph) { - final Set newNodes = new HashSet<>(); - final Set accumulator = new HashSet<>(); - newNodes.add(node); - computeRelevantSourcesFor(newNodes, accumulator, depGraph); - return accumulator; - } + private static final Set computeRelevantSourcesFor(String node, DependencyGraph depGraph) { + final Set newNodes = new HashSet<>(); + final Set accumulator = new HashSet<>(); + newNodes.add(node); + computeRelevantSourcesFor(newNodes, accumulator, depGraph); + return accumulator; + } - private static final void computeRelevantSourcesFor(Set newNodes, Set accumulator, DependencyGraph depGraph) { - newNodes.stream().// - filter(depGraph.getSources()::contains).// - collect(() -> accumulator, Set::add, Set::addAll); + private static final void computeRelevantSourcesFor(Set newNodes, Set accumulator, + DependencyGraph depGraph) { + newNodes.stream().// + filter(depGraph.getSources()::contains).// + collect(() -> accumulator, Set::add, Set::addAll); - final Set newNodesToEvaluate = newNodes.stream().// - filter(expr -> !depGraph.getSources().contains(expr)).// - map(depGraph.getGraph()::get).// - collect(HashSet::new, HashSet::addAll, HashSet::addAll); + final Set newNodesToEvaluate = newNodes.stream().// + filter(expr -> !depGraph.getSources().contains(expr)).// + map(depGraph.getGraph()::get).// + filter(x -> x != null).// + collect(HashSet::new, HashSet::addAll, HashSet::addAll); - if (!newNodesToEvaluate.isEmpty()) { - computeRelevantSourcesFor(newNodesToEvaluate, accumulator, depGraph); - } - } + if (!newNodesToEvaluate.isEmpty()) { + computeRelevantSourcesFor(newNodesToEvaluate, accumulator, depGraph); + } + } } diff --git a/Dream2/src/main/java/dream/common/utils/FinalNodesDetector.java b/Dream2/src/main/java/dream/common/utils/FinalNodesDetector.java index d467823..5f02d0a 100755 --- a/Dream2/src/main/java/dream/common/utils/FinalNodesDetector.java +++ b/Dream2/src/main/java/dream/common/utils/FinalNodesDetector.java @@ -11,40 +11,40 @@ * given source and do not have any other node that deoends on them. */ public final class FinalNodesDetector { - DependencyGraph depGraph = DependencyGraph.instance; - - // Source -> set of final nodes - private final Map> finalNodes = new HashMap<>(); - - public final synchronized void consolidate() { - computeFinalNodes(); - } - - /** - * Return the set of final nodes for the given source. - * - * @param source - * the source. - * @return the set of final nodes for source. - */ - public final synchronized Set getFinalNodesFor(String source) { - return finalNodes.get(source); - } - - private final void computeFinalNodes() { - finalNodes.clear(); - final Map> closure = DependencyGraphUtils.computeDependencyClosure(); - final Set finalNodesSet = DependencyGraphUtils.computeFinalNodes(); - - closure.entrySet().forEach(e -> { - finalNodes.put(e.getKey(), intersect(finalNodesSet, e.getValue())); - }); - } - - private final Set intersect(Set set1, Set set2) { - final Set result = new HashSet<>(set1); - result.retainAll(set2); - return result; - } + DependencyGraph depGraph = DependencyGraph.instance; + + // Source -> set of final nodes + private final Map> finalNodes = new HashMap<>(); + + public final synchronized void consolidate() { + computeFinalNodes(); + } + + /** + * Return the set of final nodes for the given source. + * + * @param source + * the source. + * @return the set of final nodes for source. + */ + public final synchronized Set getFinalNodesFor(String source) { + return finalNodes.get(source); + } + + private final void computeFinalNodes() { + finalNodes.clear(); + final Map> closure = DependencyGraphUtils.computeDependencyClosure(); + final Set finalNodesSet = DependencyGraphUtils.computeFinalNodes(); + + closure.entrySet().forEach(e -> { + finalNodes.put(e.getKey(), intersect(finalNodesSet, e.getValue())); + }); + } + + private final Set intersect(Set set1, Set set2) { + final Set result = new HashSet<>(set1); + result.retainAll(set2); + return result; + } } diff --git a/Dream2/src/main/java/dream/common/utils/InterSourceDependencyDetector.java b/Dream2/src/main/java/dream/common/utils/InterSourceDependencyDetector.java index 288eced..be4aa7f 100644 --- a/Dream2/src/main/java/dream/common/utils/InterSourceDependencyDetector.java +++ b/Dream2/src/main/java/dream/common/utils/InterSourceDependencyDetector.java @@ -6,7 +6,7 @@ /** * An InterSourceDependencyDetector is a dependency detector used to detect - * dependencies in the propagations from starting from different sources. + * dependencies in propagations starting from different sources. * * For each source, the detector returns the nodes that require to be locked * during the propagation. @@ -15,25 +15,25 @@ * guarantees. */ public abstract class InterSourceDependencyDetector { - protected final DependencyGraph graph = DependencyGraph.instance; + protected final DependencyGraph graph = DependencyGraph.instance; - protected Map> dependencyClosure = new HashMap<>(); + protected Map> dependencyClosure = new HashMap<>(); - public final synchronized void consolidate() { - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - computeDataStructs(); - } + public final synchronized void consolidate() { + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + computeDataStructs(); + } - protected abstract void computeDataStructs(); + protected abstract void computeDataStructs(); - /** - * Returns the nodes that require to be locked during the propagation of an - * update originated at the given source. - * - * @param source - * the source. - * @return the nodes that need to be locked during the propagation. - */ - public abstract Set getNodesToLockFor(String source); + /** + * Returns the nodes that require to be locked during the propagation of an + * update originated at the given source. + * + * @param source + * the source. + * @return the nodes that need to be locked during the propagation. + */ + public abstract Set getNodesToLockFor(String source); } diff --git a/Dream2/src/main/java/dream/common/utils/IntraSourceDependencyDetector.java b/Dream2/src/main/java/dream/common/utils/IntraSourceDependencyDetector.java index 0020ba2..5056ea9 100755 --- a/Dream2/src/main/java/dream/common/utils/IntraSourceDependencyDetector.java +++ b/Dream2/src/main/java/dream/common/utils/IntraSourceDependencyDetector.java @@ -9,73 +9,73 @@ import dream.common.packets.content.Event; public enum IntraSourceDependencyDetector implements DependencyDetector { - instance; + instance; - private final DependencyGraph depGraph = DependencyGraph.instance; - private Map> relevantSources = new HashMap<>(); + private final DependencyGraph depGraph = DependencyGraph.instance; + private Map> relevantSources = new HashMap<>(); - // Stores the dependencies to compute expressions - // Expression Expr -> Initial expression that caused the recomputation -> - // Wait recommendations - private final Map>> recommendations = new HashMap<>(); + // Stores the dependencies to compute expressions + // Expression Expr -> Initial expression that caused the recomputation -> + // Wait recommendations + private final Map>> recommendations = new HashMap<>(); - public synchronized final Set getWaitRecommendations(Event event, String initialVar) { - final Map> innerMap = recommendations.get(event.getSignature()); - if (innerMap == null) { - return new HashSet<>(); - } - return innerMap.containsKey(initialVar) ? innerMap.get(initialVar) : new HashSet<>(); - } + public synchronized final Set getWaitRecommendations(Event event, String initialVar) { + final Map> innerMap = recommendations.get(event.getSignature()); + if (innerMap == null) { + return new HashSet<>(); + } + return innerMap.containsKey(initialVar) ? innerMap.get(initialVar) : new HashSet<>(); + } - @Override - public synchronized final void consolidate() { - recommendations.clear(); - computeRecommendations(); - } + @Override + public synchronized final void consolidate() { + recommendations.clear(); + computeRecommendations(); + } - private final void computeRecommendations() { - recommendations.clear(); - relevantSources = DependencyGraphUtils.computeRelevantSources(); - depGraph.getGraph().keySet().forEach(expr -> { - relevantSources.get(expr).forEach(initialExpr -> storeRecommendationsFor(expr, initialExpr)); - }); - } + private final void computeRecommendations() { + recommendations.clear(); + relevantSources = DependencyGraphUtils.computeRelevantSources(); + depGraph.getGraph().keySet().forEach(expr -> { + relevantSources.get(expr).forEach(initialExpr -> storeRecommendationsFor(expr, initialExpr)); + }); + } - private final void storeRecommendationsFor(String expr, String initialExpr) { - final Set dependentSiblings = computeDependentSiblingsFor(expr, initialExpr); + private final void storeRecommendationsFor(String expr, String initialExpr) { + final Set dependentSiblings = computeDependentSiblingsFor(expr, initialExpr); - if (dependentSiblings.size() > 1) { - dependentSiblings.forEach(sibling -> { - Map> recommendationsMap = recommendations.get(sibling); - if (recommendationsMap == null) { - recommendationsMap = new HashMap<>(); - recommendations.put(sibling, recommendationsMap); - } - Set recommendationsSet = recommendationsMap.get(initialExpr); - if (recommendationsSet == null) { - recommendationsSet = new HashSet<>(); - recommendationsMap.put(initialExpr, recommendationsSet); - } - final WaitRecommendations wr = new WaitRecommendations(expr); - recommendationsSet.add(wr); - dependentSiblings.stream().// - filter(e -> !e.equals(sibling)).// - forEach(wr::addRecommendation); - }); - } - } + if (dependentSiblings.size() > 1) { + dependentSiblings.forEach(sibling -> { + Map> recommendationsMap = recommendations.get(sibling); + if (recommendationsMap == null) { + recommendationsMap = new HashMap<>(); + recommendations.put(sibling, recommendationsMap); + } + Set recommendationsSet = recommendationsMap.get(initialExpr); + if (recommendationsSet == null) { + recommendationsSet = new HashSet<>(); + recommendationsMap.put(initialExpr, recommendationsSet); + } + final WaitRecommendations wr = new WaitRecommendations(expr); + recommendationsSet.add(wr); + dependentSiblings.stream().// + filter(e -> !e.equals(sibling)).// + forEach(wr::addRecommendation); + }); + } + } - /** - * Compute the set of all expressions with the following properties: - * - * 1) expr directly depends on them - * - * 2) they directly or indirectly depend on the initialExpression - */ - private final Set computeDependentSiblingsFor(String expr, String initialExpression) { - return depGraph.getGraph().get(expr).stream().// - filter(dep -> relevantSources.get(dep).contains(initialExpression)).// - collect(Collectors.toSet()); - } + /** + * Compute the set of all expressions with the following properties: + * + * 1) expr directly depends on them + * + * 2) they directly or indirectly depend on the initialExpression + */ + private final Set computeDependentSiblingsFor(String expr, String initialExpression) { + return depGraph.getGraph().get(expr).stream().// + filter(dep -> relevantSources.getOrDefault(dep, new HashSet<>()).contains(initialExpression)).// + collect(Collectors.toSet()); + } } diff --git a/Dream2/src/main/java/dream/common/utils/WaitRecommendations.java b/Dream2/src/main/java/dream/common/utils/WaitRecommendations.java index 8290ae3..cfdb4c1 100755 --- a/Dream2/src/main/java/dream/common/utils/WaitRecommendations.java +++ b/Dream2/src/main/java/dream/common/utils/WaitRecommendations.java @@ -5,44 +5,45 @@ import java.util.Set; /** - * A WaitRecommendations object is stored inside an event E. It is used by the server to prevent glitches while - * delivering E to the clients. It tells a client C that it must wait for other events before processing E. + * A WaitRecommendations object is stored inside an event E. It is used by the + * server to prevent glitches while delivering E to the clients. It tells a + * client C that it must wait for other events before processing E. */ public class WaitRecommendations implements Serializable { - private static final long serialVersionUID = 5700944080087353096L; + private static final long serialVersionUID = 5700944080087353096L; - private final String expression; - private final Set expressionsToWaitFor = new HashSet(); + private final String expression; + private final Set expressionsToWaitFor = new HashSet(); - public WaitRecommendations(String expression) { - this.expression = expression; - } + public WaitRecommendations(String expression) { + this.expression = expression; + } - public final void addRecommendation(String expressionToWaitFor) { - expressionsToWaitFor.add(expressionToWaitFor); - } + public final void addRecommendation(String expressionToWaitFor) { + expressionsToWaitFor.add(expressionToWaitFor); + } - public final String getExpression() { - return expression; - } + public final String getExpression() { + return expression; + } - public final Set getRecommendations() { - return expressionsToWaitFor; - } + public final Set getRecommendations() { + return expressionsToWaitFor; + } - public final WaitRecommendations dup() { - WaitRecommendations result = new WaitRecommendations(expression); - result.expressionsToWaitFor.addAll(expressionsToWaitFor); - return result; - } + public final WaitRecommendations dup() { + WaitRecommendations result = new WaitRecommendations(expression); + result.expressionsToWaitFor.addAll(expressionsToWaitFor); + return result; + } - public final void removeExpressionToWaitFor(String expressionToWaitFor) { - expressionsToWaitFor.remove(expressionToWaitFor); - } + public final void removeExpressionToWaitFor(String expressionToWaitFor) { + expressionsToWaitFor.remove(expressionToWaitFor); + } - @Override - public String toString() { - return "WaitRecommendations [expression=" + expression + ", expressionsToWaitFor=" + expressionsToWaitFor + "]"; - } + @Override + public String toString() { + return "WaitRecommendations [expression=" + expression + ", expressionsToWaitFor=" + expressionsToWaitFor + "]"; + } } diff --git a/Dream2/src/main/java/dream/locking/LockManager.java b/Dream2/src/main/java/dream/locking/LockManager.java index 9112088..d998838 100644 --- a/Dream2/src/main/java/dream/locking/LockManager.java +++ b/Dream2/src/main/java/dream/locking/LockManager.java @@ -14,175 +14,176 @@ import dream.common.packets.locking.LockType; class LockManager { - // Pending requests - private final List pendingRequests = new ArrayList<>(); - - // All stored locks - private final Map activeLocks = new HashMap<>(); - - // Stored read and write locks - private final Map readLocks = new HashMap<>(); - private final WriteLockManager writeLocks = new WriteLockManager(); - - /** - * Process the given request. Returns true if the lock can be granted. - * - * @param request - * the request. - * @return true if the lock is granted, false otherwise. - */ - final boolean processLockRequest(LockRequestPacket request) { - if (canBeGranted(request)) { - lock(request); - return true; - } else { - pendingRequests.add(request); - return false; - } - } - - /** - * Process the given release. Returns the set of pending requests that can now - * obtain a lock. - * - * @param release - * the release. - * @return the set of granted locks. - */ - final Set processLockRelease(LockReleasePacket release) { - final UUID lockID = release.getLockID(); - assert activeLocks.containsKey(lockID); - final LockRequestPacket reqPkt = activeLocks.get(lockID); - - final Set result = new HashSet<>(); - if (release(reqPkt.getLockID(), reqPkt.getLockNodes(), reqPkt.getType())) { - final Iterator it = pendingRequests.iterator(); - while (it.hasNext()) { - final LockRequestPacket request = it.next(); - if (canBeGranted(request)) { - lock(request); - result.add(request); - it.remove(); - } - } - } - return result; - } - - private final boolean canBeGranted(LockRequestPacket request) { - final LockType type = request.getType(); - final Set lockNodes = request.getLockNodes(); - final boolean writeConflicts = lockNodes.stream()// - .anyMatch(n -> writeLocks.isLocked(n)); - if (writeConflicts) { - return false; - } - final boolean readConflicts = type == LockType.READ_WRITE && // - lockNodes.stream().anyMatch(n -> readLocks.containsKey(n)); - return !readConflicts; - } - - private final void lock(LockRequestPacket request) { - activeLocks.put(request.getLockID(), request); - final LockType type = request.getType(); - final Set lockNodes = request.getLockNodes(); - switch (type) { - case READ_ONLY: - lockNodes.forEach(n -> { - final Integer count = readLocks.get(n); - if (count == null) { - readLocks.put(n, 1); - } else { - readLocks.put(n, count + 1); - } - }); - break; - case READ_WRITE: - writeLocks.grant(request); - break; - default: - assert false : type; - break; - } - } - - /** - * Return true if the packet released at least one node - */ - private final boolean release(UUID lockId, Set lockNodes, LockType type) { - boolean result = false; - switch (type) { - case READ_ONLY: - for (final String lockNode : lockNodes) { - final int newCount = readLocks.get(lockNode) - 1; - if (newCount == 0) { - readLocks.remove(lockNode); - activeLocks.remove(lockId); - result = true; - } else { - readLocks.put(lockNode, newCount); - } - } - break; - case READ_WRITE: - if (writeLocks.release(lockId)) { - activeLocks.remove(lockId); - result = true; - } - break; - default: - assert false : type; - break; - } - return result; - } - - /** - * Store information about the write locks that have been granted. - */ - private class WriteLockManager { - private final Map grantedLocks = new HashMap<>(); - private final Map> lockedNodesMap = new HashMap<>(); - private final Set lockedNodes = new HashSet<>(); - - /** - * Store the lock coming from the given source and having the given lockId. - */ - void grant(LockRequestPacket request) { - final UUID lockId = request.getLockID(); - final Set nodesToLock = request.getLockNodes(); - assert!grantedLocks.containsKey(lockId); - assert!lockedNodesMap.containsKey(lockId); - - grantedLocks.put(lockId, request.getUnlockNodes().size()); - lockedNodesMap.put(lockId, new HashSet<>(nodesToLock)); - lockedNodes.addAll(nodesToLock); - } - - /** - * Return true if the given node is already locked. - */ - boolean isLocked(String node) { - return lockedNodes.contains(node); - } - - /** - * Return true if the lock has been entirely released. - */ - boolean release(UUID lockId) { - assert grantedLocks.containsKey(lockId); - Integer count = grantedLocks.get(lockId); - if (--count == 0) { - grantedLocks.remove(lockId); - lockedNodesMap.get(lockId).forEach(lockedNodes::remove); - lockedNodesMap.remove(lockId); - return true; - } else { - grantedLocks.put(lockId, count); - return false; - } - } - - } + // Pending requests + private final List pendingRequests = new ArrayList<>(); + + // All stored locks + private final Map activeLocks = new HashMap<>(); + + // Stored read and write locks + private final Map readLocks = new HashMap<>(); + private final WriteLockManager writeLocks = new WriteLockManager(); + + /** + * Process the given request. Returns true if the lock can be granted. + * + * @param request + * the request. + * @return true if the lock is granted, false otherwise. + */ + final boolean processLockRequest(LockRequestPacket request) { + if (canBeGranted(request)) { + lock(request); + return true; + } else { + pendingRequests.add(request); + return false; + } + } + + /** + * Process the given release. Returns the set of pending requests that can + * now obtain a lock. + * + * @param release + * the release. + * @return the set of granted locks. + */ + final Set processLockRelease(LockReleasePacket release) { + final UUID lockID = release.getLockID(); + assert activeLocks.containsKey(lockID); + final LockRequestPacket reqPkt = activeLocks.get(lockID); + + final Set result = new HashSet<>(); + if (reqPkt != null && release(reqPkt.getLockID(), reqPkt.getLockNodes(), reqPkt.getType())) { + final Iterator it = pendingRequests.iterator(); + while (it.hasNext()) { + final LockRequestPacket request = it.next(); + if (canBeGranted(request)) { + lock(request); + result.add(request); + it.remove(); + } + } + } + return result; + } + + private final boolean canBeGranted(LockRequestPacket request) { + final LockType type = request.getType(); + final Set lockNodes = request.getLockNodes(); + final boolean writeConflicts = lockNodes.stream()// + .anyMatch(n -> writeLocks.isLocked(n)); + if (writeConflicts) { + return false; + } + final boolean readConflicts = type == LockType.READ_WRITE && // + lockNodes.stream().anyMatch(n -> readLocks.containsKey(n)); + return !readConflicts; + } + + private final void lock(LockRequestPacket request) { + activeLocks.put(request.getLockID(), request); + final LockType type = request.getType(); + final Set lockNodes = request.getLockNodes(); + switch (type) { + case READ_ONLY: + lockNodes.forEach(n -> { + final Integer count = readLocks.get(n); + if (count == null) { + readLocks.put(n, 1); + } else { + readLocks.put(n, count + 1); + } + }); + break; + case READ_WRITE: + writeLocks.grant(request); + break; + default: + assert false : type; + break; + } + } + + /** + * Return true if the packet released at least one node + */ + private final boolean release(UUID lockId, Set lockNodes, LockType type) { + boolean result = false; + switch (type) { + case READ_ONLY: + for (final String lockNode : lockNodes) { + final int newCount = readLocks.get(lockNode) - 1; + if (newCount == 0) { + readLocks.remove(lockNode); + activeLocks.remove(lockId); + result = true; + } else { + readLocks.put(lockNode, newCount); + } + } + break; + case READ_WRITE: + if (writeLocks.release(lockId)) { + activeLocks.remove(lockId); + result = true; + } + break; + default: + assert false : type; + break; + } + return result; + } + + /** + * Store information about the write locks that have been granted. + */ + private class WriteLockManager { + private final Map grantedLocks = new HashMap<>(); + private final Map> lockedNodesMap = new HashMap<>(); + private final Set lockedNodes = new HashSet<>(); + + /** + * Store the lock coming from the given source and having the given + * lockId. + */ + void grant(LockRequestPacket request) { + final UUID lockId = request.getLockID(); + final Set nodesToLock = request.getLockNodes(); + assert!grantedLocks.containsKey(lockId); + assert!lockedNodesMap.containsKey(lockId); + + grantedLocks.put(lockId, request.getUnlockNodes().size()); + lockedNodesMap.put(lockId, new HashSet<>(nodesToLock)); + lockedNodes.addAll(nodesToLock); + } + + /** + * Return true if the given node is already locked. + */ + boolean isLocked(String node) { + return lockedNodes.contains(node); + } + + /** + * Return true if the lock has been entirely released. + */ + boolean release(UUID lockId) { + assert grantedLocks.containsKey(lockId); + Integer count = grantedLocks.get(lockId); + if (--count == 0) { + grantedLocks.remove(lockId); + lockedNodesMap.get(lockId).forEach(lockedNodes::remove); + lockedNodesMap.remove(lockId); + return true; + } else { + grantedLocks.put(lockId, count); + return false; + } + } + + } } diff --git a/Dream2/src/main/java/dream/locking/LockManagerForwarder.java b/Dream2/src/main/java/dream/locking/LockManagerForwarder.java index cb368b9..d5a04cb 100644 --- a/Dream2/src/main/java/dream/locking/LockManagerForwarder.java +++ b/Dream2/src/main/java/dream/locking/LockManagerForwarder.java @@ -14,44 +14,45 @@ import polimi.reds.broker.routing.PacketForwarder; public class LockManagerForwarder implements PacketForwarder { - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - private final LockManager lockManager = new LockManager(); + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + private final LockManager lockManager = new LockManager(); - @Override - public final Collection forwardPacket(String subject, NodeDescriptor sender, Serializable packet, Collection neighbors, Outbox outbox) { - if (subject.equals(LockRequestPacket.subject)) { - assert packet instanceof LockRequestPacket; - final LockRequestPacket reqPkt = (LockRequestPacket) packet; - logger.fine("Received a request packet: " + reqPkt); - processRequestPacket(sender, reqPkt, outbox); - } else if (subject.equals(LockReleasePacket.subject)) { - assert packet instanceof LockReleasePacket; - final LockReleasePacket relPkt = (LockReleasePacket) packet; - logger.finer("Received a release packet: " + relPkt); - processReleasePacket(sender, relPkt, outbox); - } else { - assert false; - logger.warning("Received an unknown packet subject"); - } - return new ArrayList(); - } + @Override + public final Collection forwardPacket(String subject, NodeDescriptor sender, Serializable packet, + Collection neighbors, Outbox outbox) { + if (subject.equals(LockRequestPacket.subject)) { + assert packet instanceof LockRequestPacket; + final LockRequestPacket reqPkt = (LockRequestPacket) packet; + logger.fine("Received a request packet: " + reqPkt); + processRequestPacket(sender, reqPkt, outbox); + } else if (subject.equals(LockReleasePacket.subject)) { + assert packet instanceof LockReleasePacket; + final LockReleasePacket relPkt = (LockReleasePacket) packet; + logger.finer("Received a release packet: " + relPkt); + processReleasePacket(sender, relPkt, outbox); + } else { + assert false; + logger.warning("Received an unknown packet subject"); + } + return new ArrayList(); + } - private final void processRequestPacket(NodeDescriptor sender, LockRequestPacket reqPkt, Outbox outbox) { - final boolean granted = lockManager.processLockRequest(reqPkt); - if (granted) { - final Collection recipients = new ArrayList<>(1); - recipients.add(sender); - outbox.add(LockGrantPacket.subject, new LockGrantPacket(reqPkt), recipients); - } - } + private final void processRequestPacket(NodeDescriptor sender, LockRequestPacket reqPkt, Outbox outbox) { + final boolean granted = lockManager.processLockRequest(reqPkt); + if (granted) { + final Collection recipients = new ArrayList<>(1); + recipients.add(sender); + outbox.add(LockGrantPacket.subject, new LockGrantPacket(reqPkt), recipients); + } + } - private final void processReleasePacket(NodeDescriptor sender, LockReleasePacket relPkt, Outbox outbox) { - final Set granted = lockManager.processLockRelease(relPkt); - granted.forEach(req -> { - final Collection recipients = new ArrayList<>(1); - recipients.add(req.getApplicant()); - outbox.add(LockGrantPacket.subject, new LockGrantPacket(req), recipients); - }); - } + private final void processReleasePacket(NodeDescriptor sender, LockReleasePacket relPkt, Outbox outbox) { + final Set granted = lockManager.processLockRelease(relPkt); + granted.forEach(req -> { + final Collection recipients = new ArrayList<>(1); + recipients.add(req.getApplicant()); + outbox.add(LockGrantPacket.subject, new LockGrantPacket(req), recipients); + }); + } } diff --git a/Dream2/src/main/java/dream/locking/LockManagerLauncher.java b/Dream2/src/main/java/dream/locking/LockManagerLauncher.java index 74c94a2..307cde9 100644 --- a/Dream2/src/main/java/dream/locking/LockManagerLauncher.java +++ b/Dream2/src/main/java/dream/locking/LockManagerLauncher.java @@ -19,54 +19,54 @@ import polimi.reds.broker.routing.GenericRouter; public class LockManagerLauncher implements NeighborhoodChangeListener { - private static LockManagerLauncher launcher; + private static LockManagerLauncher launcher; - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - private final Overlay overlay; + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + private final Overlay overlay; - private LockManagerLauncher() { - final Transport tr = new TCPTransport(Consts.lockManagerPort); - final TopologyManager tm = new SimpleTopologyManager(); - overlay = new GenericOverlay(tm, tr); - final GenericRouter router = new GenericRouter(overlay); - final LockManagerForwarder forwarder = new LockManagerForwarder(); - router.setPacketForwarder(LockRequestPacket.subject, forwarder); - router.setPacketForwarder(LockReleasePacket.subject, forwarder); - overlay.addNeighborhoodChangeListener(this); - } + private LockManagerLauncher() { + final Transport tr = new TCPTransport(Consts.lockManagerPort); + final TopologyManager tm = new SimpleTopologyManager(); + overlay = new GenericOverlay(tm, tr); + final GenericRouter router = new GenericRouter(overlay); + final LockManagerForwarder forwarder = new LockManagerForwarder(); + router.setPacketForwarder(LockRequestPacket.subject, forwarder); + router.setPacketForwarder(LockReleasePacket.subject, forwarder); + overlay.addNeighborhoodChangeListener(this); + } - public static final void start() { - if (launcher == null) { - launcher = new LockManagerLauncher(); - } - launcher.logger.info("Starting lock manager"); - launcher.overlay.start(); - } + public static final void start() { + if (launcher == null) { + launcher = new LockManagerLauncher(); + } + launcher.logger.info("Starting lock manager"); + launcher.overlay.start(); + } - public static final void stop() { - if (launcher != null) { - launcher.logger.info("Stopping lock manager"); - launcher.overlay.stop(); - } - } + public static final void stop() { + if (launcher != null) { + launcher.logger.info("Stopping lock manager"); + launcher.overlay.stop(); + } + } - @Override - public void notifyNeighborAdded(NodeDescriptor sender) { - try { - overlay.send(LockManagerHelloPacket.subject, new LockManagerHelloPacket(), sender); - } catch (IOException | NotRunningException e) { - e.printStackTrace(); - } - } + @Override + public void notifyNeighborAdded(NodeDescriptor sender) { + try { + overlay.send(LockManagerHelloPacket.subject, new LockManagerHelloPacket(), sender); + } catch (IOException | NotRunningException e) { + e.printStackTrace(); + } + } - @Override - public void notifyNeighborDead(NodeDescriptor sender) { - // Nothing to do - } + @Override + public void notifyNeighborDead(NodeDescriptor sender) { + // Nothing to do + } - @Override - public void notifyNeighborRemoved(NodeDescriptor sender) { - // Nothing to do - } + @Override + public void notifyNeighborRemoved(NodeDescriptor sender) { + // Nothing to do + } } diff --git a/Dream2/src/main/java/dream/server/AdvertisementTable.java b/Dream2/src/main/java/dream/server/AdvertisementTable.java index fbb8caa..3d41140 100755 --- a/Dream2/src/main/java/dream/server/AdvertisementTable.java +++ b/Dream2/src/main/java/dream/server/AdvertisementTable.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Predicate; @@ -13,38 +14,42 @@ import polimi.reds.NodeDescriptor; final class AdvertisementTable { - private final Map> advs = new HashMap>(); - - final void addAdvertisement(NodeDescriptor node, Advertisement adv) { - Collection advsList = advs.get(node); - if (advsList == null) { - advsList = new ArrayList(); - advs.put(node, advsList); - } - advsList.add(adv); - } - - final void removeAdvertisement(NodeDescriptor node, Advertisement adv) { - final Collection advsList = advs.get(node); - if (advsList == null) { - return; - } - advsList.remove(adv); - if (advsList.isEmpty()) { - advs.remove(node); - } - } - - final Set getMatchingNodes(Subscription sub) { - final Predicate isAdvSat = adv -> adv.isSatisfiedBy(sub); - final Predicate hasAdvSat = node -> advs.get(node).stream().anyMatch(isAdvSat); - return advs.keySet().stream().// - filter(hasAdvSat).// - collect(Collectors.toSet()); - } - - final void removeAllAdvertisementsFor(NodeDescriptor node) { - advs.remove(node); - } + private final Map> advs = new HashMap>(); + + final void addAdvertisement(NodeDescriptor node, Advertisement adv) { + Collection advsList = advs.get(node); + if (advsList == null) { + advsList = new ArrayList(); + advs.put(node, advsList); + } + advsList.add(adv); + } + + final void removeAdvertisement(NodeDescriptor node, Advertisement adv) { + final Collection advsList = advs.get(node); + if (advsList == null) { + return; + } + advsList.remove(adv); + if (advsList.isEmpty()) { + advs.remove(node); + } + } + + final Set getMatchingNodes(Subscription sub) { + final Predicate isAdvSat = adv -> adv.isSatisfiedBy(sub); + final Predicate hasAdvSat = node -> advs.get(node).stream().anyMatch(isAdvSat); + return advs.keySet().stream().// + filter(hasAdvSat).// + collect(Collectors.toSet()); + } + + final void removeAllAdvertisementsFor(NodeDescriptor node) { + advs.remove(node); + } + + final Set getAllAdvertisements() { + return advs.values().stream().collect(HashSet::new, HashSet::addAll, HashSet::addAll); + } } diff --git a/Dream2/src/main/java/dream/server/ServerEventForwarder.java b/Dream2/src/main/java/dream/server/ServerEventForwarder.java index 21baf90..f75ed9c 100755 --- a/Dream2/src/main/java/dream/server/ServerEventForwarder.java +++ b/Dream2/src/main/java/dream/server/ServerEventForwarder.java @@ -1,8 +1,10 @@ package dream.server; +import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.logging.Logger; @@ -12,116 +14,140 @@ import dream.common.packets.SubscriptionPacket; import polimi.reds.NodeDescriptor; import polimi.reds.broker.overlay.NeighborhoodChangeListener; +import polimi.reds.broker.overlay.NotRunningException; +import polimi.reds.broker.overlay.Overlay; import polimi.reds.broker.routing.Outbox; import polimi.reds.broker.routing.PacketForwarder; public class ServerEventForwarder implements PacketForwarder, NeighborhoodChangeListener { - protected final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - protected final SubscriptionTable clientsSubTable = new SubscriptionTable(); - protected final SubscriptionTable brokersSubTable = new SubscriptionTable(); - protected final AdvertisementTable advTable = new AdvertisementTable(); - - @Override - public Collection forwardPacket(String subject, NodeDescriptor sender, Serializable packet, Collection neighbors, Outbox outbox) { - if (subject.equals(SubscriptionPacket.subject)) { - assert packet instanceof SubscriptionPacket; - final SubscriptionPacket subPkt = (SubscriptionPacket) packet; - logger.fine("Received a subscription packet: " + subPkt); - processSubscription(sender, subPkt, neighbors, outbox); - } else if (subject.equals(EventPacket.subject)) { - assert packet instanceof EventPacket; - final EventPacket evPkt = (EventPacket) packet; - logger.finer("Received an event packet: " + evPkt); - processEvent(sender, evPkt, neighbors, outbox); - } else if (subject.equals(AdvertisementPacket.subject)) { - assert packet instanceof AdvertisementPacket; - final AdvertisementPacket advPkt = (AdvertisementPacket) packet; - logger.fine("Received an advertisement packet: " + advPkt); - processAdvertisement(sender, advPkt, neighbors, outbox); - } else { - assert false; - logger.warning("Received an unknown packet subject"); - } - return new ArrayList(); - } - - private final void processSubscription(NodeDescriptor sender, SubscriptionPacket packet, Collection neighbors, Outbox box) { - updateSubscriptionTables(sender, packet); - final Set matchingNodes = advTable.getMatchingNodes(packet.getSubscription()); - if (!matchingNodes.isEmpty()) { - sendTo(SubscriptionPacket.subject, packet, box, matchingNodes); - } - } - - private final void updateSubscriptionTables(NodeDescriptor sender, SubscriptionPacket subPkt) { - final SubscriptionTable table = sender.isClient() ? clientsSubTable : brokersSubTable; - switch (subPkt.getSubType()) { - case SUB: - table.addSubscription(sender, subPkt.getSubscription()); - break; - case UNSUB: - table.removeSubscription(sender, subPkt.getSubscription()); - break; - default: - assert false : subPkt.getSubType(); - } - } - - private void processEvent(NodeDescriptor sender, EventPacket packet, Collection neighbors, Outbox outbox) { - final Map matchingClients = clientsSubTable.getMatchingNodes(packet.getEvent()); - final Map matchingBrokers = brokersSubTable.getMatchingNodes(packet.getEvent()); - sendTo(EventPacket.subject, packet, outbox, matchingClients.keySet()); - sendTo(EventPacket.subject, packet, outbox, matchingBrokers.keySet()); - } - - private final void processAdvertisement(NodeDescriptor sender, AdvertisementPacket packet, Collection neighbors, Outbox outbox) { - if (packet.isPublic()) { - switch (packet.getAdvType()) { - case ADV: - advTable.addAdvertisement(sender, packet.getAdvertisement()); - break; - case UNADV: - advTable.removeAdvertisement(sender, packet.getAdvertisement()); - break; - } - } - outbox.add(AdvertisementPacket.subject, packet, getAllNodesExcept(sender, neighbors)); - } - - private final void sendTo(String subject, Serializable packet, Outbox box, Collection recipients) { - box.add(subject, packet, recipients); - } - - private final Collection getAllNodesExcept(NodeDescriptor nodeToSkip, Collection neighbors) { - final Collection result = new ArrayList<>(neighbors); - result.remove(nodeToSkip); - return result; - } - - private final void reactToRemovedNeighbor(NodeDescriptor node) { - logger.fine("Removing neighbor"); - if (node.isBroker()) { - brokersSubTable.removeAllSubscriptionsFor(node); - advTable.removeAllAdvertisementsFor(node); - } else { - clientsSubTable.removeAllSubscriptionsFor(node); - } - } - - @Override - public final void notifyNeighborAdded(NodeDescriptor node) { - // Nothing to do - } - - @Override - public final void notifyNeighborDead(NodeDescriptor node) { - reactToRemovedNeighbor(node); - } - - @Override - public final void notifyNeighborRemoved(NodeDescriptor node) { - reactToRemovedNeighbor(node); - } + protected final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + protected final SubscriptionTable clientsSubTable = new SubscriptionTable(); + protected final SubscriptionTable brokersSubTable = new SubscriptionTable(); + protected final AdvertisementTable advTable = new AdvertisementTable(); + + private final Set allValidAdvertisements = new HashSet<>(); + private final Overlay overlay; + + public ServerEventForwarder(final Overlay overlay) { + this.overlay = overlay; + } + + @Override + public Collection forwardPacket(String subject, NodeDescriptor sender, Serializable packet, + Collection neighbors, Outbox outbox) { + if (subject.equals(SubscriptionPacket.subject)) { + assert packet instanceof SubscriptionPacket; + final SubscriptionPacket subPkt = (SubscriptionPacket) packet; + logger.fine("Received a subscription packet: " + subPkt); + processSubscription(sender, subPkt, neighbors, outbox); + } else if (subject.equals(EventPacket.subject)) { + assert packet instanceof EventPacket; + final EventPacket evPkt = (EventPacket) packet; + logger.finer("Received an event packet: " + evPkt); + processEvent(sender, evPkt, neighbors, outbox); + } else if (subject.equals(AdvertisementPacket.subject)) { + assert packet instanceof AdvertisementPacket; + final AdvertisementPacket advPkt = (AdvertisementPacket) packet; + logger.fine("Received an advertisement packet: " + advPkt); + processAdvertisement(sender, advPkt, neighbors, outbox); + } else { + assert false; + logger.warning("Received an unknown packet subject"); + } + return new ArrayList(); + } + + private final void processSubscription(NodeDescriptor sender, SubscriptionPacket packet, + Collection neighbors, Outbox box) { + updateSubscriptionTables(sender, packet); + final Set matchingNodes = advTable.getMatchingNodes(packet.getSubscription()); + if (!matchingNodes.isEmpty()) { + sendTo(SubscriptionPacket.subject, packet, box, matchingNodes); + } + } + + private final void updateSubscriptionTables(NodeDescriptor sender, SubscriptionPacket subPkt) { + final SubscriptionTable table = sender.isClient() ? clientsSubTable : brokersSubTable; + switch (subPkt.getSubType()) { + case SUB: + table.addSubscription(sender, subPkt.getSubscription()); + break; + case UNSUB: + table.removeSubscription(sender, subPkt.getSubscription()); + break; + default: + assert false : subPkt.getSubType(); + } + } + + private void processEvent(NodeDescriptor sender, EventPacket packet, Collection neighbors, + Outbox outbox) { + final Map matchingClients = clientsSubTable.getMatchingNodes(packet.getEvent()); + final Map matchingBrokers = brokersSubTable.getMatchingNodes(packet.getEvent()); + sendTo(EventPacket.subject, packet, outbox, matchingClients.keySet()); + sendTo(EventPacket.subject, packet, outbox, matchingBrokers.keySet()); + } + + private final void processAdvertisement(NodeDescriptor sender, AdvertisementPacket packet, + Collection neighbors, Outbox outbox) { + if (packet.isPublic()) { + switch (packet.getAdvType()) { + case ADV: + allValidAdvertisements.add(packet); + advTable.addAdvertisement(sender, packet.getAdvertisement()); + break; + case UNADV: + allValidAdvertisements.removeIf(p -> p.getAdvertisement().equals(packet.getAdvertisement())); + advTable.removeAdvertisement(sender, packet.getAdvertisement()); + break; + } + } + outbox.add(AdvertisementPacket.subject, packet, getAllNodesExcept(sender, neighbors)); + } + + private final void sendTo(String subject, Serializable packet, Outbox box, Collection recipients) { + box.add(subject, packet, recipients); + } + + private final Collection getAllNodesExcept(NodeDescriptor nodeToSkip, + Collection neighbors) { + final Collection result = new ArrayList<>(neighbors); + result.remove(nodeToSkip); + return result; + } + + private final void reactToRemovedNeighbor(NodeDescriptor node) { + logger.fine("Removing neighbor"); + if (node.isBroker()) { + brokersSubTable.removeAllSubscriptionsFor(node); + advTable.removeAllAdvertisementsFor(node); + } else { + clientsSubTable.removeAllSubscriptionsFor(node); + } + } + + @Override + public final void notifyNeighborAdded(NodeDescriptor node) { + if (node.isClient()) { + allValidAdvertisements.forEach(advPkt -> { + try { + overlay.send(AdvertisementPacket.subject, advPkt, node); + } catch (IOException | NotRunningException e) { + e.printStackTrace(); + } + }); + } + } + + @Override + public final void notifyNeighborDead(NodeDescriptor node) { + reactToRemovedNeighbor(node); + } + + @Override + public final void notifyNeighborRemoved(NodeDescriptor node) { + reactToRemovedNeighbor(node); + } } diff --git a/Dream2/src/main/java/dream/server/ServerLauncher.java b/Dream2/src/main/java/dream/server/ServerLauncher.java index 8cf53c9..40927be 100755 --- a/Dream2/src/main/java/dream/server/ServerLauncher.java +++ b/Dream2/src/main/java/dream/server/ServerLauncher.java @@ -20,56 +20,56 @@ import polimi.reds.broker.routing.GenericRouter; public class ServerLauncher implements NeighborhoodChangeListener { - private static ServerLauncher launcher; + private static ServerLauncher launcher; - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - private final Overlay overlay; + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + private final Overlay overlay; - private ServerLauncher() { - final Transport tr = new TCPTransport(Consts.serverPort); - final TopologyManager tm = new SimpleTopologyManager(); - overlay = new GenericOverlay(tm, tr); - final GenericRouter router = new GenericRouter(overlay); - final ServerEventForwarder forwarder = new ServerEventForwarder(); - overlay.addNeighborhoodChangeListener(forwarder); - router.setPacketForwarder(EventPacket.subject, forwarder); - router.setPacketForwarder(SubscriptionPacket.subject, forwarder); - router.setPacketForwarder(AdvertisementPacket.subject, forwarder); - overlay.addNeighborhoodChangeListener(this); - } + private ServerLauncher() { + final Transport tr = new TCPTransport(Consts.serverPort); + final TopologyManager tm = new SimpleTopologyManager(); + overlay = new GenericOverlay(tm, tr); + final GenericRouter router = new GenericRouter(overlay); + final ServerEventForwarder forwarder = new ServerEventForwarder(overlay); + overlay.addNeighborhoodChangeListener(forwarder); + router.setPacketForwarder(EventPacket.subject, forwarder); + router.setPacketForwarder(SubscriptionPacket.subject, forwarder); + router.setPacketForwarder(AdvertisementPacket.subject, forwarder); + overlay.addNeighborhoodChangeListener(this); + } - public static final void start() { - if (launcher == null) { - launcher = new ServerLauncher(); - } - launcher.logger.info("Starting server"); - launcher.overlay.start(); - } + public static final void start() { + if (launcher == null) { + launcher = new ServerLauncher(); + } + launcher.logger.info("Starting server"); + launcher.overlay.start(); + } - public static final void stop() { - if (launcher != null) { - launcher.logger.info("Stopping server"); - launcher.overlay.stop(); - } - } + public static final void stop() { + if (launcher != null) { + launcher.logger.info("Stopping server"); + launcher.overlay.stop(); + } + } - @Override - public void notifyNeighborAdded(NodeDescriptor sender) { - try { - overlay.send(ServerHelloPacket.subject, new ServerHelloPacket(), sender); - } catch (IOException | NotRunningException e) { - e.printStackTrace(); - } - } + @Override + public void notifyNeighborAdded(NodeDescriptor sender) { + try { + overlay.send(ServerHelloPacket.subject, new ServerHelloPacket(), sender); + } catch (IOException | NotRunningException e) { + e.printStackTrace(); + } + } - @Override - public void notifyNeighborDead(NodeDescriptor sender) { - // Nothing to do - } + @Override + public void notifyNeighborDead(NodeDescriptor sender) { + // Nothing to do + } - @Override - public void notifyNeighborRemoved(NodeDescriptor sender) { - // Nothing to do - } + @Override + public void notifyNeighborRemoved(NodeDescriptor sender) { + // Nothing to do + } } diff --git a/Dream2/src/main/java/dream/server/SubscriptionTable.java b/Dream2/src/main/java/dream/server/SubscriptionTable.java index af62b4c..d8bb787 100755 --- a/Dream2/src/main/java/dream/server/SubscriptionTable.java +++ b/Dream2/src/main/java/dream/server/SubscriptionTable.java @@ -10,51 +10,51 @@ import polimi.reds.NodeDescriptor; final class SubscriptionTable { - private final Map>> subs = new HashMap<>(); - - final void addSubscription(NodeDescriptor node, Subscription sub) { - Collection> subsList = subs.get(node); - if (subsList == null) { - subsList = new ArrayList>(); - subs.put(node, subsList); - } - subsList.add(sub); - } - - final void removeSubscription(NodeDescriptor node, Subscription sub) { - final Collection> subsList = subs.get(node); - if (subsList == null) { - return; - } - subsList.remove(sub); - if (subsList.isEmpty()) { - subs.remove(node); - } - } - - final Map getMatchingNodes(Event ev) { - final Map result = new HashMap(); - for (final NodeDescriptor node : subs.keySet()) { - int count = 0; - for (final Subscription sub : subs.get(node)) { - if (sub.isSatisfiedBy(ev)) { - count++; - } - } - if (count != 0) { - result.put(node, count); - } - } - return result; - } - - final void removeAllSubscriptionsFor(NodeDescriptor node) { - subs.remove(node); - } - - @Override - public String toString() { - return "SubscriptionTable [subs=" + subs + "]"; - } + private final Map>> subs = new HashMap<>(); + + final void addSubscription(NodeDescriptor node, Subscription sub) { + Collection> subsList = subs.get(node); + if (subsList == null) { + subsList = new ArrayList>(); + subs.put(node, subsList); + } + subsList.add(sub); + } + + final void removeSubscription(NodeDescriptor node, Subscription sub) { + final Collection> subsList = subs.get(node); + if (subsList == null) { + return; + } + subsList.remove(sub); + if (subsList.isEmpty()) { + subs.remove(node); + } + } + + final Map getMatchingNodes(Event ev) { + final Map result = new HashMap(); + for (final NodeDescriptor node : subs.keySet()) { + int count = 0; + for (final Subscription sub : subs.get(node)) { + if (sub.isSatisfiedBy(ev)) { + count++; + } + } + if (count != 0) { + result.put(node, count); + } + } + return result; + } + + final void removeAllSubscriptionsFor(NodeDescriptor node) { + subs.remove(node); + } + + @Override + public String toString() { + return "SubscriptionTable [subs=" + subs + "]"; + } } diff --git a/Dream2/src/resources/dream/examples/chat/License.txt b/Dream2/src/resources/dream/examples/chat/License.txt new file mode 100644 index 0000000..741a409 --- /dev/null +++ b/Dream2/src/resources/dream/examples/chat/License.txt @@ -0,0 +1,2 @@ +Owner: http://p.yusukekamiyamane.com/ +License: http://creativecommons.org/licenses/by/3.0/ \ No newline at end of file diff --git a/Dream2/src/resources/dream/examples/chat/status-busy.png b/Dream2/src/resources/dream/examples/chat/status-busy.png new file mode 100644 index 0000000..a9d5f4d Binary files /dev/null and b/Dream2/src/resources/dream/examples/chat/status-busy.png differ diff --git a/Dream2/src/resources/dream/examples/chat/status-offline.png b/Dream2/src/resources/dream/examples/chat/status-offline.png new file mode 100644 index 0000000..f148af4 Binary files /dev/null and b/Dream2/src/resources/dream/examples/chat/status-offline.png differ diff --git a/Dream2/src/resources/dream/examples/chat/status-online.png b/Dream2/src/resources/dream/examples/chat/status-online.png new file mode 100644 index 0000000..680bb8a Binary files /dev/null and b/Dream2/src/resources/dream/examples/chat/status-online.png differ diff --git a/Dream2/src/test/java/dream/LocalTest.java b/Dream2/src/test/java/dream/LocalTest.java index 8d8a13d..bdd6b03 100755 --- a/Dream2/src/test/java/dream/LocalTest.java +++ b/Dream2/src/test/java/dream/LocalTest.java @@ -11,76 +11,80 @@ import dream.server.ServerLauncher; public class LocalTest { - private boolean serverStarted = false; - private final boolean lockManagerStarted = false; + private boolean serverStarted = false; + private final boolean lockManagerStarted = false; - @Test - public void localTest1() { - startServerIfNeeded(); - startTokenServiceIfNeeded(); + @Test + public void localTest1() { + startServerIfNeeded(); + startTokenServiceIfNeeded(); - DependencyGraph.instance.clear(); + DependencyGraph.instance.clear(); - final Var varInt = new Var<>("varInt", Integer.valueOf(1)); - final Var varString1 = new Var<>("varString1", ""); - final Var varString2 = new Var<>("varString2", ""); + final Var varInt = new Var<>("varInt", Integer.valueOf(1)); + final Var varString1 = new Var<>("varString1", ""); + final Var varString2 = new Var<>("varString2", ""); - final Signal signalInt = new Signal("signalInt", () -> 10 - 2 + (varInt.get() * 2 + varInt.get()) / 2, varInt); - final Signal signalString = new Signal("signalString", () -> varString1.get() + varString2.get(), varString1, varString2); - final Signal signalInt2 = new Signal("signalInt2", () -> signalInt.get() * 2, signalInt); + final Signal signalInt = new Signal("signalInt", + () -> 10 - 2 + (varInt.get() * 2 + varInt.get()) / 2, varInt); + final Signal signalString = new Signal("signalString", + () -> varString1.get() + varString2.get(), varString1, varString2); + final Signal signalInt2 = new Signal("signalInt2", () -> signalInt.get() * 2, signalInt); - final Var varStart = new Var<>("varStart", Integer.valueOf(1)); - final Signal signalMid1 = new Signal("signalMid1", () -> varStart.get() * 2, varStart); - final Signal signalMid2 = new Signal("signalMid2", () -> signalMid1.get() * 2, signalMid1); - final Signal signalFinal = new Signal("signalFinal", () -> signalMid1.get() + signalMid2.get(), signalMid1, signalMid2); - final Signal signalFinal2 = new Signal("signalFinal2", () -> signalMid1.get() + varStart.get(), signalMid1, varStart); + final Var varStart = new Var<>("varStart", Integer.valueOf(1)); + final Signal signalMid1 = new Signal("signalMid1", () -> varStart.get() * 2, varStart); + final Signal signalMid2 = new Signal("signalMid2", () -> signalMid1.get() * 2, signalMid1); + final Signal signalFinal = new Signal("signalFinal", + () -> signalMid1.get() + signalMid2.get(), signalMid1, signalMid2); + final Signal signalFinal2 = new Signal("signalFinal2", + () -> signalMid1.get() + varStart.get(), signalMid1, varStart); - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } - varInt.set(100); - varString1.set("Hello "); - varString2.set("World!"); - varStart.set(100); + varInt.set(100); + varString1.set("Hello "); + varString2.set("World!"); + varStart.set(100); - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } - assertEquals(signalInt.get(), Integer.valueOf(158)); - assertEquals(signalString.get(), "Hello World!"); - assertEquals(signalInt2.get(), Integer.valueOf(316)); - assertEquals(signalMid1.get(), Integer.valueOf(200)); - assertEquals(signalMid2.get(), Integer.valueOf(400)); - assertEquals(signalFinal.get(), Integer.valueOf(600)); - assertEquals(signalFinal2.get(), Integer.valueOf(300)); - } + assertEquals(signalInt.get(), Integer.valueOf(158)); + assertEquals(signalString.get(), "Hello World!"); + assertEquals(signalInt2.get(), Integer.valueOf(316)); + assertEquals(signalMid1.get(), Integer.valueOf(200)); + assertEquals(signalMid2.get(), Integer.valueOf(400)); + assertEquals(signalFinal.get(), Integer.valueOf(600)); + assertEquals(signalFinal2.get(), Integer.valueOf(300)); + } - private final void startServerIfNeeded() { - if (!serverStarted) { - ServerLauncher.start(); - serverStarted = true; - } - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } + private final void startServerIfNeeded() { + if (!serverStarted) { + ServerLauncher.start(); + serverStarted = true; + } + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } - private final void startTokenServiceIfNeeded() { - if (!lockManagerStarted) { - LockManagerLauncher.start(); - } - try { - Thread.sleep(500); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } + private final void startTokenServiceIfNeeded() { + if (!lockManagerStarted) { + LockManagerLauncher.start(); + } + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } } diff --git a/Dream2/src/test/java/dream/RegressionTests.java b/Dream2/src/test/java/dream/RegressionTests.java index 382b386..e4cbb25 100755 --- a/Dream2/src/test/java/dream/RegressionTests.java +++ b/Dream2/src/test/java/dream/RegressionTests.java @@ -12,13 +12,13 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ // - IntraSourceDependencyDetectorTest.class, // - DependencyGraphUtilsTest.class, // - CompleteGlitchFreeDependencyDetectorTest.class, // - AtomicDependencyDetectorTest.class, // - FinalNodesDetectorTest.class, // - LockManagerTest.class, // - LocalTest.class }) + IntraSourceDependencyDetectorTest.class, // + DependencyGraphUtilsTest.class, // + CompleteGlitchFreeDependencyDetectorTest.class, // + AtomicDependencyDetectorTest.class, // + FinalNodesDetectorTest.class, // + LockManagerTest.class, // + LocalTest.class }) public class RegressionTests { diff --git a/Dream2/src/test/java/dream/UnknownVar.java b/Dream2/src/test/java/dream/UnknownVar.java new file mode 100644 index 0000000..7dd1a37 --- /dev/null +++ b/Dream2/src/test/java/dream/UnknownVar.java @@ -0,0 +1,56 @@ +package dream; + +import org.junit.BeforeClass; +import org.junit.Test; + +import dream.client.RemoteVar; +import dream.client.Signal; +import dream.locking.LockManagerLauncher; +import dream.server.ServerLauncher; + +public class UnknownVar { + + private static boolean serverStarted = false; + private final static boolean lockManagerStarted = false; + + @BeforeClass + public static void setup() { + startServerIfNeeded(); + startTokenServiceIfNeeded(); + } + + @Test + public void testUnknownVar() { + RemoteVar listener = new RemoteVar("Server", "Variable"); + Signal listenerSignal = new Signal("listener", () -> { + if (listener.get() == null) + return ""; + else + return listener.get(); + } , listener); + listenerSignal.change().addHandler((o, n) -> System.out.println(o + "->" + n)); + } + + private final static void startServerIfNeeded() { + if (!serverStarted) { + ServerLauncher.start(); + serverStarted = true; + } + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + + private final static void startTokenServiceIfNeeded() { + if (!lockManagerStarted) { + LockManagerLauncher.start(); + } + try { + Thread.sleep(500); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/Dream2/src/test/java/dream/common/utils/AtomicDependencyDetectorTest.java b/Dream2/src/test/java/dream/common/utils/AtomicDependencyDetectorTest.java index 266ba3e..090a3c4 100644 --- a/Dream2/src/test/java/dream/common/utils/AtomicDependencyDetectorTest.java +++ b/Dream2/src/test/java/dream/common/utils/AtomicDependencyDetectorTest.java @@ -13,98 +13,97 @@ public class AtomicDependencyDetectorTest { - @Test - public void test1() { - final DependencyGraph graph = DependencyGraph.instance; - graph.clear(); - final AtomicDependencyDetector depDetector = new AtomicDependencyDetector(); - - graph.processAdv(new Advertisement("host", "A")); - depDetector.consolidate(); - assertEquals(1, depDetector.getNodesToLockFor("A@host").size()); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); - - final Set> subsB = new HashSet<>(); - subsB.add(new Subscription<>("host", "A")); - graph.processAdv(new Advertisement("host", "B"), subsB); - depDetector.consolidate(); - assertEquals(2, depDetector.getNodesToLockFor("A@host").size()); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("B@host")); - - final Set> subsC = new HashSet<>(); - subsC.add(new Subscription<>("host", "A")); - graph.processAdv(new Advertisement("host", "C"), subsC); - depDetector.consolidate(); - assertEquals(3, depDetector.getNodesToLockFor("A@host").size()); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("C@host")); - - final Set> subsD = new HashSet<>(); - subsD.add(new Subscription<>("host", "B")); - subsD.add(new Subscription<>("host", "C")); - graph.processAdv(new Advertisement("host", "D"), subsD); - depDetector.consolidate(); - assertEquals(4, depDetector.getNodesToLockFor("A@host").size()); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("C@host")); - assertTrue(depDetector.getNodesToLockFor("A@host").contains("D@host")); - } - - @Test - public void test2() { - final DependencyGraph graph = DependencyGraph.instance; - graph.clear(); - final AtomicDependencyDetector depDetector = new AtomicDependencyDetector(); - - graph.processAdv(new Advertisement("host", "A1")); - graph.processAdv(new Advertisement("host", "A2")); - depDetector.consolidate(); - assertEquals(1, depDetector.getNodesToLockFor("A1@host").size()); - assertEquals(1, depDetector.getNodesToLockFor("A2@host").size()); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); - - final Set> subsB = new HashSet<>(); - subsB.add(new Subscription<>("host", "A1")); - subsB.add(new Subscription<>("host", "A2")); - graph.processAdv(new Advertisement("host", "B"), subsB); - depDetector.consolidate(); - assertEquals(2, depDetector.getNodesToLockFor("A1@host").size()); - assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); - - final Set> subsC = new HashSet<>(); - subsC.add(new Subscription<>("host", "A1")); - graph.processAdv(new Advertisement("host", "C"), subsC); - depDetector.consolidate(); - assertEquals(3, depDetector.getNodesToLockFor("A1@host").size()); - assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); - - final Set> subsD = new HashSet<>(); - subsD.add(new Subscription<>("host", "B")); - subsD.add(new Subscription<>("host", "C")); - graph.processAdv(new Advertisement("host", "D"), subsD); - depDetector.consolidate(); - assertEquals(4, depDetector.getNodesToLockFor("A1@host").size()); - assertEquals(3, depDetector.getNodesToLockFor("A2@host").size()); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("D@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("D@host")); - } - + @Test + public void test1() { + final DependencyGraph graph = DependencyGraph.instance; + graph.clear(); + final AtomicDependencyDetector depDetector = new AtomicDependencyDetector(); + + graph.processAdv(new Advertisement("host", "A")); + depDetector.consolidate(); + assertEquals(1, depDetector.getNodesToLockFor("A@host").size()); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); + + final Set> subsB = new HashSet<>(); + subsB.add(new Subscription<>("host", "A")); + graph.processAdv(new Advertisement("host", "B"), subsB); + depDetector.consolidate(); + assertEquals(2, depDetector.getNodesToLockFor("A@host").size()); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("B@host")); + + final Set> subsC = new HashSet<>(); + subsC.add(new Subscription<>("host", "A")); + graph.processAdv(new Advertisement("host", "C"), subsC); + depDetector.consolidate(); + assertEquals(3, depDetector.getNodesToLockFor("A@host").size()); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("C@host")); + + final Set> subsD = new HashSet<>(); + subsD.add(new Subscription<>("host", "B")); + subsD.add(new Subscription<>("host", "C")); + graph.processAdv(new Advertisement("host", "D"), subsD); + depDetector.consolidate(); + assertEquals(4, depDetector.getNodesToLockFor("A@host").size()); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("A@host")); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("C@host")); + assertTrue(depDetector.getNodesToLockFor("A@host").contains("D@host")); + } + + @Test + public void test2() { + final DependencyGraph graph = DependencyGraph.instance; + graph.clear(); + final AtomicDependencyDetector depDetector = new AtomicDependencyDetector(); + + graph.processAdv(new Advertisement("host", "A1")); + graph.processAdv(new Advertisement("host", "A2")); + depDetector.consolidate(); + assertEquals(1, depDetector.getNodesToLockFor("A1@host").size()); + assertEquals(1, depDetector.getNodesToLockFor("A2@host").size()); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); + + final Set> subsB = new HashSet<>(); + subsB.add(new Subscription<>("host", "A1")); + subsB.add(new Subscription<>("host", "A2")); + graph.processAdv(new Advertisement("host", "B"), subsB); + depDetector.consolidate(); + assertEquals(2, depDetector.getNodesToLockFor("A1@host").size()); + assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); + + final Set> subsC = new HashSet<>(); + subsC.add(new Subscription<>("host", "A1")); + graph.processAdv(new Advertisement("host", "C"), subsC); + depDetector.consolidate(); + assertEquals(3, depDetector.getNodesToLockFor("A1@host").size()); + assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); + + final Set> subsD = new HashSet<>(); + subsD.add(new Subscription<>("host", "B")); + subsD.add(new Subscription<>("host", "C")); + graph.processAdv(new Advertisement("host", "D"), subsD); + depDetector.consolidate(); + assertEquals(4, depDetector.getNodesToLockFor("A1@host").size()); + assertEquals(3, depDetector.getNodesToLockFor("A2@host").size()); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("A1@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("A2@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("D@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("D@host")); + } } diff --git a/Dream2/src/test/java/dream/common/utils/CompleteGlitchFreeDependencyDetectorTest.java b/Dream2/src/test/java/dream/common/utils/CompleteGlitchFreeDependencyDetectorTest.java index 841bfe3..0dd95c8 100644 --- a/Dream2/src/test/java/dream/common/utils/CompleteGlitchFreeDependencyDetectorTest.java +++ b/Dream2/src/test/java/dream/common/utils/CompleteGlitchFreeDependencyDetectorTest.java @@ -13,140 +13,139 @@ public class CompleteGlitchFreeDependencyDetectorTest { - @Test - public void test1() { - final DependencyGraph graph = DependencyGraph.instance; - graph.clear(); - final CompleteGlitchFreeDependencyDetector depDetector = new CompleteGlitchFreeDependencyDetector(); - - graph.processAdv(new Advertisement("host", "A")); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); - - final Set> subsB = new HashSet<>(); - subsB.add(new Subscription<>("host", "A")); - graph.processAdv(new Advertisement("host", "B"), subsB); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - - final Set> subsC = new HashSet<>(); - subsC.add(new Subscription<>("host", "A")); - graph.processAdv(new Advertisement("host", "C"), subsC); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); - - final Set> subsD = new HashSet<>(); - subsD.add(new Subscription<>("host", "B")); - subsD.add(new Subscription<>("host", "C")); - graph.processAdv(new Advertisement("host", "D"), subsD); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("D@host").isEmpty()); - } - - @Test - public void test2() { - final DependencyGraph graph = DependencyGraph.instance; - graph.clear(); - final CompleteGlitchFreeDependencyDetector depDetector = new CompleteGlitchFreeDependencyDetector(); - - graph.processAdv(new Advertisement("host", "A1")); - graph.processAdv(new Advertisement("host", "A2")); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); - - final Set> subsB = new HashSet<>(); - subsB.add(new Subscription<>("host", "A1")); - subsB.add(new Subscription<>("host", "A2")); - graph.processAdv(new Advertisement("host", "B"), subsB); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - - final Set> subsC = new HashSet<>(); - subsC.add(new Subscription<>("host", "A1")); - graph.processAdv(new Advertisement("host", "C"), subsC); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); - - final Set> subsD = new HashSet<>(); - subsD.add(new Subscription<>("host", "B")); - subsD.add(new Subscription<>("host", "C")); - graph.processAdv(new Advertisement("host", "D"), subsD); - depDetector.consolidate(); - assertEquals(2, depDetector.getNodesToLockFor("A1@host").size()); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("D@host")); - assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("D@host")); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("D@host").isEmpty()); - } - - @Test - public void test3() { - final DependencyGraph graph = DependencyGraph.instance; - graph.clear(); - final CompleteGlitchFreeDependencyDetector depDetector = new CompleteGlitchFreeDependencyDetector(); - - graph.processAdv(new Advertisement("host", "A1")); - graph.processAdv(new Advertisement("host", "A2")); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); - - final Set> subsB = new HashSet<>(); - subsB.add(new Subscription<>("host", "A1")); - subsB.add(new Subscription<>("host", "A2")); - graph.processAdv(new Advertisement("host", "B"), subsB); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - - final Set> subsC = new HashSet<>(); - subsC.add(new Subscription<>("host", "A1")); - subsC.add(new Subscription<>("host", "A2")); - graph.processAdv(new Advertisement("host", "C"), subsC); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); - assertEquals(2, depDetector.getNodesToLockFor("A1@host").size()); - assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("C@host")); - - final Set> subsD = new HashSet<>(); - subsD.add(new Subscription<>("host", "B")); - subsD.add(new Subscription<>("host", "C")); - graph.processAdv(new Advertisement("host", "D"), subsD); - depDetector.consolidate(); - assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); - assertTrue(depDetector.getNodesToLockFor("D@host").isEmpty()); - assertEquals(3, depDetector.getNodesToLockFor("A1@host").size()); - assertEquals(3, depDetector.getNodesToLockFor("A2@host").size()); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); - assertTrue(depDetector.getNodesToLockFor("A1@host").contains("D@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("C@host")); - assertTrue(depDetector.getNodesToLockFor("A2@host").contains("D@host")); - - } + @Test + public void test1() { + final DependencyGraph graph = DependencyGraph.instance; + graph.clear(); + final CompleteGlitchFreeDependencyDetector depDetector = new CompleteGlitchFreeDependencyDetector(); + + graph.processAdv(new Advertisement("host", "A")); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); + + final Set> subsB = new HashSet<>(); + subsB.add(new Subscription<>("host", "A")); + graph.processAdv(new Advertisement("host", "B"), subsB); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + + final Set> subsC = new HashSet<>(); + subsC.add(new Subscription<>("host", "A")); + graph.processAdv(new Advertisement("host", "C"), subsC); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); + + final Set> subsD = new HashSet<>(); + subsD.add(new Subscription<>("host", "B")); + subsD.add(new Subscription<>("host", "C")); + graph.processAdv(new Advertisement("host", "D"), subsD); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("D@host").isEmpty()); + } + + @Test + public void test2() { + final DependencyGraph graph = DependencyGraph.instance; + graph.clear(); + final CompleteGlitchFreeDependencyDetector depDetector = new CompleteGlitchFreeDependencyDetector(); + + graph.processAdv(new Advertisement("host", "A1")); + graph.processAdv(new Advertisement("host", "A2")); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); + + final Set> subsB = new HashSet<>(); + subsB.add(new Subscription<>("host", "A1")); + subsB.add(new Subscription<>("host", "A2")); + graph.processAdv(new Advertisement("host", "B"), subsB); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + + final Set> subsC = new HashSet<>(); + subsC.add(new Subscription<>("host", "A1")); + graph.processAdv(new Advertisement("host", "C"), subsC); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); + + final Set> subsD = new HashSet<>(); + subsD.add(new Subscription<>("host", "B")); + subsD.add(new Subscription<>("host", "C")); + graph.processAdv(new Advertisement("host", "D"), subsD); + depDetector.consolidate(); + assertEquals(2, depDetector.getNodesToLockFor("A1@host").size()); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("D@host")); + assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("D@host")); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("D@host").isEmpty()); + } + + @Test + public void test3() { + final DependencyGraph graph = DependencyGraph.instance; + graph.clear(); + final CompleteGlitchFreeDependencyDetector depDetector = new CompleteGlitchFreeDependencyDetector(); + + graph.processAdv(new Advertisement("host", "A1")); + graph.processAdv(new Advertisement("host", "A2")); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); + + final Set> subsB = new HashSet<>(); + subsB.add(new Subscription<>("host", "A1")); + subsB.add(new Subscription<>("host", "A2")); + graph.processAdv(new Advertisement("host", "B"), subsB); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("A1@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("A2@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + + final Set> subsC = new HashSet<>(); + subsC.add(new Subscription<>("host", "A1")); + subsC.add(new Subscription<>("host", "A2")); + graph.processAdv(new Advertisement("host", "C"), subsC); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); + assertEquals(2, depDetector.getNodesToLockFor("A1@host").size()); + assertEquals(2, depDetector.getNodesToLockFor("A2@host").size()); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("C@host")); + + final Set> subsD = new HashSet<>(); + subsD.add(new Subscription<>("host", "B")); + subsD.add(new Subscription<>("host", "C")); + graph.processAdv(new Advertisement("host", "D"), subsD); + depDetector.consolidate(); + assertTrue(depDetector.getNodesToLockFor("B@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("C@host").isEmpty()); + assertTrue(depDetector.getNodesToLockFor("D@host").isEmpty()); + assertEquals(3, depDetector.getNodesToLockFor("A1@host").size()); + assertEquals(3, depDetector.getNodesToLockFor("A2@host").size()); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("C@host")); + assertTrue(depDetector.getNodesToLockFor("A1@host").contains("D@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("B@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("C@host")); + assertTrue(depDetector.getNodesToLockFor("A2@host").contains("D@host")); + } } diff --git a/Dream2/src/test/java/dream/common/utils/DependencyGraphUtilsTest.java b/Dream2/src/test/java/dream/common/utils/DependencyGraphUtilsTest.java index 1e2a60c..e068539 100644 --- a/Dream2/src/test/java/dream/common/utils/DependencyGraphUtilsTest.java +++ b/Dream2/src/test/java/dream/common/utils/DependencyGraphUtilsTest.java @@ -14,224 +14,223 @@ public class DependencyGraphUtilsTest { - @Test - public void test1() { - final DependencyGraph graph = DependencyGraph.instance; - graph.clear(); - - assertTrue(DependencyGraphUtils.computeRelevantSources().isEmpty()); - assertTrue(DependencyGraphUtils.computeDependencyClosure().isEmpty()); - - graph.processAdv(new Advertisement("host", "A")); - - Map> relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(1, relevantSources.size()); - assertTrue(relevantSources.containsKey("A@host")); - assertTrue(relevantSources.get("A@host").contains("A@host")); - - Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(1, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A@host")); - assertEquals(1, dependencyClosure.get("A@host").size()); - assertTrue(dependencyClosure.get("A@host").contains("A@host")); - - final Set> subsB = new HashSet<>(); - subsB.add(new Subscription<>("host", "A")); - graph.processAdv(new Advertisement("host", "B"), subsB); - - relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(2, relevantSources.size()); - assertTrue(relevantSources.containsKey("A@host")); - assertEquals(1, relevantSources.get("A@host").size()); - assertTrue(relevantSources.get("A@host").contains("A@host")); - assertTrue(relevantSources.containsKey("B@host")); - assertEquals(1, relevantSources.get("B@host").size()); - assertTrue(relevantSources.get("B@host").contains("A@host")); - - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(1, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A@host")); - assertEquals(2, dependencyClosure.get("A@host").size()); - assertTrue(dependencyClosure.get("A@host").contains("A@host")); - assertTrue(dependencyClosure.get("A@host").contains("B@host")); - - final Set> subsC = new HashSet<>(); - subsC.add(new Subscription<>("host", "A")); - graph.processAdv(new Advertisement("host", "C"), subsC); - - relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(3, relevantSources.size()); - assertTrue(relevantSources.containsKey("A@host")); - assertTrue(relevantSources.containsKey("B@host")); - assertTrue(relevantSources.containsKey("C@host")); - assertEquals(1, relevantSources.get("A@host").size()); - assertEquals(1, relevantSources.get("B@host").size()); - assertEquals(1, relevantSources.get("C@host").size()); - assertTrue(relevantSources.get("B@host").contains("A@host")); - assertTrue(relevantSources.get("C@host").contains("A@host")); - - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(1, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A@host")); - assertEquals(3, dependencyClosure.get("A@host").size()); - assertTrue(dependencyClosure.get("A@host").contains("A@host")); - assertTrue(dependencyClosure.get("A@host").contains("B@host")); - assertTrue(dependencyClosure.get("A@host").contains("C@host")); - - final Set> subsD = new HashSet<>(); - subsD.add(new Subscription<>("host", "B")); - subsD.add(new Subscription<>("host", "C")); - graph.processAdv(new Advertisement("host", "D"), subsD); - - relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(4, relevantSources.size()); - assertTrue(relevantSources.containsKey("A@host")); - assertTrue(relevantSources.containsKey("B@host")); - assertTrue(relevantSources.containsKey("C@host")); - assertTrue(relevantSources.containsKey("D@host")); - assertEquals(1, relevantSources.get("A@host").size()); - assertEquals(1, relevantSources.get("B@host").size()); - assertEquals(1, relevantSources.get("C@host").size()); - assertEquals(1, relevantSources.get("D@host").size()); - assertTrue(relevantSources.get("A@host").contains("A@host")); - assertTrue(relevantSources.get("B@host").contains("A@host")); - assertTrue(relevantSources.get("C@host").contains("A@host")); - assertTrue(relevantSources.get("D@host").contains("A@host")); - - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(1, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A@host")); - assertEquals(4, dependencyClosure.get("A@host").size()); - assertTrue(dependencyClosure.get("A@host").contains("A@host")); - assertTrue(dependencyClosure.get("A@host").contains("B@host")); - assertTrue(dependencyClosure.get("A@host").contains("C@host")); - assertTrue(dependencyClosure.get("A@host").contains("D@host")); - - } - - @Test - public void test2() { - final DependencyGraph graph = DependencyGraph.instance; - graph.clear(); - - assertTrue(DependencyGraphUtils.computeRelevantSources().isEmpty()); - assertTrue(DependencyGraphUtils.computeDependencyClosure().isEmpty()); - - graph.processAdv(new Advertisement("host", "A1")); - graph.processAdv(new Advertisement("host", "A2")); - - Map> relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(2, relevantSources.size()); - assertTrue(relevantSources.containsKey("A1@host")); - assertTrue(relevantSources.get("A1@host").contains("A1@host")); - assertTrue(relevantSources.containsKey("A2@host")); - assertTrue(relevantSources.get("A2@host").contains("A2@host")); - - Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(2, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A1@host")); - assertEquals(1, dependencyClosure.get("A1@host").size()); - assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); - assertTrue(dependencyClosure.containsKey("A2@host")); - assertEquals(1, dependencyClosure.get("A2@host").size()); - assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); - - final Set> subsB = new HashSet<>(); - subsB.add(new Subscription<>("host", "A1")); - subsB.add(new Subscription<>("host", "A2")); - graph.processAdv(new Advertisement("host", "B"), subsB); - - relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(3, relevantSources.size()); - assertTrue(relevantSources.containsKey("A1@host")); - assertEquals(1, relevantSources.get("A1@host").size()); - assertTrue(relevantSources.get("A1@host").contains("A1@host")); - assertTrue(relevantSources.containsKey("A2@host")); - assertEquals(1, relevantSources.get("A2@host").size()); - assertTrue(relevantSources.get("A2@host").contains("A2@host")); - assertTrue(relevantSources.containsKey("B@host")); - assertEquals(2, relevantSources.get("B@host").size()); - assertTrue(relevantSources.get("B@host").contains("A1@host")); - assertTrue(relevantSources.get("B@host").contains("A2@host")); - - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(2, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A1@host")); - assertEquals(2, dependencyClosure.get("A1@host").size()); - assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); - assertTrue(dependencyClosure.get("A1@host").contains("B@host")); - assertTrue(dependencyClosure.containsKey("A2@host")); - assertEquals(2, dependencyClosure.get("A2@host").size()); - assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); - assertTrue(dependencyClosure.get("A2@host").contains("B@host")); - - final Set> subsC = new HashSet<>(); - subsC.add(new Subscription<>("host", "A1")); - graph.processAdv(new Advertisement("host", "C"), subsC); - - relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(4, relevantSources.size()); - assertTrue(relevantSources.containsKey("A1@host")); - assertTrue(relevantSources.containsKey("A2@host")); - assertTrue(relevantSources.containsKey("B@host")); - assertTrue(relevantSources.containsKey("C@host")); - assertEquals(1, relevantSources.get("A1@host").size()); - assertEquals(1, relevantSources.get("A2@host").size()); - assertEquals(2, relevantSources.get("B@host").size()); - assertEquals(1, relevantSources.get("C@host").size()); - assertTrue(relevantSources.get("B@host").contains("A1@host")); - assertTrue(relevantSources.get("B@host").contains("A2@host")); - assertTrue(relevantSources.get("C@host").contains("A1@host")); - - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(2, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A1@host")); - assertTrue(dependencyClosure.containsKey("A2@host")); - assertEquals(3, dependencyClosure.get("A1@host").size()); - assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); - assertTrue(dependencyClosure.get("A1@host").contains("B@host")); - assertTrue(dependencyClosure.get("A1@host").contains("C@host")); - assertEquals(2, dependencyClosure.get("A2@host").size()); - assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); - assertTrue(dependencyClosure.get("A2@host").contains("B@host")); - - final Set> subsD = new HashSet<>(); - subsD.add(new Subscription<>("host", "B")); - subsD.add(new Subscription<>("host", "C")); - graph.processAdv(new Advertisement("host", "D"), subsD); - - relevantSources = DependencyGraphUtils.computeRelevantSources(); - assertEquals(5, relevantSources.size()); - assertTrue(relevantSources.containsKey("A1@host")); - assertTrue(relevantSources.containsKey("A2@host")); - assertTrue(relevantSources.containsKey("B@host")); - assertTrue(relevantSources.containsKey("C@host")); - assertTrue(relevantSources.containsKey("D@host")); - assertEquals(1, relevantSources.get("A1@host").size()); - assertEquals(1, relevantSources.get("A2@host").size()); - assertEquals(2, relevantSources.get("B@host").size()); - assertEquals(1, relevantSources.get("C@host").size()); - assertEquals(2, relevantSources.get("D@host").size()); - assertTrue(relevantSources.get("A1@host").contains("A1@host")); - assertTrue(relevantSources.get("B@host").contains("A1@host")); - assertTrue(relevantSources.get("B@host").contains("A2@host")); - assertTrue(relevantSources.get("C@host").contains("A1@host")); - assertTrue(relevantSources.get("D@host").contains("A1@host")); - - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - assertEquals(2, dependencyClosure.size()); - assertTrue(dependencyClosure.containsKey("A1@host")); - assertTrue(dependencyClosure.containsKey("A2@host")); - assertEquals(4, dependencyClosure.get("A1@host").size()); - assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); - assertTrue(dependencyClosure.get("A1@host").contains("B@host")); - assertTrue(dependencyClosure.get("A1@host").contains("C@host")); - assertTrue(dependencyClosure.get("A1@host").contains("D@host")); - assertEquals(3, dependencyClosure.get("A2@host").size()); - assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); - assertTrue(dependencyClosure.get("A2@host").contains("B@host")); - assertTrue(dependencyClosure.get("A2@host").contains("D@host")); - - } + @Test + public void test1() { + final DependencyGraph graph = DependencyGraph.instance; + graph.clear(); + + assertTrue(DependencyGraphUtils.computeRelevantSources().isEmpty()); + assertTrue(DependencyGraphUtils.computeDependencyClosure().isEmpty()); + + graph.processAdv(new Advertisement("host", "A")); + + Map> relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(1, relevantSources.size()); + assertTrue(relevantSources.containsKey("A@host")); + assertTrue(relevantSources.get("A@host").contains("A@host")); + + Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(1, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A@host")); + assertEquals(1, dependencyClosure.get("A@host").size()); + assertTrue(dependencyClosure.get("A@host").contains("A@host")); + + final Set> subsB = new HashSet<>(); + subsB.add(new Subscription<>("host", "A")); + graph.processAdv(new Advertisement("host", "B"), subsB); + + relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(2, relevantSources.size()); + assertTrue(relevantSources.containsKey("A@host")); + assertEquals(1, relevantSources.get("A@host").size()); + assertTrue(relevantSources.get("A@host").contains("A@host")); + assertTrue(relevantSources.containsKey("B@host")); + assertEquals(1, relevantSources.get("B@host").size()); + assertTrue(relevantSources.get("B@host").contains("A@host")); + + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(1, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A@host")); + assertEquals(2, dependencyClosure.get("A@host").size()); + assertTrue(dependencyClosure.get("A@host").contains("A@host")); + assertTrue(dependencyClosure.get("A@host").contains("B@host")); + + final Set> subsC = new HashSet<>(); + subsC.add(new Subscription<>("host", "A")); + graph.processAdv(new Advertisement("host", "C"), subsC); + + relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(3, relevantSources.size()); + assertTrue(relevantSources.containsKey("A@host")); + assertTrue(relevantSources.containsKey("B@host")); + assertTrue(relevantSources.containsKey("C@host")); + assertEquals(1, relevantSources.get("A@host").size()); + assertEquals(1, relevantSources.get("B@host").size()); + assertEquals(1, relevantSources.get("C@host").size()); + assertTrue(relevantSources.get("B@host").contains("A@host")); + assertTrue(relevantSources.get("C@host").contains("A@host")); + + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(1, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A@host")); + assertEquals(3, dependencyClosure.get("A@host").size()); + assertTrue(dependencyClosure.get("A@host").contains("A@host")); + assertTrue(dependencyClosure.get("A@host").contains("B@host")); + assertTrue(dependencyClosure.get("A@host").contains("C@host")); + + final Set> subsD = new HashSet<>(); + subsD.add(new Subscription<>("host", "B")); + subsD.add(new Subscription<>("host", "C")); + graph.processAdv(new Advertisement("host", "D"), subsD); + + relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(4, relevantSources.size()); + assertTrue(relevantSources.containsKey("A@host")); + assertTrue(relevantSources.containsKey("B@host")); + assertTrue(relevantSources.containsKey("C@host")); + assertTrue(relevantSources.containsKey("D@host")); + assertEquals(1, relevantSources.get("A@host").size()); + assertEquals(1, relevantSources.get("B@host").size()); + assertEquals(1, relevantSources.get("C@host").size()); + assertEquals(1, relevantSources.get("D@host").size()); + assertTrue(relevantSources.get("A@host").contains("A@host")); + assertTrue(relevantSources.get("B@host").contains("A@host")); + assertTrue(relevantSources.get("C@host").contains("A@host")); + assertTrue(relevantSources.get("D@host").contains("A@host")); + + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(1, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A@host")); + assertEquals(4, dependencyClosure.get("A@host").size()); + assertTrue(dependencyClosure.get("A@host").contains("A@host")); + assertTrue(dependencyClosure.get("A@host").contains("B@host")); + assertTrue(dependencyClosure.get("A@host").contains("C@host")); + assertTrue(dependencyClosure.get("A@host").contains("D@host")); + + } + + @Test + public void test2() { + final DependencyGraph graph = DependencyGraph.instance; + graph.clear(); + + assertTrue(DependencyGraphUtils.computeRelevantSources().isEmpty()); + assertTrue(DependencyGraphUtils.computeDependencyClosure().isEmpty()); + + graph.processAdv(new Advertisement("host", "A1")); + graph.processAdv(new Advertisement("host", "A2")); + + Map> relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(2, relevantSources.size()); + assertTrue(relevantSources.containsKey("A1@host")); + assertTrue(relevantSources.get("A1@host").contains("A1@host")); + assertTrue(relevantSources.containsKey("A2@host")); + assertTrue(relevantSources.get("A2@host").contains("A2@host")); + + Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(2, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A1@host")); + assertEquals(1, dependencyClosure.get("A1@host").size()); + assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); + assertTrue(dependencyClosure.containsKey("A2@host")); + assertEquals(1, dependencyClosure.get("A2@host").size()); + assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); + + final Set> subsB = new HashSet<>(); + subsB.add(new Subscription<>("host", "A1")); + subsB.add(new Subscription<>("host", "A2")); + graph.processAdv(new Advertisement("host", "B"), subsB); + + relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(3, relevantSources.size()); + assertTrue(relevantSources.containsKey("A1@host")); + assertEquals(1, relevantSources.get("A1@host").size()); + assertTrue(relevantSources.get("A1@host").contains("A1@host")); + assertTrue(relevantSources.containsKey("A2@host")); + assertEquals(1, relevantSources.get("A2@host").size()); + assertTrue(relevantSources.get("A2@host").contains("A2@host")); + assertTrue(relevantSources.containsKey("B@host")); + assertEquals(2, relevantSources.get("B@host").size()); + assertTrue(relevantSources.get("B@host").contains("A1@host")); + assertTrue(relevantSources.get("B@host").contains("A2@host")); + + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(2, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A1@host")); + assertEquals(2, dependencyClosure.get("A1@host").size()); + assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); + assertTrue(dependencyClosure.get("A1@host").contains("B@host")); + assertTrue(dependencyClosure.containsKey("A2@host")); + assertEquals(2, dependencyClosure.get("A2@host").size()); + assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); + assertTrue(dependencyClosure.get("A2@host").contains("B@host")); + + final Set> subsC = new HashSet<>(); + subsC.add(new Subscription<>("host", "A1")); + graph.processAdv(new Advertisement("host", "C"), subsC); + + relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(4, relevantSources.size()); + assertTrue(relevantSources.containsKey("A1@host")); + assertTrue(relevantSources.containsKey("A2@host")); + assertTrue(relevantSources.containsKey("B@host")); + assertTrue(relevantSources.containsKey("C@host")); + assertEquals(1, relevantSources.get("A1@host").size()); + assertEquals(1, relevantSources.get("A2@host").size()); + assertEquals(2, relevantSources.get("B@host").size()); + assertEquals(1, relevantSources.get("C@host").size()); + assertTrue(relevantSources.get("B@host").contains("A1@host")); + assertTrue(relevantSources.get("B@host").contains("A2@host")); + assertTrue(relevantSources.get("C@host").contains("A1@host")); + + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(2, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A1@host")); + assertTrue(dependencyClosure.containsKey("A2@host")); + assertEquals(3, dependencyClosure.get("A1@host").size()); + assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); + assertTrue(dependencyClosure.get("A1@host").contains("B@host")); + assertTrue(dependencyClosure.get("A1@host").contains("C@host")); + assertEquals(2, dependencyClosure.get("A2@host").size()); + assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); + assertTrue(dependencyClosure.get("A2@host").contains("B@host")); + + final Set> subsD = new HashSet<>(); + subsD.add(new Subscription<>("host", "B")); + subsD.add(new Subscription<>("host", "C")); + graph.processAdv(new Advertisement("host", "D"), subsD); + + relevantSources = DependencyGraphUtils.computeRelevantSources(); + assertEquals(5, relevantSources.size()); + assertTrue(relevantSources.containsKey("A1@host")); + assertTrue(relevantSources.containsKey("A2@host")); + assertTrue(relevantSources.containsKey("B@host")); + assertTrue(relevantSources.containsKey("C@host")); + assertTrue(relevantSources.containsKey("D@host")); + assertEquals(1, relevantSources.get("A1@host").size()); + assertEquals(1, relevantSources.get("A2@host").size()); + assertEquals(2, relevantSources.get("B@host").size()); + assertEquals(1, relevantSources.get("C@host").size()); + assertEquals(2, relevantSources.get("D@host").size()); + assertTrue(relevantSources.get("A1@host").contains("A1@host")); + assertTrue(relevantSources.get("B@host").contains("A1@host")); + assertTrue(relevantSources.get("B@host").contains("A2@host")); + assertTrue(relevantSources.get("C@host").contains("A1@host")); + assertTrue(relevantSources.get("D@host").contains("A1@host")); + + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + assertEquals(2, dependencyClosure.size()); + assertTrue(dependencyClosure.containsKey("A1@host")); + assertTrue(dependencyClosure.containsKey("A2@host")); + assertEquals(4, dependencyClosure.get("A1@host").size()); + assertTrue(dependencyClosure.get("A1@host").contains("A1@host")); + assertTrue(dependencyClosure.get("A1@host").contains("B@host")); + assertTrue(dependencyClosure.get("A1@host").contains("C@host")); + assertTrue(dependencyClosure.get("A1@host").contains("D@host")); + assertEquals(3, dependencyClosure.get("A2@host").size()); + assertTrue(dependencyClosure.get("A2@host").contains("A2@host")); + assertTrue(dependencyClosure.get("A2@host").contains("B@host")); + assertTrue(dependencyClosure.get("A2@host").contains("D@host")); + } } diff --git a/Dream2/src/test/java/dream/common/utils/FinalNodesDetectorTest.java b/Dream2/src/test/java/dream/common/utils/FinalNodesDetectorTest.java index 796fadc..36caf4e 100755 --- a/Dream2/src/test/java/dream/common/utils/FinalNodesDetectorTest.java +++ b/Dream2/src/test/java/dream/common/utils/FinalNodesDetectorTest.java @@ -13,258 +13,259 @@ public class FinalNodesDetectorTest { - private static final String hostId = "hostId"; - private static final String atHostId = "@" + hostId; - - @Test - public void singleExpressionTest() { - // A - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(1, results.size()); - assertTrue(results.contains("A" + atHostId)); - } - - @Test - public void simpleDependencyTest() { - // A - // B = f(A) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(1, results.size()); - assertTrue(results.contains("B" + atHostId)); - } - - @Test - public void simpleDependencyTest2() { - // A - // B = f(A) - // C = f(B) - // D = f(C) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "B"); - generateAdvertisementPacket(finalNodesDetector, "D", "C"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(1, results.size()); - assertTrue(results.contains("D" + atHostId)); - } - - @Test - public void simpleDependencyTest3() { - // A - // B = f(A) - // C = f(A) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "A"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(2, results.size()); - assertTrue(results.contains("B" + atHostId)); - assertTrue(results.contains("C" + atHostId)); - } - - @Test - public void doubleDependencyTest() { - // A - // B = f(A) - // C = f(B) - // D = f(B) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "B"); - generateAdvertisementPacket(finalNodesDetector, "D", "B"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(2, results.size()); - assertTrue(results.contains("C" + atHostId)); - assertTrue(results.contains("C" + atHostId)); - } - - @Test - public void tripleDependencyTest() { - // A - // B = f(A) - // C = f(B) - // D = f(B) - // E = f(D) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "B"); - generateAdvertisementPacket(finalNodesDetector, "D", "B"); - generateAdvertisementPacket(finalNodesDetector, "E", "D"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(2, results.size()); - assertTrue(results.contains("C" + atHostId)); - assertTrue(results.contains("E" + atHostId)); - } - - @Test - public void treeDependencyTest() { - // A - // B = f(A) - // C = f(A) - // D = f(B) - // E = f(B) - // F = f(C) - // G = f(C) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "A"); - generateAdvertisementPacket(finalNodesDetector, "D", "B"); - generateAdvertisementPacket(finalNodesDetector, "E", "B"); - generateAdvertisementPacket(finalNodesDetector, "F", "C"); - generateAdvertisementPacket(finalNodesDetector, "G", "C"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(4, results.size()); - assertTrue(results.contains("D" + atHostId)); - assertTrue(results.contains("E" + atHostId)); - assertTrue(results.contains("F" + atHostId)); - assertTrue(results.contains("G" + atHostId)); - } - - @Test - public void treeDependencyTest2() { - // A - // B = f(A) - // C = f(A) - // D = f(B) - // E = f(B) - // F = f(C) - // G = f(C) - // H = f(G) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "A"); - generateAdvertisementPacket(finalNodesDetector, "D", "B"); - generateAdvertisementPacket(finalNodesDetector, "E", "B"); - generateAdvertisementPacket(finalNodesDetector, "F", "C"); - generateAdvertisementPacket(finalNodesDetector, "G", "C"); - generateAdvertisementPacket(finalNodesDetector, "H", "G"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(4, results.size()); - assertTrue(results.contains("D" + atHostId)); - assertTrue(results.contains("E" + atHostId)); - assertTrue(results.contains("F" + atHostId)); - assertTrue(results.contains("H" + atHostId)); - } - - @Test - public void graphDependencyTest() { - // A - // B - // C = f(A, B) - // D = f(A, B) - // E = f(C, D) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B"); - generateAdvertisementPacket(finalNodesDetector, "C", "A", "B"); - generateAdvertisementPacket(finalNodesDetector, "D", "A", "B"); - generateAdvertisementPacket(finalNodesDetector, "E", "C", "D"); - finalNodesDetector.consolidate(); - - final Set resultsA = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(1, resultsA.size()); - assertTrue(resultsA.contains("E" + atHostId)); - - final Set resultsB = finalNodesDetector.getFinalNodesFor("B" + atHostId); - assertEquals(1, resultsB.size()); - assertTrue(resultsB.contains("E" + atHostId)); - } - - @Test - public void triangularDependencyTest() { - // A - // B = f(A) - // C = f(A, B) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "A", "B"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(1, results.size()); - assertTrue(results.contains("C" + atHostId)); - } - - @Test - public void cycleDependencyTest() { - // A - // B = f(A) - // C = f(A) - // D = f(B, C) - DependencyGraph.instance.clear(); - final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); - - generateAdvertisementPacket(finalNodesDetector, "A"); - generateAdvertisementPacket(finalNodesDetector, "B", "A"); - generateAdvertisementPacket(finalNodesDetector, "C", "A"); - generateAdvertisementPacket(finalNodesDetector, "D", "B", "C"); - finalNodesDetector.consolidate(); - - final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); - assertEquals(1, results.size()); - assertTrue(results.contains("D" + atHostId)); - } - - private final void generateAdvertisementPacket(FinalNodesDetector finalNodesDetector, String name, String... subsNames) { - final Advertisement adv = new Advertisement(hostId, name); - final Set> subs = new HashSet<>(); - for (final String subName : subsNames) { - final Subscription sub = new Subscription<>(hostId, subName); - subs.add(sub); - } - if (subs.isEmpty()) { - DependencyGraph.instance.processAdv(adv); - } else { - DependencyGraph.instance.processAdv(adv, subs); - } - } + private static final String hostId = "hostId"; + private static final String atHostId = "@" + hostId; + + @Test + public void singleExpressionTest() { + // A + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(1, results.size()); + assertTrue(results.contains("A" + atHostId)); + } + + @Test + public void simpleDependencyTest() { + // A + // B = f(A) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(1, results.size()); + assertTrue(results.contains("B" + atHostId)); + } + + @Test + public void simpleDependencyTest2() { + // A + // B = f(A) + // C = f(B) + // D = f(C) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "B"); + generateAdvertisementPacket(finalNodesDetector, "D", "C"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(1, results.size()); + assertTrue(results.contains("D" + atHostId)); + } + + @Test + public void simpleDependencyTest3() { + // A + // B = f(A) + // C = f(A) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "A"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(2, results.size()); + assertTrue(results.contains("B" + atHostId)); + assertTrue(results.contains("C" + atHostId)); + } + + @Test + public void doubleDependencyTest() { + // A + // B = f(A) + // C = f(B) + // D = f(B) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "B"); + generateAdvertisementPacket(finalNodesDetector, "D", "B"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(2, results.size()); + assertTrue(results.contains("C" + atHostId)); + assertTrue(results.contains("C" + atHostId)); + } + + @Test + public void tripleDependencyTest() { + // A + // B = f(A) + // C = f(B) + // D = f(B) + // E = f(D) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "B"); + generateAdvertisementPacket(finalNodesDetector, "D", "B"); + generateAdvertisementPacket(finalNodesDetector, "E", "D"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(2, results.size()); + assertTrue(results.contains("C" + atHostId)); + assertTrue(results.contains("E" + atHostId)); + } + + @Test + public void treeDependencyTest() { + // A + // B = f(A) + // C = f(A) + // D = f(B) + // E = f(B) + // F = f(C) + // G = f(C) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "A"); + generateAdvertisementPacket(finalNodesDetector, "D", "B"); + generateAdvertisementPacket(finalNodesDetector, "E", "B"); + generateAdvertisementPacket(finalNodesDetector, "F", "C"); + generateAdvertisementPacket(finalNodesDetector, "G", "C"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(4, results.size()); + assertTrue(results.contains("D" + atHostId)); + assertTrue(results.contains("E" + atHostId)); + assertTrue(results.contains("F" + atHostId)); + assertTrue(results.contains("G" + atHostId)); + } + + @Test + public void treeDependencyTest2() { + // A + // B = f(A) + // C = f(A) + // D = f(B) + // E = f(B) + // F = f(C) + // G = f(C) + // H = f(G) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "A"); + generateAdvertisementPacket(finalNodesDetector, "D", "B"); + generateAdvertisementPacket(finalNodesDetector, "E", "B"); + generateAdvertisementPacket(finalNodesDetector, "F", "C"); + generateAdvertisementPacket(finalNodesDetector, "G", "C"); + generateAdvertisementPacket(finalNodesDetector, "H", "G"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(4, results.size()); + assertTrue(results.contains("D" + atHostId)); + assertTrue(results.contains("E" + atHostId)); + assertTrue(results.contains("F" + atHostId)); + assertTrue(results.contains("H" + atHostId)); + } + + @Test + public void graphDependencyTest() { + // A + // B + // C = f(A, B) + // D = f(A, B) + // E = f(C, D) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B"); + generateAdvertisementPacket(finalNodesDetector, "C", "A", "B"); + generateAdvertisementPacket(finalNodesDetector, "D", "A", "B"); + generateAdvertisementPacket(finalNodesDetector, "E", "C", "D"); + finalNodesDetector.consolidate(); + + final Set resultsA = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(1, resultsA.size()); + assertTrue(resultsA.contains("E" + atHostId)); + + final Set resultsB = finalNodesDetector.getFinalNodesFor("B" + atHostId); + assertEquals(1, resultsB.size()); + assertTrue(resultsB.contains("E" + atHostId)); + } + + @Test + public void triangularDependencyTest() { + // A + // B = f(A) + // C = f(A, B) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "A", "B"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(1, results.size()); + assertTrue(results.contains("C" + atHostId)); + } + + @Test + public void cycleDependencyTest() { + // A + // B = f(A) + // C = f(A) + // D = f(B, C) + DependencyGraph.instance.clear(); + final FinalNodesDetector finalNodesDetector = new FinalNodesDetector(); + + generateAdvertisementPacket(finalNodesDetector, "A"); + generateAdvertisementPacket(finalNodesDetector, "B", "A"); + generateAdvertisementPacket(finalNodesDetector, "C", "A"); + generateAdvertisementPacket(finalNodesDetector, "D", "B", "C"); + finalNodesDetector.consolidate(); + + final Set results = finalNodesDetector.getFinalNodesFor("A" + atHostId); + assertEquals(1, results.size()); + assertTrue(results.contains("D" + atHostId)); + } + + private final void generateAdvertisementPacket(FinalNodesDetector finalNodesDetector, String name, + String... subsNames) { + final Advertisement adv = new Advertisement(hostId, name); + final Set> subs = new HashSet<>(); + for (final String subName : subsNames) { + final Subscription sub = new Subscription<>(hostId, subName); + subs.add(sub); + } + if (subs.isEmpty()) { + DependencyGraph.instance.processAdv(adv); + } else { + DependencyGraph.instance.processAdv(adv, subs); + } + } } diff --git a/Dream2/src/test/java/dream/common/utils/IntraSourceDependencyDetectorTest.java b/Dream2/src/test/java/dream/common/utils/IntraSourceDependencyDetectorTest.java index 0ba8cc3..e76f161 100755 --- a/Dream2/src/test/java/dream/common/utils/IntraSourceDependencyDetectorTest.java +++ b/Dream2/src/test/java/dream/common/utils/IntraSourceDependencyDetectorTest.java @@ -14,870 +14,870 @@ public class IntraSourceDependencyDetectorTest { - @Test - public void noDependencyTest() { - // B = f(A) - // D = f(B, C) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription("Host", "A"); - final Subscription subB = new Subscription("Host", "B"); - final Subscription subC = new Subscription("Host", "C"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet<>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to B and C (B, C generate D) - final Set> subsD = new HashSet<>(); - subsD.add(subB); - subsD.add(subC); - graph.processAdv(advD, subsD); - - graph.processAdv(advA); - graph.processAdv(advC); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event<>("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA, "A@Host").size(), 0); - - // EventB - final Event evB = new Event<>("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB, "A@Host").size(), 0); - - // EventC - final Event evC = new Event<>("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC, "A@Host").size(), 0); - - // EventD - final Event evD = new Event<>("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD, "A@Host").size(), 0); - } - - @Test - public void basicTriangularCycleTest() { - // B = f(A) - // C = f(A, B) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription("Host", "A"); - final Subscription subB = new Subscription("Host", "B"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet<>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to A, B (A, B generates C) - final Set> subsC = new HashSet<>(); - subsC.add(subA); - subsC.add(subB); - graph.processAdv(advC, subsC); - - graph.processAdv(advA); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); - final Event evA2 = new Event("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evA2, "A@Host")) { - assertTrue(wr.getExpression().equals("C@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("B@Host")); - } - - // EventB - final Event evB1 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); - final Event evB2 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { - assertTrue(wr.getExpression().equals("C@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("A@Host")); - } - - // EventC - final Event evC = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC, "").size(), 0); - } - - @Test - public void basicDualCycleTest() { - // B = f(A) - // C = f(A) - // D = f(B, C) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription("Host", "A"); - final Subscription subB = new Subscription("Host", "B"); - final Subscription subC = new Subscription("Host", "C"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to A (A generates C) - final Set> subsC = new HashSet>(); - subsC.add(subA); - graph.processAdv(advC, subsC); - - // Subscription to B, C (B, C generate D) - final Set> subsD = new HashSet>(); - subsD.add(subB); - subsD.add(subC); - graph.processAdv(advD, subsD); - - graph.processAdv(advA); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); - - // EventB - final Event evB1 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); - final Event evB2 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("C@Host")); - } - - // EventC - final Event evC1 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); - final Event evC2 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("B@Host")); - } - - // EventD - final Event evD = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD, "").size(), 0); - } - - @Test - public void basicDualCycleTest2() { - // B = f(A) - // C = f(A) - // D = f(C) - // E = f(B, D) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription<>("Host", "A"); - final Subscription subB = new Subscription<>("Host", "B"); - final Subscription subC = new Subscription<>("Host", "C"); - final Subscription subD = new Subscription<>("Host", "D"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - final Advertisement advE = new Advertisement("Host", "E"); - - graph.processAdv(advA); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to A (A generates C) - final Set> subsC = new HashSet>(); - subsC.add(subA); - graph.processAdv(advC, subsC); - - // Subscription to C (C generate D) - final Set> subsD = new HashSet>(); - subsD.add(subC); - graph.processAdv(advD, subsD); - - // Subscription to B, D (B, D generate E) - final Set> subsE = new HashSet>(); - subsE.add(subB); - subsE.add(subD); - graph.processAdv(advE, subsE); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); - - // EventB - final Event evB1 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); - final Event evB2 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { - assertTrue(wr.getExpression().equals("E@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("D@Host")); - } - - // EventC - final Event evC1 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); - final Event evC2 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 0); - - // EventD - final Event evD1 = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD1, "").size(), 0); - final Event evD2 = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evD2, "A@Host")) { - assertTrue(wr.getExpression().equals("E@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("B@Host")); - } - - // EventE - final Event evE = new Event("E", "Host", 1); - assertEquals(depDetector.getWaitRecommendations(evE, "").size(), 0); - } - - @Test - public void basicDualTriangle() { - // B = f(A) - // C = f(B) - // D = f(B, C) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription<>("Host", "A"); - final Subscription subB = new Subscription<>("Host", "B"); - final Subscription subC = new Subscription<>("Host", "C"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to B (B generates C) - final Set> subsC = new HashSet>(); - subsC.add(subB); - graph.processAdv(advC, subsC); - - // Subscription to B, C (B, C generate D) - final Set> subsD = new HashSet>(); - subsD.add(subB); - subsD.add(subC); - graph.processAdv(advD, subsD); - - graph.processAdv(advA); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); - - // EventB - final Event evB1 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); - final Event evB2 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("C@Host")); - } - - // EventC - final Event evC1 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); - final Event evC2 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("B@Host")); - } - - // EventD - final Event evD1 = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD1, "").size(), 0); - final Event evD2 = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD2, "A@Host").size(), 0); - } - - @Test - public void basicTripleCycleTest() { - // B = f(A) - // C = f(A) - // D = f(A) - // E = f(B, C, D) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription<>("Host", "A"); - final Subscription subB = new Subscription<>("Host", "B"); - final Subscription subC = new Subscription<>("Host", "C"); - final Subscription subD = new Subscription<>("Host", "D"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - final Advertisement advE = new Advertisement("Host", "E"); - - graph.processAdv(advA); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to A (A generates C) - final Set> subsC = new HashSet>(); - subsC.add(subA); - graph.processAdv(advC, subsC); - - // Subscription to A (A generates D) - final Set> subsD = new HashSet>(); - subsD.add(subA); - graph.processAdv(advD, subsD); - - // Subscription to B, C, D (B, C, D generate E) - final Set> subsE = new HashSet>(); - subsE.add(subB); - subsE.add(subC); - subsE.add(subD); - graph.processAdv(advE, subsE); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); - - // EventB - final Event evB1 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); - final Event evB2 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { - assertTrue(wr.getExpression().equals("E@Host")); - assertEquals(wr.getRecommendations().size(), 2); - assertTrue(wr.getRecommendations().contains("C@Host")); - assertTrue(wr.getRecommendations().contains("D@Host")); - } - - // EventC - final Event evC1 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); - final Event evC2 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { - assertTrue(wr.getExpression().equals("E@Host")); - assertEquals(wr.getRecommendations().size(), 2); - assertTrue(wr.getRecommendations().contains("B@Host")); - assertTrue(wr.getRecommendations().contains("D@Host")); - } - - // EventD - final Event evD1 = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD1, "").size(), 0); - final Event evD2 = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evD2, "A@Host")) { - assertTrue(wr.getExpression().equals("E@Host")); - assertEquals(wr.getRecommendations().size(), 2); - assertTrue(wr.getRecommendations().contains("B@Host")); - assertTrue(wr.getRecommendations().contains("C@Host")); - } - - // EventE - final Event evE = new Event("Host", "E", 1); - assertEquals(depDetector.getWaitRecommendations(evE, "A@Host").size(), 0); - } - - @Test - public void dualCyclesTest() { - // B1 = f(A1) - // C1 = f(A1) - // B2 = f(A2) - // C2 = f(A2) - // D = f(B1, C1, B2, C2) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA1 = new Subscription<>("Host", "A1"); - final Subscription subA2 = new Subscription<>("Host", "A2"); - final Subscription subB1 = new Subscription<>("Host", "B1"); - final Subscription subB2 = new Subscription<>("Host", "B2"); - final Subscription subC1 = new Subscription<>("Host", "C1"); - final Subscription subC2 = new Subscription<>("Host", "C2"); - - final Advertisement advA1 = new Advertisement("Host", "A1"); - final Advertisement advA2 = new Advertisement("Host", "A2"); - final Advertisement advB1 = new Advertisement("Host", "B1"); - final Advertisement advB2 = new Advertisement("Host", "B2"); - final Advertisement advC1 = new Advertisement("Host", "C1"); - final Advertisement advC2 = new Advertisement("Host", "C2"); - final Advertisement advD = new Advertisement("Host", "D"); - - // Subscription to A1 (A1 generates B2) - final Set> subsB1 = new HashSet>(); - subsB1.add(subA1); - graph.processAdv(advB1, subsB1); - - // Subscription to A2 (A2 generates B2) - final Set> subsB2 = new HashSet>(); - subsB2.add(subA2); - graph.processAdv(advB2, subsB2); - - // Subscription to A1 (A1 generates C1) - final Set> subsC1 = new HashSet>(); - subsC1.add(subA1); - graph.processAdv(advC1, subsC1); - - // Subscription to A2 (A2 generates C2) - final Set> subsC2 = new HashSet>(); - subsC2.add(subA2); - graph.processAdv(advC2, subsC2); - - // Subscription to B1, B2, C1, C2 (B1, B2, C1, C2 generate D) - final Set> subsD = new HashSet>(); - subsD.add(subB1); - subsD.add(subB2); - subsD.add(subC1); - subsD.add(subC2); - graph.processAdv(advD, subsD); - - graph.processAdv(advA1); - graph.processAdv(advA2); - - // Consolidate - depDetector.consolidate(); - - // EventA1 - final Event evA1 = new Event("Host", "A1", 1); - assertEquals(depDetector.getWaitRecommendations(evA1, "A1@Host").size(), 0); - - // EventA2 - final Event evA2 = new Event("Host", "A2", 1); - assertEquals(depDetector.getWaitRecommendations(evA2, "A2@Host").size(), 0); - - // EventB1 - final Event evB1 = new Event("Host", "B1", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "A1@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB1, "A1@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("C1@Host")); - } - - // EventC1 - final Event evC1 = new Event("Host", "C1", 1); - assertEquals(depDetector.getWaitRecommendations(evC1, "A1@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC1, "A1@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("B1@Host")); - } - - // EventB2 - final Event evB2 = new Event("Host", "B2", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A2@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A2@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("C2@Host")); - } - - // EventC2 - final Event evC2 = new Event("Host", "C2", 1); - assertEquals(depDetector.getWaitRecommendations(evC2, "A2@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A2@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("B2@Host")); - } - - // EventD - final Event evD = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD, "A2@Host").size(), 0); - } - - @Test - public void dualDependencyTest() { - // B = f(A1) - // C = f(A1, A2) - // D = f(B, C) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA1 = new Subscription<>("Host", "A1"); - final Subscription subA2 = new Subscription<>("Host", "A2"); - final Subscription subB = new Subscription<>("Host", "B"); - final Subscription subC = new Subscription<>("Host", "C"); - - final Advertisement advA1 = new Advertisement("Host", "A1"); - final Advertisement advA2 = new Advertisement("Host", "A2"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - - graph.processAdv(advA1); - graph.processAdv(advA2); - - // Subscription to A1 (A1 generates B) - final Set> subsB = new HashSet>(); - subsB.add(subA1); - graph.processAdv(advB, subsB); - - // Subscription to A1, A2 (A1, A2 generate C) - final Set> subsC = new HashSet>(); - subsC.add(subA1); - subsC.add(subA2); - graph.processAdv(advC, subsC); - - // Subscription to D (B, C generate D) - final Set> subsD = new HashSet>(); - subsD.add(subB); - subsD.add(subC); - graph.processAdv(advD, subsD); - - // Consolidate - depDetector.consolidate(); - - // EventA1 - final Event evA1 = new Event("Host", "A1", 1); - assertEquals(depDetector.getWaitRecommendations(evA1, "A1@Host").size(), 0); - - // EventA2 - final Event evA2 = new Event("Host", "A2", 1); - assertEquals(depDetector.getWaitRecommendations(evA2, "A2@Host").size(), 0); - - // EventB from A1 - final Event evB1 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); - final Event evB2 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A1@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A1@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("C@Host")); - } - - // EventC from A1 - final Event evC1_1 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC1_1, "").size(), 0); - final Event evC1_2 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC1_2, "A1@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC1_2, "A1@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("B@Host")); - } - - // EventC from A2 - final Event evC2_1 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC2_1, "").size(), 0); - final Event evC2_2 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC2_2, "A2@Host").size(), 0); - - // EventD - final Event evD = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD, "A2@Host").size(), 0); - } - - @Test - public void nestedCyclesTest() { - // B = f(A) - // C = f(A) - // E = f(A) - // G = f(E) - // F = f(E) - // H = f(F, G) - // D = f(B, C, H) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription<>("Host", "A"); - final Subscription subB = new Subscription<>("Host", "B"); - final Subscription subC = new Subscription<>("Host", "C"); - final Subscription subE = new Subscription<>("Host", "E"); - final Subscription subF = new Subscription<>("Host", "F"); - final Subscription subG = new Subscription<>("Host", "G"); - final Subscription subH = new Subscription<>("Host", "H"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - final Advertisement advE = new Advertisement("Host", "E"); - final Advertisement advF = new Advertisement("Host", "F"); - final Advertisement advG = new Advertisement("Host", "G"); - final Advertisement advH = new Advertisement("Host", "H"); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to A (A generates C) - final Set> subsC = new HashSet>(); - subsC.add(subA); - graph.processAdv(advC, subsC); - - // Subscription to A (A generates E) - final Set> subsE = new HashSet>(); - subsE.add(subA); - graph.processAdv(advE, subsE); - - // Subscription to E (E generates G) - final Set> subsG = new HashSet>(); - subsG.add(subE); - graph.processAdv(advG, subsG); - - // Subscription to E (E generates F) - final Set> subsF = new HashSet>(); - subsF.add(subE); - graph.processAdv(advF, subsF); - - // Subscription to F, G (F, G generate H) - final Set> subsH = new HashSet>(); - subsH.add(subF); - subsH.add(subG); - graph.processAdv(advH, subsH); - - // Subscription to B, C, H (B, C, H generate D) - final Set> subsD = new HashSet>(); - subsD.add(subB); - subsD.add(subC); - subsD.add(subH); - graph.processAdv(advD, subsD); - - graph.processAdv(advA); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event("Host", "A", 1); - assertEquals(depDetector.getWaitRecommendations(evA, "A@Host").size(), 0); - - // EventB - final Event evB1 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); - final Event evB2 = new Event("Host", "B", 1); - assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 2); - assertTrue(wr.getRecommendations().contains("C@Host")); - assertTrue(wr.getRecommendations().contains("H@Host")); - } - - // EventC - final Event evC1 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); - final Event evC2 = new Event("Host", "C", 1); - assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 2); - assertTrue(wr.getRecommendations().contains("B@Host")); - assertTrue(wr.getRecommendations().contains("H@Host")); - } - - // EventE - final Event evE = new Event("Host", "E", 1); - assertEquals(depDetector.getWaitRecommendations(evE, "A@Host").size(), 0); - - // EventF - final Event evF1 = new Event("Host", "F", 1); - assertEquals(depDetector.getWaitRecommendations(evF1, "").size(), 0); - final Event evF2 = new Event("Host", "F", 1); - assertEquals(depDetector.getWaitRecommendations(evF2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evF2, "A@Host")) { - assertTrue(wr.getExpression().equals("H@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("G@Host")); - } - - // EventG - final Event evG1 = new Event("Host", "G", 1); - assertEquals(depDetector.getWaitRecommendations(evG1, "").size(), 0); - final Event evG2 = new Event("Host", "G", 1); - assertEquals(depDetector.getWaitRecommendations(evG2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evG2, "A@Host")) { - assertTrue(wr.getExpression().equals("H@Host")); - assertEquals(wr.getRecommendations().size(), 1); - assertTrue(wr.getRecommendations().contains("F@Host")); - } - - // EventH - final Event evH1 = new Event("Host", "H", 1); - assertEquals(depDetector.getWaitRecommendations(evH1, "").size(), 0); - final Event evH2 = new Event("Host", "H", 1); - assertEquals(depDetector.getWaitRecommendations(evH2, "A@Host").size(), 1); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evH2, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(wr.getRecommendations().size(), 2); - assertTrue(wr.getRecommendations().contains("B@Host")); - assertTrue(wr.getRecommendations().contains("C@Host")); - } - - // EventD - final Event evD = new Event("Host", "D", 1); - assertEquals(depDetector.getWaitRecommendations(evD, "A@Host").size(), 0); - } - - @Test - public void multipleCyclesTest() { - // B = f(A) - // C = f(A, B) - // D = f(B, C) - // E = f(A, D) - final DependencyGraph graph = DependencyGraph.instance; - final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; - graph.clear(); - - final Subscription subA = new Subscription<>("Host", "A"); - final Subscription subB = new Subscription<>("Host", "B"); - final Subscription subC = new Subscription<>("Host", "C"); - final Subscription subD = new Subscription<>("Host", "D"); - - final Advertisement advA = new Advertisement("Host", "A"); - final Advertisement advB = new Advertisement("Host", "B"); - final Advertisement advC = new Advertisement("Host", "C"); - final Advertisement advD = new Advertisement("Host", "D"); - final Advertisement advE = new Advertisement("Host", "E"); - - // Subscription to A (A generates B) - final Set> subsB = new HashSet>(); - subsB.add(subA); - graph.processAdv(advB, subsB); - - // Subscription to A, B (A, B generate C) - final Set> subsC = new HashSet>(); - subsC.add(subA); - subsC.add(subB); - graph.processAdv(advC, subsC); - - // Subscription to B, C (B, C generate D) - final Set> subsD = new HashSet>(); - subsD.add(subB); - subsD.add(subC); - graph.processAdv(advD, subsD); - - // Subscription to A, D (A, D generate E) - final Set> subsE = new HashSet>(); - subsE.add(subA); - subsE.add(subD); - graph.processAdv(advE, subsE); - - graph.processAdv(advA); - - // Consolidate - depDetector.consolidate(); - - // EventA - final Event evA = new Event("Host", "A", 1); - assertEquals(2, depDetector.getWaitRecommendations(evA, "A@Host").size()); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evA, "A@Host")) { - assertTrue(wr.getExpression().equals("C@Host") || wr.getExpression().equals("E@Host")); - if (wr.getExpression().equals("C@Host")) { - assertEquals(1, wr.getRecommendations().size()); - assertTrue(wr.getRecommendations().contains("B@Host")); - } - if (wr.getExpression().equals("E@Host")) { - assertEquals(1, wr.getRecommendations().size()); - assertTrue(wr.getRecommendations().contains("D@Host")); - } - } - - // EventB - final Event evB = new Event("Host", "B", 1); - assertEquals(2, depDetector.getWaitRecommendations(evB, "A@Host").size()); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB, "A@Host")) { - assertTrue(wr.getExpression().equals("C@Host") || wr.getExpression().equals("D@Host")); - if (wr.getExpression().equals("C@Host")) { - assertEquals(1, wr.getRecommendations().size()); - assertTrue(wr.getRecommendations().contains("A@Host")); - } - if (wr.getExpression().equals("D@Host")) { - assertEquals(1, wr.getRecommendations().size()); - assertTrue(wr.getRecommendations().contains("C@Host")); - } - } - - // EventC - final Event evC = new Event("Host", "C", 1); - assertEquals(1, depDetector.getWaitRecommendations(evC, "A@Host").size()); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC, "A@Host")) { - assertTrue(wr.getExpression().equals("D@Host")); - assertEquals(1, wr.getRecommendations().size()); - assertTrue(wr.getRecommendations().contains("B@Host")); - } - - // EventD - final Event evD = new Event("Host", "D", 1); - assertEquals(1, depDetector.getWaitRecommendations(evD, "A@Host").size()); - for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evD, "A@Host")) { - assertTrue(wr.getExpression().equals("E@Host")); - assertEquals(1, wr.getRecommendations().size()); - assertTrue(wr.getRecommendations().contains("A@Host")); - } - - // EventE - final Event evE = new Event("Host", "E", 1); - assertTrue(depDetector.getWaitRecommendations(evE, "A@Host").isEmpty()); - } + @Test + public void noDependencyTest() { + // B = f(A) + // D = f(B, C) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription("Host", "A"); + final Subscription subB = new Subscription("Host", "B"); + final Subscription subC = new Subscription("Host", "C"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet<>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to B and C (B, C generate D) + final Set> subsD = new HashSet<>(); + subsD.add(subB); + subsD.add(subC); + graph.processAdv(advD, subsD); + + graph.processAdv(advA); + graph.processAdv(advC); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event<>("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA, "A@Host").size(), 0); + + // EventB + final Event evB = new Event<>("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB, "A@Host").size(), 0); + + // EventC + final Event evC = new Event<>("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC, "A@Host").size(), 0); + + // EventD + final Event evD = new Event<>("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD, "A@Host").size(), 0); + } + + @Test + public void basicTriangularCycleTest() { + // B = f(A) + // C = f(A, B) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription("Host", "A"); + final Subscription subB = new Subscription("Host", "B"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet<>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to A, B (A, B generates C) + final Set> subsC = new HashSet<>(); + subsC.add(subA); + subsC.add(subB); + graph.processAdv(advC, subsC); + + graph.processAdv(advA); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); + final Event evA2 = new Event("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evA2, "A@Host")) { + assertTrue(wr.getExpression().equals("C@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("B@Host")); + } + + // EventB + final Event evB1 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); + final Event evB2 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { + assertTrue(wr.getExpression().equals("C@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("A@Host")); + } + + // EventC + final Event evC = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC, "").size(), 0); + } + + @Test + public void basicDualCycleTest() { + // B = f(A) + // C = f(A) + // D = f(B, C) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription("Host", "A"); + final Subscription subB = new Subscription("Host", "B"); + final Subscription subC = new Subscription("Host", "C"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to A (A generates C) + final Set> subsC = new HashSet>(); + subsC.add(subA); + graph.processAdv(advC, subsC); + + // Subscription to B, C (B, C generate D) + final Set> subsD = new HashSet>(); + subsD.add(subB); + subsD.add(subC); + graph.processAdv(advD, subsD); + + graph.processAdv(advA); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); + + // EventB + final Event evB1 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); + final Event evB2 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("C@Host")); + } + + // EventC + final Event evC1 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); + final Event evC2 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("B@Host")); + } + + // EventD + final Event evD = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD, "").size(), 0); + } + + @Test + public void basicDualCycleTest2() { + // B = f(A) + // C = f(A) + // D = f(C) + // E = f(B, D) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription<>("Host", "A"); + final Subscription subB = new Subscription<>("Host", "B"); + final Subscription subC = new Subscription<>("Host", "C"); + final Subscription subD = new Subscription<>("Host", "D"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + final Advertisement advE = new Advertisement("Host", "E"); + + graph.processAdv(advA); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to A (A generates C) + final Set> subsC = new HashSet>(); + subsC.add(subA); + graph.processAdv(advC, subsC); + + // Subscription to C (C generate D) + final Set> subsD = new HashSet>(); + subsD.add(subC); + graph.processAdv(advD, subsD); + + // Subscription to B, D (B, D generate E) + final Set> subsE = new HashSet>(); + subsE.add(subB); + subsE.add(subD); + graph.processAdv(advE, subsE); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); + + // EventB + final Event evB1 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); + final Event evB2 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { + assertTrue(wr.getExpression().equals("E@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("D@Host")); + } + + // EventC + final Event evC1 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); + final Event evC2 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 0); + + // EventD + final Event evD1 = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD1, "").size(), 0); + final Event evD2 = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evD2, "A@Host")) { + assertTrue(wr.getExpression().equals("E@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("B@Host")); + } + + // EventE + final Event evE = new Event("E", "Host", 1); + assertEquals(depDetector.getWaitRecommendations(evE, "").size(), 0); + } + + @Test + public void basicDualTriangle() { + // B = f(A) + // C = f(B) + // D = f(B, C) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription<>("Host", "A"); + final Subscription subB = new Subscription<>("Host", "B"); + final Subscription subC = new Subscription<>("Host", "C"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to B (B generates C) + final Set> subsC = new HashSet>(); + subsC.add(subB); + graph.processAdv(advC, subsC); + + // Subscription to B, C (B, C generate D) + final Set> subsD = new HashSet>(); + subsD.add(subB); + subsD.add(subC); + graph.processAdv(advD, subsD); + + graph.processAdv(advA); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); + + // EventB + final Event evB1 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); + final Event evB2 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("C@Host")); + } + + // EventC + final Event evC1 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); + final Event evC2 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("B@Host")); + } + + // EventD + final Event evD1 = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD1, "").size(), 0); + final Event evD2 = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD2, "A@Host").size(), 0); + } + + @Test + public void basicTripleCycleTest() { + // B = f(A) + // C = f(A) + // D = f(A) + // E = f(B, C, D) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription<>("Host", "A"); + final Subscription subB = new Subscription<>("Host", "B"); + final Subscription subC = new Subscription<>("Host", "C"); + final Subscription subD = new Subscription<>("Host", "D"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + final Advertisement advE = new Advertisement("Host", "E"); + + graph.processAdv(advA); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to A (A generates C) + final Set> subsC = new HashSet>(); + subsC.add(subA); + graph.processAdv(advC, subsC); + + // Subscription to A (A generates D) + final Set> subsD = new HashSet>(); + subsD.add(subA); + graph.processAdv(advD, subsD); + + // Subscription to B, C, D (B, C, D generate E) + final Set> subsE = new HashSet>(); + subsE.add(subB); + subsE.add(subC); + subsE.add(subD); + graph.processAdv(advE, subsE); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA, "").size(), 0); + + // EventB + final Event evB1 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); + final Event evB2 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { + assertTrue(wr.getExpression().equals("E@Host")); + assertEquals(wr.getRecommendations().size(), 2); + assertTrue(wr.getRecommendations().contains("C@Host")); + assertTrue(wr.getRecommendations().contains("D@Host")); + } + + // EventC + final Event evC1 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); + final Event evC2 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { + assertTrue(wr.getExpression().equals("E@Host")); + assertEquals(wr.getRecommendations().size(), 2); + assertTrue(wr.getRecommendations().contains("B@Host")); + assertTrue(wr.getRecommendations().contains("D@Host")); + } + + // EventD + final Event evD1 = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD1, "").size(), 0); + final Event evD2 = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evD2, "A@Host")) { + assertTrue(wr.getExpression().equals("E@Host")); + assertEquals(wr.getRecommendations().size(), 2); + assertTrue(wr.getRecommendations().contains("B@Host")); + assertTrue(wr.getRecommendations().contains("C@Host")); + } + + // EventE + final Event evE = new Event("Host", "E", 1); + assertEquals(depDetector.getWaitRecommendations(evE, "A@Host").size(), 0); + } + + @Test + public void dualCyclesTest() { + // B1 = f(A1) + // C1 = f(A1) + // B2 = f(A2) + // C2 = f(A2) + // D = f(B1, C1, B2, C2) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA1 = new Subscription<>("Host", "A1"); + final Subscription subA2 = new Subscription<>("Host", "A2"); + final Subscription subB1 = new Subscription<>("Host", "B1"); + final Subscription subB2 = new Subscription<>("Host", "B2"); + final Subscription subC1 = new Subscription<>("Host", "C1"); + final Subscription subC2 = new Subscription<>("Host", "C2"); + + final Advertisement advA1 = new Advertisement("Host", "A1"); + final Advertisement advA2 = new Advertisement("Host", "A2"); + final Advertisement advB1 = new Advertisement("Host", "B1"); + final Advertisement advB2 = new Advertisement("Host", "B2"); + final Advertisement advC1 = new Advertisement("Host", "C1"); + final Advertisement advC2 = new Advertisement("Host", "C2"); + final Advertisement advD = new Advertisement("Host", "D"); + + // Subscription to A1 (A1 generates B2) + final Set> subsB1 = new HashSet>(); + subsB1.add(subA1); + graph.processAdv(advB1, subsB1); + + // Subscription to A2 (A2 generates B2) + final Set> subsB2 = new HashSet>(); + subsB2.add(subA2); + graph.processAdv(advB2, subsB2); + + // Subscription to A1 (A1 generates C1) + final Set> subsC1 = new HashSet>(); + subsC1.add(subA1); + graph.processAdv(advC1, subsC1); + + // Subscription to A2 (A2 generates C2) + final Set> subsC2 = new HashSet>(); + subsC2.add(subA2); + graph.processAdv(advC2, subsC2); + + // Subscription to B1, B2, C1, C2 (B1, B2, C1, C2 generate D) + final Set> subsD = new HashSet>(); + subsD.add(subB1); + subsD.add(subB2); + subsD.add(subC1); + subsD.add(subC2); + graph.processAdv(advD, subsD); + + graph.processAdv(advA1); + graph.processAdv(advA2); + + // Consolidate + depDetector.consolidate(); + + // EventA1 + final Event evA1 = new Event("Host", "A1", 1); + assertEquals(depDetector.getWaitRecommendations(evA1, "A1@Host").size(), 0); + + // EventA2 + final Event evA2 = new Event("Host", "A2", 1); + assertEquals(depDetector.getWaitRecommendations(evA2, "A2@Host").size(), 0); + + // EventB1 + final Event evB1 = new Event("Host", "B1", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "A1@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB1, "A1@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("C1@Host")); + } + + // EventC1 + final Event evC1 = new Event("Host", "C1", 1); + assertEquals(depDetector.getWaitRecommendations(evC1, "A1@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC1, "A1@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("B1@Host")); + } + + // EventB2 + final Event evB2 = new Event("Host", "B2", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A2@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A2@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("C2@Host")); + } + + // EventC2 + final Event evC2 = new Event("Host", "C2", 1); + assertEquals(depDetector.getWaitRecommendations(evC2, "A2@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A2@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("B2@Host")); + } + + // EventD + final Event evD = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD, "A2@Host").size(), 0); + } + + @Test + public void dualDependencyTest() { + // B = f(A1) + // C = f(A1, A2) + // D = f(B, C) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA1 = new Subscription<>("Host", "A1"); + final Subscription subA2 = new Subscription<>("Host", "A2"); + final Subscription subB = new Subscription<>("Host", "B"); + final Subscription subC = new Subscription<>("Host", "C"); + + final Advertisement advA1 = new Advertisement("Host", "A1"); + final Advertisement advA2 = new Advertisement("Host", "A2"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + + graph.processAdv(advA1); + graph.processAdv(advA2); + + // Subscription to A1 (A1 generates B) + final Set> subsB = new HashSet>(); + subsB.add(subA1); + graph.processAdv(advB, subsB); + + // Subscription to A1, A2 (A1, A2 generate C) + final Set> subsC = new HashSet>(); + subsC.add(subA1); + subsC.add(subA2); + graph.processAdv(advC, subsC); + + // Subscription to D (B, C generate D) + final Set> subsD = new HashSet>(); + subsD.add(subB); + subsD.add(subC); + graph.processAdv(advD, subsD); + + // Consolidate + depDetector.consolidate(); + + // EventA1 + final Event evA1 = new Event("Host", "A1", 1); + assertEquals(depDetector.getWaitRecommendations(evA1, "A1@Host").size(), 0); + + // EventA2 + final Event evA2 = new Event("Host", "A2", 1); + assertEquals(depDetector.getWaitRecommendations(evA2, "A2@Host").size(), 0); + + // EventB from A1 + final Event evB1 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); + final Event evB2 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A1@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A1@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("C@Host")); + } + + // EventC from A1 + final Event evC1_1 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC1_1, "").size(), 0); + final Event evC1_2 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC1_2, "A1@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC1_2, "A1@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("B@Host")); + } + + // EventC from A2 + final Event evC2_1 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC2_1, "").size(), 0); + final Event evC2_2 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC2_2, "A2@Host").size(), 0); + + // EventD + final Event evD = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD, "A2@Host").size(), 0); + } + + @Test + public void nestedCyclesTest() { + // B = f(A) + // C = f(A) + // E = f(A) + // G = f(E) + // F = f(E) + // H = f(F, G) + // D = f(B, C, H) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription<>("Host", "A"); + final Subscription subB = new Subscription<>("Host", "B"); + final Subscription subC = new Subscription<>("Host", "C"); + final Subscription subE = new Subscription<>("Host", "E"); + final Subscription subF = new Subscription<>("Host", "F"); + final Subscription subG = new Subscription<>("Host", "G"); + final Subscription subH = new Subscription<>("Host", "H"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + final Advertisement advE = new Advertisement("Host", "E"); + final Advertisement advF = new Advertisement("Host", "F"); + final Advertisement advG = new Advertisement("Host", "G"); + final Advertisement advH = new Advertisement("Host", "H"); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to A (A generates C) + final Set> subsC = new HashSet>(); + subsC.add(subA); + graph.processAdv(advC, subsC); + + // Subscription to A (A generates E) + final Set> subsE = new HashSet>(); + subsE.add(subA); + graph.processAdv(advE, subsE); + + // Subscription to E (E generates G) + final Set> subsG = new HashSet>(); + subsG.add(subE); + graph.processAdv(advG, subsG); + + // Subscription to E (E generates F) + final Set> subsF = new HashSet>(); + subsF.add(subE); + graph.processAdv(advF, subsF); + + // Subscription to F, G (F, G generate H) + final Set> subsH = new HashSet>(); + subsH.add(subF); + subsH.add(subG); + graph.processAdv(advH, subsH); + + // Subscription to B, C, H (B, C, H generate D) + final Set> subsD = new HashSet>(); + subsD.add(subB); + subsD.add(subC); + subsD.add(subH); + graph.processAdv(advD, subsD); + + graph.processAdv(advA); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event("Host", "A", 1); + assertEquals(depDetector.getWaitRecommendations(evA, "A@Host").size(), 0); + + // EventB + final Event evB1 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB1, "").size(), 0); + final Event evB2 = new Event("Host", "B", 1); + assertEquals(depDetector.getWaitRecommendations(evB2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB2, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 2); + assertTrue(wr.getRecommendations().contains("C@Host")); + assertTrue(wr.getRecommendations().contains("H@Host")); + } + + // EventC + final Event evC1 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC1, "").size(), 0); + final Event evC2 = new Event("Host", "C", 1); + assertEquals(depDetector.getWaitRecommendations(evC2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC2, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 2); + assertTrue(wr.getRecommendations().contains("B@Host")); + assertTrue(wr.getRecommendations().contains("H@Host")); + } + + // EventE + final Event evE = new Event("Host", "E", 1); + assertEquals(depDetector.getWaitRecommendations(evE, "A@Host").size(), 0); + + // EventF + final Event evF1 = new Event("Host", "F", 1); + assertEquals(depDetector.getWaitRecommendations(evF1, "").size(), 0); + final Event evF2 = new Event("Host", "F", 1); + assertEquals(depDetector.getWaitRecommendations(evF2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evF2, "A@Host")) { + assertTrue(wr.getExpression().equals("H@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("G@Host")); + } + + // EventG + final Event evG1 = new Event("Host", "G", 1); + assertEquals(depDetector.getWaitRecommendations(evG1, "").size(), 0); + final Event evG2 = new Event("Host", "G", 1); + assertEquals(depDetector.getWaitRecommendations(evG2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evG2, "A@Host")) { + assertTrue(wr.getExpression().equals("H@Host")); + assertEquals(wr.getRecommendations().size(), 1); + assertTrue(wr.getRecommendations().contains("F@Host")); + } + + // EventH + final Event evH1 = new Event("Host", "H", 1); + assertEquals(depDetector.getWaitRecommendations(evH1, "").size(), 0); + final Event evH2 = new Event("Host", "H", 1); + assertEquals(depDetector.getWaitRecommendations(evH2, "A@Host").size(), 1); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evH2, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(wr.getRecommendations().size(), 2); + assertTrue(wr.getRecommendations().contains("B@Host")); + assertTrue(wr.getRecommendations().contains("C@Host")); + } + + // EventD + final Event evD = new Event("Host", "D", 1); + assertEquals(depDetector.getWaitRecommendations(evD, "A@Host").size(), 0); + } + + @Test + public void multipleCyclesTest() { + // B = f(A) + // C = f(A, B) + // D = f(B, C) + // E = f(A, D) + final DependencyGraph graph = DependencyGraph.instance; + final IntraSourceDependencyDetector depDetector = IntraSourceDependencyDetector.instance; + graph.clear(); + + final Subscription subA = new Subscription<>("Host", "A"); + final Subscription subB = new Subscription<>("Host", "B"); + final Subscription subC = new Subscription<>("Host", "C"); + final Subscription subD = new Subscription<>("Host", "D"); + + final Advertisement advA = new Advertisement("Host", "A"); + final Advertisement advB = new Advertisement("Host", "B"); + final Advertisement advC = new Advertisement("Host", "C"); + final Advertisement advD = new Advertisement("Host", "D"); + final Advertisement advE = new Advertisement("Host", "E"); + + // Subscription to A (A generates B) + final Set> subsB = new HashSet>(); + subsB.add(subA); + graph.processAdv(advB, subsB); + + // Subscription to A, B (A, B generate C) + final Set> subsC = new HashSet>(); + subsC.add(subA); + subsC.add(subB); + graph.processAdv(advC, subsC); + + // Subscription to B, C (B, C generate D) + final Set> subsD = new HashSet>(); + subsD.add(subB); + subsD.add(subC); + graph.processAdv(advD, subsD); + + // Subscription to A, D (A, D generate E) + final Set> subsE = new HashSet>(); + subsE.add(subA); + subsE.add(subD); + graph.processAdv(advE, subsE); + + graph.processAdv(advA); + + // Consolidate + depDetector.consolidate(); + + // EventA + final Event evA = new Event("Host", "A", 1); + assertEquals(2, depDetector.getWaitRecommendations(evA, "A@Host").size()); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evA, "A@Host")) { + assertTrue(wr.getExpression().equals("C@Host") || wr.getExpression().equals("E@Host")); + if (wr.getExpression().equals("C@Host")) { + assertEquals(1, wr.getRecommendations().size()); + assertTrue(wr.getRecommendations().contains("B@Host")); + } + if (wr.getExpression().equals("E@Host")) { + assertEquals(1, wr.getRecommendations().size()); + assertTrue(wr.getRecommendations().contains("D@Host")); + } + } + + // EventB + final Event evB = new Event("Host", "B", 1); + assertEquals(2, depDetector.getWaitRecommendations(evB, "A@Host").size()); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evB, "A@Host")) { + assertTrue(wr.getExpression().equals("C@Host") || wr.getExpression().equals("D@Host")); + if (wr.getExpression().equals("C@Host")) { + assertEquals(1, wr.getRecommendations().size()); + assertTrue(wr.getRecommendations().contains("A@Host")); + } + if (wr.getExpression().equals("D@Host")) { + assertEquals(1, wr.getRecommendations().size()); + assertTrue(wr.getRecommendations().contains("C@Host")); + } + } + + // EventC + final Event evC = new Event("Host", "C", 1); + assertEquals(1, depDetector.getWaitRecommendations(evC, "A@Host").size()); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evC, "A@Host")) { + assertTrue(wr.getExpression().equals("D@Host")); + assertEquals(1, wr.getRecommendations().size()); + assertTrue(wr.getRecommendations().contains("B@Host")); + } + + // EventD + final Event evD = new Event("Host", "D", 1); + assertEquals(1, depDetector.getWaitRecommendations(evD, "A@Host").size()); + for (final WaitRecommendations wr : depDetector.getWaitRecommendations(evD, "A@Host")) { + assertTrue(wr.getExpression().equals("E@Host")); + assertEquals(1, wr.getRecommendations().size()); + assertTrue(wr.getRecommendations().contains("A@Host")); + } + + // EventE + final Event evE = new Event("Host", "E", 1); + assertTrue(depDetector.getWaitRecommendations(evE, "A@Host").isEmpty()); + } } \ No newline at end of file diff --git a/Dream2/src/test/java/dream/locking/LockManagerTest.java b/Dream2/src/test/java/dream/locking/LockManagerTest.java index ffc8548..c00305e 100644 --- a/Dream2/src/test/java/dream/locking/LockManagerTest.java +++ b/Dream2/src/test/java/dream/locking/LockManagerTest.java @@ -17,119 +17,129 @@ public class LockManagerTest { - @Test - public void test1() { - final LockManager manager = new LockManager(); - - final Set lockNodes = new HashSet<>(); - lockNodes.add("A"); - lockNodes.add("B"); - - final Set unlockNodes = new HashSet<>(); - unlockNodes.add("A"); - unlockNodes.add("B"); - - final LockRequestPacket req1 = new LockRequestPacket(new NodeDescriptor(true), lockNodes, unlockNodes, LockType.READ_WRITE); - assertTrue(manager.processLockRequest(req1)); - - final LockRequestPacket req2 = new LockRequestPacket(new NodeDescriptor(true), lockNodes, unlockNodes, LockType.READ_WRITE); - assertFalse(manager.processLockRequest(req2)); - - final UUID reqID1 = req1.getLockID(); - final LockReleasePacket rel1 = new LockReleasePacket(reqID1); - Set result = manager.processLockRelease(rel1); - assertTrue(result.isEmpty()); - - final LockRequestPacket req3 = new LockRequestPacket(new NodeDescriptor(true), lockNodes, unlockNodes, LockType.READ_WRITE); - assertFalse(manager.processLockRequest(req3)); - - final LockReleasePacket rel2 = new LockReleasePacket(reqID1); - result = manager.processLockRelease(rel2); - assertEquals(1, result.size()); - assertTrue(result.contains(req2)); - - final UUID reqID2 = req2.getLockID(); - final LockReleasePacket rel3 = new LockReleasePacket(reqID2); - result = manager.processLockRelease(rel3); - assertTrue(result.isEmpty()); - - final LockReleasePacket rel4 = new LockReleasePacket(reqID2); - result = manager.processLockRelease(rel4); - assertEquals(1, result.size()); - assertTrue(result.contains(req3)); - } - - @Test - public void test2() { - final LockManager manager = new LockManager(); - - final Set lockNodesA = new HashSet<>(); - lockNodesA.add("A"); - - final Set lockNodesB = new HashSet<>(); - lockNodesB.add("B"); - - final Set lockNodesAB = new HashSet<>(); - lockNodesAB.add("A"); - lockNodesAB.add("B"); - - final Set unlockNodes = new HashSet<>(); - unlockNodes.add("C"); - - final LockRequestPacket reqAB = new LockRequestPacket(new NodeDescriptor(true), lockNodesAB, unlockNodes, LockType.READ_WRITE); - assertTrue(manager.processLockRequest(reqAB)); - - final LockRequestPacket reqA = new LockRequestPacket(new NodeDescriptor(true), lockNodesA, unlockNodes, LockType.READ_WRITE); - assertFalse(manager.processLockRequest(reqA)); - - final LockRequestPacket reqB = new LockRequestPacket(new NodeDescriptor(true), lockNodesB, unlockNodes, LockType.READ_WRITE); - assertFalse(manager.processLockRequest(reqB)); - - final UUID id = reqAB.getLockID(); - final LockReleasePacket rel = new LockReleasePacket(id); - final Set result = manager.processLockRelease(rel); - assertEquals(2, result.size()); - assertTrue(result.contains(reqA)); - assertTrue(result.contains(reqB)); - } - - @Test - public void test3() { - final LockManager manager = new LockManager(); - - final Set lockNodesA = new HashSet<>(); - lockNodesA.add("A"); - - final Set lockNodesB = new HashSet<>(); - lockNodesB.add("B"); - - final Set lockNodesAB = new HashSet<>(); - lockNodesAB.add("A"); - lockNodesAB.add("B"); - - final Set unlockNodes = new HashSet<>(); - unlockNodes.add("C"); - - final LockRequestPacket reqAB = new LockRequestPacket(new NodeDescriptor(true), lockNodesAB, unlockNodes, LockType.READ_ONLY); - assertTrue(manager.processLockRequest(reqAB)); - - final LockRequestPacket reqA1 = new LockRequestPacket(new NodeDescriptor(true), lockNodesA, unlockNodes, LockType.READ_ONLY); - assertTrue(manager.processLockRequest(reqA1)); - - final LockRequestPacket reqA2 = new LockRequestPacket(new NodeDescriptor(true), lockNodesA, unlockNodes, LockType.READ_ONLY); - assertTrue(manager.processLockRequest(reqA2)); - - final LockRequestPacket reqB = new LockRequestPacket(new NodeDescriptor(true), lockNodesB, unlockNodes, LockType.READ_WRITE); - assertFalse(manager.processLockRequest(reqB)); - - UUID id = reqA1.getLockID(); - final LockReleasePacket relA1 = new LockReleasePacket(id); - assertTrue(manager.processLockRelease(relA1).isEmpty()); - - id = reqAB.getLockID(); - final LockReleasePacket relB = new LockReleasePacket(id); - final Set result = manager.processLockRelease(relB); - assertEquals(1, result.size()); - assertTrue(result.contains(reqB)); - } + @Test + public void test1() { + final LockManager manager = new LockManager(); + + final Set lockNodes = new HashSet<>(); + lockNodes.add("A"); + lockNodes.add("B"); + + final Set unlockNodes = new HashSet<>(); + unlockNodes.add("A"); + unlockNodes.add("B"); + + final LockRequestPacket req1 = new LockRequestPacket(new NodeDescriptor(true), lockNodes, unlockNodes, + LockType.READ_WRITE); + assertTrue(manager.processLockRequest(req1)); + + final LockRequestPacket req2 = new LockRequestPacket(new NodeDescriptor(true), lockNodes, unlockNodes, + LockType.READ_WRITE); + assertFalse(manager.processLockRequest(req2)); + + final UUID reqID1 = req1.getLockID(); + final LockReleasePacket rel1 = new LockReleasePacket(reqID1); + Set result = manager.processLockRelease(rel1); + assertTrue(result.isEmpty()); + + final LockRequestPacket req3 = new LockRequestPacket(new NodeDescriptor(true), lockNodes, unlockNodes, + LockType.READ_WRITE); + assertFalse(manager.processLockRequest(req3)); + + final LockReleasePacket rel2 = new LockReleasePacket(reqID1); + result = manager.processLockRelease(rel2); + assertEquals(1, result.size()); + assertTrue(result.contains(req2)); + + final UUID reqID2 = req2.getLockID(); + final LockReleasePacket rel3 = new LockReleasePacket(reqID2); + result = manager.processLockRelease(rel3); + assertTrue(result.isEmpty()); + + final LockReleasePacket rel4 = new LockReleasePacket(reqID2); + result = manager.processLockRelease(rel4); + assertEquals(1, result.size()); + assertTrue(result.contains(req3)); + } + + @Test + public void test2() { + final LockManager manager = new LockManager(); + + final Set lockNodesA = new HashSet<>(); + lockNodesA.add("A"); + + final Set lockNodesB = new HashSet<>(); + lockNodesB.add("B"); + + final Set lockNodesAB = new HashSet<>(); + lockNodesAB.add("A"); + lockNodesAB.add("B"); + + final Set unlockNodes = new HashSet<>(); + unlockNodes.add("C"); + + final LockRequestPacket reqAB = new LockRequestPacket(new NodeDescriptor(true), lockNodesAB, unlockNodes, + LockType.READ_WRITE); + assertTrue(manager.processLockRequest(reqAB)); + + final LockRequestPacket reqA = new LockRequestPacket(new NodeDescriptor(true), lockNodesA, unlockNodes, + LockType.READ_WRITE); + assertFalse(manager.processLockRequest(reqA)); + + final LockRequestPacket reqB = new LockRequestPacket(new NodeDescriptor(true), lockNodesB, unlockNodes, + LockType.READ_WRITE); + assertFalse(manager.processLockRequest(reqB)); + + final UUID id = reqAB.getLockID(); + final LockReleasePacket rel = new LockReleasePacket(id); + final Set result = manager.processLockRelease(rel); + assertEquals(2, result.size()); + assertTrue(result.contains(reqA)); + assertTrue(result.contains(reqB)); + } + + @Test + public void test3() { + final LockManager manager = new LockManager(); + + final Set lockNodesA = new HashSet<>(); + lockNodesA.add("A"); + + final Set lockNodesB = new HashSet<>(); + lockNodesB.add("B"); + + final Set lockNodesAB = new HashSet<>(); + lockNodesAB.add("A"); + lockNodesAB.add("B"); + + final Set unlockNodes = new HashSet<>(); + unlockNodes.add("C"); + + final LockRequestPacket reqAB = new LockRequestPacket(new NodeDescriptor(true), lockNodesAB, unlockNodes, + LockType.READ_ONLY); + assertTrue(manager.processLockRequest(reqAB)); + + final LockRequestPacket reqA1 = new LockRequestPacket(new NodeDescriptor(true), lockNodesA, unlockNodes, + LockType.READ_ONLY); + assertTrue(manager.processLockRequest(reqA1)); + + final LockRequestPacket reqA2 = new LockRequestPacket(new NodeDescriptor(true), lockNodesA, unlockNodes, + LockType.READ_ONLY); + assertTrue(manager.processLockRequest(reqA2)); + + final LockRequestPacket reqB = new LockRequestPacket(new NodeDescriptor(true), lockNodesB, unlockNodes, + LockType.READ_WRITE); + assertFalse(manager.processLockRequest(reqB)); + + UUID id = reqA1.getLockID(); + final LockReleasePacket relA1 = new LockReleasePacket(id); + assertTrue(manager.processLockRelease(relA1).isEmpty()); + + id = reqAB.getLockID(); + final LockReleasePacket relB = new LockReleasePacket(id); + final Set result = manager.processLockRelease(relB); + assertEquals(1, result.size()); + assertTrue(result.contains(reqB)); + } } diff --git a/DreamSim/.settings/org.eclipse.jdt.ui.prefs b/DreamSim/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..07ccfe5 --- /dev/null +++ b/DreamSim/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,62 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_Dream +formatter_settings_version=12 +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=false +sp_cleanup.always_use_this_for_non_static_method_access=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=false +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=false +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.on_save_use_additional_actions=false +sp_cleanup.organize_imports=true +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=false +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_type_arguments=true +sp_cleanup.remove_trailing_whitespaces=false +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=false +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=true +sp_cleanup.use_parentheses_in_expressions=false +sp_cleanup.use_this_for_non_static_field_access=false +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true +sp_cleanup.use_this_for_non_static_method_access=false +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true +sp_cleanup.use_type_arguments=false diff --git a/DreamSim/conf/dream.conf b/DreamSim/conf/dream.conf index a6ff14f..56310c7 100755 --- a/DreamSim/conf/dream.conf +++ b/DreamSim/conf/dream.conf @@ -35,7 +35,8 @@ consistencyType = 6 # minCommunicationDelayInMs = 1 maxCommunicationDelayInMs = 5 -linkLength = 1 +numHopsPerLink = 1 +numHopsToLockManager = 2 # # LOAD GENERATION diff --git a/DreamSim/scripts/plotScriptSidUp.plot b/DreamSim/scripts/plotScriptSidUp.plot index 2b7b94b..58ad85d 100644 --- a/DreamSim/scripts/plotScriptSidUp.plot +++ b/DreamSim/scripts/plotScriptSidUp.plot @@ -1,4 +1,4 @@ -set terminal postscript enhance color dashed dl 4 font 16 +set terminal postscript enhance color dashed dl 4 font 1b6 set pointsize 3 # set size ratio 0.55 @@ -135,7 +135,7 @@ plot "../resultsAvg/numGraphDependencies_causal_TrafficByte" u ($1):($8/1000) t # GRAPH SHARE PROBABILITY # ########################### -set xlabel "Probability for a signal to depend on multiple sources" offset 0,0.2 +set xlabel "Degree of nodes sharing" offset 0,0.2 set output "../graphs/graphShareDelay.ps" set ylabel "Average Delay (ms)" offset 0.5,0 diff --git a/DreamSim/scripts/plotScriptSidUpIntervals.plot b/DreamSim/scripts/plotScriptSidUpIntervals.plot index 1899433..048c7b5 100644 --- a/DreamSim/scripts/plotScriptSidUpIntervals.plot +++ b/DreamSim/scripts/plotScriptSidUpIntervals.plot @@ -1,24 +1,34 @@ -set terminal postscript enhance color dashed dl 4 font 16 +set terminal pdf fsize 15 size 4.2,3.6 + set pointsize 3 -# set size ratio 0.55 +# set size ratio 0.4 -set style line 1 lw 4 lt rgb 'orange' pt 1 -set style line 2 lw 4 lt rgb 'black' pt 6 -set style line 3 lw 4 lt rgb 'green' pt 8 -set style line 4 lw 4 lt rgb 'blue' pt 3 -set style line 5 lw 4 lt rgb 'red' pt 2 +set style line 1 lw 4 lt 1 lc rgb 'orange' pt 1 +set style line 2 lw 4 lt 2 lc rgb 'black' pt 6 +set style line 3 lw 4 lt 3 lc rgb 'green' pt 8 +set style line 4 lw 4 lt 4 lc rgb 'blue' pt 3 +set style line 5 lw 4 lt 5 lc rgb 'red' pt 2 + +# set style line 1 linecolor rgb "black" lw 3 dashtype 1 pt 1 +# set style line 2 linecolor rgb "black" lw 3 dashtype 2 pt 6 +# set style line 3 linecolor rgb "black" lw 3 dashtype 3 pt 8 +# set style line 4 linecolor rgb "black" lw 3 dashtype 4 pt 3 +# set style line 5 linecolor rgb "black" lw 3 dashtype 5 pt 2 -set key above set log y +set format y "10^%T" ############ # LOCALITY # ############ +set key bottom left + set xlabel "Degree of locality" offset 0,0.2 -set output "../graphs/localityDelay.ps" +set output "../graphs/localityDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr plot "../resultsAvg/locality_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls 1, \ "../resultsAvg/locality_single_glitch_free_DelayAvg" u 1:2:3 t "Single" w yerrorbars ls 2, \ @@ -31,8 +41,9 @@ plot "../resultsAvg/locality_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls "../resultsAvg/locality_atomic_DelayAvg" u 1:2 notitle w lines ls 4, \ "../resultsAvg/locality_sid_up_DelayAvg" u 1:2 notitle w lines ls 5 -set output "../graphs/localityTraffic.ps" +set output "../graphs/localityTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr plot "../resultsAvg/locality_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/locality_single_glitch_free_TrafficByte" u ($1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -49,10 +60,14 @@ plot "../resultsAvg/locality_causal_TrafficByte" u ($1):($8/1000):($15/1000) t " # NUMBER OF BROKERS # ##################### +set key top right + set xlabel "Number of brokers" offset 0,0.2 -set output "../graphs/numBrokersDelay.ps" +set output "../graphs/numBrokersDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr +set xtics 5 plot "../resultsAvg/numBrokers_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls 1, \ "../resultsAvg/numBrokers_single_glitch_free_DelayAvg" u 1:2:3 t "Single" w yerrorbars ls 2, \ @@ -65,8 +80,9 @@ plot "../resultsAvg/numBrokers_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars "../resultsAvg/numBrokers_atomic_DelayAvg" u 1:2 notitle w lines ls 4, \ "../resultsAvg/numBrokers_sid_up_DelayAvg" u 1:2 notitle w lines ls 5 -set output "../graphs/numBrokersTraffic.ps" +set output "../graphs/numBrokersTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr plot "../resultsAvg/numBrokers_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/numBrokers_single_glitch_free_TrafficByte" u ($1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -79,14 +95,20 @@ plot "../resultsAvg/numBrokers_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "../resultsAvg/numBrokers_atomic_TrafficByte" u ($1):($8/1000) notitle w lines ls 4, \ "../resultsAvg/numBrokers_sid_up_TrafficByte" u ($1):($8/1000) notitle w lines ls 5 +set xtics auto + ################## # NUMBER OF VARS # ################## +set key center right + set xlabel "Number of sources (vars) in the graph" offset 0,0.2 -set output "../graphs/numVarsDelay.ps" +set output "../graphs/numVarsDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr +set xtics 20 plot "../resultsAvg/numVars_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls 1, \ "../resultsAvg/numVars_single_glitch_free_DelayAvg" u 1:2:3 t "Single" w yerrorbars ls 2, \ @@ -99,8 +121,11 @@ plot "../resultsAvg/numVars_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls "../resultsAvg/numVars_atomic_DelayAvg" u 1:2 notitle w lines ls 4, \ "../resultsAvg/numVars_sid_up_DelayAvg" u 1:2 notitle w lines ls 5 -set output "../graphs/numVarsTraffic.ps" +set key bottom right + +set output "../graphs/numVarsTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr plot "../resultsAvg/numVars_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/numVars_single_glitch_free_TrafficByte" u ($1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -113,14 +138,19 @@ plot "../resultsAvg/numVars_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "C "../resultsAvg/numVars_atomic_TrafficByte" u ($1):($8/1000) notitle w lines ls 4, \ "../resultsAvg/numVars_sid_up_TrafficByte" u ($1):($8/1000) notitle w lines ls 5 +set xtics auto + ############### # GRAPH DEPTH # ############### +set key bottom right + set xlabel "Depth of the dependency graph" offset 0,0.2 -set output "../graphs/graphDepthDelay.ps" +set output "../graphs/graphDepthDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr plot "../resultsAvg/graphDepth_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls 1, \ "../resultsAvg/graphDepth_single_glitch_free_DelayAvg" u 1:2:3 t "Single" w yerrorbars ls 2, \ @@ -133,8 +163,9 @@ plot "../resultsAvg/graphDepth_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars "../resultsAvg/graphDepth_atomic_DelayAvg" u 1:2 notitle w lines ls 4, \ "../resultsAvg/graphDepth_sid_up_DelayAvg" u 1:2 notitle w lines ls 5 -set output "../graphs/graphDepthTraffic.ps" +set output "../graphs/graphDepthTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr plot "../resultsAvg/graphDepth_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/graphDepth_single_glitch_free_TrafficByte" u ($1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -151,10 +182,14 @@ plot "../resultsAvg/graphDepth_causal_TrafficByte" u ($1):($8/1000):($15/1000) t # NUMBER OF DEPENDENCIES PER SIGNAL # ##################################### +set key bottom right + set xlabel "Number of dependencies per signal" offset 0,0.2 -set output "../graphs/numGraphDependenciesDelay.ps" +set output "../graphs/numGraphDependenciesDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr +set yr[1:] plot "../resultsAvg/numGraphDependencies_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls 1, \ "../resultsAvg/numGraphDependencies_single_glitch_free_DelayAvg" u 1:2:3 t "Single" w yerrorbars ls 2, \ @@ -167,8 +202,10 @@ plot "../resultsAvg/numGraphDependencies_causal_DelayAvg" u 1:2:3 t "Causal" w y "../resultsAvg/numGraphDependencies_atomic_DelayAvg" u 1:2 notitle w lines ls 4, \ "../resultsAvg/numGraphDependencies_sid_up_DelayAvg" u 1:2 notitle w lines ls 5 -set output "../graphs/numGraphDependenciesTraffic.ps" +set output "../graphs/numGraphDependenciesTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr +set yr[1:] plot "../resultsAvg/numGraphDependencies_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/numGraphDependencies_single_glitch_free_TrafficByte" u ($1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -185,10 +222,13 @@ plot "../resultsAvg/numGraphDependencies_causal_TrafficByte" u ($1):($8/1000):($ # GRAPH SHARE PROBABILITY # ########################### -set xlabel "Probability for a signal to depend on multiple sources" offset 0,0.2 +set key top left -set output "../graphs/graphShareDelay.ps" +set xlabel "Degree of nodes sharing" offset 0,0.2 + +set output "../graphs/graphShareDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr plot "../resultsAvg/graphShare_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars ls 1, \ "../resultsAvg/graphShare_single_glitch_free_DelayAvg" u 1:2:3 t "Single" w yerrorbars ls 2, \ @@ -201,8 +241,10 @@ plot "../resultsAvg/graphShare_causal_DelayAvg" u 1:2:3 t "Causal" w yerrorbars "../resultsAvg/graphShare_atomic_DelayAvg" u 1:2 notitle w lines ls 4, \ "../resultsAvg/graphShare_sid_up_DelayAvg" u 1:2 notitle w lines ls 5 -set output "../graphs/graphShareTraffic.ps" +set output "../graphs/graphShareTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr +set yr[:10000] plot "../resultsAvg/graphShare_causal_TrafficByte" u ($1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/graphShare_single_glitch_free_TrafficByte" u ($1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -219,11 +261,15 @@ plot "../resultsAvg/graphShare_causal_TrafficByte" u ($1):($8/1000):($15/1000) t # TIME BETWEEN EVENTS # ####################### +set key top left + set xlabel "Publication frequency (k events/s)" offset 0,0.2 set log x -set output "../graphs/pubFrequencyDelay.ps" +set output "../graphs/pubFrequencyDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr +set yr[:10000000] plot "../resultsAvg/timeBetweenEvents_causal_DelayAvg" u (1000/$1):($2):($3) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/timeBetweenEvents_single_glitch_free_DelayAvg" u (1000/$1):($2):($3) t "Single" w yerrorbars ls 2, \ @@ -236,8 +282,11 @@ plot "../resultsAvg/timeBetweenEvents_causal_DelayAvg" u (1000/$1):($2):($3) t " "../resultsAvg/timeBetweenEvents_atomic_DelayAvg" u (1000/$1):($2) notitle w lines ls 4, \ "../resultsAvg/timeBetweenEvents_sid_up_DelayAvg" u (1000/$1):($2) notitle w lines ls 5 -set output "../graphs/pubFrequencyTraffic.ps" +set key bottom right + +set output "../graphs/pubFrequencyTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr plot "../resultsAvg/timeBetweenEvents_causal_TrafficByte" u (1000/$1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/timeBetweenEvents_single_glitch_free_TrafficByte" u (1000/$1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -254,12 +303,15 @@ plot "../resultsAvg/timeBetweenEvents_causal_TrafficByte" u (1000/$1):($8/1000): # TIME BETWEEN READS # ###################### +set key top left + set xlabel "Signal access frequency (k reads/s)" offset 0,0.2 set log x set xr [0.1:2.5] -set output "../graphs/readFrequencyDelay.ps" +set output "../graphs/readFrequencyDelay.pdf" set ylabel "Average Delay (ms)" offset 0.5,0 +unset yr plot "../resultsAvg/timeBetweenReads_causal_DelayAvg" u (1000/$1):($2):($3) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/timeBetweenReads_single_glitch_free_DelayAvg" u (1000/$1):($2):($3) t "Single" w yerrorbars ls 2, \ @@ -272,8 +324,9 @@ plot "../resultsAvg/timeBetweenReads_causal_DelayAvg" u (1000/$1):($2):($3) t "C "../resultsAvg/timeBetweenReads_atomic_DelayAvg" u (1000/$1):($2) notitle w lines ls 4, \ "../resultsAvg/timeBetweenReads_sid_up_DelayAvg" u (1000/$1):($2) notitle w lines ls 5 -set output "../graphs/readFrequencyTraffic.ps" +set output "../graphs/readFrequencyTraffic.pdf" set ylabel "Overall Traffic (KB/s)" offset 0.5,0 +unset yr plot "../resultsAvg/timeBetweenReads_causal_TrafficByte" u (1000/$1):($8/1000):($15/1000) t "Causal" w yerrorbars ls 1, \ "../resultsAvg/timeBetweenReads_single_glitch_free_TrafficByte" u (1000/$1):($8/1000):($15/1000) t "Single" w yerrorbars ls 2, \ @@ -291,24 +344,27 @@ plot "../resultsAvg/timeBetweenReads_causal_TrafficByte" u (1000/$1):($8/1000):( ########### reset +set terminal pdf fsize 12 size 4.2,3.0 -set style line 1 lw 2 lt rgb 'orange' pt 1 -set style line 2 lw 2 lt rgb 'black' pt 6 -set style line 3 lw 2 lt rgb 'green' pt 8 -set style line 4 lw 2 lt rgb 'blue' pt 3 -set style line 5 lw 2 lt rgb 'red' pt 2 +set style line 1 lw 2 lt 1 lc rgb 'black' pt 1 set style data histogram -set style histogram cluster gap 5 -set style fill solid border 0 +set style histogram cluster gap 1 +# set style fill solid border 0 + +set key above +set log y +set format y "10^%T" + set log y -unset xlabel -set xtics rotate by 35 offset -0.5,-2 +set xtics rotate by 35 offset -1.2,-1.6 -set output "../graphs/defaultTraffic.ps" +set output "../graphs/defaultTraffic.pdf" + +set ylabel "Overall Traffic (KB/s)" offset 0.5,0 -plot "../resultsAvg/defaultTraffic" u 2:xticlabel(1) ls 1 title "Causal", \ -"../resultsAvg/defaultTraffic" u 3:xticlabel(1) ls 2 title "Single", \ -"../resultsAvg/defaultTraffic" u 4:xticlabel(1) ls 3 title "Complete", \ -"../resultsAvg/defaultTraffic" u 5:xticlabel(1) ls 4 title "Atomic", \ -"../resultsAvg/defaultTraffic" u 6:xticlabel(1) ls 5 title "Sid Up" \ No newline at end of file +plot "../resultsAvg/defaultTraffic" u ($2/1000):xticlabel(1) ls 1 fs pattern 1 title "Causal", \ +"../resultsAvg/defaultTraffic" u ($3/1000):xticlabel(1) ls 1 fs pattern 2 title "Single", \ +"../resultsAvg/defaultTraffic" u ($4/1000):xticlabel(1) ls 1 fs pattern 3 title "Complete", \ +"../resultsAvg/defaultTraffic" u ($5/1000):xticlabel(1) ls 1 fs pattern 4 title "Atomic", \ +"../resultsAvg/defaultTraffic" u ($6/1000):xticlabel(1) ls 1 fs pattern 5 title "Sid Up" \ No newline at end of file diff --git a/DreamSim/scripts/summarize.py b/DreamSim/scripts/summarize.py index 702aaad..3765fd8 100755 --- a/DreamSim/scripts/summarize.py +++ b/DreamSim/scripts/summarize.py @@ -213,6 +213,14 @@ def avgDelay(filename, suffix, numRepetitions): "\t" + str(deltaDelay) + \ "\n") +def avgAll(filename, values): + global numSeeds + global protocols + for protocol in protocols: + avgTraffic(filename, protocol + "_Traffic", numSeeds) + avgTraffic(filename, protocol + "_TrafficByte", numSeeds) + avgDelay(filename, protocol + "_DelayAvg", numSeeds) + def prepareDefaultTraffic(): causal = open("../resultsAvg/default_causal_TrafficByte", "r").readlines()[0].replace("\n", "").split("\t") single = open("../resultsAvg/default_single_glitch_free_TrafficByte", "r").readlines()[0].replace("\n", "").split("\t") @@ -222,7 +230,7 @@ def prepareDefaultTraffic(): result = open("../resultsAvg/defaultTraffic", "w") - result.write("Events\t" + causal[1] + "\t" + single[1] + "\t" + complete[1] + "\t" + atomic[1] + "\t" + sidup[1] + "\n") + result.write("Ev.\t" + causal[1] + "\t" + single[1] + "\t" + complete[1] + "\t" + atomic[1] + "\t" + sidup[1] + "\n") result.write("Adv.\t" + causal[3] + "\t" + single[3] + "\t" + complete[3] + "\t" + atomic[3] + "\t" + sidup[3] + "\n") result.write("Subs.\t" + causal[2] + "\t" + single[2] + "\t" + complete[2] + "\t" + atomic[2] + "\t" + sidup[2] + "\n") result.write("Req.\t" + causal[5] + "\t" + single[5] + "\t" + complete[5] + "\t" + atomic[5] + "\t" + sidup[5] + "\n") @@ -243,20 +251,11 @@ def prepareDefaultDelay(): result.write("Complete\t" + complete[1] + "\t" + complete[2] + "\n") result.write("Atomic \t" + atomic[1] + "\t" + atomic[2] + "\n") result.write("Sid Up\t" + sidup[1] + "\t" + sidup[2] + "\n") - -def avgAll(filename, values): - global numSeeds - global protocols - for protocol in protocols: - avgTraffic(filename, protocol + "_Traffic", numSeeds) - avgTraffic(filename, protocol + "_TrafficByte", numSeeds) - avgDelay(filename, protocol + "_DelayAvg", numSeeds) # Values default = [0] -centralized = [0] locality = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] -numBrokers = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] +numBrokers = [1, 3, 5, 10, 15, 20] numVars = [1, 4, 7, 10, 40, 70, 100] graphDepth = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] numGraphDependencies = [1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -267,7 +266,6 @@ def avgAll(filename, values): # Invocations summarizeAll("default", default) -summarizeAll("centralized", centralized) summarizeAll("locality", locality) summarizeAll("numBrokers", numBrokers) summarizeAll("numVars", numVars) @@ -278,7 +276,6 @@ def avgAll(filename, values): summarizeAll("timeBetweenReads", timeBetweenReads) avgAll("default", default) -avgAll("centralized", centralized) avgAll("locality", locality) avgAll("numBrokers", numBrokers) avgAll("numVars", numVars) diff --git a/DreamSim/scripts/summarizeSingleRun.py b/DreamSim/scripts/summarizeSingleRun.py index f316d2e..3927faf 100644 --- a/DreamSim/scripts/summarizeSingleRun.py +++ b/DreamSim/scripts/summarizeSingleRun.py @@ -238,36 +238,20 @@ def prepareDefaultTraffic(): result = open("../resultsAvg/defaultTraffic", "w") - result.write("Events\t" + causal[1] + "\t" + single[1] + "\t" + complete[1] + "\t" + atomic[1] + "\t" + sidup[1] + "\n") + result.write("Ev.\t" + causal[1] + "\t" + single[1] + "\t" + complete[1] + "\t" + atomic[1] + "\t" + sidup[1] + "\n") result.write("Adv.\t" + causal[3] + "\t" + single[3] + "\t" + complete[3] + "\t" + atomic[3] + "\t" + sidup[3] + "\n") result.write("Subs.\t" + causal[2] + "\t" + single[2] + "\t" + complete[2] + "\t" + atomic[2] + "\t" + sidup[2] + "\n") result.write("Req.\t" + causal[5] + "\t" + single[5] + "\t" + complete[5] + "\t" + atomic[5] + "\t" + sidup[5] + "\n") result.write("Grant\t" + causal[6] + "\t" + single[6] + "\t" + complete[6] + "\t" + atomic[6] + "\t" + sidup[6] + "\n") result.write("Rel.\t" + causal[4] + "\t" + single[4] + "\t" + complete[4] + "\t" + atomic[4] + "\t" + sidup[4] + "\n") -def prepareDefaultDelay(): - causal = open("../resultsAvg/default_causal_DelayAvg", "r").readlines()[0].replace("\n", "").split("\t") - single = open("../resultsAvg/default_single_glitch_free_DelayAvg", "r").readlines()[0].replace("\n", "").split("\t") - complete = open("../resultsAvg/default_complete_glitch_free_DelayAvg", "r").readlines()[0].replace("\n", "").split("\t") - atomic = open("../resultsAvg/default_atomic_DelayAvg", "r").readlines()[0].replace("\n", "").split("\t") - sidup = open("../resultsAvg/default_sid_up_DelayAvg", "r").readlines()[0].replace("\n", "").split("\t") - - result = open("../resultsAvg/defaultDelay", "w") - - result.write("Causal\t" + causal[1] + "\t" + causal[2] + "\n") - result.write("Single\t" + single[1] + "\t" + single[2] + "\n") - result.write("Complete\t" + complete[1] + "\t" + complete[2] + "\n") - result.write("Atomic \t" + atomic[1] + "\t" + atomic[2] + "\n") - result.write("Sid Up\t" + sidup[1] + "\t" + sidup[2] + "\n") - # Values default = [0] -centralized = [0] locality = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] -numBrokers = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] +numBrokers = [1, 3, 5, 10, 15, 20] numVars = [1, 4, 7, 10, 40, 70, 100] graphDepth = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -numGraphDependencies = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +numGraphDependencies = [1, 2, 3, 4, 5, 6, 7, 8, 9] graphShare = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] timeBetweenEvents = [100, 400, 700, 1000, 4000, 7000, 10000] # timeBetweenReads = [100, 400, 700, 1000, 4000, 7000, 10000] @@ -275,7 +259,6 @@ def prepareDefaultDelay(): # Invocations summarizeAll("default", default) -summarizeAll("centralized", centralized) summarizeAll("locality", locality) summarizeAll("numBrokers", numBrokers) summarizeAll("numVars", numVars) @@ -286,7 +269,6 @@ def prepareDefaultDelay(): summarizeAll("timeBetweenReads", timeBetweenReads) avgAll("default", default) -avgAll("centralized", centralized) avgAll("locality", locality) avgAll("numBrokers", numBrokers) avgAll("numVars", numVars) @@ -297,4 +279,3 @@ def prepareDefaultDelay(): avgAll("timeBetweenReads", timeBetweenReads) prepareDefaultTraffic() -prepareDefaultDelay() diff --git a/DreamSim/src/dream/client/ClientEventForwarder.java b/DreamSim/src/dream/client/ClientEventForwarder.java index 56375f3..555c187 100755 --- a/DreamSim/src/dream/client/ClientEventForwarder.java +++ b/DreamSim/src/dream/client/ClientEventForwarder.java @@ -29,234 +29,237 @@ import protopeer.util.quantities.Time; class ClientEventForwarder extends BasePeerlet { - private ConnectionManager connectionManager; - private final ClientSubscriptionTable subTable = new ClientSubscriptionTable(); - private DreamConfiguration conf; - - // Dependency detectors - private final CompleteGlitchFreeDependencyDetector completeGlitchDepDetector = CompleteGlitchFreeDependencyDetector.instance; - private final AtomicDependencyDetector atomicDepDetector = AtomicDependencyDetector.instance; - private final FinalNodesDetector finalNodesDetector = FinalNodesDetector.instance; - - // Lock applicants waiting for a grant - private final Map lockApplicants = new HashMap<>(); - - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - @Override - public void init(Peer peer) { - super.init(peer); - conf = DreamConfiguration.get(); - connectionManager = (ConnectionManager) peer.getPeerletOfType(ConnectionManager.class); - } - - @Override - public void handleIncomingMessage(Message packet) { - if (packet instanceof AdvertisementPacket) { - logger.finer("Received an advertisement packet " + packet); - processAdvertisementFromServer((AdvertisementPacket) packet); - } else if (packet instanceof SubscriptionPacket) { - logger.fine("Received a subscription packet " + packet); - processSubscriptionFromServer((SubscriptionPacket) packet); - } else if (packet instanceof EventPacket) { - logger.finer("Received an event packet " + packet); - processEventFromServer((EventPacket) packet); - } else if (packet instanceof LockGrantPacket) { - logger.finer("Received lock grant packet " + packet); - processLockGrant((LockGrantPacket) packet); - } - } - - final void sendEvent(UUID id, Event ev, double creationTime, String initialVar) { - logger.finer("Sending an event " + ev); - Set lockReleaseNodes; - switch (conf.consistencyType) { - case DreamConfiguration.COMPLETE_GLITCH_FREE: - case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: - lockReleaseNodes = completeGlitchDepDetector.getNodesToLockFor(initialVar); - break; - case DreamConfiguration.ATOMIC: - case DreamConfiguration.SIDUP: - lockReleaseNodes = finalNodesDetector.getFinalNodesFor(initialVar); - break; - default: - lockReleaseNodes = new HashSet<>(); - } - - final EventPacket evPkt = new EventPacket(ev, id, creationTime, initialVar); - evPkt.setLockReleaseNodes(lockReleaseNodes); - subTable.getMatchingSubscribers(ev).forEach(s -> s.notifyEventReceived(evPkt)); - if (subTable.needsToDeliverToServer(ev)) { - connectionManager.sendEvent(evPkt); - } - } - - /** - * Return false if the lock request is not needed - */ - final void sendReadOnlyLockRequest(String node, LockApplicant applicant) { - if (conf.consistencyType != DreamConfiguration.ATOMIC) { - assert false : conf.consistencyType; - logger.warning("Invoked sendReadOnlyLockRequest() even if the consistency level does not require it."); - return; - } - - logger.finer("Invoked sendReadOnlyLockRequest for node " + node); - final Set nodesToLock = new HashSet<>(); - nodesToLock.add(node); - - final UUID lockId = UUID.randomUUID(); - final LockRequestPacket reqPkt = new LockRequestPacket(getPeer().getNetworkAddress(), lockId, nodesToLock, nodesToLock, LockType.READ_ONLY); - lockApplicants.put(lockId, applicant); - - connectionManager.sendLockRequest(reqPkt); - } - - /** - * Return false if the lock request is not needed - */ - final boolean sendReadWriteLockRequest(String source, UUID packetID, LockApplicant applicant) { - if (conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE && // - conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && // - conf.consistencyType != DreamConfiguration.ATOMIC && // - conf.consistencyType != DreamConfiguration.SIDUP) { - assert false : conf.consistencyType; - logger.warning("Invoked sendReadWriteLockRequest() even if the consistency level does not require it."); - return false; - } - - logger.finer("Invoked sendReadWriteLockRequest for source " + source); - Set nodesToLock; - switch (conf.consistencyType) { - case DreamConfiguration.COMPLETE_GLITCH_FREE: - case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: - nodesToLock = completeGlitchDepDetector.getNodesToLockFor(source); - break; - case DreamConfiguration.ATOMIC: - nodesToLock = atomicDepDetector.getNodesToLockFor(source); - break; - case DreamConfiguration.SIDUP: - nodesToLock = new HashSet<>(); - nodesToLock.add(source); - break; - default: - assert false : conf.consistencyType; - logger.warning("Invoked sendReadWriteLockRequest() even if the consistency level does not require it."); - return false; - } - - final Set releaseNodes = getLockReleaseNodesFor(source); - - if (nodesToLock.isEmpty()) { - return false; - } - - final LockRequestPacket reqPkt = new LockRequestPacket(getPeer().getNetworkAddress(), packetID, nodesToLock, releaseNodes, LockType.READ_WRITE); - lockApplicants.put(packetID, applicant); - - connectionManager.sendLockRequest(reqPkt); - return true; - } - - final Set getLockReleaseNodesFor(String source) { - switch (conf.consistencyType) { - case DreamConfiguration.COMPLETE_GLITCH_FREE: - case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: - return completeGlitchDepDetector.getNodesToLockFor(source); - case DreamConfiguration.ATOMIC: - case DreamConfiguration.SIDUP: - return finalNodesDetector.getFinalNodesFor(source); - default: - return new HashSet<>(); - } - } - - final void sendLockRelease(UUID lockID) { - if (conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE && // - conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && // - conf.consistencyType != DreamConfiguration.ATOMIC && // - conf.consistencyType != DreamConfiguration.SIDUP) { - assert false : conf.consistencyType; - logger.warning("Invoked sendLockRelease() even if the consistency level does not require it."); - return; - } - - connectionManager.sendLockRelease(new LockReleasePacket(lockID)); - } - - final void advertise(Advertisement adv) { - logger.fine("Sending advertisement " + adv); - connectionManager.sendAdvertisement(adv); - } - - final void unadvertise(Advertisement adv) { - logger.fine("Sending unadvertisement " + adv); - connectionManager.sendUnadvertisement(adv); - } - - final void advertise(Advertisement adv, Set subs) { - logger.fine("Sending advertisement " + adv + " with subscriptions " + subs); - connectionManager.sendAdvertisement(adv, subs); - } - - final void unadvertise(Advertisement adv, Set subs, boolean isPublic) { - logger.fine("Sending unadvertisement " + adv + " with subscriptions " + subs); - connectionManager.sendUnadvertisement(adv); - } - - final void addSubscription(Subscriber subscriber, Subscription subscription) { - logger.fine("Adding subscription " + subscription); - subTable.addSubscription(subscriber, subscription); - if (!isLocal(subscription)) { - final Timer timer = getPeer().getClock().createNewTimer(); - timer.addTimerListener(t -> { - connectionManager.sendSubscription(subscription); - }); - timer.schedule(Time.inSeconds(Consts.delayBeforeSendingSubscriptions)); - } - } - - final void removeSubscription(Subscriber subscriber, Subscription subscription) { - logger.fine("Removing subscription " + subscription); - subTable.addSubscription(subscriber, subscription); - if (!isLocal(subscription)) { - connectionManager.sendSubscription(subscription); - } - } - - private final boolean isLocal(Subscription sub) { - final int clientId = ((TrafficGeneratorPeerlet) getPeer().getPeerletOfType(TrafficGeneratorPeerlet.class)).getClientId(); - final String hostId = Consts.hostPrefix + clientId; - return sub.getHostId().equals(hostId); - } - - private final void processEventFromServer(EventPacket evPkt) { - subTable.getMatchingSubscribers(evPkt.getEvent()).forEach(sub -> sub.notifyEventReceived(evPkt)); - } - - private final void processAdvertisementFromServer(AdvertisementPacket advPkt) { - // Nothing to do: in the simulation the update detectors are implemented as - // a singleton object shared between nodes - } - - private final void processSubscriptionFromServer(SubscriptionPacket subPkt) { - switch (subPkt.getSubType()) { - case SUB: - subTable.addServerSubscription(subPkt.getSubscription()); - break; - case UNSUB: - subTable.removeServerSubscription(subPkt.getSubscription()); - break; - default: - assert false : subPkt.getSubType(); - } - } - - private final void processLockGrant(LockGrantPacket lockGrant) { - final UUID lockID = lockGrant.getLockID(); - assert lockApplicants.containsKey(lockID); - final LockApplicant applicant = lockApplicants.remove(lockID); - applicant.notifyLockGranted(lockGrant); - } + private ConnectionManager connectionManager; + private final ClientSubscriptionTable subTable = new ClientSubscriptionTable(); + private DreamConfiguration conf; + + // Dependency detectors + private final CompleteGlitchFreeDependencyDetector completeGlitchDepDetector = CompleteGlitchFreeDependencyDetector.instance; + private final AtomicDependencyDetector atomicDepDetector = AtomicDependencyDetector.instance; + private final FinalNodesDetector finalNodesDetector = FinalNodesDetector.instance; + + // Lock applicants waiting for a grant + private final Map lockApplicants = new HashMap<>(); + + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + @Override + public void init(Peer peer) { + super.init(peer); + conf = DreamConfiguration.get(); + connectionManager = (ConnectionManager) peer.getPeerletOfType(ConnectionManager.class); + } + + @Override + public void handleIncomingMessage(Message packet) { + if (packet instanceof AdvertisementPacket) { + logger.finer("Received an advertisement packet " + packet); + processAdvertisementFromServer((AdvertisementPacket) packet); + } else if (packet instanceof SubscriptionPacket) { + logger.fine("Received a subscription packet " + packet); + processSubscriptionFromServer((SubscriptionPacket) packet); + } else if (packet instanceof EventPacket) { + logger.finer("Received an event packet " + packet); + processEventFromServer((EventPacket) packet); + } else if (packet instanceof LockGrantPacket) { + logger.finer("Received lock grant packet " + packet); + processLockGrant((LockGrantPacket) packet); + } + } + + final void sendEvent(UUID id, Event ev, double creationTime, String initialVar) { + logger.finer("Sending an event " + ev); + Set lockReleaseNodes; + switch (conf.consistencyType) { + case DreamConfiguration.COMPLETE_GLITCH_FREE: + case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: + lockReleaseNodes = completeGlitchDepDetector.getNodesToLockFor(initialVar); + break; + case DreamConfiguration.ATOMIC: + case DreamConfiguration.SIDUP: + lockReleaseNodes = finalNodesDetector.getFinalNodesFor(initialVar); + break; + default: + lockReleaseNodes = new HashSet<>(); + } + + final EventPacket evPkt = new EventPacket(ev, id, creationTime, initialVar); + evPkt.setLockReleaseNodes(lockReleaseNodes); + subTable.getMatchingSubscribers(ev).forEach(s -> s.notifyEventReceived(evPkt)); + if (subTable.needsToDeliverToServer(ev)) { + connectionManager.sendEvent(evPkt); + } + } + + /** + * Return false if the lock request is not needed + */ + final void sendReadOnlyLockRequest(String node, LockApplicant applicant) { + if (conf.consistencyType != DreamConfiguration.ATOMIC) { + assert false : conf.consistencyType; + logger.warning("Invoked sendReadOnlyLockRequest() even if the consistency level does not require it."); + return; + } + + logger.finer("Invoked sendReadOnlyLockRequest for node " + node); + final Set nodesToLock = new HashSet<>(); + nodesToLock.add(node); + + final UUID lockId = UUID.randomUUID(); + final LockRequestPacket reqPkt = new LockRequestPacket(getPeer().getNetworkAddress(), lockId, nodesToLock, + nodesToLock, LockType.READ_ONLY); + lockApplicants.put(lockId, applicant); + + connectionManager.sendLockRequest(reqPkt); + } + + /** + * Return false if the lock request is not needed + */ + final boolean sendReadWriteLockRequest(String source, UUID packetID, LockApplicant applicant) { + if (conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE && // + conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && // + conf.consistencyType != DreamConfiguration.ATOMIC && // + conf.consistencyType != DreamConfiguration.SIDUP) { + assert false : conf.consistencyType; + logger.warning("Invoked sendReadWriteLockRequest() even if the consistency level does not require it."); + return false; + } + + logger.finer("Invoked sendReadWriteLockRequest for source " + source); + Set nodesToLock; + switch (conf.consistencyType) { + case DreamConfiguration.COMPLETE_GLITCH_FREE: + case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: + nodesToLock = completeGlitchDepDetector.getNodesToLockFor(source); + break; + case DreamConfiguration.ATOMIC: + nodesToLock = atomicDepDetector.getNodesToLockFor(source); + break; + case DreamConfiguration.SIDUP: + nodesToLock = new HashSet<>(); + nodesToLock.add(source); + break; + default: + assert false : conf.consistencyType; + logger.warning("Invoked sendReadWriteLockRequest() even if the consistency level does not require it."); + return false; + } + + final Set releaseNodes = getLockReleaseNodesFor(source); + + if (nodesToLock.isEmpty()) { + return false; + } + + final LockRequestPacket reqPkt = new LockRequestPacket(getPeer().getNetworkAddress(), packetID, nodesToLock, + releaseNodes, LockType.READ_WRITE); + lockApplicants.put(packetID, applicant); + + connectionManager.sendLockRequest(reqPkt); + return true; + } + + final Set getLockReleaseNodesFor(String source) { + switch (conf.consistencyType) { + case DreamConfiguration.COMPLETE_GLITCH_FREE: + case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: + return completeGlitchDepDetector.getNodesToLockFor(source); + case DreamConfiguration.ATOMIC: + case DreamConfiguration.SIDUP: + return finalNodesDetector.getFinalNodesFor(source); + default: + return new HashSet<>(); + } + } + + final void sendLockRelease(UUID lockID) { + if (conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE && // + conf.consistencyType != DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && // + conf.consistencyType != DreamConfiguration.ATOMIC && // + conf.consistencyType != DreamConfiguration.SIDUP) { + assert false : conf.consistencyType; + logger.warning("Invoked sendLockRelease() even if the consistency level does not require it."); + return; + } + + connectionManager.sendLockRelease(new LockReleasePacket(lockID)); + } + + final void advertise(Advertisement adv) { + logger.fine("Sending advertisement " + adv); + connectionManager.sendAdvertisement(adv); + } + + final void unadvertise(Advertisement adv) { + logger.fine("Sending unadvertisement " + adv); + connectionManager.sendUnadvertisement(adv); + } + + final void advertise(Advertisement adv, Set subs) { + logger.fine("Sending advertisement " + adv + " with subscriptions " + subs); + connectionManager.sendAdvertisement(adv, subs); + } + + final void unadvertise(Advertisement adv, Set subs, boolean isPublic) { + logger.fine("Sending unadvertisement " + adv + " with subscriptions " + subs); + connectionManager.sendUnadvertisement(adv); + } + + final void addSubscription(Subscriber subscriber, Subscription subscription) { + logger.fine("Adding subscription " + subscription); + subTable.addSubscription(subscriber, subscription); + if (!isLocal(subscription)) { + final Timer timer = getPeer().getClock().createNewTimer(); + timer.addTimerListener(t -> { + connectionManager.sendSubscription(subscription); + }); + timer.schedule(Time.inSeconds(Consts.delayBeforeSendingSubscriptions)); + } + } + + final void removeSubscription(Subscriber subscriber, Subscription subscription) { + logger.fine("Removing subscription " + subscription); + subTable.addSubscription(subscriber, subscription); + if (!isLocal(subscription)) { + connectionManager.sendSubscription(subscription); + } + } + + private final boolean isLocal(Subscription sub) { + final int clientId = ((TrafficGeneratorPeerlet) getPeer().getPeerletOfType(TrafficGeneratorPeerlet.class)) + .getClientId(); + final String hostId = Consts.hostPrefix + clientId; + return sub.getHostId().equals(hostId); + } + + private final void processEventFromServer(EventPacket evPkt) { + subTable.getMatchingSubscribers(evPkt.getEvent()).forEach(sub -> sub.notifyEventReceived(evPkt)); + } + + private final void processAdvertisementFromServer(AdvertisementPacket advPkt) { + // Nothing to do: in the simulation the update detectors are implemented as + // a singleton object shared between nodes + } + + private final void processSubscriptionFromServer(SubscriptionPacket subPkt) { + switch (subPkt.getSubType()) { + case SUB: + subTable.addServerSubscription(subPkt.getSubscription()); + break; + case UNSUB: + subTable.removeServerSubscription(subPkt.getSubscription()); + break; + default: + assert false : subPkt.getSubType(); + } + } + + private final void processLockGrant(LockGrantPacket lockGrant) { + final UUID lockID = lockGrant.getLockID(); + assert lockApplicants.containsKey(lockID); + final LockApplicant applicant = lockApplicants.remove(lockID); + applicant.notifyLockGranted(lockGrant); + } } diff --git a/DreamSim/src/dream/client/ClientFactory.java b/DreamSim/src/dream/client/ClientFactory.java index 121c884..84824de 100755 --- a/DreamSim/src/dream/client/ClientFactory.java +++ b/DreamSim/src/dream/client/ClientFactory.java @@ -7,14 +7,14 @@ public class ClientFactory implements PeerFactory { - @Override - public Peer createPeer(int peerIndex, Experiment experiment) { - final Peer newPeer = new Peer(peerIndex); - newPeer.addPeerlet(new ConnectionManager()); - newPeer.addPeerlet(new ClientEventForwarder()); - newPeer.addPeerlet(new ClientMeasurementPeerlet()); - newPeer.addPeerlet(new TrafficGeneratorPeerlet()); - return newPeer; - } + @Override + public Peer createPeer(int peerIndex, Experiment experiment) { + final Peer newPeer = new Peer(peerIndex); + newPeer.addPeerlet(new ConnectionManager()); + newPeer.addPeerlet(new ClientEventForwarder()); + newPeer.addPeerlet(new ClientMeasurementPeerlet()); + newPeer.addPeerlet(new TrafficGeneratorPeerlet()); + return newPeer; + } } diff --git a/DreamSim/src/dream/client/ClientSubscriptionTable.java b/DreamSim/src/dream/client/ClientSubscriptionTable.java index 598af2f..43fb5ee 100755 --- a/DreamSim/src/dream/client/ClientSubscriptionTable.java +++ b/DreamSim/src/dream/client/ClientSubscriptionTable.java @@ -12,61 +12,62 @@ import dream.common.packets.content.Subscription; final class ClientSubscriptionTable { - private final Map> subs = new HashMap>(); - private final Collection serverSubscriptions = new ArrayList(); + private final Map> subs = new HashMap>(); + private final Collection serverSubscriptions = new ArrayList(); - final void addSubscription(Subscriber subscriber, Subscription sub) { - Collection subsList = subs.get(subscriber); - if (subsList == null) { - subsList = new ArrayList(); - subs.put(subscriber, subsList); - } - subsList.add(sub); - } + final void addSubscription(Subscriber subscriber, Subscription sub) { + Collection subsList = subs.get(subscriber); + if (subsList == null) { + subsList = new ArrayList(); + subs.put(subscriber, subsList); + } + subsList.add(sub); + } - final void addSubscriptions(Subscriber subscriber, Collection subs) { - subs.forEach(sub -> addSubscription(subscriber, sub)); - } + final void addSubscriptions(Subscriber subscriber, Collection subs) { + subs.forEach(sub -> addSubscription(subscriber, sub)); + } - final void addServerSubscription(Subscription sub) { - serverSubscriptions.add(sub); - } + final void addServerSubscription(Subscription sub) { + serverSubscriptions.add(sub); + } - final void removeSubscription(Subscriber subscriber, Subscription sub) { - final Collection subscriptions = subs.get(subscriber); - if (subscriptions == null) { - return; - } - subscriptions.remove(sub); - if (subscriptions.isEmpty()) { - subs.remove(subscriber); - } - } + final void removeSubscription(Subscriber subscriber, Subscription sub) { + final Collection subscriptions = subs.get(subscriber); + if (subscriptions == null) { + return; + } + subscriptions.remove(sub); + if (subscriptions.isEmpty()) { + subs.remove(subscriber); + } + } - final void removeSubscriptions(Subscriber subscriber, Collection subs) { - subs.forEach(sub -> removeSubscription(subscriber, sub)); - } + final void removeSubscriptions(Subscriber subscriber, Collection subs) { + subs.forEach(sub -> removeSubscription(subscriber, sub)); + } - final void removeServerSubscription(Subscription sub) { - serverSubscriptions.remove(sub); - } + final void removeServerSubscription(Subscription sub) { + serverSubscriptions.remove(sub); + } - final Set getMatchingSubscribers(Event ev) { - return getSubscribersWithAnySubscriptionMatching(sub -> sub.isSatisfiedBy(ev)); - } + final Set getMatchingSubscribers(Event ev) { + return getSubscribersWithAnySubscriptionMatching(sub -> sub.isSatisfiedBy(ev)); + } - private final Set getSubscribersWithAnySubscriptionMatching(Predicate predicate) { - final Predicate hasSubscriptionMatchingOnlySignature = subscriber -> subs.get(subscriber).stream().anyMatch(predicate); - return subs.keySet().stream().filter(hasSubscriptionMatchingOnlySignature).collect(Collectors.toSet()); - } + private final Set getSubscribersWithAnySubscriptionMatching(Predicate predicate) { + final Predicate hasSubscriptionMatchingOnlySignature = subscriber -> subs.get(subscriber).stream() + .anyMatch(predicate); + return subs.keySet().stream().filter(hasSubscriptionMatchingOnlySignature).collect(Collectors.toSet()); + } - final boolean needsToDeliverToServer(Event ev) { - return serverSubscriptions.stream().anyMatch(sub -> sub.isSatisfiedBy(ev)); - } + final boolean needsToDeliverToServer(Event ev) { + return serverSubscriptions.stream().anyMatch(sub -> sub.isSatisfiedBy(ev)); + } - @Override - public String toString() { - return "ClientSubscriptionTable [\n subs=" + subs + "\n serverSubscriptions=" + serverSubscriptions + "\n]"; - } + @Override + public String toString() { + return "ClientSubscriptionTable [\n subs=" + subs + "\n serverSubscriptions=" + serverSubscriptions + "\n]"; + } } diff --git a/DreamSim/src/dream/client/ConnectionManager.java b/DreamSim/src/dream/client/ConnectionManager.java index 7a1ec9f..936c6b5 100755 --- a/DreamSim/src/dream/client/ConnectionManager.java +++ b/DreamSim/src/dream/client/ConnectionManager.java @@ -23,83 +23,84 @@ import protopeer.network.NetworkAddress; class ConnectionManager extends BasePeerlet { - private NetworkAddress server = null; - private NetworkAddress lockManager = null; - private DreamConfiguration conf; - - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - @Override - public void init(Peer peer) { - super.init(peer); - conf = DreamConfiguration.get(); - final IClientAssociationGenerator associationGenerator = ClientAssociationGenerator.get(); - final Set componentAssociations = associationGenerator.getAssociation(); - for (final Link l : componentAssociations) { - if (l.getNode2().getId() == peer.getIndexNumber()) { - server = Experiment.getSingleton().getAddressToBindTo(l.getNode1().getId()); - logger.fine("Associating component " + peer.getIndexNumber() + " to " + server); - break; - } - } - lockManager = Experiment.getSingleton().getAddressToBindTo(conf.numberOfBrokers + conf.numberOfClients + 1); - if (server == null) { - logger.warning("server is null"); - } - if (lockManager == null) { - logger.warning("lock manager is null"); - } - } - - final void sendEvent(EventPacket pkt) { - sendToServer(EventPacket.subject, pkt); - } - - final void sendSubscription(Subscription sub) { - final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.SUB); - sendToServer(SubscriptionPacket.subject, pkt); - } - - final void sendUnsubscription(Subscription sub) { - final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.UNSUB); - sendToServer(SubscriptionPacket.subject, pkt); - } - - final void sendAdvertisement(Advertisement adv) { - sendAdvertisement(adv, AdvType.ADV, null); - } - - final void sendAdvertisement(Advertisement adv, Set subs) { - sendAdvertisement(adv, AdvType.ADV, subs); - } - - final void sendUnadvertisement(Advertisement adv) { - sendAdvertisement(adv, AdvType.UNADV, null); - } - - final void sendUnadvertisement(Advertisement adv, Set subs) { - sendAdvertisement(adv, AdvType.UNADV, subs); - } - - final void sendLockRequest(LockRequestPacket req) { - sendToLockManager(LockRequestPacket.subject, req); - } - - final void sendLockRelease(LockReleasePacket rel) { - sendToLockManager(LockReleasePacket.subject, rel); - } - - private final void sendAdvertisement(Advertisement adv, AdvType advType, Set subs) { - final AdvertisementPacket pkt = subs != null ? new AdvertisementPacket(adv, advType, subs) : new AdvertisementPacket(adv, advType); - sendToServer(AdvertisementPacket.subject, pkt); - } - - private final void sendToServer(String subject, Message packet) { - getPeer().sendMessage(server, packet); - } - - private final void sendToLockManager(String subject, Message packet) { - getPeer().sendMessage(lockManager, packet); - } + private NetworkAddress server = null; + private NetworkAddress lockManager = null; + private DreamConfiguration conf; + + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + @Override + public void init(Peer peer) { + super.init(peer); + conf = DreamConfiguration.get(); + final IClientAssociationGenerator associationGenerator = ClientAssociationGenerator.get(); + final Set componentAssociations = associationGenerator.getAssociation(); + for (final Link l : componentAssociations) { + if (l.getNode2().getId() == peer.getIndexNumber()) { + server = Experiment.getSingleton().getAddressToBindTo(l.getNode1().getId()); + logger.fine("Associating component " + peer.getIndexNumber() + " to " + server); + break; + } + } + lockManager = Experiment.getSingleton().getAddressToBindTo(conf.numberOfBrokers + conf.numberOfClients + 1); + if (server == null) { + logger.warning("server is null"); + } + if (lockManager == null) { + logger.warning("lock manager is null"); + } + } + + final void sendEvent(EventPacket pkt) { + sendToServer(EventPacket.subject, pkt); + } + + final void sendSubscription(Subscription sub) { + final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.SUB); + sendToServer(SubscriptionPacket.subject, pkt); + } + + final void sendUnsubscription(Subscription sub) { + final SubscriptionPacket pkt = new SubscriptionPacket(sub, SubType.UNSUB); + sendToServer(SubscriptionPacket.subject, pkt); + } + + final void sendAdvertisement(Advertisement adv) { + sendAdvertisement(adv, AdvType.ADV, null); + } + + final void sendAdvertisement(Advertisement adv, Set subs) { + sendAdvertisement(adv, AdvType.ADV, subs); + } + + final void sendUnadvertisement(Advertisement adv) { + sendAdvertisement(adv, AdvType.UNADV, null); + } + + final void sendUnadvertisement(Advertisement adv, Set subs) { + sendAdvertisement(adv, AdvType.UNADV, subs); + } + + final void sendLockRequest(LockRequestPacket req) { + sendToLockManager(LockRequestPacket.subject, req); + } + + final void sendLockRelease(LockReleasePacket rel) { + sendToLockManager(LockReleasePacket.subject, rel); + } + + private final void sendAdvertisement(Advertisement adv, AdvType advType, Set subs) { + final AdvertisementPacket pkt = subs != null ? new AdvertisementPacket(adv, advType, subs) + : new AdvertisementPacket(adv, advType); + sendToServer(AdvertisementPacket.subject, pkt); + } + + private final void sendToServer(String subject, Message packet) { + getPeer().sendMessage(server, packet); + } + + private final void sendToLockManager(String subject, Message packet) { + getPeer().sendMessage(lockManager, packet); + } } diff --git a/DreamSim/src/dream/client/LockApplicant.java b/DreamSim/src/dream/client/LockApplicant.java index d891785..8fbb122 100644 --- a/DreamSim/src/dream/client/LockApplicant.java +++ b/DreamSim/src/dream/client/LockApplicant.java @@ -7,12 +7,12 @@ */ interface LockApplicant { - /** - * Method invoked when a lock is granted. - * - * @param lockGrant - * the granted lock. - */ - void notifyLockGranted(LockGrantPacket lockGrant); + /** + * Method invoked when a lock is granted. + * + * @param lockGrant + * the granted lock. + */ + void notifyLockGranted(LockGrantPacket lockGrant); } diff --git a/DreamSim/src/dream/client/QueueManager.java b/DreamSim/src/dream/client/QueueManager.java index 20530c0..b033190 100755 --- a/DreamSim/src/dream/client/QueueManager.java +++ b/DreamSim/src/dream/client/QueueManager.java @@ -19,82 +19,82 @@ * to make sure that no glitch can occur. */ class QueueManager { - // WaitingElements, partitioned by id - private final Map waitingElements = new HashMap(); - // Candidate results to deliver (they can be effectively delivered only there - // are no waiting elements). - private final Set pendingResults = new HashSet<>(); + // WaitingElements, partitioned by id + private final Map waitingElements = new HashMap(); + // Candidate results to deliver (they can be effectively delivered only there + // are no waiting elements). + private final Set pendingResults = new HashSet<>(); - final List processEventPacket(EventPacket evPkt, String expression) { - if (DreamConfiguration.get().consistencyType == DreamConfiguration.CAUSAL) { - final List result = new ArrayList<>(); - result.add(evPkt); - return result; - } + final List processEventPacket(EventPacket evPkt, String expression) { + if (DreamConfiguration.get().consistencyType == DreamConfiguration.CAUSAL) { + final List result = new ArrayList<>(); + result.add(evPkt); + return result; + } - final UUID id = evPkt.getId(); - final Set waitingRecommendations = // - IntraSourceDependencyDetector.instance.// - getWaitRecommendations(evPkt.getEvent(), evPkt.getSource()).// - stream().filter(wr -> wr.getExpression().equals(expression)).// - collect(Collectors.toSet()); + final UUID id = evPkt.getId(); + final Set waitingRecommendations = // + IntraSourceDependencyDetector.instance.// + getWaitRecommendations(evPkt.getEvent(), evPkt.getSource()).// + stream().filter(wr -> wr.getExpression().equals(expression)).// + collect(Collectors.toSet()); - if (waitingElements.containsKey(id)) { - final WaitingElement elem = waitingElements.get(id); - elem.processEvent(evPkt); - if (elem.hasFinishedWaiting()) { - elem.getReceivedEvents().forEach(pendingResults::add); - waitingElements.remove(id); - } - } else { - final Set expressionsToWaitFor = getExpressionsToWaitFor(waitingRecommendations); - if (!expressionsToWaitFor.isEmpty()) { - final WaitingElement elem = new WaitingElement(expressionsToWaitFor, evPkt); - waitingElements.put(id, elem); - } else { - pendingResults.add(evPkt); - } - } + if (waitingElements.containsKey(id)) { + final WaitingElement elem = waitingElements.get(id); + elem.processEvent(evPkt); + if (elem.hasFinishedWaiting()) { + elem.getReceivedEvents().forEach(pendingResults::add); + waitingElements.remove(id); + } + } else { + final Set expressionsToWaitFor = getExpressionsToWaitFor(waitingRecommendations); + if (!expressionsToWaitFor.isEmpty()) { + final WaitingElement elem = new WaitingElement(expressionsToWaitFor, evPkt); + waitingElements.put(id, elem); + } else { + pendingResults.add(evPkt); + } + } - final List result = new ArrayList<>(); - if (!waitingElements.containsKey(id)) { - result.addAll(pendingResults); - pendingResults.clear(); - } - return result; - } + final List result = new ArrayList<>(); + if (!waitingElements.containsKey(id)) { + result.addAll(pendingResults); + pendingResults.clear(); + } + return result; + } - private final Set getExpressionsToWaitFor(Set recommendations) { - return recommendations.stream().// - map(wr -> wr.getRecommendations()).// - collect(HashSet::new, HashSet::addAll, HashSet::addAll); - } + private final Set getExpressionsToWaitFor(Set recommendations) { + return recommendations.stream().// + map(wr -> wr.getRecommendations()).// + collect(HashSet::new, HashSet::addAll, HashSet::addAll); + } - private class WaitingElement { - // Set of expressions we are waiting for before delivering the events with - // the given id - private final Set waitingFor = new HashSet<>(); - // Set of events received with the given id - private final Set receivedEvents = new HashSet<>(); + private class WaitingElement { + // Set of expressions we are waiting for before delivering the events with + // the given id + private final Set waitingFor = new HashSet<>(); + // Set of events received with the given id + private final Set receivedEvents = new HashSet<>(); - WaitingElement(Set waitingFor, EventPacket evPkt) { - this.waitingFor.addAll(waitingFor); - receivedEvents.add(evPkt); - } + WaitingElement(Set waitingFor, EventPacket evPkt) { + this.waitingFor.addAll(waitingFor); + receivedEvents.add(evPkt); + } - final void processEvent(EventPacket evPkt) { - final String signature = evPkt.getEvent().getSignature(); - assert waitingFor.contains(signature); - waitingFor.remove(signature); - receivedEvents.add(evPkt); - } + final void processEvent(EventPacket evPkt) { + final String signature = evPkt.getEvent().getSignature(); + assert waitingFor.contains(signature); + waitingFor.remove(signature); + receivedEvents.add(evPkt); + } - final boolean hasFinishedWaiting() { - return waitingFor.isEmpty(); - } + final boolean hasFinishedWaiting() { + return waitingFor.isEmpty(); + } - final Set getReceivedEvents() { - return receivedEvents; - } - } + final Set getReceivedEvents() { + return receivedEvents; + } + } } diff --git a/DreamSim/src/dream/client/Signal.java b/DreamSim/src/dream/client/Signal.java index 5ddc8d1..9e196c6 100755 --- a/DreamSim/src/dream/client/Signal.java +++ b/DreamSim/src/dream/client/Signal.java @@ -20,144 +20,151 @@ import protopeer.util.quantities.Time; public class Signal implements LockApplicant, Subscriber { - private final ClientEventForwarder forwarder; - private final QueueManager queueManager = new QueueManager(); - DreamConfiguration conf = DreamConfiguration.get(); - - private final Peer peer; - private final String host; - private final String object; - - private final Queue pendingEvents = new LinkedList<>(); - - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - public Signal(Peer peer, String host, String object, Set subs) { - this.peer = peer; - this.host = host; - this.object = object; - forwarder = (ClientEventForwarder) peer.getPeerletOfType(ClientEventForwarder.class); - forwarder.advertise(new Advertisement(host, object), subs); - subs.forEach(s -> forwarder.addSubscription(this, s)); - } - - @Override - public void notifyEventReceived(EventPacket evPkt) { - logger.finest("processTask method invoked with " + evPkt); - final List eventsList = queueManager.processEventPacket(evPkt, object + "@" + host); - logger.finest("The queueManager returned the following pairs " + eventsList); - - if (!eventsList.isEmpty()) { - logger.finest("Actual update"); - // Extract information from any of the packets - final EventPacket anyPkt = eventsList.stream().findAny().get(); - - // Save event delay - // TODO: check we are using the intended delay semantics - eventsList.forEach(ev -> { - final double delay = peer.getClock().getCurrentTime() - ev.getCreationTime(); - MeasurementLogger.getLogger().saveDelay(delay); - }); - - // Notify local and remote dependent objects - logger.finest("Sending event to dependent objects."); - final Event event = new Event(host, object); - - // Notify remote subscribers (acquiring locks if needed) - final EventPacket packet = new EventPacket(event, anyPkt.getId(), anyPkt.getCreationTime(), anyPkt.getSource()); - pendingEvents.add(packet); - if (pendingEvents.size() == 1) { - processNextEvent(); - } - - // Release locks, if needed - if (anyPkt.getLockReleaseNodes().contains(object + "@" + host) // - && (conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE && LocalityDetector.instance.sourceRequiresLock(anyPkt.getSource()) || // - conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && LocalityDetector.instance.sourceRequiresLock(anyPkt.getSource()) || // - conf.consistencyType == DreamConfiguration.ATOMIC && LocalityDetector.instance.sourceRequiresLock(anyPkt.getSource()) || // - conf.consistencyType == DreamConfiguration.SIDUP)) { - forwarder.sendLockRelease(anyPkt.getId()); - } - - } else { - logger.finest(object + ": update call but waiting: " + evPkt); - } - - } - - private final void processNextEvent() { - if (!pendingEvents.isEmpty()) { - final EventPacket nextPacket = pendingEvents.peek(); - // A signal needs to acquire a lock only in the case of optimized complete - // glitch freedom - if (conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && // - nextPacket.getLockRequestingNode().equals(object + "@" + host)) { - final boolean lockRequired = forwarder.sendReadWriteLockRequest(nextPacket.getSource(), nextPacket.getId(), this); - if (!lockRequired) { - sendNextEventPacket(); - processNextEvent(); - } - } - // Otherwise the update can be immediately processed - else { - sendNextEventPacket(); - processNextEvent(); - } - } - } - - private final void sendNextEventPacket() { - assert !pendingEvents.isEmpty(); - final EventPacket p = pendingEvents.poll(); - forwarder.sendEvent(p.getId(), p.getEvent(), p.getCreationTime(), p.getSource()); - } - - public void atomicRead() { - if (LocalityDetector.instance.nodeRequiresReadLock(object + "@" + host)) { - acquireReadLock(); - } - } - - private final synchronized void acquireReadLock() { - if (conf.consistencyType != DreamConfiguration.ATOMIC) { - logger.warning("Trying to acquire read lock byt consistency is not atomic"); - } else { - forwarder.sendReadOnlyLockRequest(object + "@" + host, this); - } - } - - private final synchronized void releaseLock(UUID lockID) { - if (conf.consistencyType != DreamConfiguration.ATOMIC) { - logger.warning("Trying to acquire read lock byt consistency is not atomic"); - } else { - forwarder.sendLockRelease(lockID); - } - } - - @Override - public final synchronized void notifyLockGranted(LockGrantPacket lockGrant) { - final UUID lockID = lockGrant.getLockID(); - switch (lockGrant.getType()) { - // Reply to a read access to the value of the signal - case READ_ONLY: - // This is possible only in the case of atomic consistency - assert conf.consistencyType == DreamConfiguration.ATOMIC; - final int lockDuration = DreamConfiguration.get().readLockDurationInMs; - final Timer timer = peer.getClock().createNewTimer(); - timer.addTimerListener(t -> releaseLock(lockID)); - timer.schedule(Time.inMilliseconds(lockDuration)); - break; - // Reply to a read-write lock (update to the signal) - case READ_WRITE: - // This is possible only in the case of optimized complete glitch freedom - assert conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED; - assert !pendingEvents.isEmpty(); - sendNextEventPacket(); - processNextEvent(); - break; - default: - assert false : lockGrant.getType(); - } - } + private final ClientEventForwarder forwarder; + private final QueueManager queueManager = new QueueManager(); + DreamConfiguration conf = DreamConfiguration.get(); + + private final Peer peer; + private final String host; + private final String object; + + private final Queue pendingEvents = new LinkedList<>(); + + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + public Signal(Peer peer, String host, String object, Set subs) { + this.peer = peer; + this.host = host; + this.object = object; + forwarder = (ClientEventForwarder) peer.getPeerletOfType(ClientEventForwarder.class); + forwarder.advertise(new Advertisement(host, object), subs); + subs.forEach(s -> forwarder.addSubscription(this, s)); + } + + @Override + public void notifyEventReceived(EventPacket evPkt) { + logger.finest("processTask method invoked with " + evPkt); + final List eventsList = queueManager.processEventPacket(evPkt, object + "@" + host); + logger.finest("The queueManager returned the following pairs " + eventsList); + + if (!eventsList.isEmpty()) { + logger.finest("Actual update"); + // Extract information from any of the packets + final EventPacket anyPkt = eventsList.stream().findAny().get(); + + // Save event delay + // TODO: check we are using the intended delay semantics + eventsList.forEach(ev -> { + final double delay = peer.getClock().getCurrentTime() - ev.getCreationTime(); + MeasurementLogger.getLogger().saveDelay(delay); + }); + + // Notify local and remote dependent objects + logger.finest("Sending event to dependent objects."); + final Event event = new Event(host, object); + + // Notify remote subscribers (acquiring locks if needed) + final EventPacket packet = new EventPacket(event, anyPkt.getId(), anyPkt.getCreationTime(), anyPkt.getSource()); + pendingEvents.add(packet); + if (pendingEvents.size() == 1) { + processNextEvent(); + } + + // Release locks, if needed + if (anyPkt.getLockReleaseNodes().contains(object + "@" + host) // + && (conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE + && LocalityDetector.instance.sourceRequiresLock(anyPkt.getSource()) + || // + conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED + && LocalityDetector.instance.sourceRequiresLock(anyPkt.getSource()) + || // + conf.consistencyType == DreamConfiguration.ATOMIC + && LocalityDetector.instance.sourceRequiresLock(anyPkt.getSource()) + || // + conf.consistencyType == DreamConfiguration.SIDUP)) { + forwarder.sendLockRelease(anyPkt.getId()); + } + + } else { + logger.finest(object + ": update call but waiting: " + evPkt); + } + + } + + private final void processNextEvent() { + if (!pendingEvents.isEmpty()) { + final EventPacket nextPacket = pendingEvents.peek(); + // A signal needs to acquire a lock only in the case of optimized complete + // glitch freedom + if (conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && // + nextPacket.getLockRequestingNode().equals(object + "@" + host)) { + final boolean lockRequired = forwarder.sendReadWriteLockRequest(nextPacket.getSource(), nextPacket.getId(), + this); + if (!lockRequired) { + sendNextEventPacket(); + processNextEvent(); + } + } + // Otherwise the update can be immediately processed + else { + sendNextEventPacket(); + processNextEvent(); + } + } + } + + private final void sendNextEventPacket() { + assert !pendingEvents.isEmpty(); + final EventPacket p = pendingEvents.poll(); + forwarder.sendEvent(p.getId(), p.getEvent(), p.getCreationTime(), p.getSource()); + } + + public void atomicRead() { + if (LocalityDetector.instance.nodeRequiresReadLock(object + "@" + host)) { + acquireReadLock(); + } + } + + private final synchronized void acquireReadLock() { + if (conf.consistencyType != DreamConfiguration.ATOMIC) { + logger.warning("Trying to acquire read lock byt consistency is not atomic"); + } else { + forwarder.sendReadOnlyLockRequest(object + "@" + host, this); + } + } + + private final synchronized void releaseLock(UUID lockID) { + if (conf.consistencyType != DreamConfiguration.ATOMIC) { + logger.warning("Trying to acquire read lock byt consistency is not atomic"); + } else { + forwarder.sendLockRelease(lockID); + } + } + + @Override + public final synchronized void notifyLockGranted(LockGrantPacket lockGrant) { + final UUID lockID = lockGrant.getLockID(); + switch (lockGrant.getType()) { + // Reply to a read access to the value of the signal + case READ_ONLY: + // This is possible only in the case of atomic consistency + assert conf.consistencyType == DreamConfiguration.ATOMIC; + final int lockDuration = DreamConfiguration.get().readLockDurationInMs; + final Timer timer = peer.getClock().createNewTimer(); + timer.addTimerListener(t -> releaseLock(lockID)); + timer.schedule(Time.inMilliseconds(lockDuration)); + break; + // Reply to a read-write lock (update to the signal) + case READ_WRITE: + // This is possible only in the case of optimized complete glitch freedom + assert conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED; + assert !pendingEvents.isEmpty(); + sendNextEventPacket(); + processNextEvent(); + break; + default: + assert false : lockGrant.getType(); + } + } } diff --git a/DreamSim/src/dream/client/Subscriber.java b/DreamSim/src/dream/client/Subscriber.java index f79c141..be94527 100644 --- a/DreamSim/src/dream/client/Subscriber.java +++ b/DreamSim/src/dream/client/Subscriber.java @@ -8,11 +8,11 @@ */ public interface Subscriber { - /** - * Notifies the subscriber that the given event has occurred. - * - * @param event - * the occurred event. - */ - public void notifyEventReceived(EventPacket event); + /** + * Notifies the subscriber that the given event has occurred. + * + * @param event + * the occurred event. + */ + public void notifyEventReceived(EventPacket event); } diff --git a/DreamSim/src/dream/client/TrafficGeneratorPeerlet.java b/DreamSim/src/dream/client/TrafficGeneratorPeerlet.java index bd667d3..0fef009 100755 --- a/DreamSim/src/dream/client/TrafficGeneratorPeerlet.java +++ b/DreamSim/src/dream/client/TrafficGeneratorPeerlet.java @@ -16,98 +16,98 @@ import protopeer.util.quantities.Time; public class TrafficGeneratorPeerlet extends BasePeerlet implements GraphGeneratorListener { - private static int clientIdCount = 0; - - private int clientId; - - public static final void resetCount() { - clientIdCount = 0; - } - - @Override - public void init(Peer peer) { - super.init(peer); - clientId = clientIdCount; - clientIdCount++; - startGraphGeneration(); - registerToGraphGenerator(); - notifyGraph(); - } - - @Override - public void notifyVar(String name) { - final Var var = new Var(getPeer(), name.split("@")[1], name.split("@")[0]); - final Timer timer = getPeer().getClock().createNewTimer(); - - timer.addTimerListener(t -> { - var.modify(); - t.schedule(Time.inMilliseconds(getTimeBetweenVarUpdateInMs())); - }); - - timer.schedule(Time.inSeconds(Consts.startSendingEventsAtSecond)); - } - - @Override - public void notifySignal(String signalName, Set dependencies) { - final Set subs = dependencies.stream()// - .map(dep -> new Subscription(dep.split("@")[1], dep.split("@")[0]))// - .collect(Collectors.toSet()); - final Signal s = new Signal(getPeer(), signalName.split("@")[1], signalName.split("@")[0], subs); - - if (DreamConfiguration.get().consistencyType == DreamConfiguration.ATOMIC) { - final Timer timer = getPeer().getClock().createNewTimer(); - - timer.addTimerListener(t -> { - s.atomicRead(); - t.schedule(Time.inMilliseconds(getTimeBetweenSignalReadInMs())); - }); - - timer.schedule(Time.inSeconds(Consts.startReadingSignalsAtSecond)); - } - } - - public int getClientId() { - return clientId; - } - - private final void registerToGraphGenerator() { - final Timer registerGraphTimer = getPeer().getClock().createNewTimer(); - registerGraphTimer.addTimerListener(timer -> { - GraphGenerator.get().addGraphGeneratorListener(TrafficGeneratorPeerlet.this, clientId); - }); - registerGraphTimer.schedule(Time.inSeconds(Consts.registerToGraphsGeneratorAtSecond)); - } - - private final void startGraphGeneration() { - final Timer graphGenTimer = getPeer().getClock().createNewTimer(); - graphGenTimer.addTimerListener(timer -> { - GraphGenerator.get().generateGraphs(clientId); - }); - graphGenTimer.schedule(Time.inSeconds(Consts.startGraphCreationAtSecond)); - } - - private final void notifyGraph() { - final Timer notifyGraphTimer = getPeer().getClock().createNewTimer(); - notifyGraphTimer.addTimerListener(timer -> { - GraphGenerator.get().notifyListeners(clientId); - }); - notifyGraphTimer.schedule(Time.inSeconds(Consts.startNotifyGraphAtSecond)); - } - - private final double getTimeBetweenVarUpdateInMs() { - final DreamConfiguration conf = DreamConfiguration.get(); - final Random rand = RandomGenerator.get(); - final int minTime = conf.minTimeBetweenEventsInMs; - final int maxTime = conf.maxTimeBetweenEventsInMs; - return minTime == maxTime ? maxTime : minTime + rand.nextInt(maxTime - minTime + 1); - } - - private final double getTimeBetweenSignalReadInMs() { - final DreamConfiguration conf = DreamConfiguration.get(); - final Random rand = RandomGenerator.get(); - final int minTime = conf.minTimeBetweenSignalReadsInMs; - final int maxTime = conf.maxTimeBetweenSignalReadsInMs; - return minTime == maxTime ? maxTime : minTime + rand.nextInt(maxTime - minTime + 1); - } + private static int clientIdCount = 0; + + private int clientId; + + public static final void resetCount() { + clientIdCount = 0; + } + + @Override + public void init(Peer peer) { + super.init(peer); + clientId = clientIdCount; + clientIdCount++; + startGraphGeneration(); + registerToGraphGenerator(); + notifyGraph(); + } + + @Override + public void notifyVar(String name) { + final Var var = new Var(getPeer(), name.split("@")[1], name.split("@")[0]); + final Timer timer = getPeer().getClock().createNewTimer(); + + timer.addTimerListener(t -> { + var.modify(); + t.schedule(Time.inMilliseconds(getTimeBetweenVarUpdateInMs())); + }); + + timer.schedule(Time.inSeconds(Consts.startSendingEventsAtSecond)); + } + + @Override + public void notifySignal(String signalName, Set dependencies) { + final Set subs = dependencies.stream()// + .map(dep -> new Subscription(dep.split("@")[1], dep.split("@")[0]))// + .collect(Collectors.toSet()); + final Signal s = new Signal(getPeer(), signalName.split("@")[1], signalName.split("@")[0], subs); + + if (DreamConfiguration.get().consistencyType == DreamConfiguration.ATOMIC) { + final Timer timer = getPeer().getClock().createNewTimer(); + + timer.addTimerListener(t -> { + s.atomicRead(); + t.schedule(Time.inMilliseconds(getTimeBetweenSignalReadInMs())); + }); + + timer.schedule(Time.inSeconds(Consts.startReadingSignalsAtSecond)); + } + } + + public int getClientId() { + return clientId; + } + + private final void registerToGraphGenerator() { + final Timer registerGraphTimer = getPeer().getClock().createNewTimer(); + registerGraphTimer.addTimerListener(timer -> { + GraphGenerator.get().addGraphGeneratorListener(TrafficGeneratorPeerlet.this, clientId); + }); + registerGraphTimer.schedule(Time.inSeconds(Consts.registerToGraphsGeneratorAtSecond)); + } + + private final void startGraphGeneration() { + final Timer graphGenTimer = getPeer().getClock().createNewTimer(); + graphGenTimer.addTimerListener(timer -> { + GraphGenerator.get().generateGraphs(clientId); + }); + graphGenTimer.schedule(Time.inSeconds(Consts.startGraphCreationAtSecond)); + } + + private final void notifyGraph() { + final Timer notifyGraphTimer = getPeer().getClock().createNewTimer(); + notifyGraphTimer.addTimerListener(timer -> { + GraphGenerator.get().notifyListeners(clientId); + }); + notifyGraphTimer.schedule(Time.inSeconds(Consts.startNotifyGraphAtSecond)); + } + + private final double getTimeBetweenVarUpdateInMs() { + final DreamConfiguration conf = DreamConfiguration.get(); + final Random rand = RandomGenerator.get(); + final int minTime = conf.minTimeBetweenEventsInMs; + final int maxTime = conf.maxTimeBetweenEventsInMs; + return minTime == maxTime ? maxTime : minTime + rand.nextInt(maxTime - minTime + 1); + } + + private final double getTimeBetweenSignalReadInMs() { + final DreamConfiguration conf = DreamConfiguration.get(); + final Random rand = RandomGenerator.get(); + final int minTime = conf.minTimeBetweenSignalReadsInMs; + final int maxTime = conf.maxTimeBetweenSignalReadsInMs; + return minTime == maxTime ? maxTime : minTime + rand.nextInt(maxTime - minTime + 1); + } } diff --git a/DreamSim/src/dream/client/Var.java b/DreamSim/src/dream/client/Var.java index 494828a..e3347cc 100755 --- a/DreamSim/src/dream/client/Var.java +++ b/DreamSim/src/dream/client/Var.java @@ -13,66 +13,72 @@ import protopeer.Peer; public class Var implements LockApplicant { - private final ClientEventForwarder forwarder; - DreamConfiguration conf; + private final ClientEventForwarder forwarder; + DreamConfiguration conf; - private final Peer peer; - private final String host; - private final String object; + private final Peer peer; + private final String host; + private final String object; - private final Queue pendingEvents = new LinkedList<>(); + private final Queue pendingEvents = new LinkedList<>(); - public Var(Peer peer, String host, String object) { - this.peer = peer; - this.forwarder = (ClientEventForwarder) peer.getPeerletOfType(ClientEventForwarder.class); - this.host = host; - this.object = object; - conf = DreamConfiguration.get(); - forwarder.advertise(new Advertisement(host, object)); - } + public Var(Peer peer, String host, String object) { + this.peer = peer; + this.forwarder = (ClientEventForwarder) peer.getPeerletOfType(ClientEventForwarder.class); + this.host = host; + this.object = object; + conf = DreamConfiguration.get(); + forwarder.advertise(new Advertisement(host, object)); + } - public final void modify() { - final EventPacket ev = new EventPacket(new Event(host, object), UUID.randomUUID(), peer.getClock().getCurrentTime(), object + "@" + host); - pendingEvents.add(ev); - if (pendingEvents.size() == 1) { - processNextEvent(); - } - } + public final void modify() { + final EventPacket ev = new EventPacket(new Event(host, object), UUID.randomUUID(), peer.getClock().getCurrentTime(), + object + "@" + host); + pendingEvents.add(ev); + if (pendingEvents.size() == 1) { + processNextEvent(); + } + } - private final void processNextEvent() { - if (!pendingEvents.isEmpty()) { - final EventPacket packet = pendingEvents.peek(); - // In the case of complete glitch freedom or atomic consistency, we - // possibly need to acquire a lock before processing the update - if (conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE && LocalityDetector.instance.sourceRequiresLock(object + "@" + host) || // - conf.consistencyType == DreamConfiguration.ATOMIC && LocalityDetector.instance.sourceRequiresLock(object + "@" + host) || // - conf.consistencyType == DreamConfiguration.SIDUP || // - conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED && packet.getLockRequestingNode().equals(object + "@" + host)) { - final boolean lockRequired = forwarder.sendReadWriteLockRequest(packet.getSource(), packet.getId(), this); - if (!lockRequired) { - sendNextEventPacket(); - processNextEvent(); - } - } - // Otherwise the update can be immediately processed - else { - sendNextEventPacket(); - processNextEvent(); - } - } - } + private final void processNextEvent() { + if (!pendingEvents.isEmpty()) { + final EventPacket packet = pendingEvents.peek(); + // In the case of complete glitch freedom or atomic consistency, we + // possibly need to acquire a lock before processing the update + if (conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE + && LocalityDetector.instance.sourceRequiresLock(object + "@" + host) + || // + conf.consistencyType == DreamConfiguration.ATOMIC + && LocalityDetector.instance.sourceRequiresLock(object + "@" + host) + || // + conf.consistencyType == DreamConfiguration.SIDUP || // + conf.consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED + && packet.getLockRequestingNode().equals(object + "@" + host)) { + final boolean lockRequired = forwarder.sendReadWriteLockRequest(packet.getSource(), packet.getId(), this); + if (!lockRequired) { + sendNextEventPacket(); + processNextEvent(); + } + } + // Otherwise the update can be immediately processed + else { + sendNextEventPacket(); + processNextEvent(); + } + } + } - private final void sendNextEventPacket() { - assert !pendingEvents.isEmpty(); - final EventPacket p = pendingEvents.poll(); - forwarder.sendEvent(p.getId(), p.getEvent(), p.getCreationTime(), p.getEvent().getSignature()); - } + private final void sendNextEventPacket() { + assert !pendingEvents.isEmpty(); + final EventPacket p = pendingEvents.poll(); + forwarder.sendEvent(p.getId(), p.getEvent(), p.getCreationTime(), p.getEvent().getSignature()); + } - @Override - public void notifyLockGranted(LockGrantPacket lockGrant) { - assert !pendingEvents.isEmpty(); - sendNextEventPacket(); - processNextEvent(); - } + @Override + public void notifyLockGranted(LockGrantPacket lockGrant) { + assert !pendingEvents.isEmpty(); + sendNextEventPacket(); + processNextEvent(); + } } diff --git a/DreamSim/src/dream/common/Consts.java b/DreamSim/src/dream/common/Consts.java index 5a98422..d9aa78d 100644 --- a/DreamSim/src/dream/common/Consts.java +++ b/DreamSim/src/dream/common/Consts.java @@ -8,30 +8,30 @@ import java.util.logging.Logger; public final class Consts { - private static final String LOGGING_PROPERTIES_FILE_NAME = "logging.properties"; + private static final String LOGGING_PROPERTIES_FILE_NAME = "logging.properties"; - public static final String hostPrefix = "host"; - public static final String objPrefix = "obj"; + public static final String hostPrefix = "host"; + public static final String objPrefix = "obj"; - public static final double startGraphCreationAtSecond = 1; - public static final double registerToGraphsGeneratorAtSecond = 2; - public static final double startNotifyGraphAtSecond = 3; - public static final double delayBeforeSendingSubscriptions = 1; - public static final double startSendingEventsAtSecond = 10; - public static final double startReadingSignalsAtSecond = 10; + public static final double startGraphCreationAtSecond = 1; + public static final double registerToGraphsGeneratorAtSecond = 2; + public static final double startNotifyGraphAtSecond = 3; + public static final double delayBeforeSendingSubscriptions = 1; + public static final double startSendingEventsAtSecond = 10; + public static final double startReadingSignalsAtSecond = 10; - static { - /** - * Read logging properties - */ - final LogManager manager = LogManager.getLogManager(); - try { - manager.readConfiguration(new FileInputStream(new File(LOGGING_PROPERTIES_FILE_NAME))); - } catch (SecurityException | IOException e) { - e.printStackTrace(); - } - final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - final ConsoleHandler consoleHandler = new ConsoleHandler(); - logger.addHandler(consoleHandler); - } + static { + /** + * Read logging properties + */ + final LogManager manager = LogManager.getLogManager(); + try { + manager.readConfiguration(new FileInputStream(new File(LOGGING_PROPERTIES_FILE_NAME))); + } catch (SecurityException | IOException e) { + e.printStackTrace(); + } + final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + final ConsoleHandler consoleHandler = new ConsoleHandler(); + logger.addHandler(consoleHandler); + } } diff --git a/DreamSim/src/dream/common/Outbox.java b/DreamSim/src/dream/common/Outbox.java index a059eb8..52f9ce0 100755 --- a/DreamSim/src/dream/common/Outbox.java +++ b/DreamSim/src/dream/common/Outbox.java @@ -30,24 +30,24 @@ import protopeer.network.NetworkAddress; public class Outbox { - private final Map> packetsToSend = new HashMap>(); - - // Subject is not used, but introduced to preserve API compatibility - public void add(String subject, Message packet, Collection recipients) { - Collection addressSet = packetsToSend.get(packet); - if (addressSet == null) { - addressSet = new HashSet(); - packetsToSend.put(packet, addressSet); - } - addressSet.addAll(recipients); - } - - public Set getPacketsToSend() { - return packetsToSend.keySet(); - } - - public Collection getRecipientsFor(Message packet) { - return packetsToSend.get(packet); - } + private final Map> packetsToSend = new HashMap>(); + + // Subject is not used, but introduced to preserve API compatibility + public void add(String subject, Message packet, Collection recipients) { + Collection addressSet = packetsToSend.get(packet); + if (addressSet == null) { + addressSet = new HashSet(); + packetsToSend.put(packet, addressSet); + } + addressSet.addAll(recipients); + } + + public Set getPacketsToSend() { + return packetsToSend.keySet(); + } + + public Collection getRecipientsFor(Message packet) { + return packetsToSend.get(packet); + } } diff --git a/DreamSim/src/dream/common/packets/AdvertisementPacket.java b/DreamSim/src/dream/common/packets/AdvertisementPacket.java index 43ef396..8470ec5 100755 --- a/DreamSim/src/dream/common/packets/AdvertisementPacket.java +++ b/DreamSim/src/dream/common/packets/AdvertisementPacket.java @@ -17,48 +17,48 @@ * includes the set of subscriptions that define such dependencies. */ public class AdvertisementPacket extends Message implements Serializable { - private static final long serialVersionUID = 5219175796450319466L; - public static final String subject = "__DREAM_ADVERTISEMENT_PACKET_SUBJECT"; + private static final long serialVersionUID = 5219175796450319466L; + public static final String subject = "__DREAM_ADVERTISEMENT_PACKET_SUBJECT"; - private final Advertisement advertisement; - private final AdvType advType; - private final Set subscriptions = new HashSet<>(); + private final Advertisement advertisement; + private final AdvType advType; + private final Set subscriptions = new HashSet<>(); - public AdvertisementPacket(Advertisement advertisement, AdvType advType, Set subscriptions) { - this(advertisement, advType); - this.subscriptions.addAll(subscriptions); - } + public AdvertisementPacket(Advertisement advertisement, AdvType advType, Set subscriptions) { + this(advertisement, advType); + this.subscriptions.addAll(subscriptions); + } - public AdvertisementPacket(Advertisement advertisement, AdvType advType) { - this.advertisement = advertisement; - this.advType = advType; - } + public AdvertisementPacket(Advertisement advertisement, AdvType advType) { + this.advertisement = advertisement; + this.advType = advType; + } - public Advertisement getAdvertisement() { - return advertisement; - } + public Advertisement getAdvertisement() { + return advertisement; + } - public AdvType getAdvType() { - return advType; - } + public AdvType getAdvType() { + return advType; + } - public final Set getSubscriptions() { - return subscriptions; - } + public final Set getSubscriptions() { + return subscriptions; + } - @Override - public Data getSize() { - // TODO: estimate the real size - return Data.inKByte(1); - } + @Override + public Data getSize() { + // TODO: estimate the real size + return Data.inKByte(1); + } - @Override - public String toString() { - if (subscriptions != null) { - return advType + ": " + advertisement.toString() + " - Depending on: " + subscriptions; - } else { - return advType + ": " + advertisement.toString(); - } - } + @Override + public String toString() { + if (subscriptions != null) { + return advType + ": " + advertisement.toString() + " - Depending on: " + subscriptions; + } else { + return advType + ": " + advertisement.toString(); + } + } } diff --git a/DreamSim/src/dream/common/packets/EventPacket.java b/DreamSim/src/dream/common/packets/EventPacket.java index af30c0b..53adb3e 100755 --- a/DreamSim/src/dream/common/packets/EventPacket.java +++ b/DreamSim/src/dream/common/packets/EventPacket.java @@ -15,77 +15,78 @@ * Packet used to deliver events, which notify about some state change. */ public class EventPacket extends Message implements Serializable { - private static final long serialVersionUID = 8208653909787190211L; - public static final String subject = "__DREAM_PUBLICATION_PACKET_SUBJECT"; - - private final Event event; - - // Uniquely identifies a propagation. In the case of complete glitch free and - // atomic consistency, it is identical to the id of the read lock associated - // to the propagation. - private final UUID id; - - // Creation time - private final double creationTime; - - // Original source of the change - private final String source; - - // Node that should request the lock for the propagation, if any - private final String lockRequestingNode; - - // Nodes that should release the lock for the propagation, if any - private final Set lockReleaseNodes = new HashSet<>(); - - public EventPacket(Event event, UUID id, double creationTime, String source) { - this.event = event; - this.id = id; - this.creationTime = creationTime; - this.source = source; - this.lockRequestingNode = // - DreamConfiguration.get().consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED // - ? CompleteGlitchFreeDependencyDetector.instance.getLockRequestNodeFor(source) // - : source; - } - - public final Event getEvent() { - return event; - } - - public final UUID getId() { - return id; - } - - public final double getCreationTime() { - return creationTime; - } - - public final String getSource() { - return source; - } - - public final String getLockRequestingNode() { - return lockRequestingNode; - } - - public final void setLockReleaseNodes(Set lockReleaseNodes) { - this.lockReleaseNodes.addAll(lockReleaseNodes); - lockReleaseNodes.remove(lockRequestingNode); - } - - public final Set getLockReleaseNodes() { - return lockReleaseNodes; - } - - @Override - public Data getSize() { - // TODO: estimate the real size - return Data.inKByte(1); - } - - @Override - public String toString() { - return "EventPacket [event=" + event + ", id=" + id + ", source=" + source + ", lockReleaseNodes=" + lockReleaseNodes + "]"; - } + private static final long serialVersionUID = 8208653909787190211L; + public static final String subject = "__DREAM_PUBLICATION_PACKET_SUBJECT"; + + private final Event event; + + // Uniquely identifies a propagation. In the case of complete glitch free and + // atomic consistency, it is identical to the id of the read lock associated + // to the propagation. + private final UUID id; + + // Creation time + private final double creationTime; + + // Original source of the change + private final String source; + + // Node that should request the lock for the propagation, if any + private final String lockRequestingNode; + + // Nodes that should release the lock for the propagation, if any + private final Set lockReleaseNodes = new HashSet<>(); + + public EventPacket(Event event, UUID id, double creationTime, String source) { + this.event = event; + this.id = id; + this.creationTime = creationTime; + this.source = source; + this.lockRequestingNode = // + DreamConfiguration.get().consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED // + ? CompleteGlitchFreeDependencyDetector.instance.getLockRequestNodeFor(source) // + : source; + } + + public final Event getEvent() { + return event; + } + + public final UUID getId() { + return id; + } + + public final double getCreationTime() { + return creationTime; + } + + public final String getSource() { + return source; + } + + public final String getLockRequestingNode() { + return lockRequestingNode; + } + + public final void setLockReleaseNodes(Set lockReleaseNodes) { + this.lockReleaseNodes.addAll(lockReleaseNodes); + lockReleaseNodes.remove(lockRequestingNode); + } + + public final Set getLockReleaseNodes() { + return lockReleaseNodes; + } + + @Override + public Data getSize() { + // TODO: estimate the real size + return Data.inKByte(1); + } + + @Override + public String toString() { + return "EventPacket [event=" + event + ", id=" + id + ", source=" + source + ", lockReleaseNodes=" + + lockReleaseNodes + "]"; + } } diff --git a/DreamSim/src/dream/common/packets/SubscriptionPacket.java b/DreamSim/src/dream/common/packets/SubscriptionPacket.java index 606fa28..1896011 100755 --- a/DreamSim/src/dream/common/packets/SubscriptionPacket.java +++ b/DreamSim/src/dream/common/packets/SubscriptionPacket.java @@ -12,34 +12,34 @@ * specific events. */ public class SubscriptionPacket extends Message implements Serializable { - private static final long serialVersionUID = -9026500933220636540L; - public static final String subject = "__DREAM_SUBSCRIPTION_PACKET_SUBJECT"; - - private final Subscription subscription; - private final SubType subType; - - public SubscriptionPacket(Subscription subscription, SubType subType) { - this.subscription = subscription; - this.subType = subType; - } - - public final SubType getSubType() { - return subType; - } - - public final Subscription getSubscription() { - return subscription; - } - - @Override - public Data getSize() { - // TODO: estimate the real size - return Data.inKByte(1); - } - - @Override - public String toString() { - return subType + " " + subscription.toString(); - } + private static final long serialVersionUID = -9026500933220636540L; + public static final String subject = "__DREAM_SUBSCRIPTION_PACKET_SUBJECT"; + + private final Subscription subscription; + private final SubType subType; + + public SubscriptionPacket(Subscription subscription, SubType subType) { + this.subscription = subscription; + this.subType = subType; + } + + public final SubType getSubType() { + return subType; + } + + public final Subscription getSubscription() { + return subscription; + } + + @Override + public Data getSize() { + // TODO: estimate the real size + return Data.inKByte(1); + } + + @Override + public String toString() { + return subType + " " + subscription.toString(); + } } diff --git a/DreamSim/src/dream/common/packets/content/AdvType.java b/DreamSim/src/dream/common/packets/content/AdvType.java index 3aa2541..a6653f2 100755 --- a/DreamSim/src/dream/common/packets/content/AdvType.java +++ b/DreamSim/src/dream/common/packets/content/AdvType.java @@ -1,5 +1,5 @@ package dream.common.packets.content; public enum AdvType { - ADV, UNADV + ADV, UNADV } diff --git a/DreamSim/src/dream/common/packets/content/Advertisement.java b/DreamSim/src/dream/common/packets/content/Advertisement.java index 240c49f..985bb18 100755 --- a/DreamSim/src/dream/common/packets/content/Advertisement.java +++ b/DreamSim/src/dream/common/packets/content/Advertisement.java @@ -3,35 +3,35 @@ import java.io.Serializable; public class Advertisement implements Serializable { - private static final long serialVersionUID = -6636280874981657399L; + private static final long serialVersionUID = -6636280874981657399L; - private final String hostId; - private final String objectId; + private final String hostId; + private final String objectId; - public Advertisement(String hostId, String objectId) { - this.hostId = hostId; - this.objectId = objectId; - } + public Advertisement(String hostId, String objectId) { + this.hostId = hostId; + this.objectId = objectId; + } - public boolean isSatisfiedBy(Subscription sub) { - return hostId.equals(sub.getHostId()) && objectId.equals(sub.getObjectId()); - } + public boolean isSatisfiedBy(Subscription sub) { + return hostId.equals(sub.getHostId()) && objectId.equals(sub.getObjectId()); + } - public final String getObjectId() { - return objectId; - } + public final String getObjectId() { + return objectId; + } - public final String getHostId() { - return hostId; - } + public final String getHostId() { + return hostId; + } - public final String getSignature() { - return objectId + "@" + hostId; - } + public final String getSignature() { + return objectId + "@" + hostId; + } - @Override - public String toString() { - return "Advertisement [" + getSignature() + "]"; - } + @Override + public String toString() { + return "Advertisement [" + getSignature() + "]"; + } } diff --git a/DreamSim/src/dream/common/packets/content/Event.java b/DreamSim/src/dream/common/packets/content/Event.java index 6916a6c..98ee64e 100755 --- a/DreamSim/src/dream/common/packets/content/Event.java +++ b/DreamSim/src/dream/common/packets/content/Event.java @@ -3,31 +3,31 @@ import java.io.Serializable; public class Event implements Serializable { - private static final long serialVersionUID = 831217881290695190L; + private static final long serialVersionUID = 831217881290695190L; - private final String objectId; - private final String hostId; + private final String objectId; + private final String hostId; - public Event(String hostId, String objectId) { - this.hostId = hostId; - this.objectId = objectId; - } + public Event(String hostId, String objectId) { + this.hostId = hostId; + this.objectId = objectId; + } - public final String getObjectId() { - return objectId; - } + public final String getObjectId() { + return objectId; + } - public final String getHostId() { - return hostId; - } + public final String getHostId() { + return hostId; + } - public final String getSignature() { - return objectId + "@" + hostId; - } + public final String getSignature() { + return objectId + "@" + hostId; + } - @Override - public String toString() { - return "Event [" + getSignature() + "]"; - } + @Override + public String toString() { + return "Event [" + getSignature() + "]"; + } } diff --git a/DreamSim/src/dream/common/packets/content/SubType.java b/DreamSim/src/dream/common/packets/content/SubType.java index a328524..53fa264 100755 --- a/DreamSim/src/dream/common/packets/content/SubType.java +++ b/DreamSim/src/dream/common/packets/content/SubType.java @@ -1,5 +1,5 @@ package dream.common.packets.content; public enum SubType { - SUB, UNSUB + SUB, UNSUB } diff --git a/DreamSim/src/dream/common/packets/content/Subscription.java b/DreamSim/src/dream/common/packets/content/Subscription.java index 6b59356..d526c9a 100755 --- a/DreamSim/src/dream/common/packets/content/Subscription.java +++ b/DreamSim/src/dream/common/packets/content/Subscription.java @@ -3,35 +3,35 @@ import java.io.Serializable; public class Subscription implements Serializable { - private static final long serialVersionUID = -3452847781395458670L; + private static final long serialVersionUID = -3452847781395458670L; - private final String objectId; - private final String hostId; + private final String objectId; + private final String hostId; - public Subscription(String hostId, String objectId) { - this.hostId = hostId; - this.objectId = objectId; - } + public Subscription(String hostId, String objectId) { + this.hostId = hostId; + this.objectId = objectId; + } - public final boolean isSatisfiedBy(Event ev) { - return ev.getHostId().equals(hostId) && ev.getObjectId().equals(objectId); - } + public final boolean isSatisfiedBy(Event ev) { + return ev.getHostId().equals(hostId) && ev.getObjectId().equals(objectId); + } - public final String getObjectId() { - return objectId; - } + public final String getObjectId() { + return objectId; + } - public final String getHostId() { - return hostId; - } + public final String getHostId() { + return hostId; + } - public final String getSignature() { - return objectId + "@" + hostId; - } + public final String getSignature() { + return objectId + "@" + hostId; + } - @Override - public String toString() { - return "Subscription[" + getSignature() + "]"; - } + @Override + public String toString() { + return "Subscription[" + getSignature() + "]"; + } } diff --git a/DreamSim/src/dream/common/packets/discovery/LockManagerHelloPacket.java b/DreamSim/src/dream/common/packets/discovery/LockManagerHelloPacket.java index 1f3cd04..9c94dd1 100644 --- a/DreamSim/src/dream/common/packets/discovery/LockManagerHelloPacket.java +++ b/DreamSim/src/dream/common/packets/discovery/LockManagerHelloPacket.java @@ -7,7 +7,7 @@ * connects to it. */ public class LockManagerHelloPacket implements Serializable { - private static final long serialVersionUID = -7563002622651694641L; + private static final long serialVersionUID = -7563002622651694641L; - public static final String subject = "__DREAM_LOCK_MANAGER_HELLO_PACKET_SUBJECT"; + public static final String subject = "__DREAM_LOCK_MANAGER_HELLO_PACKET_SUBJECT"; } diff --git a/DreamSim/src/dream/common/packets/discovery/ServerHelloPacket.java b/DreamSim/src/dream/common/packets/discovery/ServerHelloPacket.java index 6e6b227..35f98f0 100644 --- a/DreamSim/src/dream/common/packets/discovery/ServerHelloPacket.java +++ b/DreamSim/src/dream/common/packets/discovery/ServerHelloPacket.java @@ -7,7 +7,7 @@ * connects to it. */ public class ServerHelloPacket implements Serializable { - private static final long serialVersionUID = 3429557416466895040L; + private static final long serialVersionUID = 3429557416466895040L; - public static final String subject = "__DREAM_SERVER_HELLO_PACKET_SUBJECT"; + public static final String subject = "__DREAM_SERVER_HELLO_PACKET_SUBJECT"; } diff --git a/DreamSim/src/dream/common/packets/locking/LockGrantPacket.java b/DreamSim/src/dream/common/packets/locking/LockGrantPacket.java index 106b606..abf1218 100644 --- a/DreamSim/src/dream/common/packets/locking/LockGrantPacket.java +++ b/DreamSim/src/dream/common/packets/locking/LockGrantPacket.java @@ -7,34 +7,34 @@ import protopeer.util.quantities.Data; public class LockGrantPacket extends Message implements Serializable { - private static final long serialVersionUID = -3499224800050816098L; - public static final String subject = "__DREAM_LOCK_GRANT_PACKET_SUBJECT"; - - private final UUID lockID; - private final LockType type; - - public LockGrantPacket(LockRequestPacket reqPkt) { - this.lockID = reqPkt.getLockID(); - this.type = reqPkt.getType(); - } - - public final UUID getLockID() { - return lockID; - } - - public final LockType getType() { - return type; - } - - @Override - public Data getSize() { - // TODO: estimate the real size - return Data.inKByte(1); - } - - @Override - public String toString() { - return "LockGrantPacket [lockID=" + lockID + "]"; - } + private static final long serialVersionUID = -3499224800050816098L; + public static final String subject = "__DREAM_LOCK_GRANT_PACKET_SUBJECT"; + + private final UUID lockID; + private final LockType type; + + public LockGrantPacket(LockRequestPacket reqPkt) { + this.lockID = reqPkt.getLockID(); + this.type = reqPkt.getType(); + } + + public final UUID getLockID() { + return lockID; + } + + public final LockType getType() { + return type; + } + + @Override + public Data getSize() { + // TODO: estimate the real size + return Data.inKByte(1); + } + + @Override + public String toString() { + return "LockGrantPacket [lockID=" + lockID + "]"; + } } diff --git a/DreamSim/src/dream/common/packets/locking/LockReleasePacket.java b/DreamSim/src/dream/common/packets/locking/LockReleasePacket.java index 586cd8c..55ef18e 100644 --- a/DreamSim/src/dream/common/packets/locking/LockReleasePacket.java +++ b/DreamSim/src/dream/common/packets/locking/LockReleasePacket.java @@ -11,28 +11,28 @@ * assumes that requests are sequential (e.g., generated from a single server). */ public class LockReleasePacket extends Message implements Serializable { - private static final long serialVersionUID = -1523880233653918696L; - public static final String subject = "__DREAM_LOCK_RELEASE_PACKET_SUBJECT"; + private static final long serialVersionUID = -1523880233653918696L; + public static final String subject = "__DREAM_LOCK_RELEASE_PACKET_SUBJECT"; - private final UUID lockID; + private final UUID lockID; - public LockReleasePacket(UUID lockID) { - this.lockID = lockID; - } + public LockReleasePacket(UUID lockID) { + this.lockID = lockID; + } - public final UUID getLockID() { - return lockID; - } + public final UUID getLockID() { + return lockID; + } - @Override - public Data getSize() { - // TODO: estimate the real size - return Data.inKByte(1); - } + @Override + public Data getSize() { + // TODO: estimate the real size + return Data.inKByte(1); + } - @Override - public String toString() { - return "LockReleasePacket [lockID=" + lockID + "]"; - } + @Override + public String toString() { + return "LockReleasePacket [lockID=" + lockID + "]"; + } } diff --git a/DreamSim/src/dream/common/packets/locking/LockRequestPacket.java b/DreamSim/src/dream/common/packets/locking/LockRequestPacket.java index a2bc07a..7e4699f 100644 --- a/DreamSim/src/dream/common/packets/locking/LockRequestPacket.java +++ b/DreamSim/src/dream/common/packets/locking/LockRequestPacket.java @@ -10,64 +10,65 @@ import protopeer.util.quantities.Data; public class LockRequestPacket extends Message implements Serializable { - private static final long serialVersionUID = -1523880233653918696L; - public static final String subject = "__DREAM_LOCK_REQUEST_PACKET_SUBJECT"; - - /** - * Node that requests the lock. - */ - private final NetworkAddress applicant; - - /** - * Nodes to lock. - */ - private final Set lockNodes; - - /** - * Nodes that will sent a lock release. - */ - private final Set unlockNodes; - - private final LockType type; - private final UUID lockID; - - public LockRequestPacket(NetworkAddress applicant, UUID lockID, Set lockNodes, Set unlockNodes, LockType type) { - this.applicant = applicant; - this.lockID = lockID; - this.lockNodes = new HashSet<>(lockNodes); - this.unlockNodes = new HashSet<>(unlockNodes); - this.type = type; - } - - public final NetworkAddress getApplicant() { - return applicant; - } - - public final Set getLockNodes() { - return lockNodes; - } - - public final Set getUnlockNodes() { - return unlockNodes; - } - - public final LockType getType() { - return type; - } - - public final UUID getLockID() { - return lockID; - } - - @Override - public Data getSize() { - // TODO: estimate the real size - return Data.inKByte(1); - } - - @Override - public String toString() { - return "LockRequestPacket [lockID=" + lockID + ", lockNodes=" + lockNodes + "]"; - } + private static final long serialVersionUID = -1523880233653918696L; + public static final String subject = "__DREAM_LOCK_REQUEST_PACKET_SUBJECT"; + + /** + * Node that requests the lock. + */ + private final NetworkAddress applicant; + + /** + * Nodes to lock. + */ + private final Set lockNodes; + + /** + * Nodes that will sent a lock release. + */ + private final Set unlockNodes; + + private final LockType type; + private final UUID lockID; + + public LockRequestPacket(NetworkAddress applicant, UUID lockID, Set lockNodes, Set unlockNodes, + LockType type) { + this.applicant = applicant; + this.lockID = lockID; + this.lockNodes = new HashSet<>(lockNodes); + this.unlockNodes = new HashSet<>(unlockNodes); + this.type = type; + } + + public final NetworkAddress getApplicant() { + return applicant; + } + + public final Set getLockNodes() { + return lockNodes; + } + + public final Set getUnlockNodes() { + return unlockNodes; + } + + public final LockType getType() { + return type; + } + + public final UUID getLockID() { + return lockID; + } + + @Override + public Data getSize() { + // TODO: estimate the real size + return Data.inKByte(1); + } + + @Override + public String toString() { + return "LockRequestPacket [lockID=" + lockID + ", lockNodes=" + lockNodes + "]"; + } } diff --git a/DreamSim/src/dream/common/packets/locking/LockType.java b/DreamSim/src/dream/common/packets/locking/LockType.java index b5b785d..bc07cdb 100644 --- a/DreamSim/src/dream/common/packets/locking/LockType.java +++ b/DreamSim/src/dream/common/packets/locking/LockType.java @@ -1,5 +1,5 @@ package dream.common.packets.locking; public enum LockType { - READ_WRITE, READ_ONLY + READ_WRITE, READ_ONLY } diff --git a/DreamSim/src/dream/common/packets/overlay/AddBrokerMessage.java b/DreamSim/src/dream/common/packets/overlay/AddBrokerMessage.java index 6ca6837..807adf6 100644 --- a/DreamSim/src/dream/common/packets/overlay/AddBrokerMessage.java +++ b/DreamSim/src/dream/common/packets/overlay/AddBrokerMessage.java @@ -10,32 +10,32 @@ */ public class AddBrokerMessage extends Message { - private static final long serialVersionUID = -7791413194580191036L; - - private final NetworkAddress newBroker; - - /** - * Create a new broker. - * - * @param newBroker - * New broker to add. - */ - public AddBrokerMessage(NetworkAddress newBroker) { - this.newBroker = newBroker; - } - - /** - * Get the address of the new broker the new broker to add. - * - * @return The new broker to add. - */ - public NetworkAddress getNewBroker() { - return newBroker; - } - - @Override - public String toString() { - return "ADDBROKER (+" + newBroker + ")"; - } + private static final long serialVersionUID = -7791413194580191036L; + + private final NetworkAddress newBroker; + + /** + * Create a new broker. + * + * @param newBroker + * New broker to add. + */ + public AddBrokerMessage(NetworkAddress newBroker) { + this.newBroker = newBroker; + } + + /** + * Get the address of the new broker the new broker to add. + * + * @return The new broker to add. + */ + public NetworkAddress getNewBroker() { + return newBroker; + } + + @Override + public String toString() { + return "ADDBROKER (+" + newBroker + ")"; + } } diff --git a/DreamSim/src/dream/common/packets/overlay/RemoveBrokerMessage.java b/DreamSim/src/dream/common/packets/overlay/RemoveBrokerMessage.java index a0c3c2f..d229d4d 100644 --- a/DreamSim/src/dream/common/packets/overlay/RemoveBrokerMessage.java +++ b/DreamSim/src/dream/common/packets/overlay/RemoveBrokerMessage.java @@ -10,31 +10,31 @@ */ public class RemoveBrokerMessage extends Message { - private static final long serialVersionUID = 5205869805158147763L; + private static final long serialVersionUID = 5205869805158147763L; - private final NetworkAddress existingBroker; + private final NetworkAddress existingBroker; - /** - * Creates a message for removing an existing broker. - * - * @param existingBroker - * Existing broker to remove - */ - public RemoveBrokerMessage(NetworkAddress existingBroker) { - this.existingBroker = existingBroker; - } + /** + * Creates a message for removing an existing broker. + * + * @param existingBroker + * Existing broker to remove + */ + public RemoveBrokerMessage(NetworkAddress existingBroker) { + this.existingBroker = existingBroker; + } - /** - * Get the address of the existing broker to remove. - * - * @return Existing broker to remove - */ - public NetworkAddress getExistingBroker() { - return existingBroker; - } + /** + * Get the address of the existing broker to remove. + * + * @return Existing broker to remove + */ + public NetworkAddress getExistingBroker() { + return existingBroker; + } - @Override - public String toString() { - return "REMOVEBROKER (-" + existingBroker + ")"; - } + @Override + public String toString() { + return "REMOVEBROKER (-" + existingBroker + ")"; + } } diff --git a/DreamSim/src/dream/common/packets/overlay/ReplaceBrokerMessage.java b/DreamSim/src/dream/common/packets/overlay/ReplaceBrokerMessage.java index 34bfbc8..22a3d09 100644 --- a/DreamSim/src/dream/common/packets/overlay/ReplaceBrokerMessage.java +++ b/DreamSim/src/dream/common/packets/overlay/ReplaceBrokerMessage.java @@ -11,44 +11,44 @@ */ public class ReplaceBrokerMessage extends Message { - private static final long serialVersionUID = 527500412680135179L; - - private final NetworkAddress existingBroker; - private final NetworkAddress newBroker; - - /** - * Create a message for replacing a broker. - * - * @param existingBroker - * Existing broker to replace - * @param newBroker - * New broker to replace the existing one - */ - public ReplaceBrokerMessage(NetworkAddress existingBroker, NetworkAddress newBroker) { - this.existingBroker = existingBroker; - this.newBroker = newBroker; - } - - /** - * Get the address of the existing broker. - * - * @return Address of the existing broker - */ - public NetworkAddress getExistingBroker() { - return existingBroker; - } - - /** - * Get the address of the new broker. - * - * @return Address of the new broker - */ - public NetworkAddress getNewBroker() { - return newBroker; - } - - @Override - public String toString() { - return "REPLACEBROKER (-" + existingBroker + " +" + newBroker + ")"; - } + private static final long serialVersionUID = 527500412680135179L; + + private final NetworkAddress existingBroker; + private final NetworkAddress newBroker; + + /** + * Create a message for replacing a broker. + * + * @param existingBroker + * Existing broker to replace + * @param newBroker + * New broker to replace the existing one + */ + public ReplaceBrokerMessage(NetworkAddress existingBroker, NetworkAddress newBroker) { + this.existingBroker = existingBroker; + this.newBroker = newBroker; + } + + /** + * Get the address of the existing broker. + * + * @return Address of the existing broker + */ + public NetworkAddress getExistingBroker() { + return existingBroker; + } + + /** + * Get the address of the new broker. + * + * @return Address of the new broker + */ + public NetworkAddress getNewBroker() { + return newBroker; + } + + @Override + public String toString() { + return "REPLACEBROKER (-" + existingBroker + " +" + newBroker + ")"; + } } diff --git a/DreamSim/src/dream/common/utils/AtomicDependencyDetector.java b/DreamSim/src/dream/common/utils/AtomicDependencyDetector.java index deeffbe..98b43fa 100644 --- a/DreamSim/src/dream/common/utils/AtomicDependencyDetector.java +++ b/DreamSim/src/dream/common/utils/AtomicDependencyDetector.java @@ -5,26 +5,26 @@ import java.util.Set; public enum AtomicDependencyDetector { - instance; + instance; - protected final DependencyGraph graph = DependencyGraph.instance; + protected final DependencyGraph graph = DependencyGraph.instance; - protected Map> dependencyClosure = new HashMap<>(); + protected Map> dependencyClosure = new HashMap<>(); - public final synchronized void consolidate() { - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - } + public final synchronized void consolidate() { + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + } - /** - * Returns the nodes that require to be locked during the propagation of an - * update originated at the given source. - * - * @param source - * the source. - * @return the nodes that need to be locked during the propagation. - */ - public Set getNodesToLockFor(String source) { - return dependencyClosure.get(source); - } + /** + * Returns the nodes that require to be locked during the propagation of an + * update originated at the given source. + * + * @param source + * the source. + * @return the nodes that need to be locked during the propagation. + */ + public Set getNodesToLockFor(String source) { + return dependencyClosure.get(source); + } } diff --git a/DreamSim/src/dream/common/utils/CompleteGlitchFreeDependencyDetector.java b/DreamSim/src/dream/common/utils/CompleteGlitchFreeDependencyDetector.java index 922203d..461b6d5 100644 --- a/DreamSim/src/dream/common/utils/CompleteGlitchFreeDependencyDetector.java +++ b/DreamSim/src/dream/common/utils/CompleteGlitchFreeDependencyDetector.java @@ -19,95 +19,95 @@ * depends on both s and s'. */ public enum CompleteGlitchFreeDependencyDetector { - instance; + instance; - private final DependencyGraph graph = DependencyGraph.instance; - private Map> dependencyClosure = new HashMap<>(); + private final DependencyGraph graph = DependencyGraph.instance; + private Map> dependencyClosure = new HashMap<>(); - private final Map> sharedNodes = new HashMap<>(); - private final Map lockRequestNode = new HashMap<>(); + private final Map> sharedNodes = new HashMap<>(); + private final Map lockRequestNode = new HashMap<>(); - public final void consolidate() { - dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - sharedNodes.clear(); - lockRequestNode.clear(); - computeSharedNodes(); - computeLockRequestNodes(); - } + public final void consolidate() { + dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + sharedNodes.clear(); + lockRequestNode.clear(); + computeSharedNodes(); + computeLockRequestNodes(); + } - /** - * Return the nodes that require to be locked during the propagation of an - * update originated at the given source. - * - * @param source - * the source. - * @return the nodes that need to be locked during the propagation. - */ - public final synchronized Set getNodesToLockFor(String source) { - return sharedNodes.containsKey(source) // - ? sharedNodes.get(source) // - : new HashSet<>(); - } + /** + * Return the nodes that require to be locked during the propagation of an + * update originated at the given source. + * + * @param source + * the source. + * @return the nodes that need to be locked during the propagation. + */ + public final synchronized Set getNodesToLockFor(String source) { + return sharedNodes.containsKey(source) // + ? sharedNodes.get(source) // + : new HashSet<>(); + } - /** - * Return the node that is responsible to send a lock request for a given - * source. - * - * @param source - * the source. - * @return the node that need to request a lock during the propagation. - */ - public final synchronized String getLockRequestNodeFor(String source) { - return lockRequestNode.get(source); - } + /** + * Return the node that is responsible to send a lock request for a given + * source. + * + * @param source + * the source. + * @return the node that need to request a lock during the propagation. + */ + public final synchronized String getLockRequestNodeFor(String source) { + return lockRequestNode.get(source); + } - private final void computeSharedNodes() { - graph.getSources()// - .forEach(source -> sharedNodes.put(source, computeSharedNodesFor(source))); - } + private final void computeSharedNodes() { + graph.getSources()// + .forEach(source -> sharedNodes.put(source, computeSharedNodesFor(source))); + } - private final void computeLockRequestNodes() { - graph.getSources()// - .forEach(source -> lockRequestNode.put(source, computeLockRequestNodeFor(source))); - } + private final void computeLockRequestNodes() { + graph.getSources()// + .forEach(source -> lockRequestNode.put(source, computeLockRequestNodeFor(source))); + } - private final Set computeSharedNodesFor(String source) { - final Set result = new HashSet<>(); - final Set depNodes = dependencyClosure.get(source); - if (depNodes.size() < 2) { - return result; - } - dependencyClosure.entrySet().stream() // - .filter(entry -> !entry.getKey().equals(source)) // - .forEach(entry -> { - final Set intersect = intersect(depNodes, entry.getValue()); - if (intersect.size() >= 2) { - result.addAll(intersect); - } - }); - return result; - } + private final Set computeSharedNodesFor(String source) { + final Set result = new HashSet<>(); + final Set depNodes = dependencyClosure.get(source); + if (depNodes.size() < 2) { + return result; + } + dependencyClosure.entrySet().stream() // + .filter(entry -> !entry.getKey().equals(source)) // + .forEach(entry -> { + final Set intersect = intersect(depNodes, entry.getValue()); + if (intersect.size() >= 2) { + result.addAll(intersect); + } + }); + return result; + } - private final String computeLockRequestNodeFor(String source) { - // Select the nodes on which all the nodes to lock depend - final Set nodesToLock = sharedNodes.get(source); - final List candidateNodes = dependencyClosure.get(source).stream()// - .filter(n -> dependencyClosure.get(n).containsAll(nodesToLock))// - .collect(Collectors.toList()); + private final String computeLockRequestNodeFor(String source) { + // Select the nodes on which all the nodes to lock depend + final Set nodesToLock = sharedNodes.get(source); + final List candidateNodes = dependencyClosure.get(source).stream()// + .filter(n -> dependencyClosure.get(n).containsAll(nodesToLock))// + .collect(Collectors.toList()); - Collections.sort(candidateNodes, (n1, n2) -> { - assert dependencyClosure.get(n1).contains(n2) || dependencyClosure.get(n2).contains(n1); - return dependencyClosure.get(n1).contains(n2) ? -1 : 1; - }); + Collections.sort(candidateNodes, (n1, n2) -> { + assert dependencyClosure.get(n1).contains(n2) || dependencyClosure.get(n2).contains(n1); + return dependencyClosure.get(n1).contains(n2) ? -1 : 1; + }); - assert !candidateNodes.isEmpty(); - return candidateNodes.get(0); - } + assert !candidateNodes.isEmpty(); + return candidateNodes.get(0); + } - private final Set intersect(Set set1, Set set2) { - return set1.stream().// - filter(elem -> set2.contains(elem)).// - collect(Collectors.toSet()); - } + private final Set intersect(Set set1, Set set2) { + return set1.stream().// + filter(elem -> set2.contains(elem)).// + collect(Collectors.toSet()); + } } diff --git a/DreamSim/src/dream/common/utils/DependencyDetector.java b/DreamSim/src/dream/common/utils/DependencyDetector.java index ddf25af..c95614e 100644 --- a/DreamSim/src/dream/common/utils/DependencyDetector.java +++ b/DreamSim/src/dream/common/utils/DependencyDetector.java @@ -9,10 +9,10 @@ */ public interface DependencyDetector { - /** - * Compute the accessory data structures required to speed-up the query - * process. It needs to be invoked when the dependency graph changes. - */ - public void consolidate(); + /** + * Compute the accessory data structures required to speed-up the query + * process. It needs to be invoked when the dependency graph changes. + */ + public void consolidate(); } diff --git a/DreamSim/src/dream/common/utils/DependencyGraph.java b/DreamSim/src/dream/common/utils/DependencyGraph.java index e0ca219..d9a4417 100644 --- a/DreamSim/src/dream/common/utils/DependencyGraph.java +++ b/DreamSim/src/dream/common/utils/DependencyGraph.java @@ -7,33 +7,33 @@ import java.util.Set; public enum DependencyGraph { - instance; - - // Node -> set of nodes it directly depends on - private final Map> graph = new HashMap<>(); - // Sources - private final Set sources = new HashSet<>(); - - public synchronized final void clear() { - graph.clear(); - sources.clear(); - } - - public synchronized final void addVar(String name) { - sources.add(name); - } - - public synchronized final void addSignal(String name, Collection deps) { - assert!deps.isEmpty(); - graph.put(name, deps); - } - - public synchronized final Map> getGraph() { - return graph; - } - - public synchronized final Set getSources() { - return sources; - } + instance; + + // Node -> set of nodes it directly depends on + private final Map> graph = new HashMap<>(); + // Sources + private final Set sources = new HashSet<>(); + + public synchronized final void clear() { + graph.clear(); + sources.clear(); + } + + public synchronized final void addVar(String name) { + sources.add(name); + } + + public synchronized final void addSignal(String name, Collection deps) { + assert !deps.isEmpty(); + graph.put(name, deps); + } + + public synchronized final Map> getGraph() { + return graph; + } + + public synchronized final Set getSources() { + return sources; + } } diff --git a/DreamSim/src/dream/common/utils/DependencyGraphUtils.java b/DreamSim/src/dream/common/utils/DependencyGraphUtils.java index 9a49b72..4bb7ec1 100644 --- a/DreamSim/src/dream/common/utils/DependencyGraphUtils.java +++ b/DreamSim/src/dream/common/utils/DependencyGraphUtils.java @@ -9,112 +9,114 @@ class DependencyGraphUtils { - /** - * Return, for each node, the set of sources it directly or indirectly depends - * on. - * - * @return the set of sources each node directly or indirectly depends on. - */ - static final Map> computeRelevantSources() { - final Map> result = new HashMap<>(); - final DependencyGraph depGraph = DependencyGraph.instance; - depGraph.getSources().forEach(s -> { - final HashSet sources = new HashSet<>(); - sources.add(s); - result.put(s, sources); - }); - depGraph.getGraph().keySet().// - forEach(node -> result.put(node, computeRelevantSourcesFor(node, depGraph))); - return result; - } + /** + * Return, for each node, the set of sources it directly or indirectly depends + * on. + * + * @return the set of sources each node directly or indirectly depends on. + */ + static final Map> computeRelevantSources() { + final Map> result = new HashMap<>(); + final DependencyGraph depGraph = DependencyGraph.instance; + depGraph.getSources().forEach(s -> { + final HashSet sources = new HashSet<>(); + sources.add(s); + result.put(s, sources); + }); + depGraph.getGraph().keySet().// + forEach(node -> result.put(node, computeRelevantSourcesFor(node, depGraph))); + return result; + } - /** - * Return the set of final nodes in the propagation graph, that is to say, all - * the nodes that do not have any other nodes that depends on them. - * - * @return the set of final nodes in the propagation graph. - */ - static final Set computeFinalNodes() { - final Map> graph = DependencyGraph.instance.getGraph(); - final Set sources = DependencyGraph.instance.getSources(); + /** + * Return the set of final nodes in the propagation graph, that is to say, all + * the nodes that do not have any other nodes that depends on them. + * + * @return the set of final nodes in the propagation graph. + */ + static final Set computeFinalNodes() { + final Map> graph = DependencyGraph.instance.getGraph(); + final Set sources = DependencyGraph.instance.getSources(); - final Set allNodes = new HashSet<>(graph.keySet()); - allNodes.addAll(sources); + final Set allNodes = new HashSet<>(graph.keySet()); + allNodes.addAll(sources); - return allNodes.stream()// - .filter(node -> graph.values().stream() // - .allMatch(depNodes -> !depNodes.contains(node))) // - .collect(Collectors.toSet()); - } + return allNodes.stream()// + .filter(node -> graph.values().stream() // + .allMatch(depNodes -> !depNodes.contains(node))) // + .collect(Collectors.toSet()); + } - /** - * Return, for each node, the set of nodes that directly or indirectly depend - * on it. - * - * @return for each node, the set of nodes that directly or indirectly depend - * on it. - */ - static final Map> computeDependencyClosure() { - final Map> result = new HashMap<>(); - final DependencyGraph depGraph = DependencyGraph.instance; - depGraph.getSources().forEach(n -> result.put(n, computeDependencyClosureFor(n, depGraph))); - depGraph.getGraph().keySet().forEach(n -> result.put(n, computeDependencyClosureFor(n, depGraph))); - return result; - } + /** + * Return, for each node, the set of nodes that directly or indirectly depend + * on it. + * + * @return for each node, the set of nodes that directly or indirectly depend + * on it. + */ + static final Map> computeDependencyClosure() { + final Map> result = new HashMap<>(); + final DependencyGraph depGraph = DependencyGraph.instance; + depGraph.getSources().forEach(n -> result.put(n, computeDependencyClosureFor(n, depGraph))); + depGraph.getGraph().keySet().forEach(n -> result.put(n, computeDependencyClosureFor(n, depGraph))); + return result; + } - private static final Set computeDependencyClosureFor(String node, DependencyGraph depGraph) { - final Set result = new HashSet<>(); - final Set newNodes = new HashSet<>(); - result.add(node); - newNodes.add(node); - computeDependencyClosureFor(newNodes, result, depGraph); - return result; - } + private static final Set computeDependencyClosureFor(String node, DependencyGraph depGraph) { + final Set result = new HashSet<>(); + final Set newNodes = new HashSet<>(); + result.add(node); + newNodes.add(node); + computeDependencyClosureFor(newNodes, result, depGraph); + return result; + } - private static final void computeDependencyClosureFor(Set newNodes, Set accumulator, DependencyGraph depGraph) { - final Set newNodesToEvaluate = new HashSet<>(); - newNodes.forEach(n -> { - final Set depNodes = dependentNodesFor(n, depGraph); - depNodes.removeAll(accumulator); - accumulator.addAll(depNodes); - newNodesToEvaluate.addAll(depNodes); - }); - if (!newNodesToEvaluate.isEmpty()) { - computeDependencyClosureFor(newNodesToEvaluate, accumulator, depGraph); - } - } + private static final void computeDependencyClosureFor(Set newNodes, Set accumulator, + DependencyGraph depGraph) { + final Set newNodesToEvaluate = new HashSet<>(); + newNodes.forEach(n -> { + final Set depNodes = dependentNodesFor(n, depGraph); + depNodes.removeAll(accumulator); + accumulator.addAll(depNodes); + newNodesToEvaluate.addAll(depNodes); + }); + if (!newNodesToEvaluate.isEmpty()) { + computeDependencyClosureFor(newNodesToEvaluate, accumulator, depGraph); + } + } - /** - * Return the set of nodes that directly depend on node. - */ - private static Set dependentNodesFor(String node, DependencyGraph depGraph) { - return depGraph.getGraph().entrySet().stream().// - filter(e -> e.getValue().contains(node)).// - map(e -> e.getKey()).// - collect(Collectors.toSet()); - } + /** + * Return the set of nodes that directly depend on node. + */ + private static Set dependentNodesFor(String node, DependencyGraph depGraph) { + return depGraph.getGraph().entrySet().stream().// + filter(e -> e.getValue().contains(node)).// + map(e -> e.getKey()).// + collect(Collectors.toSet()); + } - private static final Set computeRelevantSourcesFor(String node, DependencyGraph depGraph) { - final Set newNodes = new HashSet<>(); - final Set accumulator = new HashSet<>(); - newNodes.add(node); - computeRelevantSourcesFor(newNodes, accumulator, depGraph); - return accumulator; - } + private static final Set computeRelevantSourcesFor(String node, DependencyGraph depGraph) { + final Set newNodes = new HashSet<>(); + final Set accumulator = new HashSet<>(); + newNodes.add(node); + computeRelevantSourcesFor(newNodes, accumulator, depGraph); + return accumulator; + } - private static final void computeRelevantSourcesFor(Set newNodes, Set accumulator, DependencyGraph depGraph) { - newNodes.stream().// - filter(depGraph.getSources()::contains).// - collect(() -> accumulator, Set::add, Set::addAll); + private static final void computeRelevantSourcesFor(Set newNodes, Set accumulator, + DependencyGraph depGraph) { + newNodes.stream().// + filter(depGraph.getSources()::contains).// + collect(() -> accumulator, Set::add, Set::addAll); - final Set newNodesToEvaluate = newNodes.stream().// - filter(expr -> !depGraph.getSources().contains(expr)).// - map(depGraph.getGraph()::get).// - collect(HashSet::new, HashSet::addAll, HashSet::addAll); + final Set newNodesToEvaluate = newNodes.stream().// + filter(expr -> !depGraph.getSources().contains(expr)).// + map(depGraph.getGraph()::get).// + collect(HashSet::new, HashSet::addAll, HashSet::addAll); - if (!newNodesToEvaluate.isEmpty()) { - computeRelevantSourcesFor(newNodesToEvaluate, accumulator, depGraph); - } - } + if (!newNodesToEvaluate.isEmpty()) { + computeRelevantSourcesFor(newNodesToEvaluate, accumulator, depGraph); + } + } } diff --git a/DreamSim/src/dream/common/utils/FinalNodesDetector.java b/DreamSim/src/dream/common/utils/FinalNodesDetector.java index 9bd9f87..766a931 100755 --- a/DreamSim/src/dream/common/utils/FinalNodesDetector.java +++ b/DreamSim/src/dream/common/utils/FinalNodesDetector.java @@ -11,42 +11,42 @@ * given source and do not have any other node that deoends on them. */ public enum FinalNodesDetector { - instance; - - DependencyGraph depGraph = DependencyGraph.instance; - - // Source -> set of final nodes - private final Map> finalNodes = new HashMap<>(); - - public final synchronized void consolidate() { - finalNodes.clear(); - computeFinalNodes(); - } - - /** - * Return the set of final nodes for the given source. - * - * @param source - * the source. - * @return the set of final nodes for source. - */ - public final synchronized Set getFinalNodesFor(String source) { - return finalNodes.get(source); - } - - private final void computeFinalNodes() { - final Map> closure = DependencyGraphUtils.computeDependencyClosure(); - final Set finalNodesSet = DependencyGraphUtils.computeFinalNodes(); - - depGraph.getSources().forEach(s -> { - finalNodes.put(s, intersect(finalNodesSet, closure.get(s))); - }); - } - - private final Set intersect(Set set1, Set set2) { - final Set result = new HashSet<>(set1); - result.retainAll(set2); - return result; - } + instance; + + DependencyGraph depGraph = DependencyGraph.instance; + + // Source -> set of final nodes + private final Map> finalNodes = new HashMap<>(); + + public final synchronized void consolidate() { + finalNodes.clear(); + computeFinalNodes(); + } + + /** + * Return the set of final nodes for the given source. + * + * @param source + * the source. + * @return the set of final nodes for source. + */ + public final synchronized Set getFinalNodesFor(String source) { + return finalNodes.get(source); + } + + private final void computeFinalNodes() { + final Map> closure = DependencyGraphUtils.computeDependencyClosure(); + final Set finalNodesSet = DependencyGraphUtils.computeFinalNodes(); + + depGraph.getSources().forEach(s -> { + finalNodes.put(s, intersect(finalNodesSet, closure.get(s))); + }); + } + + private final Set intersect(Set set1, Set set2) { + final Set result = new HashSet<>(set1); + result.retainAll(set2); + return result; + } } diff --git a/DreamSim/src/dream/common/utils/IntraSourceDependencyDetector.java b/DreamSim/src/dream/common/utils/IntraSourceDependencyDetector.java index 93abba3..6987493 100755 --- a/DreamSim/src/dream/common/utils/IntraSourceDependencyDetector.java +++ b/DreamSim/src/dream/common/utils/IntraSourceDependencyDetector.java @@ -9,73 +9,73 @@ import dream.common.packets.content.Event; public enum IntraSourceDependencyDetector implements DependencyDetector { - instance; + instance; - private final DependencyGraph depGraph = DependencyGraph.instance; - private Map> relevantSources = new HashMap<>(); + private final DependencyGraph depGraph = DependencyGraph.instance; + private Map> relevantSources = new HashMap<>(); - // Stores the dependencies to compute expressions - // Expression Expr -> Initial expression that caused the recomputation -> - // Wait recommendations - private final Map>> recommendations = new HashMap<>(); + // Stores the dependencies to compute expressions + // Expression Expr -> Initial expression that caused the recomputation -> + // Wait recommendations + private final Map>> recommendations = new HashMap<>(); - public synchronized final Set getWaitRecommendations(Event event, String initialVar) { - final Map> innerMap = recommendations.get(event.getSignature()); - if (innerMap == null) { - return new HashSet<>(); - } - return innerMap.containsKey(initialVar) ? innerMap.get(initialVar) : new HashSet<>(); - } + public synchronized final Set getWaitRecommendations(Event event, String initialVar) { + final Map> innerMap = recommendations.get(event.getSignature()); + if (innerMap == null) { + return new HashSet<>(); + } + return innerMap.containsKey(initialVar) ? innerMap.get(initialVar) : new HashSet<>(); + } - @Override - public synchronized final void consolidate() { - recommendations.clear(); - computeRecommendations(); - } + @Override + public synchronized final void consolidate() { + recommendations.clear(); + computeRecommendations(); + } - private final void computeRecommendations() { - recommendations.clear(); - relevantSources = DependencyGraphUtils.computeRelevantSources(); - depGraph.getGraph().keySet().forEach(expr -> { - relevantSources.get(expr).forEach(initialExpr -> storeRecommendationsFor(expr, initialExpr)); - }); - } + private final void computeRecommendations() { + recommendations.clear(); + relevantSources = DependencyGraphUtils.computeRelevantSources(); + depGraph.getGraph().keySet().forEach(expr -> { + relevantSources.get(expr).forEach(initialExpr -> storeRecommendationsFor(expr, initialExpr)); + }); + } - private final void storeRecommendationsFor(String expr, String initialExpr) { - final Set dependentSiblings = computeDependentSiblingsFor(expr, initialExpr); + private final void storeRecommendationsFor(String expr, String initialExpr) { + final Set dependentSiblings = computeDependentSiblingsFor(expr, initialExpr); - if (dependentSiblings.size() > 1) { - dependentSiblings.forEach(sibling -> { - Map> recommendationsMap = recommendations.get(sibling); - if (recommendationsMap == null) { - recommendationsMap = new HashMap<>(); - recommendations.put(sibling, recommendationsMap); - } - Set recommendationsSet = recommendationsMap.get(initialExpr); - if (recommendationsSet == null) { - recommendationsSet = new HashSet<>(); - recommendationsMap.put(initialExpr, recommendationsSet); - } - final WaitRecommendations wr = new WaitRecommendations(expr); - recommendationsSet.add(wr); - dependentSiblings.stream().// - filter(e -> !e.equals(sibling)).// - forEach(wr::addRecommendation); - }); - } - } + if (dependentSiblings.size() > 1) { + dependentSiblings.forEach(sibling -> { + Map> recommendationsMap = recommendations.get(sibling); + if (recommendationsMap == null) { + recommendationsMap = new HashMap<>(); + recommendations.put(sibling, recommendationsMap); + } + Set recommendationsSet = recommendationsMap.get(initialExpr); + if (recommendationsSet == null) { + recommendationsSet = new HashSet<>(); + recommendationsMap.put(initialExpr, recommendationsSet); + } + final WaitRecommendations wr = new WaitRecommendations(expr); + recommendationsSet.add(wr); + dependentSiblings.stream().// + filter(e -> !e.equals(sibling)).// + forEach(wr::addRecommendation); + }); + } + } - /** - * Compute the set of all expressions with the following properties: - * - * 1) expr directly depends on them - * - * 2) they directly or indirectly depend on the initialExpression - */ - private final Set computeDependentSiblingsFor(String expr, String initialExpression) { - return depGraph.getGraph().get(expr).stream().// - filter(dep -> relevantSources.get(dep).contains(initialExpression)).// - collect(Collectors.toSet()); - } + /** + * Compute the set of all expressions with the following properties: + * + * 1) expr directly depends on them + * + * 2) they directly or indirectly depend on the initialExpression + */ + private final Set computeDependentSiblingsFor(String expr, String initialExpression) { + return depGraph.getGraph().get(expr).stream().// + filter(dep -> relevantSources.get(dep).contains(initialExpression)).// + collect(Collectors.toSet()); + } } diff --git a/DreamSim/src/dream/common/utils/LocalityDetector.java b/DreamSim/src/dream/common/utils/LocalityDetector.java index 669e6f5..9147e15 100644 --- a/DreamSim/src/dream/common/utils/LocalityDetector.java +++ b/DreamSim/src/dream/common/utils/LocalityDetector.java @@ -11,74 +11,74 @@ * not, that is to say, if it requires the acquisition of locks or not. */ public enum LocalityDetector { - instance; - - DependencyGraph depGraph = DependencyGraph.instance; - - // Sources that need the acquisition of a lock for propagation - private final Set sourcesToLock = new HashSet<>(); - - // Nodes that need to be locked in read mode in the case of atomic consistency - private final Set nodesToLockOnRead = new HashSet<>(); - - public final synchronized void consolidate() { - sourcesToLock.clear(); - nodesToLockOnRead.clear(); - computeSourcesToLock(); - computeNodesToLockOnRead(); - } - - public final synchronized boolean sourceRequiresLock(String source) { - return sourcesToLock.contains(source); - } - - public final synchronized boolean nodeRequiresReadLock(String node) { - return nodesToLockOnRead.contains(node); - } - - /** - * A source is local if all its dependent nodes are defined in the same host - * and do not depend on remote sources. In this case, the order of - * propagations can be decided with a local synchronization mechanism between - * sources. - */ - private final void computeSourcesToLock() { - final Map> relevantSources = DependencyGraphUtils.computeRelevantSources(); - final Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - - final Predicate dependsOnRemoteSource = // - node -> relevantSources.get(node).stream() // - .anyMatch(source -> !source.split("@")[1].equals(node.split("@")[1])); - - final Predicate someNodeDependsOnRemoteSource = // - source -> dependencyClosure.get(source).stream().anyMatch(dependsOnRemoteSource); - - depGraph.getSources().stream() // - .filter(someNodeDependsOnRemoteSource) // - .collect(Collectors.toCollection(() -> sourcesToLock)); - } - - /** - * A node needs to be locked on read if it depends (directly or indirectly) on - * a node defined in a different host or if some of its (directly or - * indirectly) dependent nodes are defined in a different host. - */ - private final void computeNodesToLockOnRead() { - final Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); - - final Predicate aDependentNodeIsRemote = // - node -> dependencyClosure.get(node).stream() // - .anyMatch(depNode -> !depNode.split("@")[1].equals(node.split("@")[1])); - - final Predicate dependsOnRemoteNode = node -> // - dependencyClosure.entrySet().stream() // - .filter(e -> e.getKey().equals(node)) // - .filter(e -> e.getValue().contains(node)) // - .anyMatch(e -> !e.getKey().split("@")[1].equals(node.split("@")[1])); - - depGraph.getGraph().keySet().stream() // - .filter(aDependentNodeIsRemote.or(dependsOnRemoteNode)) // - .collect(Collectors.toCollection(() -> nodesToLockOnRead)); - } + instance; + + DependencyGraph depGraph = DependencyGraph.instance; + + // Sources that need the acquisition of a lock for propagation + private final Set sourcesToLock = new HashSet<>(); + + // Nodes that need to be locked in read mode in the case of atomic consistency + private final Set nodesToLockOnRead = new HashSet<>(); + + public final synchronized void consolidate() { + sourcesToLock.clear(); + nodesToLockOnRead.clear(); + computeSourcesToLock(); + computeNodesToLockOnRead(); + } + + public final synchronized boolean sourceRequiresLock(String source) { + return sourcesToLock.contains(source); + } + + public final synchronized boolean nodeRequiresReadLock(String node) { + return nodesToLockOnRead.contains(node); + } + + /** + * A source is local if all its dependent nodes are defined in the same host + * and do not depend on remote sources. In this case, the order of + * propagations can be decided with a local synchronization mechanism between + * sources. + */ + private final void computeSourcesToLock() { + final Map> relevantSources = DependencyGraphUtils.computeRelevantSources(); + final Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + + final Predicate dependsOnRemoteSource = // + node -> relevantSources.get(node).stream() // + .anyMatch(source -> !source.split("@")[1].equals(node.split("@")[1])); + + final Predicate someNodeDependsOnRemoteSource = // + source -> dependencyClosure.get(source).stream().anyMatch(dependsOnRemoteSource); + + depGraph.getSources().stream() // + .filter(someNodeDependsOnRemoteSource) // + .collect(Collectors.toCollection(() -> sourcesToLock)); + } + + /** + * A node needs to be locked on read if it depends (directly or indirectly) on + * a node defined in a different host or if some of its (directly or + * indirectly) dependent nodes are defined in a different host. + */ + private final void computeNodesToLockOnRead() { + final Map> dependencyClosure = DependencyGraphUtils.computeDependencyClosure(); + + final Predicate aDependentNodeIsRemote = // + node -> dependencyClosure.get(node).stream() // + .anyMatch(depNode -> !depNode.split("@")[1].equals(node.split("@")[1])); + + final Predicate dependsOnRemoteNode = node -> // + dependencyClosure.entrySet().stream() // + .filter(e -> e.getKey().equals(node)) // + .filter(e -> e.getValue().contains(node)) // + .anyMatch(e -> !e.getKey().split("@")[1].equals(node.split("@")[1])); + + depGraph.getGraph().keySet().stream() // + .filter(aDependentNodeIsRemote.or(dependsOnRemoteNode)) // + .collect(Collectors.toCollection(() -> nodesToLockOnRead)); + } } diff --git a/DreamSim/src/dream/common/utils/WaitRecommendations.java b/DreamSim/src/dream/common/utils/WaitRecommendations.java index 8290ae3..cfdb4c1 100755 --- a/DreamSim/src/dream/common/utils/WaitRecommendations.java +++ b/DreamSim/src/dream/common/utils/WaitRecommendations.java @@ -5,44 +5,45 @@ import java.util.Set; /** - * A WaitRecommendations object is stored inside an event E. It is used by the server to prevent glitches while - * delivering E to the clients. It tells a client C that it must wait for other events before processing E. + * A WaitRecommendations object is stored inside an event E. It is used by the + * server to prevent glitches while delivering E to the clients. It tells a + * client C that it must wait for other events before processing E. */ public class WaitRecommendations implements Serializable { - private static final long serialVersionUID = 5700944080087353096L; + private static final long serialVersionUID = 5700944080087353096L; - private final String expression; - private final Set expressionsToWaitFor = new HashSet(); + private final String expression; + private final Set expressionsToWaitFor = new HashSet(); - public WaitRecommendations(String expression) { - this.expression = expression; - } + public WaitRecommendations(String expression) { + this.expression = expression; + } - public final void addRecommendation(String expressionToWaitFor) { - expressionsToWaitFor.add(expressionToWaitFor); - } + public final void addRecommendation(String expressionToWaitFor) { + expressionsToWaitFor.add(expressionToWaitFor); + } - public final String getExpression() { - return expression; - } + public final String getExpression() { + return expression; + } - public final Set getRecommendations() { - return expressionsToWaitFor; - } + public final Set getRecommendations() { + return expressionsToWaitFor; + } - public final WaitRecommendations dup() { - WaitRecommendations result = new WaitRecommendations(expression); - result.expressionsToWaitFor.addAll(expressionsToWaitFor); - return result; - } + public final WaitRecommendations dup() { + WaitRecommendations result = new WaitRecommendations(expression); + result.expressionsToWaitFor.addAll(expressionsToWaitFor); + return result; + } - public final void removeExpressionToWaitFor(String expressionToWaitFor) { - expressionsToWaitFor.remove(expressionToWaitFor); - } + public final void removeExpressionToWaitFor(String expressionToWaitFor) { + expressionsToWaitFor.remove(expressionToWaitFor); + } - @Override - public String toString() { - return "WaitRecommendations [expression=" + expression + ", expressionsToWaitFor=" + expressionsToWaitFor + "]"; - } + @Override + public String toString() { + return "WaitRecommendations [expression=" + expression + ", expressionsToWaitFor=" + expressionsToWaitFor + "]"; + } } diff --git a/DreamSim/src/dream/experiments/DreamConfiguration.java b/DreamSim/src/dream/experiments/DreamConfiguration.java index 21a9249..4e42d2a 100755 --- a/DreamSim/src/dream/experiments/DreamConfiguration.java +++ b/DreamSim/src/dream/experiments/DreamConfiguration.java @@ -7,155 +7,160 @@ * This is a class for the JavaReact simulation configuration. */ public class DreamConfiguration extends Configuration { - public static final int CAUSAL = 1; - public static final int SINGLE_SOURCE_GLITCH_FREE = 2; - public static final int COMPLETE_GLITCH_FREE = 3; - public static final int COMPLETE_GLITCH_FREE_OPTIMIZED = 4; - public static final int ATOMIC = 5; - public static final int SIDUP = 6; - - private static DreamConfiguration singleton; - - public static DreamConfiguration get() { - if (singleton == null) { - singleton = new DreamConfiguration(); - } - return singleton; - } - - @Override - public void loadFromFile(String filename) throws ConfigurationException { - super.loadFromFile(filename); - // Put here validity checks on configuration values - // Launch a ConfigurationException if some of them is invalid - } - - /** - * Directory to save results - */ - public String resultsDir; - - /** - * Simulation time in seconds - */ - public int simulationTimeInSeconds; - - /** - * Duration of the epoch used to sample delays - */ - public int epochDuration; - - /** - * Random seed used during the simulation - */ - public int seed; - - /** - * Number of brokers - */ - public int numberOfBrokers; - - /** - * Number of clients - */ - public int numberOfClients; - - /** - * Initial broker topology 1 = LINEAR 2 = STAR 3 = SCALEFREE - */ - public int brokersTopologyType; - - /** - * Association for the components UNIFORM_LOWEST_ID=1 UNIFORM_HIGHEST_ID=2 - * UNIFORM_ALTERNATE_ID=3 UNIFORM_RANDOM_ID=4 - */ - public int clientsAssociationType; - - /** - * Percentage of brokers that are pure forwarders. - */ - public double percentageOfPureForwarders; - - /** - * Max communication delay for communication interface - */ - public double maxCommunicationDelayInMs; - - /** - * Min communication delay for communication interface - */ - public double minCommunicationDelayInMs; - - /** - * Real (physical) length of each virtual link - */ - public int linkLength; - - /** - * Consistency type CAUSAL=1, SINGLE_GLITCH_FREE=2, COMPLETE_GLITCH_FREE=3, - * COMPLETE_GLITCH_FREE_OPTIMIZED=4, ATOMIC=5, SID_UP=6 - */ - public int consistencyType; - - /** - * Number of sources (vars) in the dependency graph - */ - public int graphNumSources; - - /** - * Number of levels for each var - */ - public int graphDepth; - - /** - * Minimum number of nodes per level. - */ - public int graphMinNodesPerLevel; - - /** - * Maximum number of nodes per level. - */ - public int graphMaxNodesPerLevel; - - /** - * Maximum number of incoming edges (dependencies) for each node. - */ - public int graphMaxDependenciesPerNode; - - /** - * Probability for a node to be shared between two sources. - */ - public double graphNodeShareProbability; - - /** - * Probability for a node to share the same host with one of its dependent - * nodes. - */ - public double graphLocality; - - /** - * Min time between two updates to a var - */ - public int minTimeBetweenEventsInMs; - - /** - * Max time between two updates to a var - */ - public int maxTimeBetweenEventsInMs; - - /** - * Min time between two reads of a signal - */ - public int minTimeBetweenSignalReadsInMs; - - /** - * Max time between two reads of a signal - */ - public int maxTimeBetweenSignalReadsInMs; - - /** - * Duration of a read lock (how long the lock is retained) - */ - public int readLockDurationInMs; + public static final int CAUSAL = 1; + public static final int SINGLE_SOURCE_GLITCH_FREE = 2; + public static final int COMPLETE_GLITCH_FREE = 3; + public static final int COMPLETE_GLITCH_FREE_OPTIMIZED = 4; + public static final int ATOMIC = 5; + public static final int SIDUP = 6; + + private static DreamConfiguration singleton; + + public static DreamConfiguration get() { + if (singleton == null) { + singleton = new DreamConfiguration(); + } + return singleton; + } + + @Override + public void loadFromFile(String filename) throws ConfigurationException { + super.loadFromFile(filename); + // Put here validity checks on configuration values + // Launch a ConfigurationException if some of them is invalid + } + + /** + * Directory to save results + */ + public String resultsDir; + + /** + * Simulation time in seconds + */ + public int simulationTimeInSeconds; + + /** + * Duration of the epoch used to sample delays + */ + public int epochDuration; + + /** + * Random seed used during the simulation + */ + public int seed; + + /** + * Number of brokers + */ + public int numberOfBrokers; + + /** + * Number of clients + */ + public int numberOfClients; + + /** + * Initial broker topology 1 = LINEAR 2 = STAR 3 = SCALEFREE + */ + public int brokersTopologyType; + + /** + * Association for the components UNIFORM_LOWEST_ID=1 UNIFORM_HIGHEST_ID=2 + * UNIFORM_ALTERNATE_ID=3 UNIFORM_RANDOM_ID=4 + */ + public int clientsAssociationType; + + /** + * Percentage of brokers that are pure forwarders. + */ + public double percentageOfPureForwarders; + + /** + * Max communication delay for communication interface + */ + public double maxCommunicationDelayInMs; + + /** + * Min communication delay for communication interface + */ + public double minCommunicationDelayInMs; + + /** + * Real (physical) length of each virtual link + */ + public int numHopsPerLink; + + /** + * Real (physical) length of the connection to the lock manager + */ + public int numHopsToLockManager; + + /** + * Consistency type CAUSAL=1, SINGLE_GLITCH_FREE=2, COMPLETE_GLITCH_FREE=3, + * COMPLETE_GLITCH_FREE_OPTIMIZED=4, ATOMIC=5, SID_UP=6 + */ + public int consistencyType; + + /** + * Number of sources (vars) in the dependency graph + */ + public int graphNumSources; + + /** + * Number of levels for each var + */ + public int graphDepth; + + /** + * Minimum number of nodes per level. + */ + public int graphMinNodesPerLevel; + + /** + * Maximum number of nodes per level. + */ + public int graphMaxNodesPerLevel; + + /** + * Maximum number of incoming edges (dependencies) for each node. + */ + public int graphMaxDependenciesPerNode; + + /** + * Probability for a node to be shared between two sources. + */ + public double graphNodeShareProbability; + + /** + * Probability for a node to share the same host with one of its dependent + * nodes. + */ + public double graphLocality; + + /** + * Min time between two updates to a var + */ + public int minTimeBetweenEventsInMs; + + /** + * Max time between two updates to a var + */ + public int maxTimeBetweenEventsInMs; + + /** + * Min time between two reads of a signal + */ + public int minTimeBetweenSignalReadsInMs; + + /** + * Max time between two reads of a signal + */ + public int maxTimeBetweenSignalReadsInMs; + + /** + * Duration of a read lock (how long the lock is retained) + */ + public int readLockDurationInMs; } diff --git a/DreamSim/src/dream/experiments/SimulatedExperimentRunner.java b/DreamSim/src/dream/experiments/SimulatedExperimentRunner.java index 9610148..941be74 100755 --- a/DreamSim/src/dream/experiments/SimulatedExperimentRunner.java +++ b/DreamSim/src/dream/experiments/SimulatedExperimentRunner.java @@ -5,6 +5,7 @@ import dream.generator.GraphGenerator; import dream.generator.RandomGenerator; import dream.locking.LockManagerFactory; +import dream.measurement.DreamDelayModel; import dream.measurement.MeasurementLogger; import dream.overlay.ClientAssociationGenerator; import dream.overlay.TreeOverlayGenerator; @@ -15,7 +16,6 @@ import protopeer.SimulatedExperiment; import protopeer.network.NetworkInterfaceFactory; import protopeer.network.delayloss.DelayLossNetworkInterfaceFactory; -import protopeer.network.delayloss.UniformDelayModel; import protopeer.util.quantities.Time; /** @@ -23,261 +23,264 @@ * parameters and save the results for later processing. */ public class SimulatedExperimentRunner extends SimulatedExperiment { - private final static String CONFIGURATION_FILE = "conf/dream.conf"; + private final static String CONFIGURATION_FILE = "conf/dream.conf"; - private static final int protocols[] = { // - DreamConfiguration.CAUSAL, // - DreamConfiguration.SINGLE_SOURCE_GLITCH_FREE, // - DreamConfiguration.COMPLETE_GLITCH_FREE, // - DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED, // - DreamConfiguration.ATOMIC, // - DreamConfiguration.SIDUP // - }; + private static final int protocols[] = { // + DreamConfiguration.CAUSAL, // + DreamConfiguration.SINGLE_SOURCE_GLITCH_FREE, // + DreamConfiguration.COMPLETE_GLITCH_FREE, // + DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED, // + DreamConfiguration.ATOMIC, // + DreamConfiguration.SIDUP // + }; - public final void runExperiments() { - // runFromFile(0); - for (int seed = 0; seed < 10; seed++) { - runDefault(seed); - runDefaultCentralized(seed); - runLocality(seed); - runNumBrokers(seed); - runNumVars(seed); - runGraphDepth(seed); - runNumGraphDependencies(seed); - runGraphShareProbability(seed); - runTimeBetweenEvents(seed); - runTimeBetweenReads(seed); - } - } + public final void runExperiments() { + // runFromFile(0); + for (int seed = 0; seed < 10; seed++) { + runDefault(seed); + runLocality(seed); + runNumBrokers(seed); + runNumVars(seed); + runGraphDepth(seed); + runNumGraphDependencies(seed); + runGraphShareProbability(seed); + runTimeBetweenEvents(seed); + runTimeBetweenReads(seed); + } + } - @SuppressWarnings("unused") - private final void runFromFile(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - runExperiment("fromFile", String.valueOf(seed), "0", getProtocolName(DreamConfiguration.get().consistencyType)); - } + @SuppressWarnings("unused") + private final void runFromFile(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + runExperiment("fromFile", String.valueOf(seed), "0", getProtocolName(DreamConfiguration.get().consistencyType)); + } - private final void runDefault(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - runExperiment("default", String.valueOf(seed), String.valueOf(0), getProtocolName(i)); - } - } + private final void runDefault(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + runExperiment("default", String.valueOf(seed), String.valueOf(0), getProtocolName(i)); + } + } - private final void runDefaultCentralized(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - DreamConfiguration.get().numberOfBrokers = 1; - DreamConfiguration.get().linkLength = 4; - DreamConfiguration.get().minCommunicationDelayInMs *= DreamConfiguration.get().linkLength; - DreamConfiguration.get().maxCommunicationDelayInMs *= DreamConfiguration.get().linkLength; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - runExperiment("centralized", String.valueOf(seed), String.valueOf(0), getProtocolName(i)); - } - } + private final void runLocality(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int locality = 0; locality <= 100; locality += 10) { + final float floatLoc = (float) locality / 100; + DreamConfiguration.get().graphLocality = floatLoc; + runExperiment("locality", String.valueOf(seed), String.valueOf(floatLoc), getProtocolName(i)); + } + } + } - private final void runLocality(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int locality = 0; locality <= 100; locality += 10) { - final float floatLoc = (float) locality / 100; - DreamConfiguration.get().graphLocality = floatLoc; - runExperiment("locality", String.valueOf(seed), String.valueOf(floatLoc), getProtocolName(i)); - } - } - } + /** + * Here we keep the number of hops fixed, while increasing the number of + * brokers. + * + * A tree with n nodes has n-1 links. If each link consists of h hops, the + * tree has in total (n-1)*h hops. We want to keep this number identical in + * all the runs, by changing h (number of hops per link) together with n + * (number of nodes). + */ + private final void runNumBrokers(int seed) { + loadFromFile(); + final int totalNumHops = 20; + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int numBrokers = 1; numBrokers <= 20;) { + DreamConfiguration.get().numberOfBrokers = numBrokers; + DreamConfiguration.get().numHopsPerLink = totalNumHops / numBrokers; + runExperiment("numBrokers", String.valueOf(seed), String.valueOf(numBrokers), getProtocolName(i)); + if (numBrokers < 5) { + numBrokers += 2; + } else { + numBrokers += 5; + } + } + } + } - private final void runNumBrokers(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int numBrokers = 2; numBrokers < 25; numBrokers += 2) { - DreamConfiguration.get().numberOfBrokers = numBrokers; - runExperiment("numBrokers", String.valueOf(seed), String.valueOf(numBrokers), getProtocolName(i)); - } - } - } + private final void runNumVars(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int numVars = 1; numVars <= 100;) { + DreamConfiguration.get().graphNumSources = numVars; + runExperiment("numVars", String.valueOf(seed), String.valueOf(numVars), getProtocolName(i)); + if (numVars < 10) { + numVars += 3; + } else { + numVars += 30; + } + } + } + } - private final void runNumVars(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int numVars = 1; numVars <= 100;) { - DreamConfiguration.get().graphNumSources = numVars; - runExperiment("numVars", String.valueOf(seed), String.valueOf(numVars), getProtocolName(i)); - if (numVars < 10) { - numVars += 3; - } else { - numVars += 30; - } - } - } - } + private final void runGraphDepth(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int depth = 1; depth <= 10; depth++) { + DreamConfiguration.get().graphDepth = depth; + runExperiment("graphDepth", String.valueOf(seed), String.valueOf(depth), getProtocolName(i)); + } + } + } - private final void runGraphDepth(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int depth = 1; depth <= 10; depth++) { - DreamConfiguration.get().graphDepth = depth; - runExperiment("graphDepth", String.valueOf(seed), String.valueOf(depth), getProtocolName(i)); - } - } - } + private final void runNumGraphDependencies(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int dep = 1; dep < 10; dep++) { + DreamConfiguration.get().graphMaxDependenciesPerNode = dep; + runExperiment("numGraphDependencies", String.valueOf(seed), String.valueOf(dep), getProtocolName(i)); + } + } + } - private final void runNumGraphDependencies(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int dep = 1; dep < 10; dep++) { - DreamConfiguration.get().graphMaxDependenciesPerNode = dep; - runExperiment("numGraphDependencies", String.valueOf(seed), String.valueOf(dep), getProtocolName(i)); - } - } - } + private final void runGraphShareProbability(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int share = 0; share <= 100; share += 10) { + final float shareFloat = (float) share / 100; + DreamConfiguration.get().graphNodeShareProbability = shareFloat; + runExperiment("graphShare", String.valueOf(seed), String.valueOf(shareFloat), getProtocolName(i)); + } + } + } - private final void runGraphShareProbability(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int share = 0; share <= 100; share += 10) { - final float shareFloat = (float) share / 100; - DreamConfiguration.get().graphNodeShareProbability = shareFloat; - runExperiment("graphShare", String.valueOf(seed), String.valueOf(shareFloat), getProtocolName(i)); - } - } - } + private final void runTimeBetweenEvents(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int timeBetweenEvents = 100; timeBetweenEvents <= 10000;) { + // TODO: change simulation time accordingly? + DreamConfiguration.get().epochDuration = 2 * timeBetweenEvents; + DreamConfiguration.get().minTimeBetweenEventsInMs = Math.min(1, timeBetweenEvents - 1); + DreamConfiguration.get().maxTimeBetweenEventsInMs = timeBetweenEvents + 1; + runExperiment("timeBetweenEvents", String.valueOf(seed), String.valueOf(timeBetweenEvents), getProtocolName(i)); + if (timeBetweenEvents < 1000) { + timeBetweenEvents += 300; + } else { + timeBetweenEvents += 3000; + } + } + } + } - private final void runTimeBetweenEvents(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int timeBetweenEvents = 100; timeBetweenEvents <= 10000;) { - // TODO: change simulation time accordingly? - DreamConfiguration.get().epochDuration = 2 * timeBetweenEvents; - DreamConfiguration.get().minTimeBetweenEventsInMs = Math.min(1, timeBetweenEvents - 1); - DreamConfiguration.get().maxTimeBetweenEventsInMs = timeBetweenEvents + 1; - runExperiment("timeBetweenEvents", String.valueOf(seed), String.valueOf(timeBetweenEvents), getProtocolName(i)); - if (timeBetweenEvents < 1000) { - timeBetweenEvents += 300; - } else { - timeBetweenEvents += 3000; - } - } - } - } + private final void runTimeBetweenReads(int seed) { + loadFromFile(); + DreamConfiguration.get().seed = seed; + for (final int i : protocols) { + DreamConfiguration.get().consistencyType = i; + for (int timeBetweenReads = 100; timeBetweenReads <= 10000;) { + DreamConfiguration.get().minTimeBetweenSignalReadsInMs = Math.min(1, timeBetweenReads - 1); + DreamConfiguration.get().maxTimeBetweenSignalReadsInMs = timeBetweenReads + 1; + runExperiment("timeBetweenReads", String.valueOf(seed), String.valueOf(timeBetweenReads), getProtocolName(i)); + if (timeBetweenReads < 1000) { + timeBetweenReads += 300; + } else { + timeBetweenReads += 3000; + } + } + } + } - private final void runTimeBetweenReads(int seed) { - loadFromFile(); - DreamConfiguration.get().seed = seed; - for (final int i : protocols) { - DreamConfiguration.get().consistencyType = i; - for (int timeBetweenReads = 100; timeBetweenReads <= 10000;) { - DreamConfiguration.get().minTimeBetweenSignalReadsInMs = Math.min(1, timeBetweenReads - 1); - DreamConfiguration.get().maxTimeBetweenSignalReadsInMs = timeBetweenReads + 1; - runExperiment("timeBetweenReads", String.valueOf(seed), String.valueOf(timeBetweenReads), getProtocolName(i)); - if (timeBetweenReads < 1000) { - timeBetweenReads += 300; - } else { - timeBetweenReads += 3000; - } - } - } - } + private final void loadFromFile() { + try { + DreamConfiguration.get().loadFromFile(CONFIGURATION_FILE); + } catch (final ConfigurationException e) { + e.printStackTrace(); + return; + } + } - private final void loadFromFile() { - try { - DreamConfiguration.get().loadFromFile(CONFIGURATION_FILE); - } catch (final ConfigurationException e) { - e.printStackTrace(); - return; - } - } + private final void runExperiment(String name, String seed, String value, String protocol) { + final String experimentName = name + "_" + seed + "_" + value + "_" + protocol; + final MeasurementLogger mLogger = MeasurementLogger.getLogger(); - private final void runExperiment(String name, String seed, String value, String protocol) { - final String experimentName = name + "_" + seed + "_" + value + "_" + protocol; - final MeasurementLogger mLogger = MeasurementLogger.getLogger(); + // Cleanup + RandomGenerator.reset(); + mLogger.resetCounters(); + TreeOverlayGenerator.get().clean(); + ClientAssociationGenerator.get().clean(); + GraphGenerator.get().clean(); + TrafficGeneratorPeerlet.resetCount(); - // Cleanup - RandomGenerator.reset(); - mLogger.resetCounters(); - TreeOverlayGenerator.get().clean(); - ClientAssociationGenerator.get().clean(); - GraphGenerator.get().clean(); - TrafficGeneratorPeerlet.resetCount(); + // Init environment and experiment + Experiment.initEnvironment(); + final SimulatedExperimentRunner experiment = new SimulatedExperimentRunner(); + experiment.init(); - // Init environment and experiment - Experiment.initEnvironment(); - final SimulatedExperimentRunner experiment = new SimulatedExperimentRunner(); - experiment.init(); + // Init the servers + int numPeers = 0; + final PeerFactory brokerPeerFactory = new ServerFactory(); + experiment.initPeers(numPeers + 1, DreamConfiguration.get().numberOfBrokers, brokerPeerFactory); + numPeers += DreamConfiguration.get().numberOfBrokers; - // Init the servers - int numPeers = 0; - final PeerFactory brokerPeerFactory = new ServerFactory(); - experiment.initPeers(numPeers + 1, DreamConfiguration.get().numberOfBrokers, brokerPeerFactory); - numPeers += DreamConfiguration.get().numberOfBrokers; + // Init the clients + final PeerFactory componentPeerFactory = new ClientFactory(); + experiment.initPeers(numPeers + 1, DreamConfiguration.get().numberOfClients, componentPeerFactory); + numPeers += DreamConfiguration.get().numberOfClients; - // Init the clients - final PeerFactory componentPeerFactory = new ClientFactory(); - experiment.initPeers(numPeers + 1, DreamConfiguration.get().numberOfClients, componentPeerFactory); - numPeers += DreamConfiguration.get().numberOfClients; + // Init the lock manager + if (DreamConfiguration.get().consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE || // + DreamConfiguration.get().consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED || // + DreamConfiguration.get().consistencyType == DreamConfiguration.ATOMIC || // + DreamConfiguration.get().consistencyType == DreamConfiguration.SIDUP) { + final PeerFactory lockManagerFactory = new LockManagerFactory(); + experiment.initPeers(numPeers + 1, 1, lockManagerFactory); + numPeers++; + } - // Init the lock manager - if (DreamConfiguration.get().consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE || // - DreamConfiguration.get().consistencyType == DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED || // - DreamConfiguration.get().consistencyType == DreamConfiguration.ATOMIC || // - DreamConfiguration.get().consistencyType == DreamConfiguration.SIDUP) { - final PeerFactory lockManagerFactory = new LockManagerFactory(); - experiment.initPeers(numPeers + 1, 1, lockManagerFactory); - numPeers++; - } + // Start peers + experiment.startPeers(1, numPeers); - // Start peers - experiment.startPeers(1, numPeers); + // Run the simulation + System.out.println("Starting experiment " + experimentName); + experiment.runSimulation(Time.inSeconds(DreamConfiguration.get().simulationTimeInSeconds)); + System.out.println("Experiment " + experimentName + " complete"); + mLogger.printResults(experimentName + "_"); + System.out.println("Results written on file"); + } - // Run the simulation - System.out.println("Starting experiment " + experimentName); - experiment.runSimulation(Time.inSeconds(DreamConfiguration.get().simulationTimeInSeconds)); - System.out.println("Experiment " + experimentName + " complete"); - mLogger.printResults(experimentName + "_"); - System.out.println("Results written on file"); - } + private final String getProtocolName(int id) { + switch (id) { + case DreamConfiguration.CAUSAL: + return "causal"; + case DreamConfiguration.SINGLE_SOURCE_GLITCH_FREE: + return "single_glitch_free"; + case DreamConfiguration.COMPLETE_GLITCH_FREE: + return "complete_glitch_free"; + case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: + return "complete_glitch_free_optimized"; + case DreamConfiguration.ATOMIC: + return "atomic"; + case DreamConfiguration.SIDUP: + return "sid_up"; + default: + assert false : id; + return null; + } + } - private final String getProtocolName(int id) { - switch (id) { - case DreamConfiguration.CAUSAL: - return "causal"; - case DreamConfiguration.SINGLE_SOURCE_GLITCH_FREE: - return "single_glitch_free"; - case DreamConfiguration.COMPLETE_GLITCH_FREE: - return "complete_glitch_free"; - case DreamConfiguration.COMPLETE_GLITCH_FREE_OPTIMIZED: - return "complete_glitch_free_optimized"; - case DreamConfiguration.ATOMIC: - return "atomic"; - case DreamConfiguration.SIDUP: - return "sid_up"; - default: - assert false : id; - return null; - } - } - - @Override - public NetworkInterfaceFactory createNetworkInterfaceFactory() { - return new DelayLossNetworkInterfaceFactory(getEventScheduler(), // - new UniformDelayModel(DreamConfiguration.get().minCommunicationDelayInMs, DreamConfiguration.get().maxCommunicationDelayInMs)); - } + @Override + public NetworkInterfaceFactory createNetworkInterfaceFactory() { + return new DelayLossNetworkInterfaceFactory(getEventScheduler(), // + new DreamDelayModel(DreamConfiguration.get().minCommunicationDelayInMs, + DreamConfiguration.get().maxCommunicationDelayInMs)); + } } diff --git a/DreamSim/src/dream/generator/GraphGenerator.java b/DreamSim/src/dream/generator/GraphGenerator.java index 362b156..ead9179 100755 --- a/DreamSim/src/dream/generator/GraphGenerator.java +++ b/DreamSim/src/dream/generator/GraphGenerator.java @@ -20,181 +20,183 @@ import dream.experiments.DreamConfiguration; public class GraphGenerator { - private static GraphGenerator instance; - - private final DependencyGraph depGraph = DependencyGraph.instance; - // Existing nodes, organized by source - private final Map> nodesPerSource = new HashMap<>(); - private final List allNodes = new ArrayList<>(); - - private final DreamConfiguration config = DreamConfiguration.get(); - private final Random random = RandomGenerator.get(); - - private final Map listeners = new HashMap<>(); - - public static final GraphGenerator get() { - if (instance == null) { - instance = new GraphGenerator(); - } - return instance; - } - - private GraphGenerator() { - // Nothing to do - } - - public void clean() { - depGraph.clear(); - nodesPerSource.clear(); - allNodes.clear(); - listeners.clear(); - } - - public final void generateGraphs(int id) { - // Only the first client triggers a graph generation - if (id == 0) { - IntStream.range(0, config.graphNumSources).forEach(i -> generateVar()); - nodesPerSource.keySet().forEach(source -> generateGraphFor(source)); - addInterSourceEdges(); - } - } - - public final void addGraphGeneratorListener(GraphGeneratorListener listener, int id) { - final String hostName = Consts.hostPrefix + id; - listeners.put(hostName, listener); - } - - public final void notifyListeners(int id) { - // Only the first client triggers listeners notification - if (id == 0) { - // Consolidates the data structures used during the processing of the - // events - IntraSourceDependencyDetector.instance.consolidate(); - CompleteGlitchFreeDependencyDetector.instance.consolidate(); - AtomicDependencyDetector.instance.consolidate(); - FinalNodesDetector.instance.consolidate(); - LocalityDetector.instance.consolidate(); - - depGraph.getSources().forEach(s -> { - final String hostId = s.split("@")[1]; - listeners.get(hostId).notifyVar(s); - }); - - depGraph.getGraph().entrySet().forEach(e -> { - final String name = e.getKey(); - final String hostId = name.split("@")[1]; - final Set deps = e.getValue().stream().collect(Collectors.toSet()); - listeners.get(hostId).notifySignal(name, deps); - }); - } - } - - private final void generateVar() { - final String host = selectRandomHost(); - final String name = Consts.objPrefix + allNodes.size(); - final String node = name + "@" + host; - final List sourceNodes = new ArrayList<>(); - sourceNodes.add(node); - nodesPerSource.put(node, sourceNodes); - allNodes.add(node); - depGraph.addVar(node); - } - - private final void generateGraphFor(String source) { - final int numLevels = config.graphDepth; - // Start from 1 because level 0 is the source - List previousLevel = new ArrayList<>(); - previousLevel.add(source); - for (int i = 1; i < numLevels; i++) { - previousLevel = generateLevel(source, previousLevel); - } - } - - private final void addInterSourceEdges() { - final List sourceList = new ArrayList<>(nodesPerSource.keySet()); - final int numSharedSources = (int) ((sourceList.size() - 1) * config.graphNodeShareProbability); - for (int i = 0; i < numSharedSources; i++) { - final String source = sourceList.get(i); - final String nextSource = sourceList.get(i + 1); - addInterSourceEdgesBetween(source, nextSource); - } - } - - private final void addInterSourceEdgesBetween(String source1, String source2) { - if (nodesPerSource.get(source1).size() < 3 || nodesPerSource.get(source2).size() < 3) { - throw new IllegalArgumentException("The number of nodes is too small to generate inter-source edges"); - } - final List nodes1 = selectRandomSignalsFromSource(source1, 2); - final List nodes2 = selectRandomSignalsFromSource(source2, 2); - - depGraph.getGraph().get(nodes1.get(0)).add(nodes2.get(0)); - depGraph.getGraph().get(nodes1.get(1)).add(nodes2.get(1)); - } - - private final List generateLevel(String source, List previousLevel) { - final int numNodes = config.graphMinNodesPerLevel + random.nextInt(config.graphMaxNodesPerLevel - config.graphMinNodesPerLevel + 1); - final List currentLevel = new ArrayList<>(); - for (int i = 0; i <= numNodes; i++) { - currentLevel.add(generateSignal(source, previousLevel)); - } - return currentLevel; - } - - private final String generateSignal(String source, List previousLevel) { - final String name = Consts.objPrefix + allNodes.size(); - final List depNodes = selectDepNodes(source, previousLevel); - final String host = random.nextDouble() < config.graphLocality// - ? depNodes.stream().findAny().get().split("@")[1] // - : selectRandomHost(); - - final String node = name + "@" + host; - nodesPerSource.get(source).add(node); - allNodes.add(node); - depGraph.addSignal(node, depNodes); - return node; - } - - private final List selectDepNodes(String source, List previousLevel) { - final List result = new ArrayList<>(); - final int numDeps = Math.min(1 + random.nextInt(config.graphMaxDependenciesPerNode), nodesPerSource.get(source).size()); - - // Always select a node from the previous level of the source graph - result.add(selectRandomNodeFromPreviousLevel(previousLevel)); - // Select the remaining nodes from the same source - result.addAll(selectRandomNodesFromSource(source, numDeps - 1)); - - return result; - } - - private final String selectRandomNodeFromPreviousLevel(List previousLevel) { - return previousLevel.get(random.nextInt(previousLevel.size())); - } - - private final List selectRandomNodesFromSource(String source, int numNodes) { - final List sourceNodes = nodesPerSource.get(source); - Collections.shuffle(sourceNodes); - return IntStream.range(0, numNodes) // - .mapToObj(i -> sourceNodes.get(i)) // - .collect(Collectors.toList()); - } - - private final List selectRandomSignalsFromSource(String source, int numSignals) { - final List sourceNodes = nodesPerSource.get(source); - Collections.shuffle(sourceNodes); - final List result = new ArrayList<>(); - int index = 0; - while (result.size() < numSignals) { - final String node = sourceNodes.get(index++); - if (!node.equals(source)) { - result.add(node); - } - } - return result; - } - - private final String selectRandomHost() { - final int id = random.nextInt(config.numberOfClients); - return Consts.hostPrefix + id; - } + private static GraphGenerator instance; + + private final DependencyGraph depGraph = DependencyGraph.instance; + // Existing nodes, organized by source + private final Map> nodesPerSource = new HashMap<>(); + private final List allNodes = new ArrayList<>(); + + private final DreamConfiguration config = DreamConfiguration.get(); + private final Random random = RandomGenerator.get(); + + private final Map listeners = new HashMap<>(); + + public static final GraphGenerator get() { + if (instance == null) { + instance = new GraphGenerator(); + } + return instance; + } + + private GraphGenerator() { + // Nothing to do + } + + public void clean() { + depGraph.clear(); + nodesPerSource.clear(); + allNodes.clear(); + listeners.clear(); + } + + public final void generateGraphs(int id) { + // Only the first client triggers a graph generation + if (id == 0) { + IntStream.range(0, config.graphNumSources).forEach(i -> generateVar()); + nodesPerSource.keySet().forEach(source -> generateGraphFor(source)); + addInterSourceEdges(); + } + } + + public final void addGraphGeneratorListener(GraphGeneratorListener listener, int id) { + final String hostName = Consts.hostPrefix + id; + listeners.put(hostName, listener); + } + + public final void notifyListeners(int id) { + // Only the first client triggers listeners notification + if (id == 0) { + // Consolidates the data structures used during the processing of the + // events + IntraSourceDependencyDetector.instance.consolidate(); + CompleteGlitchFreeDependencyDetector.instance.consolidate(); + AtomicDependencyDetector.instance.consolidate(); + FinalNodesDetector.instance.consolidate(); + LocalityDetector.instance.consolidate(); + + depGraph.getSources().forEach(s -> { + final String hostId = s.split("@")[1]; + listeners.get(hostId).notifyVar(s); + }); + + depGraph.getGraph().entrySet().forEach(e -> { + final String name = e.getKey(); + final String hostId = name.split("@")[1]; + final Set deps = e.getValue().stream().collect(Collectors.toSet()); + listeners.get(hostId).notifySignal(name, deps); + }); + } + } + + private final void generateVar() { + final String host = selectRandomHost(); + final String name = Consts.objPrefix + allNodes.size(); + final String node = name + "@" + host; + final List sourceNodes = new ArrayList<>(); + sourceNodes.add(node); + nodesPerSource.put(node, sourceNodes); + allNodes.add(node); + depGraph.addVar(node); + } + + private final void generateGraphFor(String source) { + final int numLevels = config.graphDepth; + // Start from 1 because level 0 is the source + List previousLevel = new ArrayList<>(); + previousLevel.add(source); + for (int i = 1; i < numLevels; i++) { + previousLevel = generateLevel(source, previousLevel); + } + } + + private final void addInterSourceEdges() { + final List sourceList = new ArrayList<>(nodesPerSource.keySet()); + final int numSharedSources = (int) ((sourceList.size() - 1) * config.graphNodeShareProbability); + for (int i = 0; i < numSharedSources; i++) { + final String source = sourceList.get(i); + final String nextSource = sourceList.get(i + 1); + addInterSourceEdgesBetween(source, nextSource); + } + } + + private final void addInterSourceEdgesBetween(String source1, String source2) { + if (nodesPerSource.get(source1).size() < 3 || nodesPerSource.get(source2).size() < 3) { + throw new IllegalArgumentException("The number of nodes is too small to generate inter-source edges"); + } + final List nodes1 = selectRandomSignalsFromSource(source1, 2); + final List nodes2 = selectRandomSignalsFromSource(source2, 2); + + depGraph.getGraph().get(nodes1.get(0)).add(nodes2.get(0)); + depGraph.getGraph().get(nodes1.get(1)).add(nodes2.get(1)); + } + + private final List generateLevel(String source, List previousLevel) { + final int numNodes = config.graphMinNodesPerLevel + + random.nextInt(config.graphMaxNodesPerLevel - config.graphMinNodesPerLevel + 1); + final List currentLevel = new ArrayList<>(); + for (int i = 0; i <= numNodes; i++) { + currentLevel.add(generateSignal(source, previousLevel)); + } + return currentLevel; + } + + private final String generateSignal(String source, List previousLevel) { + final String name = Consts.objPrefix + allNodes.size(); + final List depNodes = selectDepNodes(source, previousLevel); + final String host = random.nextDouble() < config.graphLocality// + ? depNodes.stream().findAny().get().split("@")[1] // + : selectRandomHost(); + + final String node = name + "@" + host; + nodesPerSource.get(source).add(node); + allNodes.add(node); + depGraph.addSignal(node, depNodes); + return node; + } + + private final List selectDepNodes(String source, List previousLevel) { + final List result = new ArrayList<>(); + final int numDeps = Math.min(1 + random.nextInt(config.graphMaxDependenciesPerNode), + nodesPerSource.get(source).size()); + + // Always select a node from the previous level of the source graph + result.add(selectRandomNodeFromPreviousLevel(previousLevel)); + // Select the remaining nodes from the same source + result.addAll(selectRandomNodesFromSource(source, numDeps - 1)); + + return result; + } + + private final String selectRandomNodeFromPreviousLevel(List previousLevel) { + return previousLevel.get(random.nextInt(previousLevel.size())); + } + + private final List selectRandomNodesFromSource(String source, int numNodes) { + final List sourceNodes = nodesPerSource.get(source); + Collections.shuffle(sourceNodes); + return IntStream.range(0, numNodes) // + .mapToObj(i -> sourceNodes.get(i)) // + .collect(Collectors.toList()); + } + + private final List selectRandomSignalsFromSource(String source, int numSignals) { + final List sourceNodes = nodesPerSource.get(source); + Collections.shuffle(sourceNodes); + final List result = new ArrayList<>(); + int index = 0; + while (result.size() < numSignals) { + final String node = sourceNodes.get(index++); + if (!node.equals(source)) { + result.add(node); + } + } + return result; + } + + private final String selectRandomHost() { + final int id = random.nextInt(config.numberOfClients); + return Consts.hostPrefix + id; + } } diff --git a/DreamSim/src/dream/generator/GraphGeneratorListener.java b/DreamSim/src/dream/generator/GraphGeneratorListener.java index b09ca5f..83cf7bf 100755 --- a/DreamSim/src/dream/generator/GraphGeneratorListener.java +++ b/DreamSim/src/dream/generator/GraphGeneratorListener.java @@ -9,15 +9,15 @@ */ public interface GraphGeneratorListener { - /** - * Notifies the presence of a var with the given name. - */ - public void notifyVar(String varName); + /** + * Notifies the presence of a var with the given name. + */ + public void notifyVar(String varName); - /** - * Notifies the presence of a signal with the given name and the given - * dependencies. - */ - public void notifySignal(String signalName, Set dependencies); + /** + * Notifies the presence of a signal with the given name and the given + * dependencies. + */ + public void notifySignal(String signalName, Set dependencies); } diff --git a/DreamSim/src/dream/generator/RandomGenerator.java b/DreamSim/src/dream/generator/RandomGenerator.java index 99c7512..ec2150a 100755 --- a/DreamSim/src/dream/generator/RandomGenerator.java +++ b/DreamSim/src/dream/generator/RandomGenerator.java @@ -5,21 +5,21 @@ import dream.experiments.DreamConfiguration; public class RandomGenerator { - private static Random random; + private static Random random; - public static Random get() { - if (random == null) { - random = new Random(DreamConfiguration.get().seed); - } - return random; - } + public static Random get() { + if (random == null) { + random = new Random(DreamConfiguration.get().seed); + } + return random; + } - public static void reset() { - if (random == null) { - random = new Random(DreamConfiguration.get().seed); - } else { - random.setSeed(DreamConfiguration.get().seed); - } - } + public static void reset() { + if (random == null) { + random = new Random(DreamConfiguration.get().seed); + } else { + random.setSeed(DreamConfiguration.get().seed); + } + } } diff --git a/DreamSim/src/dream/locking/DreamLockManager.java b/DreamSim/src/dream/locking/DreamLockManager.java index 7c619ec..e1fc803 100644 --- a/DreamSim/src/dream/locking/DreamLockManager.java +++ b/DreamSim/src/dream/locking/DreamLockManager.java @@ -14,162 +14,162 @@ import dream.common.packets.locking.LockType; class DreamLockManager implements LockManager { - // Pending requests - private final List pendingRequests = new ArrayList<>(); - - // All stored locks - private final Map activeLocks = new HashMap<>(); - - // Stored read and write locks - private final Map readLocks = new HashMap<>(); - private final WriteLockManager writeLocks = new WriteLockManager(); - - @Override - public final boolean processLockRequest(LockRequestPacket request) { - if (canBeGranted(request)) { - lock(request); - return true; - } else { - pendingRequests.add(request); - return false; - } - } - - @Override - public final Set processLockRelease(LockReleasePacket release) { - final UUID lockID = release.getLockID(); - assert activeLocks.containsKey(lockID); - final LockRequestPacket reqPkt = activeLocks.get(lockID); - - final Set result = new HashSet<>(); - if (release(reqPkt.getLockID(), reqPkt.getLockNodes(), reqPkt.getType())) { - final Iterator it = pendingRequests.iterator(); - while (it.hasNext()) { - final LockRequestPacket request = it.next(); - if (canBeGranted(request)) { - lock(request); - result.add(request); - it.remove(); - } - } - } - return result; - } - - private final boolean canBeGranted(LockRequestPacket request) { - final LockType type = request.getType(); - final Set lockNodes = request.getLockNodes(); - final boolean writeConflicts = lockNodes.stream()// - .anyMatch(n -> writeLocks.isLocked(n)); - if (writeConflicts) { - return false; - } - final boolean readConflicts = type == LockType.READ_WRITE && // - lockNodes.stream().anyMatch(n -> readLocks.containsKey(n)); - return !readConflicts; - } - - private final void lock(LockRequestPacket request) { - activeLocks.put(request.getLockID(), request); - final LockType type = request.getType(); - final Set lockNodes = request.getLockNodes(); - switch (type) { - case READ_ONLY: - lockNodes.forEach(n -> { - final Integer count = readLocks.get(n); - if (count == null) { - readLocks.put(n, 1); - } else { - readLocks.put(n, count + 1); - } - }); - break; - case READ_WRITE: - writeLocks.grant(request); - break; - default: - assert false : type; - break; - } - } - - /** - * Return true if the packet released at least one node - */ - private final boolean release(UUID lockId, Set lockNodes, LockType type) { - boolean result = false; - switch (type) { - case READ_ONLY: - for (final String lockNode : lockNodes) { - final int newCount = readLocks.get(lockNode) - 1; - if (newCount == 0) { - readLocks.remove(lockNode); - activeLocks.remove(lockId); - result = true; - } else { - readLocks.put(lockNode, newCount); - } - } - break; - case READ_WRITE: - if (writeLocks.release(lockId)) { - activeLocks.remove(lockId); - result = true; - } - break; - default: - assert false : type; - break; - } - return result; - } - - /** - * Store information about the write locks that have been granted. - */ - private class WriteLockManager { - private final Map grantedLocks = new HashMap<>(); - private final Map> lockedNodesMap = new HashMap<>(); - private final Set lockedNodes = new HashSet<>(); - - /** - * Store the lock coming from the given source and having the given lockId. - */ - void grant(LockRequestPacket request) { - final UUID lockId = request.getLockID(); - final Set nodesToLock = request.getLockNodes(); - assert !grantedLocks.containsKey(lockId); - assert !lockedNodesMap.containsKey(lockId); - - grantedLocks.put(lockId, request.getUnlockNodes().size()); - lockedNodesMap.put(lockId, new HashSet<>(nodesToLock)); - lockedNodes.addAll(nodesToLock); - } - - /** - * Return true if the given node is already locked. - */ - boolean isLocked(String node) { - return lockedNodes.contains(node); - } - - /** - * Return true if the lock has been entirely released. - */ - boolean release(UUID lockId) { - assert grantedLocks.containsKey(lockId); - Integer count = grantedLocks.get(lockId); - if (--count == 0) { - grantedLocks.remove(lockId); - lockedNodesMap.get(lockId).forEach(lockedNodes::remove); - lockedNodesMap.remove(lockId); - return true; - } else { - grantedLocks.put(lockId, count); - return false; - } - } - - } + // Pending requests + private final List pendingRequests = new ArrayList<>(); + + // All stored locks + private final Map activeLocks = new HashMap<>(); + + // Stored read and write locks + private final Map readLocks = new HashMap<>(); + private final WriteLockManager writeLocks = new WriteLockManager(); + + @Override + public final boolean processLockRequest(LockRequestPacket request) { + if (canBeGranted(request)) { + lock(request); + return true; + } else { + pendingRequests.add(request); + return false; + } + } + + @Override + public final Set processLockRelease(LockReleasePacket release) { + final UUID lockID = release.getLockID(); + assert activeLocks.containsKey(lockID); + final LockRequestPacket reqPkt = activeLocks.get(lockID); + + final Set result = new HashSet<>(); + if (release(reqPkt.getLockID(), reqPkt.getLockNodes(), reqPkt.getType())) { + final Iterator it = pendingRequests.iterator(); + while (it.hasNext()) { + final LockRequestPacket request = it.next(); + if (canBeGranted(request)) { + lock(request); + result.add(request); + it.remove(); + } + } + } + return result; + } + + private final boolean canBeGranted(LockRequestPacket request) { + final LockType type = request.getType(); + final Set lockNodes = request.getLockNodes(); + final boolean writeConflicts = lockNodes.stream()// + .anyMatch(n -> writeLocks.isLocked(n)); + if (writeConflicts) { + return false; + } + final boolean readConflicts = type == LockType.READ_WRITE && // + lockNodes.stream().anyMatch(n -> readLocks.containsKey(n)); + return !readConflicts; + } + + private final void lock(LockRequestPacket request) { + activeLocks.put(request.getLockID(), request); + final LockType type = request.getType(); + final Set lockNodes = request.getLockNodes(); + switch (type) { + case READ_ONLY: + lockNodes.forEach(n -> { + final Integer count = readLocks.get(n); + if (count == null) { + readLocks.put(n, 1); + } else { + readLocks.put(n, count + 1); + } + }); + break; + case READ_WRITE: + writeLocks.grant(request); + break; + default: + assert false : type; + break; + } + } + + /** + * Return true if the packet released at least one node + */ + private final boolean release(UUID lockId, Set lockNodes, LockType type) { + boolean result = false; + switch (type) { + case READ_ONLY: + for (final String lockNode : lockNodes) { + final int newCount = readLocks.get(lockNode) - 1; + if (newCount == 0) { + readLocks.remove(lockNode); + activeLocks.remove(lockId); + result = true; + } else { + readLocks.put(lockNode, newCount); + } + } + break; + case READ_WRITE: + if (writeLocks.release(lockId)) { + activeLocks.remove(lockId); + result = true; + } + break; + default: + assert false : type; + break; + } + return result; + } + + /** + * Store information about the write locks that have been granted. + */ + private class WriteLockManager { + private final Map grantedLocks = new HashMap<>(); + private final Map> lockedNodesMap = new HashMap<>(); + private final Set lockedNodes = new HashSet<>(); + + /** + * Store the lock coming from the given source and having the given lockId. + */ + void grant(LockRequestPacket request) { + final UUID lockId = request.getLockID(); + final Set nodesToLock = request.getLockNodes(); + assert !grantedLocks.containsKey(lockId); + assert !lockedNodesMap.containsKey(lockId); + + grantedLocks.put(lockId, request.getUnlockNodes().size()); + lockedNodesMap.put(lockId, new HashSet<>(nodesToLock)); + lockedNodes.addAll(nodesToLock); + } + + /** + * Return true if the given node is already locked. + */ + boolean isLocked(String node) { + return lockedNodes.contains(node); + } + + /** + * Return true if the lock has been entirely released. + */ + boolean release(UUID lockId) { + assert grantedLocks.containsKey(lockId); + Integer count = grantedLocks.get(lockId); + if (--count == 0) { + grantedLocks.remove(lockId); + lockedNodesMap.get(lockId).forEach(lockedNodes::remove); + lockedNodesMap.remove(lockId); + return true; + } else { + grantedLocks.put(lockId, count); + return false; + } + } + + } } diff --git a/DreamSim/src/dream/locking/LockManager.java b/DreamSim/src/dream/locking/LockManager.java index e125afc..b9e3ce2 100644 --- a/DreamSim/src/dream/locking/LockManager.java +++ b/DreamSim/src/dream/locking/LockManager.java @@ -7,23 +7,23 @@ interface LockManager { - /** - * Process the given request. Returns true if the lock can be granted. - * - * @param request - * the request. - * @return true if the lock is granted, false otherwise. - */ - boolean processLockRequest(LockRequestPacket request); + /** + * Process the given request. Returns true if the lock can be granted. + * + * @param request + * the request. + * @return true if the lock is granted, false otherwise. + */ + boolean processLockRequest(LockRequestPacket request); - /** - * Process the given release. Returns the set of pending requests that can now - * obtain a lock. - * - * @param release - * the release. - * @return the set of granted locks. - */ - Set processLockRelease(LockReleasePacket release); + /** + * Process the given release. Returns the set of pending requests that can now + * obtain a lock. + * + * @param release + * the release. + * @return the set of granted locks. + */ + Set processLockRelease(LockReleasePacket release); } \ No newline at end of file diff --git a/DreamSim/src/dream/locking/LockManagerFactory.java b/DreamSim/src/dream/locking/LockManagerFactory.java index 38480bd..5ae4558 100644 --- a/DreamSim/src/dream/locking/LockManagerFactory.java +++ b/DreamSim/src/dream/locking/LockManagerFactory.java @@ -7,12 +7,12 @@ public class LockManagerFactory implements PeerFactory { - @Override - public Peer createPeer(int peerIndex, Experiment experiment) { - final Peer newPeer = new Peer(peerIndex); - newPeer.addPeerlet(new LockManagerForwarder()); - newPeer.addPeerlet(new LockManagerMeasurementPeerlet()); - return newPeer; - } + @Override + public Peer createPeer(int peerIndex, Experiment experiment) { + final Peer newPeer = new Peer(peerIndex); + newPeer.addPeerlet(new LockManagerForwarder()); + newPeer.addPeerlet(new LockManagerMeasurementPeerlet()); + return newPeer; + } } diff --git a/DreamSim/src/dream/locking/LockManagerForwarder.java b/DreamSim/src/dream/locking/LockManagerForwarder.java index 62986ae..15859e3 100644 --- a/DreamSim/src/dream/locking/LockManagerForwarder.java +++ b/DreamSim/src/dream/locking/LockManagerForwarder.java @@ -16,54 +16,54 @@ import protopeer.network.NetworkAddress; public class LockManagerForwarder extends BasePeerlet { - private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - private final LockManager lockManager = // - DreamConfiguration.get().consistencyType == DreamConfiguration.SIDUP // - ? new SidUpLockManager() // - : new DreamLockManager(); + private final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + private final LockManager lockManager = // + DreamConfiguration.get().consistencyType == DreamConfiguration.SIDUP // + ? new SidUpLockManager() // + : new DreamLockManager(); - @Override - public void init(Peer peer) { - super.init(peer); - } + @Override + public void init(Peer peer) { + super.init(peer); + } - @Override - public void handleIncomingMessage(Message packet) { - final Outbox outbox = new Outbox(); - if (packet instanceof LockRequestPacket) { - final LockRequestPacket reqPkt = (LockRequestPacket) packet; - logger.fine("Received a request packet: " + reqPkt); - processRequestPacket(packet.getSourceAddress(), reqPkt, outbox); - } else if (packet instanceof LockReleasePacket) { - final LockReleasePacket relPkt = (LockReleasePacket) packet; - logger.finer("Received a release packet: " + relPkt); - processReleasePacket(packet.getSourceAddress(), relPkt, outbox); - } - deliverPacketsInOutbox(outbox); - } + @Override + public void handleIncomingMessage(Message packet) { + final Outbox outbox = new Outbox(); + if (packet instanceof LockRequestPacket) { + final LockRequestPacket reqPkt = (LockRequestPacket) packet; + logger.fine("Received a request packet: " + reqPkt); + processRequestPacket(packet.getSourceAddress(), reqPkt, outbox); + } else if (packet instanceof LockReleasePacket) { + final LockReleasePacket relPkt = (LockReleasePacket) packet; + logger.finer("Received a release packet: " + relPkt); + processReleasePacket(packet.getSourceAddress(), relPkt, outbox); + } + deliverPacketsInOutbox(outbox); + } - private final void processRequestPacket(NetworkAddress sender, LockRequestPacket reqPkt, Outbox outbox) { - final boolean granted = lockManager.processLockRequest(reqPkt); - if (granted) { - final Collection recipients = new ArrayList<>(1); - recipients.add(sender); - outbox.add(LockGrantPacket.subject, new LockGrantPacket(reqPkt), recipients); - } - } + private final void processRequestPacket(NetworkAddress sender, LockRequestPacket reqPkt, Outbox outbox) { + final boolean granted = lockManager.processLockRequest(reqPkt); + if (granted) { + final Collection recipients = new ArrayList<>(1); + recipients.add(sender); + outbox.add(LockGrantPacket.subject, new LockGrantPacket(reqPkt), recipients); + } + } - private final void processReleasePacket(NetworkAddress sender, LockReleasePacket relPkt, Outbox outbox) { - final Set granted = lockManager.processLockRelease(relPkt); - granted.forEach(req -> { - final Collection recipients = new ArrayList<>(1); - recipients.add(req.getApplicant()); - outbox.add(LockGrantPacket.subject, new LockGrantPacket(req), recipients); - }); - } + private final void processReleasePacket(NetworkAddress sender, LockReleasePacket relPkt, Outbox outbox) { + final Set granted = lockManager.processLockRelease(relPkt); + granted.forEach(req -> { + final Collection recipients = new ArrayList<>(1); + recipients.add(req.getApplicant()); + outbox.add(LockGrantPacket.subject, new LockGrantPacket(req), recipients); + }); + } - private final void deliverPacketsInOutbox(Outbox outbox) { - outbox.getPacketsToSend().forEach(p -> { - outbox.getRecipientsFor(p).forEach(r -> getPeer().sendMessage(r, p)); - }); - } + private final void deliverPacketsInOutbox(Outbox outbox) { + outbox.getPacketsToSend().forEach(p -> { + outbox.getRecipientsFor(p).forEach(r -> getPeer().sendMessage(r, p)); + }); + } } diff --git a/DreamSim/src/dream/locking/SidUpLockManager.java b/DreamSim/src/dream/locking/SidUpLockManager.java index 3c35a49..1566611 100644 --- a/DreamSim/src/dream/locking/SidUpLockManager.java +++ b/DreamSim/src/dream/locking/SidUpLockManager.java @@ -9,46 +9,46 @@ import dream.common.packets.locking.LockRequestPacket; class SidUpLockManager implements LockManager { - private final Queue pendingRequests = new LinkedList<>(); - - @Override - public final boolean processLockRequest(LockRequestPacket request) { - pendingRequests.add(new PendingRequest(request)); - return pendingRequests.size() == 1; - } - - @Override - public final Set processLockRelease(LockReleasePacket release) { - assert !pendingRequests.isEmpty(); - final PendingRequest req = pendingRequests.peek(); - assert req.getRequest().getLockID().equals(release.getLockID()); - final Set result = new HashSet<>(); - if (req.decreaseCount()) { - pendingRequests.poll(); - result.add(pendingRequests.peek().getRequest()); - } - return result; - } - - private class PendingRequest { - private final LockRequestPacket request; - private int count; - - PendingRequest(LockRequestPacket request) { - super(); - this.request = request; - count = request.getUnlockNodes().size(); - } - - final LockRequestPacket getRequest() { - return request; - } - - boolean decreaseCount() { - count--; - return count == 0; - } - - } + private final Queue pendingRequests = new LinkedList<>(); + + @Override + public final boolean processLockRequest(LockRequestPacket request) { + pendingRequests.add(new PendingRequest(request)); + return pendingRequests.size() == 1; + } + + @Override + public final Set processLockRelease(LockReleasePacket release) { + assert !pendingRequests.isEmpty(); + final PendingRequest req = pendingRequests.peek(); + assert req.getRequest().getLockID().equals(release.getLockID()); + final Set result = new HashSet<>(); + if (req.decreaseCount()) { + pendingRequests.poll(); + result.add(pendingRequests.peek().getRequest()); + } + return result; + } + + private class PendingRequest { + private final LockRequestPacket request; + private int count; + + PendingRequest(LockRequestPacket request) { + super(); + this.request = request; + count = request.getUnlockNodes().size(); + } + + final LockRequestPacket getRequest() { + return request; + } + + boolean decreaseCount() { + count--; + return count == 0; + } + + } } diff --git a/DreamSim/src/dream/measurement/ClientMeasurementPeerlet.java b/DreamSim/src/dream/measurement/ClientMeasurementPeerlet.java index 222a76c..246cbce 100755 --- a/DreamSim/src/dream/measurement/ClientMeasurementPeerlet.java +++ b/DreamSim/src/dream/measurement/ClientMeasurementPeerlet.java @@ -2,27 +2,38 @@ import dream.experiments.DreamConfiguration; import protopeer.BasePeerlet; +import protopeer.Experiment; import protopeer.Peer; import protopeer.network.Message; +import protopeer.network.NetworkAddress; /** * This peerlet, installed in every client, collects and prints information * about the network traffic. */ public class ClientMeasurementPeerlet extends BasePeerlet { - private MeasurementLogger mLogger; + private MeasurementLogger mLogger; - @Override - public void init(Peer peer) { - super.init(peer); - mLogger = MeasurementLogger.getLogger(); - } + @Override + public void init(Peer peer) { + super.init(peer); + mLogger = MeasurementLogger.getLogger(); + } - @Override - public void handleOutgoingMessage(Message msg) { - for (int i = 0; i < DreamConfiguration.get().linkLength; i++) { - mLogger.saveMessage(msg); - } - } + @Override + public void handleOutgoingMessage(Message msg) { + final int numHops = destinationIsLockManager(msg) // + ? DreamConfiguration.get().numHopsToLockManager // + : DreamConfiguration.get().numHopsPerLink; + for (int i = 0; i < numHops; i++) { + mLogger.saveMessage(msg); + } + } + + private final boolean destinationIsLockManager(Message msg) { + final int lockManagerId = DreamConfiguration.get().numberOfBrokers + DreamConfiguration.get().numberOfClients + 1; + final NetworkAddress lockManagerAddress = Experiment.getSingleton().getAddressToBindTo(lockManagerId); + return msg.getDestinationAddress().equals(lockManagerAddress); + } } diff --git a/DreamSim/src/dream/measurement/DreamDelayModel.java b/DreamSim/src/dream/measurement/DreamDelayModel.java new file mode 100644 index 0000000..787d496 --- /dev/null +++ b/DreamSim/src/dream/measurement/DreamDelayModel.java @@ -0,0 +1,32 @@ +package dream.measurement; + +import dream.experiments.DreamConfiguration; +import protopeer.Experiment; +import protopeer.network.Message; +import protopeer.network.NetworkAddress; +import protopeer.network.delayloss.UniformDelayModel; +import protopeer.util.RandomnessSource; + +public class DreamDelayModel extends UniformDelayModel { + + public DreamDelayModel(double minDelay, double maxDelay) { + super(minDelay, maxDelay); + } + + @Override + public double getDelay(NetworkAddress sourceAddress, NetworkAddress destinationAddress, Message message) { + final double linkDelay = minDelay + RandomnessSource.getNextNetworkDouble() * (maxDelay - minDelay); + final int numLinks = communicationInvolvesLockManager(sourceAddress, destinationAddress) // + ? DreamConfiguration.get().numHopsToLockManager // + : DreamConfiguration.get().numHopsPerLink; + return linkDelay * numLinks; + } + + private final boolean communicationInvolvesLockManager(NetworkAddress sourceAddress, + NetworkAddress destinationAddress) { + final int lockManagerId = DreamConfiguration.get().numberOfBrokers + DreamConfiguration.get().numberOfClients + 1; + final NetworkAddress lockManagerAddress = Experiment.getSingleton().getAddressToBindTo(lockManagerId); + return sourceAddress.equals(lockManagerAddress) || destinationAddress.equals(lockManagerAddress); + } + +} diff --git a/DreamSim/src/dream/measurement/LockManagerMeasurementPeerlet.java b/DreamSim/src/dream/measurement/LockManagerMeasurementPeerlet.java index 8e850c2..661ace9 100644 --- a/DreamSim/src/dream/measurement/LockManagerMeasurementPeerlet.java +++ b/DreamSim/src/dream/measurement/LockManagerMeasurementPeerlet.java @@ -10,19 +10,19 @@ * about the network traffic. */ public class LockManagerMeasurementPeerlet extends BasePeerlet { - private MeasurementLogger mLogger; + private MeasurementLogger mLogger; - @Override - public void init(Peer peer) { - super.init(peer); - mLogger = MeasurementLogger.getLogger(); - } + @Override + public void init(Peer peer) { + super.init(peer); + mLogger = MeasurementLogger.getLogger(); + } - @Override - public void handleOutgoingMessage(Message msg) { - for (int i = 0; i < DreamConfiguration.get().linkLength; i++) { - mLogger.saveMessage(msg); - } - } + @Override + public void handleOutgoingMessage(Message msg) { + for (int i = 0; i < DreamConfiguration.get().numHopsToLockManager; i++) { + mLogger.saveMessage(msg); + } + } } diff --git a/DreamSim/src/dream/measurement/MeasurementLogger.java b/DreamSim/src/dream/measurement/MeasurementLogger.java index addf43f..3112e38 100755 --- a/DreamSim/src/dream/measurement/MeasurementLogger.java +++ b/DreamSim/src/dream/measurement/MeasurementLogger.java @@ -21,131 +21,131 @@ * @author Alessandro Margara */ public class MeasurementLogger { - private final Map storedMsgs = new HashMap(); - private final Map storedMsgsSize = new HashMap(); - private final Map> storedDelays = new HashMap>(); - private final int epochDuration; - private final int simulationTime; - private static MeasurementLogger logger = null; + private final Map storedMsgs = new HashMap(); + private final Map storedMsgsSize = new HashMap(); + private final Map> storedDelays = new HashMap>(); + private final int epochDuration; + private final int simulationTime; + private static MeasurementLogger logger = null; - public static MeasurementLogger getLogger() { - if (logger == null) { - logger = new MeasurementLogger(); - } - return logger; - } + public static MeasurementLogger getLogger() { + if (logger == null) { + logger = new MeasurementLogger(); + } + return logger; + } - private MeasurementLogger() { - // Private constructor - simulationTime = DreamConfiguration.get().simulationTimeInSeconds; - epochDuration = DreamConfiguration.get().epochDuration; - } + private MeasurementLogger() { + // Private constructor + simulationTime = DreamConfiguration.get().simulationTimeInSeconds; + epochDuration = DreamConfiguration.get().epochDuration; + } - public final void resetCounters() { - storedMsgs.clear(); - storedMsgsSize.clear(); - storedDelays.clear(); - } + public final void resetCounters() { + storedMsgs.clear(); + storedMsgsSize.clear(); + storedDelays.clear(); + } - public void saveMessage(Message msg) { - final String name = msg.getClass().getName(); - addMessage(name, msg); - } + public void saveMessage(Message msg) { + final String name = msg.getClass().getName(); + addMessage(name, msg); + } - public final void saveDelay(double delay) { - final double time = Experiment.getSingleton().getClock().getCurrentTime(); - final Integer epoch = (int) (time / epochDuration); - if (!storedDelays.containsKey(epoch)) { - final List content = new ArrayList(); - storedDelays.put(epoch, content); - } - storedDelays.get(epoch).add(delay); - } + public final void saveDelay(double delay) { + final double time = Experiment.getSingleton().getClock().getCurrentTime(); + final Integer epoch = (int) (time / epochDuration); + if (!storedDelays.containsKey(epoch)) { + final List content = new ArrayList(); + storedDelays.put(epoch, content); + } + storedDelays.get(epoch).add(delay); + } - public final void printResults(String filename) { - printTraffic(filename); - printDelay(filename); - printDelayAvg(filename); - } + public final void printResults(String filename) { + printTraffic(filename); + printDelay(filename); + printDelayAvg(filename); + } - private final void addMessage(String name, Message msg) { - if (!storedMsgs.containsKey(name)) { - storedMsgs.put(name, 1); - storedMsgsSize.put(name, Data.inByte(msg.getSize())); - } else { - final int previousCount = storedMsgs.remove(name); - storedMsgs.put(name, previousCount + 1); - final double previousSize = storedMsgsSize.remove(name); - storedMsgsSize.put(name, previousSize + Data.inByte(msg.getSize())); - } - } + private final void addMessage(String name, Message msg) { + if (!storedMsgs.containsKey(name)) { + storedMsgs.put(name, 1); + storedMsgsSize.put(name, Data.inByte(msg.getSize())); + } else { + final int previousCount = storedMsgs.remove(name); + storedMsgs.put(name, previousCount + 1); + final double previousSize = storedMsgsSize.remove(name); + storedMsgsSize.put(name, previousSize + Data.inByte(msg.getSize())); + } + } - private final void printTraffic(String filename) { - try { - final String filePrefix = DreamConfiguration.get().resultsDir + filename; - final FileOutputStream traffic = new FileOutputStream(filePrefix + "Traffic"); - final FileOutputStream trafficByte = new FileOutputStream(filePrefix + "TrafficByte"); - for (final String s : storedMsgs.keySet()) { - final int val = storedMsgs.get(s).intValue(); - traffic.write((s + "\t" + val + "\t" + (double) val / simulationTime + "\n").getBytes()); - } - for (final String s : storedMsgsSize.keySet()) { - final int val = storedMsgsSize.get(s).intValue(); - trafficByte.write((s + "\t" + val + "\t" + (double) val / simulationTime + "\n").getBytes()); - } - traffic.close(); - trafficByte.close(); - } catch (final FileNotFoundException e) { - e.printStackTrace(); - } catch (final IOException e) { - e.printStackTrace(); - } - } + private final void printTraffic(String filename) { + try { + final String filePrefix = DreamConfiguration.get().resultsDir + filename; + final FileOutputStream traffic = new FileOutputStream(filePrefix + "Traffic"); + final FileOutputStream trafficByte = new FileOutputStream(filePrefix + "TrafficByte"); + for (final String s : storedMsgs.keySet()) { + final int val = storedMsgs.get(s).intValue(); + traffic.write((s + "\t" + val + "\t" + (double) val / simulationTime + "\n").getBytes()); + } + for (final String s : storedMsgsSize.keySet()) { + final int val = storedMsgsSize.get(s).intValue(); + trafficByte.write((s + "\t" + val + "\t" + (double) val / simulationTime + "\n").getBytes()); + } + traffic.close(); + trafficByte.close(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + } - private final void printDelay(String filename) { - try { - final String filePrefix = DreamConfiguration.get().resultsDir + filename; - final FileOutputStream delay = new FileOutputStream(filePrefix + "Delay"); - final List keyList = new ArrayList(storedDelays.keySet()); - Collections.sort(keyList); - for (final Integer label : keyList) { - double sum = 0; - final double size = storedDelays.get(label).size(); - for (final Double val : storedDelays.get(label)) { - sum += val; - } - final double avgVal = sum / size; - delay.write((label * epochDuration / 1000 + "\t" + avgVal + "\n").getBytes()); - } - delay.close(); - } catch (final FileNotFoundException e) { - e.printStackTrace(); - } catch (final IOException e) { - e.printStackTrace(); - } - } + private final void printDelay(String filename) { + try { + final String filePrefix = DreamConfiguration.get().resultsDir + filename; + final FileOutputStream delay = new FileOutputStream(filePrefix + "Delay"); + final List keyList = new ArrayList(storedDelays.keySet()); + Collections.sort(keyList); + for (final Integer label : keyList) { + double sum = 0; + final double size = storedDelays.get(label).size(); + for (final Double val : storedDelays.get(label)) { + sum += val; + } + final double avgVal = sum / size; + delay.write((label * epochDuration / 1000 + "\t" + avgVal + "\n").getBytes()); + } + delay.close(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + } - private final void printDelayAvg(String filename) { - try { - final String filePrefix = DreamConfiguration.get().resultsDir + filename; - final FileOutputStream delay = new FileOutputStream(filePrefix + "DelayAvg"); - double sum = 0; - double count = 0; - for (final Integer key : storedDelays.keySet()) { - final List values = storedDelays.get(key); - for (final Double val : values) { - sum += val; - count++; - } - } - final double avgVal = sum / count; - delay.write((String.valueOf(avgVal) + "\n").getBytes()); - delay.close(); - } catch (final FileNotFoundException e) { - e.printStackTrace(); - } catch (final IOException e) { - e.printStackTrace(); - } - } + private final void printDelayAvg(String filename) { + try { + final String filePrefix = DreamConfiguration.get().resultsDir + filename; + final FileOutputStream delay = new FileOutputStream(filePrefix + "DelayAvg"); + double sum = 0; + double count = 0; + for (final Integer key : storedDelays.keySet()) { + final List values = storedDelays.get(key); + for (final Double val : values) { + sum += val; + count++; + } + } + final double avgVal = sum / count; + delay.write((String.valueOf(avgVal) + "\n").getBytes()); + delay.close(); + } catch (final FileNotFoundException e) { + e.printStackTrace(); + } catch (final IOException e) { + e.printStackTrace(); + } + } } diff --git a/DreamSim/src/dream/measurement/ServerMeasurementPeerlet.java b/DreamSim/src/dream/measurement/ServerMeasurementPeerlet.java index 92d0d09..69315b5 100755 --- a/DreamSim/src/dream/measurement/ServerMeasurementPeerlet.java +++ b/DreamSim/src/dream/measurement/ServerMeasurementPeerlet.java @@ -2,27 +2,37 @@ import dream.experiments.DreamConfiguration; import protopeer.BasePeerlet; +import protopeer.Experiment; import protopeer.Peer; import protopeer.network.Message; +import protopeer.network.NetworkAddress; /** * This peerlet, installed in every server, collects and prints information * about the network traffic. */ public class ServerMeasurementPeerlet extends BasePeerlet { - private MeasurementLogger mLogger; + private MeasurementLogger mLogger; - @Override - public void init(Peer peer) { - super.init(peer); - mLogger = MeasurementLogger.getLogger(); - } + @Override + public void init(Peer peer) { + super.init(peer); + mLogger = MeasurementLogger.getLogger(); + } - @Override - public void handleOutgoingMessage(Message msg) { - for (int i = 0; i < DreamConfiguration.get().linkLength; i++) { - mLogger.saveMessage(msg); - } - } + @Override + public void handleOutgoingMessage(Message msg) { + final int numHops = destinationIsLockManager(msg) // + ? DreamConfiguration.get().numHopsToLockManager // + : DreamConfiguration.get().numHopsPerLink; + for (int i = 0; i < numHops; i++) { + mLogger.saveMessage(msg); + } + } + private final boolean destinationIsLockManager(Message msg) { + final int lockManagerId = DreamConfiguration.get().numberOfBrokers + DreamConfiguration.get().numberOfClients + 1; + final NetworkAddress lockManagerAddress = Experiment.getSingleton().getAddressToBindTo(lockManagerId); + return msg.getDestinationAddress().equals(lockManagerAddress); + } } diff --git a/DreamSim/src/dream/overlay/ClientAssociationGenerator.java b/DreamSim/src/dream/overlay/ClientAssociationGenerator.java index ed259a5..03fc57c 100755 --- a/DreamSim/src/dream/overlay/ClientAssociationGenerator.java +++ b/DreamSim/src/dream/overlay/ClientAssociationGenerator.java @@ -18,109 +18,110 @@ * @author Daniel Dubois */ public class ClientAssociationGenerator implements IClientAssociationGenerator { - public final int UNIFORM_LOWEST_ID = 1; - public final int UNIFORM_HIGHEST_ID = 2; - public final int UNIFORM_ALTERNATE_ID = 3; - public final int UNIFORM_RANDOM_ID = 4; + public final int UNIFORM_LOWEST_ID = 1; + public final int UNIFORM_HIGHEST_ID = 2; + public final int UNIFORM_ALTERNATE_ID = 3; + public final int UNIFORM_RANDOM_ID = 4; - private static IClientAssociationGenerator instance; + private static IClientAssociationGenerator instance; - private final int type; - private final double percentageOfPureForwarders; + private final int type; + private final double percentageOfPureForwarders; - private final Set association = new HashSet<>(); - private boolean associationGenerated = false; + private final Set association = new HashSet<>(); + private boolean associationGenerated = false; - public static final IClientAssociationGenerator get() { - if (instance == null) { - instance = new ClientAssociationGenerator(); - } - return instance; - } + public static final IClientAssociationGenerator get() { + if (instance == null) { + instance = new ClientAssociationGenerator(); + } + return instance; + } - @Override - public void clean() { - association.clear(); - associationGenerated = false; - } + @Override + public void clean() { + association.clear(); + associationGenerated = false; + } - public ClientAssociationGenerator() { - this.type = DreamConfiguration.get().clientsAssociationType; - this.percentageOfPureForwarders = DreamConfiguration.get().percentageOfPureForwarders; - if (percentageOfPureForwarders < 0 || percentageOfPureForwarders > 1) { - throw new IllegalArgumentException("percentageOfPureForwarders is not valid for ComponentAssociationGenerator"); - } - switch (type) { - case UNIFORM_LOWEST_ID: - case UNIFORM_HIGHEST_ID: - case UNIFORM_ALTERNATE_ID: - case UNIFORM_RANDOM_ID: - break; - default: - throw new IllegalArgumentException("Type is not valid for ComponentAssociationGenerator"); - } - } + public ClientAssociationGenerator() { + this.type = DreamConfiguration.get().clientsAssociationType; + this.percentageOfPureForwarders = DreamConfiguration.get().percentageOfPureForwarders; + if (percentageOfPureForwarders < 0 || percentageOfPureForwarders > 1) { + throw new IllegalArgumentException("percentageOfPureForwarders is not valid for ComponentAssociationGenerator"); + } + switch (type) { + case UNIFORM_LOWEST_ID: + case UNIFORM_HIGHEST_ID: + case UNIFORM_ALTERNATE_ID: + case UNIFORM_RANDOM_ID: + break; + default: + throw new IllegalArgumentException("Type is not valid for ComponentAssociationGenerator"); + } + } - @Override - public Set getAssociation() { - if (!associationGenerated) { - associationGenerated = true; - final DreamConfiguration conf = DreamConfiguration.get(); - final int minBroker = 1; - final int maxBroker = conf.numberOfBrokers; - final int minClient = maxBroker + 1; - final int maxClient = minClient + conf.numberOfClients - 1; - final Random random = RandomnessSource.getRandom(RandomnessSourceType.TOPOLOGY); + @Override + public Set getAssociation() { + if (!associationGenerated) { + associationGenerated = true; + final DreamConfiguration conf = DreamConfiguration.get(); + final int minBroker = 1; + final int maxBroker = conf.numberOfBrokers; + final int minClient = maxBroker + 1; + final int maxClient = minClient + conf.numberOfClients - 1; + final Random random = RandomnessSource.getRandom(RandomnessSourceType.TOPOLOGY); - final List brokers = IntStream.rangeClosed(minBroker, maxBroker)// - .mapToObj(i -> new Node(i))// - .collect(Collectors.toList()); + final List brokers = IntStream.rangeClosed(minBroker, maxBroker)// + .mapToObj(i -> new Node(i))// + .collect(Collectors.toList()); - final List clients = IntStream.rangeClosed(minClient, maxClient)// - .mapToObj(i -> new Node(i))// - .collect(Collectors.toList()); + final List clients = IntStream.rangeClosed(minClient, maxClient)// + .mapToObj(i -> new Node(i))// + .collect(Collectors.toList()); - int brokersToBeRemoved = new Double(brokers.size() * percentageOfPureForwarders).intValue(); - if (brokers.size() - brokersToBeRemoved > clients.size()) { - brokersToBeRemoved = brokers.size() - clients.size(); - } - switch (type) { - case UNIFORM_LOWEST_ID: - for (int i = brokers.size() - 1; i >= 0 && brokersToBeRemoved > 0; i--) { - brokers.remove(i); - brokersToBeRemoved--; - } - break; - case UNIFORM_RANDOM_ID: - Collections.shuffle(brokers, random); - case UNIFORM_HIGHEST_ID: - while (brokersToBeRemoved > 0) { - brokers.remove(0); - brokersToBeRemoved--; - } - break; - case UNIFORM_ALTERNATE_ID: - while (brokersToBeRemoved > 0) { - for (int i = brokers.size() - 1; i >= 0 && brokersToBeRemoved > 0; i = i - 2) { - brokers.remove(i); - brokersToBeRemoved--; - } - } - break; - } - getAssociation(brokers, clients); - } - return association; - } + int brokersToBeRemoved = new Double(brokers.size() * percentageOfPureForwarders).intValue(); + if (brokers.size() - brokersToBeRemoved > clients.size()) { + brokersToBeRemoved = brokers.size() - clients.size(); + } + switch (type) { + case UNIFORM_LOWEST_ID: + for (int i = brokers.size() - 1; i >= 0 && brokersToBeRemoved > 0; i--) { + brokers.remove(i); + brokersToBeRemoved--; + } + break; + case UNIFORM_RANDOM_ID: + Collections.shuffle(brokers, random); + case UNIFORM_HIGHEST_ID: + while (brokersToBeRemoved > 0) { + brokers.remove(0); + brokersToBeRemoved--; + } + break; + case UNIFORM_ALTERNATE_ID: + while (brokersToBeRemoved > 0) { + for (int i = brokers.size() - 1; i >= 0 && brokersToBeRemoved > 0; i = i - 2) { + brokers.remove(i); + brokersToBeRemoved--; + } + } + break; + } + getAssociation(brokers, clients); + } + return association; + } - private void getAssociation(final List brokers, final List components) { - int i = 0; - while (association.size() < components.size()) { - // TODO: was links.add(new Link(brokers.get(i%components.size()), - // components.get(i))); - association.add(new Link(brokers.get(i % brokers.size()), components.get(i))); - i++; - } - } + private void getAssociation(final List brokers, final List components) { + int i = 0; + while (association.size() < components.size()) { + // TODO: was links.add(new Link(brokers.get(i%components.size()), + // components.get(i))); + association + .add(new Link(brokers.get(i % brokers.size()), components.get(i), DreamConfiguration.get().numHopsPerLink)); + i++; + } + } } diff --git a/DreamSim/src/dream/overlay/IClientAssociationGenerator.java b/DreamSim/src/dream/overlay/IClientAssociationGenerator.java index 9f39228..c2451c8 100755 --- a/DreamSim/src/dream/overlay/IClientAssociationGenerator.java +++ b/DreamSim/src/dream/overlay/IClientAssociationGenerator.java @@ -10,14 +10,14 @@ */ public interface IClientAssociationGenerator { - /** - * Get a list of associations between brokers and components. - */ - public Set getAssociation(); + /** + * Get a list of associations between brokers and components. + */ + public Set getAssociation(); - /** - * Reset the association. - */ - public void clean(); + /** + * Reset the association. + */ + public void clean(); } diff --git a/DreamSim/src/dream/overlay/IOverlayGenerator.java b/DreamSim/src/dream/overlay/IOverlayGenerator.java index 84fbbe3..42b2a9b 100755 --- a/DreamSim/src/dream/overlay/IOverlayGenerator.java +++ b/DreamSim/src/dream/overlay/IOverlayGenerator.java @@ -10,16 +10,16 @@ */ public interface IOverlayGenerator { - /** - * Generates a new random topology with the default number of links. The - * default number of links depends on the implementing classes. - * - * @return a set of links that constitutes the generated topology - */ - public Set generateOverlay(); + /** + * Generates a new random topology with the default number of links. The + * default number of links depends on the implementing classes. + * + * @return a set of links that constitutes the generated topology + */ + public Set generateOverlay(); - /** - * Reset the topology generation. - */ - public void clean(); + /** + * Reset the topology generation. + */ + public void clean(); } diff --git a/DreamSim/src/dream/overlay/IOverlayPeerlet.java b/DreamSim/src/dream/overlay/IOverlayPeerlet.java index 8ade0f0..e4cdaea 100755 --- a/DreamSim/src/dream/overlay/IOverlayPeerlet.java +++ b/DreamSim/src/dream/overlay/IOverlayPeerlet.java @@ -5,66 +5,70 @@ import protopeer.network.NetworkAddress; /** - * This is an interface for an Overlay Manager Peerlet. - * The purpose of implementors of this interface is to give access to the - * list of neighbor brokers and components. + * This is an interface for an Overlay Manager Peerlet. The purpose of + * implementors of this interface is to give access to the list of neighbor + * brokers and components. * * @author Daniel Dubois * */ public interface IOverlayPeerlet { - + /** * Add a broker to the the local view of the overlay of this broker. * - * @param broker New broker to add + * @param broker + * New broker to add * @return true if the broker has been added, false if it is already present */ public boolean addBroker(NetworkAddress broker); - + /** * Removes a broker from the local view of the overlay of this broker. * - * @param broker Existing broker to be removed + * @param broker + * Existing broker to be removed * @return true if the broker has been removed, false if it is not present */ public boolean removeBroker(NetworkAddress broker); - + /** * Add a component to the the local view of the overlay of this broker. * - * @param component New component to add + * @param component + * New component to add * @return true if the broker has been added, false if it is already present */ public boolean addComponent(NetworkAddress component); - + /** * Removes a component from the local view of the overlay of this broker. * - * @param component Existing component to be removed + * @param component + * Existing component to be removed * @return true if the broker has been removed, false if it is not present */ public boolean removeComponent(NetworkAddress component); - + /** * Get the set of broker and component neighbors of this broker. * * @return Set of broker and component neighbors */ public Set getNeighbors(); - + /** * Get the set of broker neighbors of this broker. * * @return Set of broker neighbors */ public Set getBrokers(); - + /** * Get the set of component neighbors of this broker. * * @return Set of component neighbors */ public Set getComponents(); - + } diff --git a/DreamSim/src/dream/overlay/Link.java b/DreamSim/src/dream/overlay/Link.java index f56b6c6..eed9c3a 100755 --- a/DreamSim/src/dream/overlay/Link.java +++ b/DreamSim/src/dream/overlay/Link.java @@ -2,75 +2,80 @@ import java.io.Serializable; -/** - * This class represents a generic Link between two nodes. - * - * @author Daniel Dubois - * - */ public class Link implements Serializable { - private static final long serialVersionUID = -8557693370724758574L; + private static final long serialVersionUID = -8557693370724758574L; - private final Node node1; - private final Node node2; + private final Node node1; + private final Node node2; + private final int numHops; - /** - * Create a new link representation between node1 and node2. Note: the first endpoint will always have the smallest - * id, thus if node2 has a lower id than node1 the two nodes will be SWAPPED! - * - * @param node1 First endpoint of the link - * @param node2 Second endpoint of the link - */ - public Link(Node node1, Node node2) { + /** + * Create a new link between node1 and node2 consisting of numHops hops. + * + * The first node will always have the smallest id, thus if node2 has a lower + * id than node1 the two nodes will be SWAPPED! + * + * @param node1 + * First node of the link + * @param node2 + * Second node of the link + * @param numHops + * Number of hops in the link + */ + public Link(Node node1, Node node2, int numHops) { + this.node1 = node1.getId() < node2.getId() ? node1 : node2; + this.node2 = node1.getId() < node2.getId() ? node2 : node1; + this.numHops = numHops; + } - if (node1.getId() < node2.getId()) { - this.node1 = node1; - this.node2 = node2; - } else { - this.node2 = node1; - this.node1 = node2; - } - } + /** + * Get the first endpoint of this link. + * + * @return the first endpoint of this link + */ + public final Node getNode1() { + return node1; + } - /** - * Get the first endpoint of this link. - * - * @return the first endpoint of this link - */ - public Node getNode1() { - return node1; - } + /** + * Get the second endpoint of this link. + * + * @return the second endpoint of this link + */ + public final Node getNode2() { + return node2; + } - /** - * Get the second endpoint of this link. - * - * @return the second endpoint of this link - */ - public Node getNode2() { - return node2; - } + /** + * Return the number of hops in the link. + * + * @return the number of hops in the link. + */ + public final int getNumHops() { + return numHops; + } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } else if (o instanceof Link) { - Link link = (Link) o; - return link.getNode1().equals(node1) && link.getNode2().equals(node2); - } else { - return false; - } - } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o instanceof Link) { + final Link link = (Link) o; + return link.getNode1().equals(node1) && link.getNode2().equals(node2); + } else { + return false; + } + } - @Override - public int hashCode() { - return Integer.MIN_VALUE + node1.getId() + 1000001 * node2.getId(); - } + @Override + public int hashCode() { + return Integer.MIN_VALUE + node1.getId() + 1000001 * node2.getId(); + } - @Override - public String toString() { - return "(" + node1 + " - " + node2 + ")"; - } + @Override + public String toString() { + return "(" + node1 + " - " + node2 + ")"; + } } diff --git a/DreamSim/src/dream/overlay/Node.java b/DreamSim/src/dream/overlay/Node.java index c40bb25..2567d9d 100755 --- a/DreamSim/src/dream/overlay/Node.java +++ b/DreamSim/src/dream/overlay/Node.java @@ -10,44 +10,45 @@ */ public class Node implements Serializable { - private static final long serialVersionUID = 1096390051568045115L; - private final int id; - - /** - * Creates a generic node with the given id. - * - * @param id Id of the new generic node - */ - public Node(int id) { - this.id = id; - } - - /** - * Get the id of this generic node. - * - * @return id of this generic node - */ - public int getId() { - return id; - } - - @Override - public int hashCode() { - return id; - } - - @Override - public boolean equals(Object o) { - if (o instanceof Node) { - return ((Node) o).getId() == id; - } else { - return false; - } - } - - @Override - public String toString() { - return String.valueOf(id); - } + private static final long serialVersionUID = 1096390051568045115L; + private final int id; + + /** + * Creates a generic node with the given id. + * + * @param id + * Id of the new generic node + */ + public Node(int id) { + this.id = id; + } + + /** + * Get the id of this generic node. + * + * @return id of this generic node + */ + public int getId() { + return id; + } + + @Override + public int hashCode() { + return id; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Node) { + return ((Node) o).getId() == id; + } else { + return false; + } + } + + @Override + public String toString() { + return String.valueOf(id); + } } diff --git a/DreamSim/src/dream/overlay/OverlayPeerlet.java b/DreamSim/src/dream/overlay/OverlayPeerlet.java index ab42914..f2bb4ef 100755 --- a/DreamSim/src/dream/overlay/OverlayPeerlet.java +++ b/DreamSim/src/dream/overlay/OverlayPeerlet.java @@ -15,83 +15,83 @@ import protopeer.network.NetworkAddress; public class OverlayPeerlet extends BasePeerlet implements IOverlayPeerlet { - private static final Logger logger = Logger.getLogger(OverlayPeerlet.class); - private final Set components = new HashSet(); - private final Set brokers = new HashSet(); - private Peer peer; + private static final Logger logger = Logger.getLogger(OverlayPeerlet.class); + private final Set components = new HashSet(); + private final Set brokers = new HashSet(); + private Peer peer; - @Override - public void init(Peer peer) { - this.peer = peer; - final IOverlayGenerator overlayGenerator = TreeOverlayGenerator.get(); - final Set initialTopology = overlayGenerator.generateOverlay(); - for (final Link l : initialTopology) { - if (l.getNode1().getId() == peer.getIndexNumber()) { - addBroker(Experiment.getSingleton().getAddressToBindTo(l.getNode2().getId())); - } else if (l.getNode2().getId() == peer.getIndexNumber()) { - addBroker(Experiment.getSingleton().getAddressToBindTo(l.getNode1().getId())); - } - } + @Override + public void init(Peer peer) { + this.peer = peer; + final IOverlayGenerator overlayGenerator = TreeOverlayGenerator.get(); + final Set initialTopology = overlayGenerator.generateOverlay(); + for (final Link l : initialTopology) { + if (l.getNode1().getId() == peer.getIndexNumber()) { + addBroker(Experiment.getSingleton().getAddressToBindTo(l.getNode2().getId())); + } else if (l.getNode2().getId() == peer.getIndexNumber()) { + addBroker(Experiment.getSingleton().getAddressToBindTo(l.getNode1().getId())); + } + } - final IClientAssociationGenerator associationGenerator = ClientAssociationGenerator.get(); - final Set componentAssociations = associationGenerator.getAssociation(); - for (final Link l : componentAssociations) { - if (l.getNode1().getId() == peer.getIndexNumber()) { - addComponent(Experiment.getSingleton().getAddressToBindTo(l.getNode2().getId())); - } - } - } + final IClientAssociationGenerator associationGenerator = ClientAssociationGenerator.get(); + final Set componentAssociations = associationGenerator.getAssociation(); + for (final Link l : componentAssociations) { + if (l.getNode1().getId() == peer.getIndexNumber()) { + addComponent(Experiment.getSingleton().getAddressToBindTo(l.getNode2().getId())); + } + } + } - @Override - public boolean addBroker(NetworkAddress broker) { - logger.info(peer.getIndexNumber() + ": adding broker " + broker); - return brokers.add(broker); - } + @Override + public boolean addBroker(NetworkAddress broker) { + logger.info(peer.getIndexNumber() + ": adding broker " + broker); + return brokers.add(broker); + } - @Override - public boolean removeBroker(NetworkAddress broker) { - logger.info(peer.getIndexNumber() + ": removing broker " + broker); - return brokers.remove(broker); - } + @Override + public boolean removeBroker(NetworkAddress broker) { + logger.info(peer.getIndexNumber() + ": removing broker " + broker); + return brokers.remove(broker); + } - @Override - public boolean addComponent(NetworkAddress component) { - logger.info(peer.getIndexNumber() + ": adding component " + component); - return components.add(component); - } + @Override + public boolean addComponent(NetworkAddress component) { + logger.info(peer.getIndexNumber() + ": adding component " + component); + return components.add(component); + } - @Override - public boolean removeComponent(NetworkAddress component) { - logger.info(peer.getIndexNumber() + ": removing component " + component); - return components.remove(component); - } + @Override + public boolean removeComponent(NetworkAddress component) { + logger.info(peer.getIndexNumber() + ": removing component " + component); + return components.remove(component); + } - @Override - public Set getNeighbors() { - final HashSet neighbors = new HashSet(brokers); - neighbors.addAll(components); - return neighbors; - } + @Override + public Set getNeighbors() { + final HashSet neighbors = new HashSet(brokers); + neighbors.addAll(components); + return neighbors; + } - @Override - public Set getBrokers() { - return new HashSet(brokers); - } + @Override + public Set getBrokers() { + return new HashSet(brokers); + } - @Override - public Set getComponents() { - return new HashSet(components); - } + @Override + public Set getComponents() { + return new HashSet(components); + } - @Override - public void handleIncomingMessage(Message message) { - if (message instanceof AddBrokerMessage) { - addBroker(((AddBrokerMessage) message).getNewBroker()); - } else if (message instanceof RemoveBrokerMessage) { - removeBroker(((RemoveBrokerMessage) message).getExistingBroker()); - } else if (message instanceof ReplaceBrokerMessage) { - addBroker(((ReplaceBrokerMessage) message).getNewBroker()); - removeBroker(((ReplaceBrokerMessage) message).getExistingBroker()); - } - } + @Override + public void handleIncomingMessage(Message message) { + if (message instanceof AddBrokerMessage) { + addBroker(((AddBrokerMessage) message).getNewBroker()); + } else if (message instanceof RemoveBrokerMessage) { + removeBroker(((RemoveBrokerMessage) message).getExistingBroker()); + } else if (message instanceof ReplaceBrokerMessage) { + addBroker(((ReplaceBrokerMessage) message).getNewBroker()); + removeBroker(((ReplaceBrokerMessage) message).getExistingBroker()); + } + } } diff --git a/DreamSim/src/dream/overlay/TreeOverlayGenerator.java b/DreamSim/src/dream/overlay/TreeOverlayGenerator.java index a198587..8b39fc6 100755 --- a/DreamSim/src/dream/overlay/TreeOverlayGenerator.java +++ b/DreamSim/src/dream/overlay/TreeOverlayGenerator.java @@ -13,143 +13,132 @@ import protopeer.util.RandomnessSourceType; public class TreeOverlayGenerator implements IOverlayGenerator { - public static final int LINEAR = 1; - public static final int STAR = 2; - public static final int SCALEFREE = 3; - - private final int type; - - private static TreeOverlayGenerator instance = null; - private final Set links = new HashSet<>(); - private boolean linksGenerated = false; - - public static final IOverlayGenerator get() { - if (instance == null) { - instance = new TreeOverlayGenerator(); - } - return instance; - } - - private TreeOverlayGenerator() { - this.type = DreamConfiguration.get().brokersTopologyType; - switch (type) { - case LINEAR: - case STAR: - case SCALEFREE: - break; - default: - throw new IllegalArgumentException("Unknown Tree Topology Type"); - } - } - - @Override - public void clean() { - linksGenerated = false; - links.clear(); - } - - @Override - public Set generateOverlay() { - final DreamConfiguration conf = DreamConfiguration.get(); - final int brokersMin = 1; - final int brokersMax = conf.numberOfBrokers; - final Random random = RandomnessSource.getRandom(RandomnessSourceType.TOPOLOGY); - - if (!linksGenerated) { - linksGenerated = true; - final Set nodes = IntStream.rangeClosed(brokersMin, brokersMax)// - .mapToObj(Node::new)// - .collect(Collectors.toSet()); - - switch (type) { - case LINEAR: - return generateLinearOverlay(nodes, random); - case STAR: - return generateStarOverlay(nodes, random); - case SCALEFREE: - return generateScaleFreeOverlay(nodes, random); - } - } - return links; - } - - private Set generateLinearOverlay(Set nodes, Random random) { - Node previousNode = null; - Node currentNode = null; - for (final Node n : nodes) { - previousNode = currentNode; - currentNode = n; - if (previousNode != null && currentNode != null) { - links.add(new Link(previousNode, currentNode)); - } - } - return links; - } - - private Set generateStarOverlay(Set nodes, Random random) { - Node firstNode = null; - for (final Node n : nodes) { - if (n.getId() == 1) { - firstNode = n; - break; - } - } - for (final Node n : nodes) { - if (n.equals(firstNode)) { - continue; - } - links.add(new Link(firstNode, n)); - } - return links; - } - - private Set generateScaleFreeOverlay(Set nodes, Random random) { - final Integer nlinks = nodes.size() - 1; - if (nodes.size() < 2) { - return links; - } - final Integer d = 2 * nlinks / nodes.size(); - final List tmpNodes = new ArrayList(nodes); - final List addedNodes = new ArrayList(); - for (Integer i = 0; i <= d; i++) { - addedNodes.add(tmpNodes.remove(0)); - } - for (Integer i = 0; i < d; i++) { - for (Integer j = i + 1; j <= d; j++) { - links.add(new Link(addedNodes.get(i), addedNodes.get(j))); - } - } - while (tmpNodes.size() > 0) { - final Node sourceNode = tmpNodes.remove(0); - final Node destinationNode = getCandidateNode(addedNodes, links, random); - links.add(new Link(sourceNode, destinationNode)); - addedNodes.add(sourceNode); - } - return links; - } - - private Node getCandidateNode(List tmpNodes, Set links, Random random) { - final Double p = random.nextDouble(); - Double previous_p = 0.0; - Double current_p = 0.0; - for (Integer i = 0; i < tmpNodes.size(); i++) { - previous_p = current_p; - current_p += getDegree(tmpNodes.get(i), links) / (2.0 * links.size()); - if (p >= previous_p && p <= current_p) { - return tmpNodes.get(i); - } - } - return null; - } - - private Integer getDegree(Node node, Set links) { - Integer degree = 0; - for (final Link l : links) { - if (l.getNode1().equals(node) || l.getNode2().equals(node)) { - degree++; - } - } - return degree; - } + public static final int LINEAR = 1; + public static final int STAR = 2; + public static final int SCALEFREE = 3; + + private final int type; + + private static TreeOverlayGenerator instance = null; + private final Set links = new HashSet<>(); + private boolean linksGenerated = false; + + public static final IOverlayGenerator get() { + if (instance == null) { + instance = new TreeOverlayGenerator(); + } + return instance; + } + + private TreeOverlayGenerator() { + this.type = DreamConfiguration.get().brokersTopologyType; + switch (type) { + case LINEAR: + case STAR: + case SCALEFREE: + break; + default: + throw new IllegalArgumentException("Unknown Tree Topology Type"); + } + } + + @Override + public void clean() { + linksGenerated = false; + links.clear(); + } + + @Override + public Set generateOverlay() { + final DreamConfiguration conf = DreamConfiguration.get(); + final int brokersMin = 1; + final int brokersMax = conf.numberOfBrokers; + final Random random = RandomnessSource.getRandom(RandomnessSourceType.TOPOLOGY); + + if (!linksGenerated) { + linksGenerated = true; + final Set nodes = IntStream.rangeClosed(brokersMin, brokersMax)// + .mapToObj(Node::new)// + .collect(Collectors.toSet()); + + switch (type) { + case LINEAR: + generateLinearOverlay(nodes, random); + break; + case STAR: + generateStarOverlay(nodes, random); + break; + case SCALEFREE: + generateScaleFreeOverlay(nodes, random); + break; + } + } + return links; + } + + private void generateLinearOverlay(Set nodes, Random random) { + if (nodes.size() < 2) { + return; + } + final List nodesList = new ArrayList(nodes); + for (int i = 1; i < nodesList.size(); i++) { + links.add(new Link(nodesList.get(i - 1), nodesList.get(i), DreamConfiguration.get().numHopsPerLink)); + } + } + + private void generateStarOverlay(Set nodes, Random random) { + final Node firstNode = nodes.stream() // + .filter(n -> n.getId() == 1) // + .findFirst() // + .get(); + + nodes.stream() // + .filter(n -> !n.equals(firstNode)) // + .forEach(n -> links.add(new Link(firstNode, n, DreamConfiguration.get().numHopsPerLink))); + } + + private void generateScaleFreeOverlay(Set nodes, Random random) { + if (nodes.size() < 2) { + return; + } + final int nlinks = nodes.size() - 1; + final int d = 2 * nlinks / nodes.size(); + + final List nodesList = new ArrayList<>(nodes); + final List tmpNodes = nodesList.stream().skip(d + 1).collect(Collectors.toList()); + final List addedNodes = nodesList.stream().limit(d + 1).collect(Collectors.toList()); + + for (Integer i = 0; i < d; i++) { + for (Integer j = i + 1; j <= d; j++) { + links.add(new Link(addedNodes.get(i), addedNodes.get(j), DreamConfiguration.get().numHopsPerLink)); + } + } + while (tmpNodes.size() > 0) { + final Node sourceNode = tmpNodes.remove(0); + final Node destinationNode = getCandidateNode(addedNodes, links, random); + links.add(new Link(sourceNode, destinationNode, DreamConfiguration.get().numHopsPerLink)); + addedNodes.add(sourceNode); + } + } + + private Node getCandidateNode(List tmpNodes, Set links, Random random) { + final Double p = random.nextDouble(); + Double previous_p = 0.0; + Double current_p = 0.0; + for (Integer i = 0; i < tmpNodes.size(); i++) { + previous_p = current_p; + current_p += getDegree(tmpNodes.get(i), links) / (2.0 * links.size()); + if (p >= previous_p && p <= current_p) { + return tmpNodes.get(i); + } + } + return null; + } + + private long getDegree(Node node, Set links) { + return links.stream() // + .filter(l -> l.getNode1().equals(node) || l.getNode2().equals(node)) // + .count(); + } } diff --git a/DreamSim/src/dream/server/AdvertisementTable.java b/DreamSim/src/dream/server/AdvertisementTable.java index e766db6..8a6d8f0 100755 --- a/DreamSim/src/dream/server/AdvertisementTable.java +++ b/DreamSim/src/dream/server/AdvertisementTable.java @@ -13,38 +13,38 @@ import protopeer.network.NetworkAddress; final class AdvertisementTable { - private final Map> advs = new HashMap>(); - - final void addAdvertisement(NetworkAddress node, Advertisement adv) { - Collection advsList = advs.get(node); - if (advsList == null) { - advsList = new ArrayList(); - advs.put(node, advsList); - } - advsList.add(adv); - } - - final void removeAdvertisement(NetworkAddress node, Advertisement adv) { - final Collection advsList = advs.get(node); - if (advsList == null) { - return; - } - advsList.remove(adv); - if (advsList.isEmpty()) { - advs.remove(node); - } - } - - final Set getMatchingNodes(Subscription sub) { - final Predicate isAdvSat = adv -> adv.isSatisfiedBy(sub); - final Predicate hasAdvSat = node -> advs.get(node).stream().anyMatch(isAdvSat); - return advs.keySet().stream().// - filter(hasAdvSat).// - collect(Collectors.toSet()); - } - - final void removeAllAdvertisementsFor(NetworkAddress node) { - advs.remove(node); - } + private final Map> advs = new HashMap>(); + + final void addAdvertisement(NetworkAddress node, Advertisement adv) { + Collection advsList = advs.get(node); + if (advsList == null) { + advsList = new ArrayList(); + advs.put(node, advsList); + } + advsList.add(adv); + } + + final void removeAdvertisement(NetworkAddress node, Advertisement adv) { + final Collection advsList = advs.get(node); + if (advsList == null) { + return; + } + advsList.remove(adv); + if (advsList.isEmpty()) { + advs.remove(node); + } + } + + final Set getMatchingNodes(Subscription sub) { + final Predicate isAdvSat = adv -> adv.isSatisfiedBy(sub); + final Predicate hasAdvSat = node -> advs.get(node).stream().anyMatch(isAdvSat); + return advs.keySet().stream().// + filter(hasAdvSat).// + collect(Collectors.toSet()); + } + + final void removeAllAdvertisementsFor(NetworkAddress node) { + advs.remove(node); + } } diff --git a/DreamSim/src/dream/server/ServerEventForwarder.java b/DreamSim/src/dream/server/ServerEventForwarder.java index 4e1c013..8cd329b 100755 --- a/DreamSim/src/dream/server/ServerEventForwarder.java +++ b/DreamSim/src/dream/server/ServerEventForwarder.java @@ -17,98 +17,98 @@ import protopeer.network.NetworkAddress; public class ServerEventForwarder extends BasePeerlet { - protected final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - - protected final SubscriptionTable clientsSubTable = new SubscriptionTable(); - protected final SubscriptionTable brokersSubTable = new SubscriptionTable(); - protected final AdvertisementTable advTable = new AdvertisementTable(); - - protected IOverlayPeerlet overlay; - - @Override - public void init(Peer peer) { - super.init(peer); - overlay = (IOverlayPeerlet) peer.getPeerletOfType(IOverlayPeerlet.class); - } - - @Override - public final void handleIncomingMessage(Message packet) { - final Outbox outbox = new Outbox(); - if (packet instanceof SubscriptionPacket) { - final SubscriptionPacket subPkt = (SubscriptionPacket) packet; - logger.fine("Received a subscription packet: " + subPkt); - processSubscription(packet.getSourceAddress(), subPkt, outbox); - } else if (packet instanceof EventPacket) { - final EventPacket evPkt = (EventPacket) packet; - logger.finer("Received an event packet: " + evPkt); - processEvent(packet.getSourceAddress(), evPkt, outbox); - } else if (packet instanceof AdvertisementPacket) { - final AdvertisementPacket advPkt = (AdvertisementPacket) packet; - logger.fine("Received an advertisement packet: " + advPkt); - processAdvertisement(packet.getSourceAddress(), advPkt, outbox); - } - deliverPacketsInOutbox(outbox); - } - - private final void processSubscription(NetworkAddress sender, SubscriptionPacket packet, Outbox box) { - updateSubscriptionTables(sender, packet); - final Set matchingNodes = advTable.getMatchingNodes(packet.getSubscription()); - if (!matchingNodes.isEmpty()) { - sendTo(SubscriptionPacket.subject, packet, box, matchingNodes); - } - } - - private final void updateSubscriptionTables(NetworkAddress sender, SubscriptionPacket subPkt) { - final SubscriptionTable table = isClient(sender) ? clientsSubTable : brokersSubTable; - switch (subPkt.getSubType()) { - case SUB: - table.addSubscription(sender, subPkt.getSubscription()); - break; - case UNSUB: - table.removeSubscription(sender, subPkt.getSubscription()); - break; - default: - assert false : subPkt.getSubType(); - } - } - - private void processEvent(NetworkAddress sender, EventPacket packet, Outbox outbox) { - final Map matchingClients = clientsSubTable.getMatchingNodes(packet.getEvent()); - final Map matchingBrokers = brokersSubTable.getMatchingNodes(packet.getEvent()); - sendTo(EventPacket.subject, packet, outbox, matchingClients.keySet()); - sendTo(EventPacket.subject, packet, outbox, matchingBrokers.keySet()); - } - - private final void processAdvertisement(NetworkAddress sender, AdvertisementPacket packet, Outbox outbox) { - switch (packet.getAdvType()) { - case ADV: - advTable.addAdvertisement(sender, packet.getAdvertisement()); - break; - case UNADV: - advTable.removeAdvertisement(sender, packet.getAdvertisement()); - break; - } - outbox.add(AdvertisementPacket.subject, packet, getAllNodesExcept(sender)); - } - - private final void sendTo(String subject, Message packet, Outbox box, Collection recipients) { - box.add(subject, packet, recipients); - } - - private final Collection getAllNodesExcept(NetworkAddress nodeToSkip) { - return overlay.getNeighbors().stream()// - .filter(node -> !node.equals(nodeToSkip))// - .collect(Collectors.toSet()); - } - - private final void deliverPacketsInOutbox(Outbox outbox) { - outbox.getPacketsToSend().forEach(p -> { - outbox.getRecipientsFor(p).forEach(r -> getPeer().sendMessage(r, p)); - }); - } - - private final boolean isClient(NetworkAddress address) { - return overlay.getComponents().contains(address); - } + protected final Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + + protected final SubscriptionTable clientsSubTable = new SubscriptionTable(); + protected final SubscriptionTable brokersSubTable = new SubscriptionTable(); + protected final AdvertisementTable advTable = new AdvertisementTable(); + + protected IOverlayPeerlet overlay; + + @Override + public void init(Peer peer) { + super.init(peer); + overlay = (IOverlayPeerlet) peer.getPeerletOfType(IOverlayPeerlet.class); + } + + @Override + public final void handleIncomingMessage(Message packet) { + final Outbox outbox = new Outbox(); + if (packet instanceof SubscriptionPacket) { + final SubscriptionPacket subPkt = (SubscriptionPacket) packet; + logger.fine("Received a subscription packet: " + subPkt); + processSubscription(packet.getSourceAddress(), subPkt, outbox); + } else if (packet instanceof EventPacket) { + final EventPacket evPkt = (EventPacket) packet; + logger.finer("Received an event packet: " + evPkt); + processEvent(packet.getSourceAddress(), evPkt, outbox); + } else if (packet instanceof AdvertisementPacket) { + final AdvertisementPacket advPkt = (AdvertisementPacket) packet; + logger.fine("Received an advertisement packet: " + advPkt); + processAdvertisement(packet.getSourceAddress(), advPkt, outbox); + } + deliverPacketsInOutbox(outbox); + } + + private final void processSubscription(NetworkAddress sender, SubscriptionPacket packet, Outbox box) { + updateSubscriptionTables(sender, packet); + final Set matchingNodes = advTable.getMatchingNodes(packet.getSubscription()); + if (!matchingNodes.isEmpty()) { + sendTo(SubscriptionPacket.subject, packet, box, matchingNodes); + } + } + + private final void updateSubscriptionTables(NetworkAddress sender, SubscriptionPacket subPkt) { + final SubscriptionTable table = isClient(sender) ? clientsSubTable : brokersSubTable; + switch (subPkt.getSubType()) { + case SUB: + table.addSubscription(sender, subPkt.getSubscription()); + break; + case UNSUB: + table.removeSubscription(sender, subPkt.getSubscription()); + break; + default: + assert false : subPkt.getSubType(); + } + } + + private void processEvent(NetworkAddress sender, EventPacket packet, Outbox outbox) { + final Map matchingClients = clientsSubTable.getMatchingNodes(packet.getEvent()); + final Map matchingBrokers = brokersSubTable.getMatchingNodes(packet.getEvent()); + sendTo(EventPacket.subject, packet, outbox, matchingClients.keySet()); + sendTo(EventPacket.subject, packet, outbox, matchingBrokers.keySet()); + } + + private final void processAdvertisement(NetworkAddress sender, AdvertisementPacket packet, Outbox outbox) { + switch (packet.getAdvType()) { + case ADV: + advTable.addAdvertisement(sender, packet.getAdvertisement()); + break; + case UNADV: + advTable.removeAdvertisement(sender, packet.getAdvertisement()); + break; + } + outbox.add(AdvertisementPacket.subject, packet, getAllNodesExcept(sender)); + } + + private final void sendTo(String subject, Message packet, Outbox box, Collection recipients) { + box.add(subject, packet, recipients); + } + + private final Collection getAllNodesExcept(NetworkAddress nodeToSkip) { + return overlay.getNeighbors().stream()// + .filter(node -> !node.equals(nodeToSkip))// + .collect(Collectors.toSet()); + } + + private final void deliverPacketsInOutbox(Outbox outbox) { + outbox.getPacketsToSend().forEach(p -> { + outbox.getRecipientsFor(p).forEach(r -> getPeer().sendMessage(r, p)); + }); + } + + private final boolean isClient(NetworkAddress address) { + return overlay.getComponents().contains(address); + } } diff --git a/DreamSim/src/dream/server/ServerFactory.java b/DreamSim/src/dream/server/ServerFactory.java index 20c294b..82342d7 100644 --- a/DreamSim/src/dream/server/ServerFactory.java +++ b/DreamSim/src/dream/server/ServerFactory.java @@ -8,13 +8,13 @@ public class ServerFactory implements PeerFactory { - @Override - public Peer createPeer(int peerIndex, Experiment experiment) { - final Peer newPeer = new Peer(peerIndex); - newPeer.addPeerlet(new OverlayPeerlet()); - newPeer.addPeerlet(new ServerMeasurementPeerlet()); - newPeer.addPeerlet(new ServerEventForwarder()); - return newPeer; - } + @Override + public Peer createPeer(int peerIndex, Experiment experiment) { + final Peer newPeer = new Peer(peerIndex); + newPeer.addPeerlet(new OverlayPeerlet()); + newPeer.addPeerlet(new ServerMeasurementPeerlet()); + newPeer.addPeerlet(new ServerEventForwarder()); + return newPeer; + } } diff --git a/DreamSim/src/dream/server/SubscriptionTable.java b/DreamSim/src/dream/server/SubscriptionTable.java index 9842498..ad7bb4a 100755 --- a/DreamSim/src/dream/server/SubscriptionTable.java +++ b/DreamSim/src/dream/server/SubscriptionTable.java @@ -10,51 +10,51 @@ import protopeer.network.NetworkAddress; final class SubscriptionTable { - private final Map> subs = new HashMap<>(); - - final void addSubscription(NetworkAddress node, Subscription sub) { - Collection subsList = subs.get(node); - if (subsList == null) { - subsList = new ArrayList(); - subs.put(node, subsList); - } - subsList.add(sub); - } - - final void removeSubscription(NetworkAddress node, Subscription sub) { - final Collection subsList = subs.get(node); - if (subsList == null) { - return; - } - subsList.remove(sub); - if (subsList.isEmpty()) { - subs.remove(node); - } - } - - final Map getMatchingNodes(Event ev) { - final Map result = new HashMap(); - for (final NetworkAddress node : subs.keySet()) { - int count = 0; - for (final Subscription sub : subs.get(node)) { - if (sub.isSatisfiedBy(ev)) { - count++; - } - } - if (count != 0) { - result.put(node, count); - } - } - return result; - } - - final void removeAllSubscriptionsFor(NetworkAddress node) { - subs.remove(node); - } - - @Override - public String toString() { - return "SubscriptionTable [subs=" + subs + "]"; - } + private final Map> subs = new HashMap<>(); + + final void addSubscription(NetworkAddress node, Subscription sub) { + Collection subsList = subs.get(node); + if (subsList == null) { + subsList = new ArrayList(); + subs.put(node, subsList); + } + subsList.add(sub); + } + + final void removeSubscription(NetworkAddress node, Subscription sub) { + final Collection subsList = subs.get(node); + if (subsList == null) { + return; + } + subsList.remove(sub); + if (subsList.isEmpty()) { + subs.remove(node); + } + } + + final Map getMatchingNodes(Event ev) { + final Map result = new HashMap(); + for (final NetworkAddress node : subs.keySet()) { + int count = 0; + for (final Subscription sub : subs.get(node)) { + if (sub.isSatisfiedBy(ev)) { + count++; + } + } + if (count != 0) { + result.put(node, count); + } + } + return result; + } + + final void removeAllSubscriptionsFor(NetworkAddress node) { + subs.remove(node); + } + + @Override + public String toString() { + return "SubscriptionTable [subs=" + subs + "]"; + } } diff --git a/DreamSim/src/protopeer/network/delayloss/UniformDelayModel.java b/DreamSim/src/protopeer/network/delayloss/UniformDelayModel.java index 270c8c0..cea7804 100755 --- a/DreamSim/src/protopeer/network/delayloss/UniformDelayModel.java +++ b/DreamSim/src/protopeer/network/delayloss/UniformDelayModel.java @@ -1,33 +1,34 @@ package protopeer.network.delayloss; -import java.util.*; +import java.util.Collection; -import protopeer.network.*; -import protopeer.util.*; +import protopeer.network.IntegerNetworkAddress; +import protopeer.network.Message; +import protopeer.network.NetworkAddress; +import protopeer.util.RandomnessSource; /** - * + * * A lossless network model in which the message delay is uniformely randomly * selected between some minimal and some maximal value. - * - * + * + * */ public class UniformDelayModel implements DelayLossNetworkModel { private int allocatedNodeAddress = 1; - private double minDelay; - - private double maxDelay; + protected final double minDelay; + protected final double maxDelay; /** * Creates a delay model that delays messages by a delay uniformely randomly * chosen between minDelay and maxDelay - * + * * @param minDelay - * minimum message delay in milliseconds + * minimum message delay in milliseconds * @param maxDelay - * maximum message delay in milliseconds + * maximum message delay in milliseconds */ public UniformDelayModel(double minDelay, double maxDelay) { super(); @@ -35,10 +36,12 @@ public UniformDelayModel(double minDelay, double maxDelay) { this.maxDelay = maxDelay; } + @Override public NetworkAddress allocateAddress() { return new IntegerNetworkAddress(allocatedNodeAddress++); } + @Override public double getDelay(NetworkAddress sourceAddress, NetworkAddress destinationAddress, Message message) { return minDelay + RandomnessSource.getNextNetworkDouble() * (maxDelay - minDelay); } @@ -47,10 +50,12 @@ public double getDelay(NetworkAddress sourceAddress, NetworkAddress destinationA * This network model has an practically unbounded number of addresses that * can be allocated. */ + @Override public int getNumAvailableAddresses() { return Integer.MAX_VALUE - allocatedNodeAddress; } + @Override public void deallocateAddress(NetworkAddress address) { } @@ -58,6 +63,7 @@ public void deallocateAddress(NetworkAddress address) { /** * This network model is lossless. */ + @Override public boolean getLoss(NetworkAddress sourceAddress, NetworkAddress destinationAddress, Message message) { return false; } @@ -65,6 +71,7 @@ public boolean getLoss(NetworkAddress sourceAddress, NetworkAddress destinationA /** * Not implemented in this network model */ + @Override public Collection getAddressesReachableByBroadcast(NetworkAddress srouceAddress) { throw new RuntimeException("Not implemented"); } diff --git a/README.md b/README.md index 0c23258..8f8f71f 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,156 @@ -# dream-java -## IMPL project - Kim Berninger and Michael Raulf - -The objective of this project was to use Java's generics in order to provide a -type-safe version of the _DREAM_ framework. This implementation can be found in -the `Dream2` folder. The original implementation using _ANTRL_ in order to -parse reactive expressions is contained in the `Dream` folder. - -Both projects are compatible with _Eclipse_ as well as _Maven_. However at the -time of writing the _AspectJ Maven Plugin_ was not yet compatible with -_Java 8_, so it is recommended to run the _ANTRL_ dependend _DREAM_ using -_Eclipse_. - -The `DreamSim` folder contains a custom version of _DREAM_ which is used in -order to run a _ProtoPeer_ based simulation for measuring the overall -performance of _DREAM_ in an example network. - -The _Latex_ code for a PDF containing the resulting graphs can be found in -`Graphs`. Similarly there is a roadmap of the overall project in the -`ChangeReport` folder. \ No newline at end of file +# DREAM Reactive Programming Framework + +DREAM - distributed reactive programming +middleware with flexible consistency guarantees. + +## Why DREAM? + +Different applications require different levels of consistency +and that manually implementing the required level on a middleware that +provides a lower one annuls the abstraction improvements of reactive +programming. DREAM enables the developers to select +the best trade-off between consistency and overhead for the problem at +hand. + +The reactive programming paradigm aims to simplify the development of reactive +systems. It provides abstractions to define time-changing values that are +automatically updated by the runtime according to their dependencies. + +The benefits of reactive programming in distributed settings have been +recognized for long. Most solutions for distributed reactive +programming enforce the same semantics as in single processes, introducing +communication and synchronization costs that hamper scalability. + +DREAM defines precise propagation +semantics in terms of consistency guarantees that constrain the order and +isolation of value updates. + +## Consistency Levels + +Consistency levels supported by DREAM explained in a nutshell. For a precise definition see the academic publications. + +**FIFO Consistency** Ensures that a signal reflects the changes to a single variable in the order in which they occur. + +**Causal Consistency** Analogous to causal consistency in replicated data stores, which guarantees that operations that are causally related with each other take place in the same order in all the replicas, and this order reflects the causal dependency. + +**Single-source Glitch Freedom** All the effects caused by an update on a node become visible at the same time. This means that a reader cannot observe the effects of an update on a node in an order that violates causality. + +**Complete Glitch Freedom** Ensures that the results of two propagations are the same as if the propagations took place in some sequential order, without interleaving at any node. + +**Atomic Consistency** Complete Glitch Freedom plus a read operation cannot observe only *some* of the effects of the change in a source: either it observes all of them, or none. + + + +## Academic Publications + +A. Margara, G. Salvaneschi, On the Semantics of Distributed Reactive Programming: the Cost of Consistency, IEEE Transactions on Software Engineering, 2018. + +A. Margara and G. Salvaneschi, We have a DREAM: Distributed Reactive Programming with Consistency Guarantees, In Proceedings of the 8th International Conference on Distributed Event-Based Systems (DEBS ’14). Mumbay, India, May 26–29, 2014. + +## Examples + +The relevant source code is in the Dream2 folder. + + +We initially need to assign a name to the current host `Host1`. +```java +Consts.hostName = "Host1"; +``` +Now on `Host1` we can define a Var `myVar` that is visible remotely. The var `myVar` constains a string, it is advertised with the name `exVar` and it is initialized to the value `AAA`. Later on the value is changed to `BBB`. +```java +Var myVar = new Var("exVar", "AAA"); +myVar.set("BBB"); +``` + +On a different host, `Host2` we can read the var defined on `Host1` whose name is `exVar`. We can also define a signal that builds a computation on top of it. + +```java +RemoteVar rv = new RemoteVar("Host1", "exVar"); + +Signal s = new Signal>("s", () -> { + return rv.get() + "XXX"; + }, rv); +``` +If rv is not available yet, ... +More examples: + + +```java +Var a = new Var<>("a", Integer.valueOf(1)); + +Var b = new Var<>("b", Integer.valueOf(2)); + +Signal c = + new Signal<>("c", () -> a.get() + b.get(), a, b); +``` + +Another example: + +``` +Var> lst = new Var<>("lst", new ArrayList()); + +Signal n = + new Signal<>("n", () -> lst.get().size(), lst); + + lst.modify(self -> { + self.add(1); + self.add(2); + self.add(3); + }); +``` + +### Locks +When using Atomic_Consistency it is required to lock a Var before reading its value. +``` + LockToken lock = DreamClient.instance.readLock(new HashSet<>("exVar@Host1")); + String value = rv.get(); + DreamClient.instance.unlock(lock); +``` + +### Getting Started +In the dream.examples.util-package you can find the class Client which does all the needed setup for Dream. +It starts the DreamServer if it is not already running, sets the Client Name and connects to the Dependency Graph. +It also provides some additional utilities. + +``` +public class MyClass extends Client { + + public MyClass() { + super("ClientName"); + + // Here you can add you Vars/Signals + Var myVar = new Var<>("myVar", "value"); + } +} +``` + +It can also wait for defined Vars to be available: + +``` +public class OtherClass extends Client { + + public OtherClass() { + super("OtherName"); + // The super class blocks until myVar@ClientName is available + RemoteVar theirVar = new RemoteVar<>("ClientName", "myVar"); + } + + @Override + protected List waitForVars() { + return Arrays.asList("myVar@ClientName"); + } + + @Override + protected void init() { + // The code here is executed before the the super class blocks + } +} +``` + +## Contributors + +Alessandro Margara, Guido Salvaneschi, Tobias Becker, Kim Berninger, Michael Raulf, Ram Kamath. + + + + diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..c741881 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file