diff options
author | eutarass | 2008-02-21 23:25:18 +0000 |
---|---|---|
committer | eutarass | 2008-02-21 23:25:18 +0000 |
commit | 521178c66ba2989ab837a9d7bb1c4a75216cfde2 (patch) | |
tree | 712d92bd8ef1fd4860d8f56f8a9b905bb2f216c8 /plugins/org.eclipse.tm.tcf.dsf | |
parent | 39964814a5c76b9c259bb2f670cb84e4d299abef (diff) | |
download | org.eclipse.tcf-521178c66ba2989ab837a9d7bb1c4a75216cfde2.tar.gz org.eclipse.tcf-521178c66ba2989ab837a9d7bb1c4a75216cfde2.tar.xz org.eclipse.tcf-521178c66ba2989ab837a9d7bb1c4a75216cfde2.zip |
In order to comply with naming conventions at Eclipse, plugins, packages, etc. are renamed from com.windriver.* to org.eclipse.tm.*
Copyright notices are updated to include year 2008.
Diffstat (limited to 'plugins/org.eclipse.tm.tcf.dsf')
27 files changed, 5205 insertions, 0 deletions
diff --git a/plugins/org.eclipse.tm.tcf.dsf/.classpath b/plugins/org.eclipse.tm.tcf.dsf/.classpath new file mode 100644 index 000000000..304e86186 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/plugins/org.eclipse.tm.tcf.dsf/.project b/plugins/org.eclipse.tm.tcf.dsf/.project new file mode 100644 index 000000000..68c416def --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.tm.tcf.dsf</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/plugins/org.eclipse.tm.tcf.dsf/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.tm.tcf.dsf/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..0bf81e2f5 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,272 @@ +#Tue Feb 05 15:38:16 CET 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,.svn/ +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.maxProblemPerUnit=100 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 +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_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_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_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.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +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_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.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.format_guardian_clause_on_one_line=false +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=8 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=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_at_end_of_file_if_missing=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=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=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=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_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_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_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_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_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_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_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.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=true +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +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=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +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.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error diff --git a/plugins/org.eclipse.tm.tcf.dsf/.settings/org.eclipse.jdt.ui.prefs b/plugins/org.eclipse.tm.tcf.dsf/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..abbc7248f --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,4 @@ +#Wed Jan 09 12:21:30 PST 2008
+eclipse.preferences.version=1
+formatter_profile=_Java STD
+formatter_settings_version=11
diff --git a/plugins/org.eclipse.tm.tcf.dsf/META-INF/MANIFEST.MF b/plugins/org.eclipse.tm.tcf.dsf/META-INF/MANIFEST.MF new file mode 100644 index 000000000..39e57e150 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.eclipse.tm.tcf.dsf;singleton:=true +Bundle-Version: 0.2.0 +Bundle-Activator: org.eclipse.tm.internal.tcf.dsf.Activator +Bundle-Vendor: %providerName +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.debug.core, + org.eclipse.core.resources, + org.eclipse.dd.dsf, + org.eclipse.dd.dsf.debug, + org.eclipse.cdt.core, + org.eclipse.tm.tcf, + org.eclipse.tm.tcf.debug +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy +Eclipse-LazyStart: true +Export-Package: org.eclipse.tm.internal.tcf.dsf.launch, + org.eclipse.tm.internal.tcf.dsf.services diff --git a/plugins/org.eclipse.tm.tcf.dsf/about.html b/plugins/org.eclipse.tm.tcf.dsf/about.html new file mode 100644 index 000000000..6c5b3615b --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/about.html @@ -0,0 +1,28 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>About</title> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>January 10, 2008</p> +<h3>License</h3> + +<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. +For purposes of the EPL, "Program" will mean the Content.</p> + +<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p> + +</body> +</html>
\ No newline at end of file diff --git a/plugins/org.eclipse.tm.tcf.dsf/build.properties b/plugins/org.eclipse.tm.tcf.dsf/build.properties new file mode 100644 index 000000000..2b6399957 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/build.properties @@ -0,0 +1,8 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + about.html,\ + plugin.properties +src.includes = about.html diff --git a/plugins/org.eclipse.tm.tcf.dsf/plugin.properties b/plugins/org.eclipse.tm.tcf.dsf/plugin.properties new file mode 100644 index 000000000..ee6aa5831 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/plugin.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Wind River Systems - initial implementation +############################################################################### +pluginName = TCF/DSF Integration Core +providerName = Eclipse.org + diff --git a/plugins/org.eclipse.tm.tcf.dsf/plugin.xml b/plugins/org.eclipse.tm.tcf.dsf/plugin.xml new file mode 100644 index 000000000..03786907c --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/plugin.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.2"?> +<plugin> + <extension + point="org.eclipse.debug.core.launchConfigurationTypes"> + <launchConfigurationType + sourceLocatorId="org.eclipse.tm.tcf.debug.SourceLocator" + name="DSF over TCF" + sourcePathComputerId="org.eclipse.tm.tcf.debug.SourcePathComputer" + delegate="org.eclipse.tm.internal.tcf.dsf.launch.TCFDSFLaunchDelegate" + modes="debug" + id="org.eclipse.tm.tcf.dsf.LaunchConfigurationType"> + </launchConfigurationType> + </extension> +</plugin> diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/Activator.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/Activator.java new file mode 100644 index 000000000..9d71d4f25 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/Activator.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf; + +import org.eclipse.core.runtime.Plugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends Plugin { + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.tm.tcf.dsf.core"; + + // The shared instance + private static Activator plugin; + private static BundleContext bundle_context; + + /** + * The constructor + */ + public Activator() { + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + bundle_context = context; + } + + /* + * (non-Javadoc) + * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + public static BundleContext getBundleContext() { + return bundle_context; + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFExecuter.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFExecuter.java new file mode 100644 index 000000000..309159c89 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFExecuter.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.launch; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; +import java.util.concurrent.AbstractExecutorService; +import java.util.concurrent.Callable; +import java.util.concurrent.Delayed; +import java.util.concurrent.FutureTask; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.dd.dsf.concurrent.DsfExecutor; +import org.eclipse.tm.tcf.protocol.Protocol; + + +public class TCFDSFExecuter extends AbstractExecutorService implements DsfExecutor { + + private class ScheduledFutureTask<V> extends FutureTask<V> implements ScheduledFuture<V> { + + private long time; // Milliseconds + private final int id; + private final long period; // Milliseconds + + public ScheduledFutureTask(long delay, long period, Runnable runnable, V result) { + super(runnable, result); + time = System.currentTimeMillis() + delay; + id = sf_count++; + this.period = period; + } + + public ScheduledFutureTask(long delay, Callable<V> callable) { + super(callable); + time = System.currentTimeMillis() + delay; + id = sf_count++; + period = 0; + } + + public long getDelay(TimeUnit unit) { + return unit.convert(time - System.currentTimeMillis(), TimeUnit.MILLISECONDS); + } + + public int compareTo(Delayed o) { + if (o == this) return 0; + ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)o; + if (time < x.time) return -1; + if (time > x.time) return +1; + if (id < x.id) return -1; + if (id > x.id) return +1; + assert false; + return 0; + } + + public void run() { + if (period == 0) { + super.run(); + } + else { + boolean ok = super.runAndReset(); + synchronized (TCFDSFExecuter.this) { + // Reschedule if not canceled and not shutdown + if (ok && !is_shutdown) { + time = period > 0 ? time + period : System.currentTimeMillis() - period; + queue.add(this); + notify(); + } + } + } + } + } + + private static int sf_count = 0; + private final TreeSet<ScheduledFutureTask<?>> queue = new TreeSet<ScheduledFutureTask<?>>(); + private final Thread thread; + private boolean is_shutdown; + private boolean is_terminated; + + public TCFDSFExecuter() { + thread = new Thread(new Runnable() { + public void run() { + synchronized (TCFDSFExecuter.this) { + try { + while (true) { + if (queue.isEmpty()) { + if (is_shutdown) break; + TCFDSFExecuter.this.wait(); + } + else { + long time = System.currentTimeMillis(); + ScheduledFutureTask<?> s = queue.first(); + if (s.time <= time) { + queue.remove(s); + Protocol.invokeLater(s); + } + else { + TCFDSFExecuter.this.wait(s.time - time); + } + } + } + } + catch (Throwable x) { + x.printStackTrace(); + } + is_terminated = true; + } + } + }); + thread.setName("TCF Future Task Scheduler"); + thread.start(); + } + + public boolean isInExecutorThread() { + return Protocol.isDispatchThread(); + } + + public synchronized ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { + if (command == null || unit == null) throw new NullPointerException(); + if (is_shutdown) throw new RejectedExecutionException(); + delay = unit.toMillis(delay); + ScheduledFutureTask<Boolean> s = new ScheduledFutureTask<Boolean>(delay, 0, command, Boolean.TRUE); + queue.add(s); + notify(); + return s; + } + + public synchronized <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { + if (callable == null || unit == null) throw new NullPointerException(); + if (is_shutdown) throw new RejectedExecutionException(); + delay = unit.toMillis(delay); + ScheduledFutureTask<V> s = new ScheduledFutureTask<V>(delay, callable); + queue.add(s); + notify(); + return s; + } + + public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, + long initialDelay, long period, TimeUnit unit) { + if (command == null || unit == null) throw new NullPointerException(); + if (is_shutdown) throw new RejectedExecutionException(); + if (period <= 0) throw new RejectedExecutionException(); + ScheduledFutureTask<Boolean> s = new ScheduledFutureTask<Boolean>( + unit.toMillis(initialDelay), unit.toMillis(period), command, Boolean.TRUE); + queue.add(s); + notify(); + return s; + } + + public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, + long initialDelay, long delay, TimeUnit unit) { + if (command == null || unit == null) throw new NullPointerException(); + if (is_shutdown) throw new RejectedExecutionException(); + if (delay <= 0) throw new RejectedExecutionException(); + ScheduledFutureTask<Boolean> s = new ScheduledFutureTask<Boolean>( + unit.toMillis(initialDelay), -unit.toMillis(delay), command, Boolean.TRUE); + queue.add(s); + notify(); + return s; + } + + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + thread.join(unit.toMillis(timeout)); + return is_terminated; + } + + public synchronized boolean isShutdown() { + return is_shutdown; + } + + public synchronized boolean isTerminated() { + return is_terminated; + } + + public synchronized void shutdown() { + is_shutdown = true; + notify(); + } + + public synchronized List<Runnable> shutdownNow() { + List<Runnable> res = new ArrayList<Runnable>(queue); + queue.clear(); + is_shutdown = true; + notify(); + return res; + } + + public synchronized void execute(Runnable command) { + if (is_shutdown) throw new RejectedExecutionException(); + Protocol.invokeLater(command); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunch.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunch.java new file mode 100644 index 000000000..b48b21853 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunch.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.launch; + +import org.eclipse.dd.dsf.concurrent.DsfExecutor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.tm.internal.tcf.debug.model.ITCFConstants; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.tcf.protocol.IChannel; + + +public class TCFDSFLaunch extends TCFLaunch { + + private final TCFDSFExecuter executor; + private final DsfSession session; + + public TCFDSFLaunch(ILaunchConfiguration launchConfiguration, String mode) { + super(launchConfiguration, mode); + executor = new TCFDSFExecuter(); + session = DsfSession.startSession(executor, ITCFConstants.ID_TCF_DEBUG_MODEL); + } + + @Override + protected void runLaunchSequence(final Runnable done) { + super.runLaunchSequence(new Runnable() { + public void run() { + IChannel channel = getChannel(); + if (channel != null) { + RequestMonitor monitor = new RequestMonitor(executor, null) { + @Override + protected void handleOK() { + done.run(); + } + }; + TCFDSFLaunchSequence seq = new TCFDSFLaunchSequence(session, TCFDSFLaunch.this, monitor); + executor.execute(seq); + } + else { + done.run(); + } + } + }); + } + + public DsfExecutor getDsfExecutor() { + return executor; + } + + public DsfSession getSession() { + return session; + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunchDelegate.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunchDelegate.java new file mode 100644 index 000000000..d6a9280bf --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunchDelegate.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.launch; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.tm.internal.tcf.debug.launch.TCFLaunchDelegate; + + +public class TCFDSFLaunchDelegate extends TCFLaunchDelegate { + + public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException { + return new TCFDSFLaunch(configuration, mode); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunchSequence.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunchSequence.java new file mode 100644 index 000000000..b9c996085 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/launch/TCFDSFLaunchSequence.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.launch; + +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.concurrent.Sequence; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.tm.internal.tcf.dsf.services.TCFDSFBreakpoints; +import org.eclipse.tm.internal.tcf.dsf.services.TCFDSFMemory; +import org.eclipse.tm.internal.tcf.dsf.services.TCFDSFNativeProcesses; +import org.eclipse.tm.internal.tcf.dsf.services.TCFDSFRegisters; +import org.eclipse.tm.internal.tcf.dsf.services.TCFDSFRunControl; +import org.eclipse.tm.internal.tcf.dsf.services.TCFDSFStack; +import org.eclipse.tm.internal.tcf.dsf.services.TCFDSFStepQueueManager; +import org.eclipse.tm.tcf.protocol.IChannel; + + +class TCFDSFLaunchSequence extends Sequence { + + private final Step[] steps; + + TCFDSFLaunchSequence(final DsfSession session, final TCFDSFLaunch launch, RequestMonitor monitor) { + super(session.getExecutor(), monitor); + final IChannel channel = launch.getChannel(); + steps = new Step[] { + new Step() { + @Override + public void execute(RequestMonitor monitor) { + new TCFDSFNativeProcesses(session, channel, monitor); + } + }, + new Step() { + @Override + public void execute(RequestMonitor monitor) { + new TCFDSFRunControl(session, channel, monitor); + } + }, + new Step() { + @Override + public void execute(RequestMonitor monitor) { + new TCFDSFStepQueueManager(session).initialize(monitor); + } + }, + new Step() { + @Override + public void execute(RequestMonitor monitor) { + new TCFDSFStack(session, channel, monitor); + } + }, + new Step() { + @Override + public void execute(RequestMonitor monitor) { + new TCFDSFMemory(session, channel, monitor); + } + }, + new Step() { + @Override + public void execute(RequestMonitor monitor) { + new TCFDSFRegisters(session, channel, monitor); + } + }, + new Step() { + @Override + public void execute(RequestMonitor monitor) { + new TCFDSFBreakpoints(session, launch, monitor); + } + }, + }; + } + + @Override + public Step[] getSteps() { + return steps; + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/IDataRequest.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/IDataRequest.java new file mode 100644 index 000000000..d064448fe --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/IDataRequest.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +public interface IDataRequest { + + void cancel(); + void done(); +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFAddress.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFAddress.java new file mode 100644 index 000000000..ec723ed95 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFAddress.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.math.BigInteger; + +import org.eclipse.cdt.core.IAddress; + +public final class TCFAddress implements IAddress { + + private final BigInteger addr; + + public TCFAddress(Number addr) { + if (addr instanceof BigInteger) this.addr = (BigInteger)addr; + else this.addr = new BigInteger(addr.toString(), 10); + } + + public IAddress add(BigInteger i) { + return new TCFAddress(addr.add(i)); + } + + public IAddress add(long l) { + if (l == 0) return this; + return new TCFAddress(addr.add(BigInteger.valueOf(l))); + } + + public BigInteger distanceTo(IAddress a) { + return a.getValue().subtract(addr); + } + + public int getCharsNum() { + // TODO don't know what getCharsNum() is supposed to return + return 0; + } + + public BigInteger getMaxOffset() { + // TODO don't know what getMaxOffset() is supposed to return + return null; + } + + public int getSize() { + // TODO don't know what getSize() is supposed to return + return 0; + } + + public BigInteger getValue() { + return addr; + } + + public boolean isMax() { + return false; + } + + public boolean isZero() { + return addr.equals(BigInteger.ZERO); + } + + public String toBinaryAddressString() { + return toHexAddressString(); + } + + public String toHexAddressString() { + return "0x" + toString(16); + } + + public String toString(int radix) { + return addr.toString(radix); + } + + public int compareTo(Object o) { + return addr.compareTo(((TCFAddress)o).addr); + } + + public String toString() { + return "[" + toHexAddressString() + "]"; + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFBreakpoints.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFBreakpoints.java new file mode 100644 index 000000000..6b1e00502 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFBreakpoints.java @@ -0,0 +1,306 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.AbstractDMContext; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.service.AbstractDsfService; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.dsf.service.IDsfService; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.IBreakpointManager; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.tm.internal.tcf.debug.model.ITCFBreakpointListener; +import org.eclipse.tm.internal.tcf.debug.model.ITCFConstants; +import org.eclipse.tm.internal.tcf.debug.model.TCFBreakpointsModel; +import org.eclipse.tm.internal.tcf.debug.model.TCFLaunch; +import org.eclipse.tm.internal.tcf.dsf.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.osgi.framework.BundleContext; + + +// TODO IBreakpointHitEvent + +public class TCFDSFBreakpoints extends AbstractDsfService implements org.eclipse.dd.dsf.debug.service.IBreakpoints { + + private class BreakpointDMC extends AbstractDMContext implements IBreakpointDMContext { + + final String id; + final IBreakpoint bp; + final TCFDataCache<Map<String,Object>> status; + + boolean disposed; + + public BreakpointDMC(IDsfService service, final String id, IBreakpoint bp) { + super(service, new IDMContext[0]); + this.id = id; + this.bp = bp; + cache.put(id, this); + status = new TCFDataCache<Map<String,Object>>(channel) { + @Override + public boolean startDataRetrieval() { + assert command == null; + assert !disposed; + if (tcf_bpt_service == null) { + data = null; + valid = true; + return true; + } + command = tcf_bpt_service.getStatus(id, new org.eclipse.tm.tcf.services.IBreakpoints.DoneGetStatus() { + public void doneGetStatus(IToken token, Exception err, Map<String,Object> status) { + if (command != token) return; + command = null; + if (err != null) { + data = null; + error = err; + } + else { + data = status; + } + valid = true; + validate(); + } + }); + return false; + } + }; + } + + @Override + public boolean equals(Object other) { + return super.baseEquals(other) && ((BreakpointDMC)other).id.equals(id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } + + void dispose() { + assert !disposed; + cache.remove(id); + disposed = true; + } + } + + private class BreakpointData implements IBreakpointDMData { + + final IBreakpoint bp; + final BreakpointStatus status; + + BreakpointData(IBreakpoint bp, BreakpointStatus status) { + this.bp = bp; + this.status = status; + } + + public IBreakpoint getPlatformBreakpoint() { + return bp; + } + + public BreakpointStatus getStatus() { + return status; + } + } + + private final ITCFBreakpointListener bp_listener = new ITCFBreakpointListener() { + + public void breakpointStatusChanged(String id) { + final BreakpointDMC dmc = cache.get(id); + if (dmc != null) { + Map<String, Object> map = launch.getBreakpointsStatus().getStatus(dmc.id); + dmc.status.reset(map); + IBreakpointDMEvent e = null; + if (map == null) { + e = new IBreakpointUninstalledDMEvent() { + public IBreakpointDMContext getDMContext() { + return dmc; + } + }; + } + else if (map.get(org.eclipse.tm.tcf.services.IBreakpoints.STATUS_ERROR) != null) { + e = new IBreakpointInstallFailedDMEvent() { + public IBreakpointDMContext getDMContext() { + return dmc; + } + }; + } + else if (map.get(org.eclipse.tm.tcf.services.IBreakpoints.STATUS_PLANTED) != null) { + e = new IBreakpointInstalledDMEvent() { + public IBreakpointDMContext getDMContext() { + return dmc; + } + }; + } + else { + e = new IBreakpointUninstalledDMEvent() { + public IBreakpointDMContext getDMContext() { + return dmc; + } + }; + } + getSession().dispatchEvent(e, getProperties()); + } + } + + public void breakpointRemoved(String id) { + final BreakpointDMC dmc = cache.get(id); + if (dmc != null) { + dmc.dispose(); + IBreakpointDMEvent e = new IBreakpointUninstalledDMEvent() { + public IBreakpointDMContext getDMContext() { + return dmc; + } + }; + getSession().dispatchEvent(e, getProperties()); + } + } + }; + + private final TCFLaunch launch; + private final IChannel channel; + private final org.eclipse.tm.tcf.services.IBreakpoints tcf_bpt_service; + private final Map<String,BreakpointDMC> cache = new HashMap<String,BreakpointDMC>(); + + public TCFDSFBreakpoints(DsfSession session, TCFLaunch launch, final RequestMonitor monitor) { + super(session); + this.launch = launch; + channel = launch.getChannel(); + launch.getBreakpointsStatus().addListener(bp_listener); + tcf_bpt_service = channel.getRemoteService(org.eclipse.tm.tcf.services.IBreakpoints.class); + initialize(new RequestMonitor(getExecutor(), monitor) { + @Override + protected void handleOK() { + String[] class_names = { + org.eclipse.dd.dsf.debug.service.IBreakpoints.class.getName(), + TCFDSFBreakpoints.class.getName() + }; + register(class_names, new Hashtable<String,String>()); + monitor.done(); + } + }); + } + + @Override + public void shutdown(RequestMonitor monitor) { + unregister(); + super.shutdown(monitor); + } + + @Override + protected BundleContext getBundleContext() { + return Activator.getBundleContext(); + } + + public void getAllBreakpoints(IDMContext ctx, DataRequestMonitor<IBreakpointDMContext[]> rm) { + IBreakpointManager bp_manager = DebugPlugin.getDefault().getBreakpointManager(); + TCFBreakpointsModel m = TCFBreakpointsModel.getBreakpointsModel(); + IBreakpoint[] arr = bp_manager.getBreakpoints(ITCFConstants.ID_TCF_DEBUG_MODEL); + ArrayList<IBreakpointDMContext> l = new ArrayList<IBreakpointDMContext>(); + if (arr != null && arr.length == 0) { + for (IBreakpoint bp : arr) { + if (m.isSupported(channel, bp)) { + IMarker marker = bp.getMarker(); + String id = marker.getAttribute(ITCFConstants.ID_TCF_DEBUG_MODEL + + '.' + org.eclipse.tm.tcf.services.IBreakpoints.PROP_ID, (String)null); + if (id != null) { + BreakpointDMC c = cache.get(id); + if (c == null) c = new BreakpointDMC(this, id, bp); + l.add(c); + } + } + } + } + rm.setData(l.toArray(new IBreakpointDMContext[l.size()])); + rm.done(); + } + + public void getBreakpoints(IDMContext dmc, IBreakpoint bp, DataRequestMonitor<IBreakpointDMContext[]> rm) { + TCFBreakpointsModel m = TCFBreakpointsModel.getBreakpointsModel(); + ArrayList<IBreakpointDMContext> l = new ArrayList<IBreakpointDMContext>(); + if (m.isSupported(channel, bp)) { + IMarker marker = bp.getMarker(); + String id = marker.getAttribute(ITCFConstants.ID_TCF_DEBUG_MODEL + + '.' + org.eclipse.tm.tcf.services.IBreakpoints.PROP_ID, (String)null); + if (id != null) { + BreakpointDMC c = cache.get(id); + if (c == null) c = new BreakpointDMC(this, id, bp); + l.add(c); + } + } + rm.setData(l.toArray(new IBreakpointDMContext[l.size()])); + rm.done(); + } + + public void getBreakpointData(final IDMContext dmc, final DataRequestMonitor<IBreakpointDMData> rm) { + if (dmc instanceof BreakpointDMC) { + BreakpointDMC bp = (BreakpointDMC)dmc; + if (!bp.status.validate()) { + bp.status.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getBreakpointData(dmc, rm); + } + }); + return; + } + if (bp.status.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", bp.status.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + Map<String,Object> map = bp.status.getData(); + BreakpointStatus status = BreakpointStatus.FILTERED_OUT; + if (map != null) { + if (map.get(org.eclipse.tm.tcf.services.IBreakpoints.STATUS_ERROR) != null) { + status = BreakpointStatus.FAILED_TO_INSTALL; + } + else if (map.get(org.eclipse.tm.tcf.services.IBreakpoints.STATUS_PLANTED) != null) { + status = BreakpointStatus.INSTALLED; + } + } + rm.setData(new BreakpointData(bp.bp, status)); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + @SuppressWarnings("unchecked") + public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) { + if (dmc instanceof BreakpointDMC) { + getBreakpointData((BreakpointDMC)dmc, (DataRequestMonitor<IBreakpointDMData>)rm); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFExecutionDMC.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFExecutionDMC.java new file mode 100644 index 000000000..6246cd99d --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFExecutionDMC.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import org.eclipse.dd.dsf.datamodel.AbstractDMContext; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.dd.dsf.service.IDsfService; + +public abstract class TCFDSFExecutionDMC extends AbstractDMContext implements IExecutionDMContext, IContainerDMContext { + + interface DataCache { + } + + DataCache stack_frames_cache; + DataCache memory_cache; + DataCache registers_cache; + + TCFDSFExecutionDMC(IDsfService service, IDMContext[] parents) { + super(service, parents); + } + + /** + * Get TCF ID of execution context. + * @return TCF ID. + */ + public abstract String getTcfContextId(); + + /** + * Check if this context object is disposed, because, for example, a thread has exited. + * @return true if context object is disposed. + */ + public abstract boolean isDisposed(); + + /** + * Validate execution state data. + * @return true if state is valid, false if data retrieval is started. + */ + public abstract boolean validateState(); + + /** + * Add a listener to be activated when state data retrieval is done. + * @param req - listener object. + */ + public abstract void addStateWaitingRequest(IDataRequest req); + + /** + * Get current program counter. This method must be called only when + * execution state data is valid - when validateState() return true. + * @return current program counter address. + */ + public abstract TCFAddress getPC(); +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFMemory.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFMemory.java new file mode 100644 index 000000000..cf40d6a4b --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFMemory.java @@ -0,0 +1,307 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.util.Hashtable; + +import org.eclipse.cdt.core.IAddress; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.service.AbstractDsfService; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.debug.core.model.MemoryByte; +import org.eclipse.tm.internal.tcf.dsf.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IMemory.MemoryContext; +import org.eclipse.tm.tcf.services.IMemory.MemoryError; +import org.osgi.framework.BundleContext; + + +public class TCFDSFMemory extends AbstractDsfService implements org.eclipse.dd.dsf.debug.service.IMemory { + + private class MemoryCache implements TCFDSFExecutionDMC.DataCache { + + final TCFDataCache<org.eclipse.tm.tcf.services.IMemory.MemoryContext> context; + + MemoryCache(final IChannel channel, final TCFDSFExecutionDMC exe) { + context = new TCFDataCache<org.eclipse.tm.tcf.services.IMemory.MemoryContext>(channel) { + @Override + public boolean startDataRetrieval() { + assert command == null; + String id = exe.getTcfContextId(); + if (id == null || tcf_mem_service == null) { + data = null; + valid = true; + return true; + } + command = tcf_mem_service.getContext(id, + new org.eclipse.tm.tcf.services.IMemory.DoneGetContext() { + public void doneGetContext(IToken token, Exception err, + org.eclipse.tm.tcf.services.IMemory.MemoryContext ctx) { + if (command != token) return; + command = null; + if (err != null) { + error = err; + } + else { + data = ctx; + } + valid = true; + validate(); + } + }); + return false; + } + }; + } + } + + private final org.eclipse.tm.tcf.services.IMemory.MemoryListener mem_listener = + new org.eclipse.tm.tcf.services.IMemory.MemoryListener() { + + public void contextAdded(MemoryContext[] contexts) { + } + + public void contextChanged(MemoryContext[] contexts) { + } + + public void contextRemoved(String[] context_ids) { + } + + public void memoryChanged(String context_id, Number[] addr, long[] size) { + TCFDSFRunControl rc = getServicesTracker().getService(TCFDSFRunControl.class); + TCFDSFExecutionDMC exe = rc.getContext(context_id); + if (exe == null || exe.memory_cache == null) return; + for (int n = 0; n < addr.length; n++) { + long count = size[n]; + // TODO: DSF does not support address ranges + if (count > 256) count = 256; + IAddress[] addresses = new IAddress[(int)count]; + for (int i = 0; i < (int)count; i++) { + addresses[i] = new TCFAddress(addr[n]).add(i); + } + getSession().dispatchEvent(new MemoryChangedEvent(exe, addresses), getProperties()); + } + } + }; + + private final IChannel channel; + private final org.eclipse.tm.tcf.services.IMemory tcf_mem_service; + + public TCFDSFMemory(DsfSession session, IChannel channel, final RequestMonitor monitor) { + super(session); + this.channel = channel; + tcf_mem_service = channel.getRemoteService(org.eclipse.tm.tcf.services.IMemory.class); + if (tcf_mem_service != null) tcf_mem_service.addListener(mem_listener); + initialize(new RequestMonitor(getExecutor(), monitor) { + @Override + protected void handleOK() { + String[] class_names = { + org.eclipse.dd.dsf.debug.service.IMemory.class.getName(), + TCFDSFMemory.class.getName() + }; + register(class_names, new Hashtable<String,String>()); + monitor.done(); + } + }); + } + + @Override + public void shutdown(RequestMonitor monitor) { + unregister(); + super.shutdown(monitor); + } + + @Override + protected BundleContext getBundleContext() { + return Activator.getBundleContext(); + } + + public void fillMemory(final IDMContext dmc, final IAddress address, final long offset, + final int word_size, final int count, final byte[] pattern, final RequestMonitor rm) { + if (tcf_mem_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Memory access service is not available", null)); //$NON-NLS-1$ + rm.done(); + } + else if (dmc instanceof TCFDSFExecutionDMC) { + final TCFDSFExecutionDMC ctx = (TCFDSFExecutionDMC)dmc; + if (ctx.memory_cache == null) ctx.memory_cache = new MemoryCache(channel, ctx); + MemoryCache cache = (MemoryCache)ctx.memory_cache; + if (!cache.context.validate()) { + cache.context.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + fillMemory(dmc, address, offset, word_size, count, pattern, rm); + } + }); + return; + } + if (cache.context.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.context.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + org.eclipse.tm.tcf.services.IMemory.MemoryContext mem = cache.context.getData(); + if (mem == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Invalid DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + mem.fill(address.add(offset).getValue(), word_size, pattern, count * word_size, 0, + new org.eclipse.tm.tcf.services.IMemory.DoneMemory() { + public void doneMemory(IToken token, MemoryError error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + rm.done(); + } + }); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getMemory(final IDMContext dmc, final IAddress address, final long offset, + final int word_size, final int count, final DataRequestMonitor<MemoryByte[]> rm) { + if (tcf_mem_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Memory access service is not available", null)); //$NON-NLS-1$ + rm.done(); + } + else if (dmc instanceof TCFDSFExecutionDMC) { + final TCFDSFExecutionDMC ctx = (TCFDSFExecutionDMC)dmc; + if (ctx.memory_cache == null) ctx.memory_cache = new MemoryCache(channel, ctx); + MemoryCache cache = (MemoryCache)ctx.memory_cache; + if (!cache.context.validate()) { + cache.context.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getMemory(dmc, address, offset, word_size, count, rm); + } + }); + return; + } + if (cache.context.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.context.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + org.eclipse.tm.tcf.services.IMemory.MemoryContext mem = cache.context.getData(); + if (mem == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Invalid DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + final byte[] buffer = new byte[word_size * count]; + mem.get(address.add(offset).getValue(), word_size, buffer, 0, count * word_size, 0, + new org.eclipse.tm.tcf.services.IMemory.DoneMemory() { + public void doneMemory(IToken token, MemoryError error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + MemoryByte[] res = new MemoryByte[buffer.length]; + for (int i = 0; i < buffer.length; i++) { + res[i] = new MemoryByte(buffer[i]); + } + rm.done(); + } + }); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void setMemory(final IDMContext dmc, final IAddress address, final long offset, + final int word_size, final int count, final byte[] buffer, final RequestMonitor rm) { + if (tcf_mem_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Memory access service is not available", null)); //$NON-NLS-1$ + rm.done(); + } + else if (dmc instanceof TCFDSFExecutionDMC) { + final TCFDSFExecutionDMC ctx = (TCFDSFExecutionDMC)dmc; + if (ctx.memory_cache == null) ctx.memory_cache = new MemoryCache(channel, ctx); + MemoryCache cache = (MemoryCache)ctx.memory_cache; + if (!cache.context.validate()) { + cache.context.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + setMemory(dmc, address, offset, word_size, count, buffer, rm); + } + }); + return; + } + if (cache.context.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.context.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + org.eclipse.tm.tcf.services.IMemory.MemoryContext mem = cache.context.getData(); + if (mem == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Invalid DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + mem.set(address.add(offset).getValue(), word_size, buffer, 0, count * word_size, 0, + new org.eclipse.tm.tcf.services.IMemory.DoneMemory() { + public void doneMemory(IToken token, MemoryError error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + rm.done(); + } + }); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java new file mode 100644 index 000000000..b1f66dde4 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFNativeProcesses.java @@ -0,0 +1,614 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.AbstractDMEvent; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.datamodel.ServiceDMContext; +import org.eclipse.dd.dsf.debug.service.INativeProcesses; +import org.eclipse.dd.dsf.service.AbstractDsfService; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.tm.internal.tcf.dsf.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IProcesses; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IProcesses.ProcessContext; +import org.eclipse.tm.tcf.services.IRunControl.RunControlContext; +import org.osgi.framework.BundleContext; + + +public class TCFDSFNativeProcesses extends AbstractDsfService implements INativeProcesses { + + private class ProcessDMC extends TCFDSFProcessDMC implements IProcessDMContext { + + final String id; + + ProcessDMC(String id, IDMContext parent) { + super(TCFDSFNativeProcesses.this, parent != null ? new IDMContext[]{ parent } : new IDMContext[0]); + this.id = id; + } + + @Override + public String toString() { + return baseToString() + ".context[" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public boolean equals(Object obj) { + if (!super.baseEquals(obj)) return false; + String obj_id = ((ProcessDMC)obj).id; + if (obj_id == null) return id == null; + return obj_id.equals(id); + } + + @Override + public int hashCode() { + if (id == null) return 0; + return id.hashCode(); + } + } + + private class ThreadDMC extends TCFDSFThreadDMC implements IThreadDMContext { + + final String id; + + ThreadDMC(String id) { + super(TCFDSFNativeProcesses.this, new IDMContext[0]); + this.id = id; + } + + @Override + public String toString() { + return baseToString() + ".context[" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public boolean equals(Object obj) { + if (!super.baseEquals(obj)) return false; + String obj_id = ((ThreadDMC)obj).id; + if (obj_id == null) return id == null; + return obj_id.equals(id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } + } + + private class ProcessData implements IProcessDMData { + + private final IProcesses.ProcessContext ctx; + + ProcessData(IProcesses.ProcessContext ctx) { + this.ctx = ctx; + } + + public IDMContext getDebugContext() { + return getServicesTracker().getService(TCFDSFRunControl.class).getContext(ctx.getID()); + } + + public String getId() { + return ctx.getID(); + } + + public String getName() { + return ctx.getName(); + } + + public boolean isDebuggerAttached() { + return ctx.isAttached(); + } + + public boolean isValid() { + return true; + } + } + + private class ThreadData implements IThreadDMData { + + private final TCFDSFExecutionDMC ctx; + + ThreadData(TCFDSFExecutionDMC ctx) { + this.ctx = ctx; + } + + public IDMContext getDebugContext() { + return ctx; + } + + public String getId() { + if (ctx == null) return null; + return ctx.getTcfContextId(); + } + + public String getName() { + // TODO thread name + return ""; + } + + public boolean isDebuggerAttached() { + return true; + } + + public boolean isValid() { + return true; + } + } + + private class ProcessStartedEvent extends AbstractDMEvent<IDMContext> implements IProcessStartedEvent { + + private final IProcessDMContext prs; + + ProcessStartedEvent(IDMContext dmc, IProcessDMContext prs) { + super(dmc); + this.prs = prs; + } + + public IProcessDMContext getProcess() { + return prs; + } + } + + private class ProcessExitedEvent extends AbstractDMEvent<IDMContext> implements IProcessExitedEvent { + + private final IProcessDMContext prs; + + ProcessExitedEvent(IDMContext dmc, IProcessDMContext prs) { + super(dmc); + this.prs = prs; + } + + public IProcessDMContext getProcess() { + return prs; + } + } + + private final org.eclipse.tm.tcf.services.IRunControl.RunControlListener run_listener = + new org.eclipse.tm.tcf.services.IRunControl.RunControlListener() { + + public void containerResumed(String[] context_ids) { + } + + public void containerSuspended(String context, String pc, + String reason, Map<String, Object> params, + String[] suspended_ids) { + } + + public void contextAdded(RunControlContext[] contexts) { + for (RunControlContext ctx : contexts) { + String id = ctx.getID(); + if (id.equals(ctx.getProperties().get(IRunControl.PROP_PROCESS_ID))) { + ProcessDMC dmc = new ProcessDMC(id, root_dmc); + process_cache.put(id, dmc); + getSession().dispatchEvent(new ProcessStartedEvent(root_dmc, dmc), getProperties()); + } + else { + ThreadDMC dmc = new ThreadDMC(id); + thread_cache.put(id, dmc); + } + } + } + + public void contextChanged(RunControlContext[] contexts) { + } + + public void contextException(String context, String msg) { + } + + public void contextRemoved(String[] context_ids) { + for (String id : context_ids) { + ProcessDMC dmc = process_cache.remove(id); + if (dmc != null) { + getSession().dispatchEvent(new ProcessExitedEvent(root_dmc, dmc), getProperties()); + } + else { + thread_cache.remove(id); + } + } + } + + public void contextResumed(String context) { + } + + public void contextSuspended(String context, String pc, + String reason, Map<String, Object> params) { + } + }; + + private final IProcesses tcf_prs_service; + private final org.eclipse.tm.tcf.services.IRunControl tcf_run_service; + private final Map<String,ProcessDMC> process_cache = new HashMap<String,ProcessDMC>(); // all attached processes + private final Map<String,ThreadDMC> thread_cache = new HashMap<String,ThreadDMC>(); // only some of attached threads + private final ProcessDMC root_dmc = new ProcessDMC(null, null); + private IDMContext service_dmc; + + public TCFDSFNativeProcesses(DsfSession session, IChannel channel, final RequestMonitor monitor) { + super(session); + tcf_prs_service = channel.getRemoteService(IProcesses.class); + tcf_run_service = channel.getRemoteService(org.eclipse.tm.tcf.services.IRunControl.class); + if (tcf_run_service != null) tcf_run_service.addListener(run_listener); + service_dmc = new ServiceDMContext(this, "#native_process"); + initialize(new RequestMonitor(getExecutor(), monitor) { + @Override + protected void handleOK() { + String[] class_names = { + INativeProcesses.class.getName(), + TCFDSFNativeProcesses.class.getName() + }; + register(class_names, new Hashtable<String,String>()); + monitor.done(); + } + }); + } + + @Override + public void initialize(final RequestMonitor monitor) { + final Collection<String> list = new ArrayList<String>(); + final Set<IToken> cmds = new HashSet<IToken>(); + final IProcesses.DoneGetChildren done = new IProcesses.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + if (cmds.isEmpty()) return; + assert cmds.contains(token); + cmds.remove(token); + if (error != null) { + for (IToken t : cmds) t.cancel(); + cmds.clear(); + monitor.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + monitor.done(); + } + else { + for (String id : context_ids) { + list.add(id); + cmds.add(tcf_prs_service.getChildren(id, true, this)); + } + if (cmds.isEmpty()) { + for (String id : list) { + assert id != null; + if (process_cache.get(id) != null) continue; + process_cache.put(id, new ProcessDMC(id, root_dmc)); + } + process_cache.put(null, root_dmc); + TCFDSFNativeProcesses.super.initialize(monitor); + } + } + } + }; + cmds.add(tcf_prs_service.getChildren(null, true, done)); + } + + @Override + public void shutdown(RequestMonitor monitor) { + unregister(); + super.shutdown(monitor); + } + + @Override + protected BundleContext getBundleContext() { + return Activator.getBundleContext(); + } + + public IDMContext getServiceContext() { + return service_dmc; + } + + public boolean isValid() { + return true; + } + + public void attachDebuggerToProcess(IProcessDMContext ctx, final RequestMonitor rm) { + if (tcf_prs_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$ + rm.done(); + } + else if (ctx instanceof ProcessDMC) { + final ProcessDMC p = (ProcessDMC)ctx; + tcf_prs_service.getContext(p.id, new IProcesses.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, ProcessContext context) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$ + rm.done(); + } + else if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Invalid processs ID", error)); //$NON-NLS-1$ + rm.done(); + } + else { + context.attach(new IProcesses.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot attach a process", error)); //$NON-NLS-1$ + } + assert error != null || process_cache.get(p.id) != null; + rm.done(); + } + }); + } + } + }); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void canTerminate(IDMContext ctx, final DataRequestMonitor<Boolean> rm) { + rm.setData(false); + if (tcf_prs_service == null) { + rm.done(); + } + else if (ctx instanceof ProcessDMC) { + ProcessDMC p = (ProcessDMC)ctx; + tcf_prs_service.getContext(p.id, new IProcesses.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, ProcessContext context) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$ + } + else if (context == null) { + rm.setData(false); + } + else { + rm.setData(context.canTerminate()); + } + rm.done(); + } + }); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void terminate(IDMContext ctx, final RequestMonitor rm) { + if (tcf_prs_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$ + rm.done(); + } + else if (ctx instanceof ProcessDMC) { + ProcessDMC p = (ProcessDMC)ctx; + tcf_prs_service.getContext(p.id, new IProcesses.DoneGetContext() { + public void doneGetContext(IToken token, Exception error, ProcessContext context) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$ + rm.done(); + } + else if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Invalid processs ID", error)); //$NON-NLS-1$ + rm.done(); + } + else { + context.terminate(new IProcesses.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot terminate a process", error)); //$NON-NLS-1$ + } + rm.done(); + } + }); + } + } + }); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void debugNewProcess(String file, final DataRequestMonitor<IProcessDMContext> rm) { + if (tcf_prs_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$ + rm.done(); + } + else { + tcf_prs_service.start(null, file, null, null, true, new IProcesses.DoneStart() { + public void doneStart(IToken token, Exception error, ProcessContext process) { + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot start a process", error)); //$NON-NLS-1$ + } + else { + ProcessDMC dmc = process_cache.get(process.getID()); + assert dmc != null; + rm.setData(dmc); + } + rm.done(); + } + }); + } + } + + public void runNewProcess(String file, final DataRequestMonitor<IProcessDMContext> rm) { + if (tcf_prs_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Service not available", null)); //$NON-NLS-1$ + rm.done(); + } + else { + tcf_prs_service.start(null, file, null, null, false, new IProcesses.DoneStart() { + public void doneStart(IToken token, Exception error, ProcessContext process) { + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot start a process", error)); //$NON-NLS-1$ + } + else { + assert process_cache.get(process.getID()) == null; + rm.setData(new ProcessDMC(process.getID(), root_dmc)); + } + rm.done(); + } + }); + } + } + + public IProcessDMContext getProcessForDebugContext(IDMContext ctx) { + if (ctx instanceof IProcessDMContext) { + return (IProcessDMContext)ctx; + } + if (ctx instanceof TCFDSFExecutionDMC) { + String id = ((TCFDSFExecutionDMC)ctx).getTcfContextId(); + return process_cache.get(id); + } + return null; + } + + public IThreadDMContext getThreadForDebugContext(IDMContext ctx) { + if (ctx instanceof IThreadDMContext) { + return (IThreadDMContext)ctx; + } + if (ctx instanceof TCFDSFExecutionDMC) { + String id = ((TCFDSFExecutionDMC)ctx).getTcfContextId(); + ThreadDMC dmc = thread_cache.get(id); + if (dmc == null) dmc = new ThreadDMC(id); + return dmc; + } + return null; + } + + public void getProcessesBeingDebugged(DataRequestMonitor<IProcessDMContext[]> rm) { + rm.setData(process_cache.values().toArray(new IProcessDMContext[process_cache.size()])); + rm.done(); + } + + public void getRunningProcesses(final DataRequestMonitor<IProcessDMContext[]> rm) { + final Collection<String> list = new ArrayList<String>(); + final Set<IToken> cmds = new HashSet<IToken>(); + final IProcesses.DoneGetChildren done = new IProcesses.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception error, String[] context_ids) { + if (cmds.isEmpty()) return; + assert cmds.contains(token); + cmds.remove(token); + if (error != null) { + for (IToken t : cmds) t.cancel(); + cmds.clear(); + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + rm.done(); + } + else { + for (String id : context_ids) { + list.add(id); + cmds.add(tcf_prs_service.getChildren(id, false, this)); + } + if (cmds.isEmpty()) { + int cnt = 0; + IProcessDMContext[] data = new IProcessDMContext[list.size()]; + for (String id : list) { + assert id != null; + data[cnt] = process_cache.get(id); + if (data[cnt] == null) data[cnt] = new ProcessDMC(id, root_dmc); + cnt++; + } + rm.setData(data); + rm.done(); + } + } + } + }; + cmds.add(tcf_prs_service.getChildren(null, false, done)); + } + + @SuppressWarnings("unchecked") + public void getModelData(IDMContext dmc, final DataRequestMonitor<?> rm) { + if (dmc instanceof ProcessDMC) { + getProcessData((ProcessDMC)dmc, (DataRequestMonitor<IProcessDMData>)rm); + } + else if (dmc instanceof ThreadDMC) { + getThreadData((ThreadDMC)dmc, (DataRequestMonitor<IThreadDMData>)rm); + } + else if (dmc == service_dmc) { + ((DataRequestMonitor<TCFDSFNativeProcesses>)rm).setData(this); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getProcessData(IProcessDMContext dmc, final DataRequestMonitor<IProcessDMData> rm) { + if (dmc instanceof ProcessDMC) { + tcf_prs_service.getContext(((ProcessDMC)dmc).id, new IProcesses.DoneGetContext() { + + @SuppressWarnings("unchecked") + public void doneGetContext(IToken token, Exception error, ProcessContext context) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Cannot read processs attributes", error)); //$NON-NLS-1$ + } + else if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Invalid processs ID", error)); //$NON-NLS-1$ + } + else { + rm.setData(new ProcessData(context)); + } + rm.done(); + } + }); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getThreadData(IThreadDMContext dmc, final DataRequestMonitor<IThreadDMData> rm) { + if (dmc instanceof ThreadDMC) { + String id = ((ThreadDMC)dmc).id; + TCFDSFRunControl rc = getServicesTracker().getService(TCFDSFRunControl.class); + rm.setData(new ThreadData(rc.getContext(id))); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFProcessDMC.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFProcessDMC.java new file mode 100644 index 000000000..8dacf0692 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFProcessDMC.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import org.eclipse.dd.dsf.datamodel.AbstractDMContext; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.service.INativeProcesses.IProcessDMContext; +import org.eclipse.dd.dsf.service.IDsfService; + +public abstract class TCFDSFProcessDMC extends AbstractDMContext implements IProcessDMContext { + + TCFDSFProcessDMC(IDsfService service, IDMContext[] parents) { + super(service, parents); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFRegisters.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFRegisters.java new file mode 100644 index 000000000..1614118c3 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFRegisters.java @@ -0,0 +1,1060 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.AbstractDMContext; +import org.eclipse.dd.dsf.datamodel.AbstractDMEvent; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason; +import org.eclipse.dd.dsf.service.AbstractDsfService; +import org.eclipse.dd.dsf.service.DsfServiceEventHandler; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.tm.internal.tcf.dsf.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IRegisters.DoneGet; +import org.eclipse.tm.tcf.services.IRegisters.DoneSet; +import org.eclipse.tm.tcf.services.IRegisters.NamedValue; +import org.osgi.framework.BundleContext; + + +public class TCFDSFRegisters extends AbstractDsfService implements org.eclipse.dd.dsf.debug.service.IRegisters { + + private class ObjectDMC extends AbstractDMContext implements IFormattedDataDMContext { + + final String id; + final RegistersCache children; + final Map<String,ValueDMC> values; + + org.eclipse.tm.tcf.services.IRegisters.RegistersContext context; + boolean disposed; + + ObjectDMC(String session_id, IDMContext[] parents, String id) { + super(session_id, parents); + this.id = id; + children = new RegistersCache(channel, id, new IDMContext[]{ this }); + values = new HashMap<String,ValueDMC>(); + model.put(id, this); + } + + ObjectDMC(String session_id, IDMContext[] parents, String id, RegistersCache children) { + super(session_id, parents); + this.id = id; + this.children = children; + values = new HashMap<String,ValueDMC>(); + } + + @Override + public boolean equals(Object other) { + return super.baseEquals(other) && ((ObjectDMC)other).id.equals(id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } + + public String getName() { + return context.getName(); + } + + void dispose() { + assert !disposed; + children.dispose(); + for (ValueDMC v : values.values()) v.dispose(); + values.clear(); + model.remove(id); + disposed = true; + } + } + + private class RegisterGroupDMC extends ObjectDMC implements IRegisterGroupDMContext { + + RegisterGroupDMC(String session_id, IDMContext[] parents, String id) { + super(session_id, parents, id); + } + + /* Constructor for a fake register group - DSF requires at least one group object */ + RegisterGroupDMC(String session_id, IDMContext[] parents, final String id, RegistersCache children) { + super(session_id, parents, id, children); + context = new org.eclipse.tm.tcf.services.IRegisters.RegistersContext() { + public String[] getAvailableFormats() { + return null; + } + public int[] getBitNumbers() { + return null; + } + public String getDescription() { + return null; + } + public int getFirstBitNumber() { + return 0; + } + public String getID() { + return id; + } + public String getName() { + return null; + } + public NamedValue[] getNamedValues() { + return null; + } + public String getParentID() { + return null; + } + public Map<String, Object> getProperties() { + return null; + } + public boolean hasSideEffects() { + return false; + } + public boolean isBigEndian() { + return false; + } + public boolean isFloat() { + return false; + } + public boolean isLeftToRight() { + return false; + } + public boolean isReadOnce() { + return false; + } + public boolean isReadable() { + return false; + } + public boolean isVolatile() { + return false; + } + public boolean isWriteOnce() { + return false; + } + public boolean isWriteable() { + return false; + } + public IToken get(String format, DoneGet done) { + throw new Error(); + } + public IToken set(String format, String value, DoneSet done) { + throw new Error(); + } + }; + } + } + + private class RegisterDMC extends ObjectDMC implements IRegisterDMContext { + + RegisterDMC(String session_id, IDMContext[] parents, String id) { + super(session_id, parents, id); + } + } + + private class BitFieldDMC extends ObjectDMC implements IBitFieldDMContext { + + BitFieldDMC(String session_id, IDMContext[] parents, String id) { + super(session_id, parents, id); + } + } + + private class ValueDMC extends FormattedValueDMContext { + + final RegisterValueCache cache; + + boolean disposed; + + ValueDMC(ObjectDMC parent, String fmt) { + super(TCFDSFRegisters.this, parent, fmt); + cache = new RegisterValueCache(channel, parent.context, fmt); + } + + void dispose() { + assert !disposed; + cache.dispose(); + disposed = true; + } + } + + private class RegisterGroupData implements IRegisterGroupDMData { + + final org.eclipse.tm.tcf.services.IRegisters.RegistersContext context; + + RegisterGroupData(org.eclipse.tm.tcf.services.IRegisters.RegistersContext context) { + this.context = context; + } + + public String getDescription() { + return context.getDescription(); + } + + public String getName() { + return context.getName(); + } + } + + private class RegisterData implements IRegisterDMData { + + final org.eclipse.tm.tcf.services.IRegisters.RegistersContext context; + + RegisterData(org.eclipse.tm.tcf.services.IRegisters.RegistersContext context) { + this.context = context; + } + + public String getDescription() { + return context.getDescription(); + } + + public String getName() { + return context.getName(); + } + + public boolean hasSideEffects() { + return context.hasSideEffects(); + } + + public boolean isFloat() { + return context.isFloat(); + } + + public boolean isReadOnce() { + return context.isReadOnce(); + } + + public boolean isReadable() { + return context.isReadable(); + } + + public boolean isVolatile() { + return context.isVolatile(); + } + + public boolean isWriteOnce() { + return context.isWriteOnce(); + } + + public boolean isWriteable() { + return context.isWriteable(); + } + } + + private class BitFieldData implements IBitFieldDMData { + + final org.eclipse.tm.tcf.services.IRegisters.RegistersContext context; + + IMnemonic[] mnemonics; + IBitGroup[] bit_groups; + + BitFieldData(org.eclipse.tm.tcf.services.IRegisters.RegistersContext context) { + this.context = context; + } + + public IBitGroup[] getBitGroup() { + if (bit_groups == null) { + int[] arr = context.getBitNumbers(); + if (arr == null) { + bit_groups = new IBitGroup[0]; + } + else { + Arrays.sort(arr); + ArrayList<IBitGroup> l = new ArrayList<IBitGroup>(); + int i = 0; + while (i < arr.length) { + int j = i; + while (j + 1 < arr.length && arr[j + 1] == arr[j] + 1) j++; + final int i0 = i; + final int i1 = j; + l.add(new IBitGroup() { + public int bitCount() { + return i1 - i0 + 1; + } + public int startBit() { + return i0; + } + }); + i = j + 1; + } + bit_groups = l.toArray(new IBitGroup[l.size()]); + } + } + return bit_groups; + } + + public IMnemonic getCurrentMnemonicValue() { + // TODO getCurrentMnemonicValue() should be async + return null; + } + + public String getDescription() { + return context.getDescription(); + } + + public IMnemonic[] getMnemonics() { + if (mnemonics == null) { + NamedValue[] arr = context.getNamedValues(); + if (arr == null) { + mnemonics = new IMnemonic[0]; + } + else { + int cnt = 0; + mnemonics = new IMnemonic[arr.length]; + for (final NamedValue v : arr) { + mnemonics[cnt++] = new IMnemonic() { + public String getLongName() { + return v.getDescription(); + } + public String getShortName() { + return v.getName(); + } + }; + } + } + } + return mnemonics; + } + + public String getName() { + return context.getName(); + } + + public boolean hasSideEffects() { + return context.hasSideEffects(); + } + + public boolean isReadOnce() { + return context.isReadOnce(); + } + + public boolean isReadable() { + return context.isReadable(); + } + + public boolean isWriteOnce() { + return context.isWriteOnce(); + } + + public boolean isWriteable() { + return context.isWriteable(); + } + + public boolean isZeroBasedNumbering() { + return context.getFirstBitNumber() == 0; + } + + public boolean isZeroBitLeftMost() { + return context.isLeftToRight(); + } + } + + private class RegistersCache extends TCFDataCache<Map<String,ObjectDMC>> + implements TCFDSFExecutionDMC.DataCache { + + final String id; + final IDMContext[] parents; + + boolean disposed; + + public RegistersCache(IChannel channel, String id, IDMContext[] parents) { + super(channel); + this.id = id; + this.parents = parents; + } + + void invalidateRegContents() { + if (data == null) return; + for (ObjectDMC dmc : data.values()) { + for (ValueDMC val : dmc.values.values()) val.cache.reset(); + dmc.children.invalidateRegContents(); + } + } + + void dispose() { + assert !disposed; + if (data != null) { + for (ObjectDMC dmc : data.values()) dmc.dispose(); + } + reset(); + disposed = true; + } + + @Override + public boolean startDataRetrieval() { + assert command == null; + assert !disposed; + if (tcf_reg_service == null) { + data = null; + valid = true; + return true; + } + command = tcf_reg_service.getChildren(id, new org.eclipse.tm.tcf.services.IRegisters.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception err, String[] contexts) { + if (command != token) return; + command = null; + if (err != null) { + data = null; + error = err; + } + else { + data = new LinkedHashMap<String,ObjectDMC>(); + if (contexts.length > 0) { + // TODO DSF service design does not support lazy retrieval of context attributes (because getName() is not async) + final Set<IToken> cmds = new HashSet<IToken>(); + final IToken cb = new IToken() { + public boolean cancel() { + for (IToken x : cmds) x.cancel(); + return false; + } + }; + command = cb; + org.eclipse.tm.tcf.services.IRegisters.DoneGetContext done = new org.eclipse.tm.tcf.services.IRegisters.DoneGetContext() { + public void doneGetContext(IToken token, Exception err, + org.eclipse.tm.tcf.services.IRegisters.RegistersContext context) { + cmds.remove(token); + if (command != cb) return; + if (err != null) { + command.cancel(); + command = null; + data = null; + error = err; + valid = true; + validate(); + return; + } + String id = context.getID(); + ObjectDMC dmc = null; + if (context.getBitNumbers() != null) { + dmc = new BitFieldDMC(getSession().getId(), parents, id); + } + else if (context.isReadable() || context.isWriteable()) { + dmc = new RegisterDMC(getSession().getId(), parents, id); + } + else { + dmc = new RegisterGroupDMC(getSession().getId(), parents, id); + } + dmc.context = context; + data.put(id, dmc); + if (cmds.isEmpty()) { + command = null; + valid = true; + validate(); + } + } + }; + for (String id : contexts) { + cmds.add(tcf_reg_service.getContext(id, done)); + } + return; + } + } + valid = true; + validate(); + } + }); + return false; + } + } + + private class RegisterValueCache extends TCFDataCache<FormattedValueDMData> { + + final org.eclipse.tm.tcf.services.IRegisters.RegistersContext context; + final String fmt; + + boolean disposed; + + public RegisterValueCache(IChannel channel, + org.eclipse.tm.tcf.services.IRegisters.RegistersContext context, String fmt) { + super(channel); + this.context = context; + this.fmt = fmt; + } + + @Override + public boolean startDataRetrieval() { + assert command == null; + assert tcf_reg_service != null; + assert context != null; + assert !disposed; + command = context.get(fmt, new org.eclipse.tm.tcf.services.IRegisters.DoneGet() { + public void doneGet(IToken token, Exception err, String value) { + if (command != token) return; + command = null; + if (err != null) { + data = null; + error = err; + } + else { + data = new FormattedValueDMData(value); + } + valid = true; + validate(); + } + }); + return false; + } + + void dispose() { + assert !disposed; + reset(); + disposed = true; + } + } + + private static class RegisterGroupChangedEvent extends AbstractDMEvent<IRegisterGroupDMContext> + implements IGroupChangedDMEvent { + + public RegisterGroupChangedEvent(IRegisterGroupDMContext context) { + super(context); + } + } + + private static class RegisterChangedEvent extends AbstractDMEvent<IRegisterDMContext> + implements IRegisterChangedDMEvent { + + public RegisterChangedEvent(IRegisterDMContext context) { + super(context); + } + } + + private static class BitFieldChangedEvent extends AbstractDMEvent<IBitFieldDMContext> + implements IBitFieldChangedDMEvent { + + public BitFieldChangedEvent(IBitFieldDMContext context) { + super(context); + } + } + + private static class GroupsChangedEvent + extends AbstractDMEvent<org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext> + implements IGroupsChangedDMEvent { + + public GroupsChangedEvent(IExecutionDMContext context) { + super(context); + } + } + + private final org.eclipse.tm.tcf.services.IRegisters.RegistersListener listener = + new org.eclipse.tm.tcf.services.IRegisters.RegistersListener() { + + public void contextChanged() { + TCFDSFRunControl rc = getServicesTracker().getService(TCFDSFRunControl.class); + for (TCFDSFExecutionDMC dmc : rc.getCachedContexts()) { + RegistersCache c = (RegistersCache)dmc.registers_cache; + if (c != null) { + c.dispose(); + dmc.registers_cache = null; + getSession().dispatchEvent(new GroupsChangedEvent(dmc), getProperties()); + } + } + } + + public void registerChanged(String id) { + ObjectDMC dmc = model.get(id); + if (dmc != null) { + for (ValueDMC val : dmc.values.values()) val.cache.reset(); + dmc.children.invalidateRegContents(); + if (dmc instanceof RegisterGroupDMC) { + getSession().dispatchEvent(new RegisterGroupChangedEvent((RegisterGroupDMC)dmc), getProperties()); + } + else if (dmc instanceof RegisterDMC) { + getSession().dispatchEvent(new RegisterChangedEvent((RegisterDMC)dmc), getProperties()); + } + else if (dmc instanceof BitFieldDMC) { + getSession().dispatchEvent(new BitFieldChangedEvent((BitFieldDMC)dmc), getProperties()); + } + } + } + }; + + private final IChannel channel; + private final org.eclipse.tm.tcf.services.IRegisters tcf_reg_service; + private final Map<String,ObjectDMC> model; + + public TCFDSFRegisters(DsfSession session, IChannel channel, final RequestMonitor monitor) { + super(session); + this.channel = channel; + model = new HashMap<String,ObjectDMC>(); + tcf_reg_service = channel.getRemoteService(org.eclipse.tm.tcf.services.IRegisters.class); + if (tcf_reg_service != null) tcf_reg_service.addListener(listener); + initialize(new RequestMonitor(getExecutor(), monitor) { + @Override + protected void handleOK() { + String[] class_names = { + org.eclipse.dd.dsf.debug.service.IRegisters.class.getName(), + TCFDSFRegisters.class.getName() + }; + register(class_names, new Hashtable<String,String>()); + getSession().addServiceEventListener(TCFDSFRegisters.this, null); + monitor.done(); + } + }); + } + + @Override + public void shutdown(RequestMonitor monitor) { + getSession().removeServiceEventListener(this); + unregister(); + super.shutdown(monitor); + } + + @Override + protected BundleContext getBundleContext() { + return Activator.getBundleContext(); + } + + public void getRegisterGroupData(IRegisterGroupDMContext dmc, DataRequestMonitor<IRegisterGroupDMData> rm) { + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof RegisterGroupDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + } + else { + rm.setData(new RegisterGroupData(((RegisterGroupDMC)dmc).context)); + } + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public void getRegisterData(IRegisterDMContext dmc, DataRequestMonitor<IRegisterDMData> rm) { + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof RegisterDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + } + else { + rm.setData(new RegisterData(((RegisterDMC)dmc).context)); + } + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public void getBitFieldData(IBitFieldDMContext dmc, DataRequestMonitor<IBitFieldDMData> rm) { + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof BitFieldDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + } + else { + rm.setData(new BitFieldData(((BitFieldDMC)dmc).context)); + } + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public void getRegisterGroups(final IDMContext dmc, final DataRequestMonitor<IRegisterGroupDMContext[]> rm) { + if (rm.isCanceled()) return; + RegistersCache cache = null; + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof TCFDSFExecutionDMC) { + TCFDSFExecutionDMC exe = (TCFDSFExecutionDMC)dmc; + if (exe.registers_cache == null) exe.registers_cache = + new RegistersCache(channel, exe.getTcfContextId(), new IDMContext[]{ exe }); + cache = (RegistersCache)exe.registers_cache; + } + else if (dmc instanceof ObjectDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + cache = ((ObjectDMC)dmc).children; + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + if (cache != null) { + if (!cache.validate()) { + cache.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getRegisterGroups(dmc, rm); + } + }); + return; + } + if (cache.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + Map<String,ObjectDMC> c = cache.getData(); + int cnt = 0; + for (IDMContext x : c.values()) { + if (x instanceof RegisterGroupDMC) cnt++; + } + if (cnt == 0 && c.size() > 0 && dmc instanceof TCFDSFExecutionDMC) { + // TODO DSF requires at least one group + RegisterGroupDMC[] arr = new RegisterGroupDMC[1]; + arr[0] = new RegisterGroupDMC(getSession().getId(), cache.parents, cache.id, cache); + rm.setData(arr); + } + else { + RegisterGroupDMC[] arr = new RegisterGroupDMC[cnt]; + cnt = 0; + for (IDMContext x : c.values()) { + if (x instanceof RegisterGroupDMC) arr[cnt++] = (RegisterGroupDMC)x; + } + rm.setData(arr); + } + } + rm.done(); + } + + public void getRegisterSubGroups(IDMContext dmc, DataRequestMonitor<IRegisterGroupDMContext[]> rm) { + getRegisterGroups(dmc, rm); + } + + public void getRegisters(final IDMContext dmc, final DataRequestMonitor<IRegisterDMContext[]> rm) { + if (rm.isCanceled()) return; + RegistersCache cache = null; + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof TCFDSFExecutionDMC) { + TCFDSFExecutionDMC exe = (TCFDSFExecutionDMC)dmc; + if (exe.registers_cache == null) exe.registers_cache = + new RegistersCache(channel, exe.getTcfContextId(), new IDMContext[]{ exe }); + cache = (RegistersCache)exe.registers_cache; + } + else if (dmc instanceof ObjectDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + cache = ((ObjectDMC)dmc).children; + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + if (cache != null) { + if (!cache.validate()) { + cache.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getRegisters(dmc, rm); + } + }); + return; + } + if (cache.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + Map<String,ObjectDMC> c = cache.getData(); + int cnt = 0; + for (IDMContext x : c.values()) { + if (x instanceof RegisterDMC) cnt++; + } + RegisterDMC[] arr = new RegisterDMC[cnt]; + cnt = 0; + for (IDMContext x : c.values()) { + if (x instanceof RegisterDMC) arr[cnt++] = (RegisterDMC)x; + } + rm.setData(arr); + } + rm.done(); + } + + public void getBitFields(final IDMContext dmc, final DataRequestMonitor<IBitFieldDMContext[]> rm) { + if (rm.isCanceled()) return; + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof ObjectDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + RegistersCache cache = ((ObjectDMC)dmc).children; + if (!cache.validate()) { + cache.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getBitFields(dmc, rm); + } + }); + return; + } + if (cache.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + Map<String,ObjectDMC> c = cache.getData(); + int cnt = 0; + for (IDMContext x : c.values()) { + if (x instanceof BitFieldDMC) cnt++; + } + BitFieldDMC[] arr = new BitFieldDMC[cnt]; + cnt = 0; + for (IDMContext x : c.values()) { + if (x instanceof BitFieldDMC) arr[cnt++] = (BitFieldDMC)x; + } + rm.setData(arr); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public void writeBitField(IDMContext dmc, String val, String fmt, final RequestMonitor rm) { + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof ObjectDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + ((ObjectDMC)dmc).context.set(fmt, val, new org.eclipse.tm.tcf.services.IRegisters.DoneSet() { + public void doneSet(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + rm.done(); + } + }); + return; + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public void writeBitField(IDMContext dmc, IMnemonic mnemonic, final RequestMonitor rm) { + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof ObjectDMC) { + if (((ObjectDMC)dmc).disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + NamedValue[] arr = ((ObjectDMC)dmc).context.getNamedValues(); + if (arr != null) { + for (NamedValue nv : arr) { + if (nv.getName().equals(mnemonic.getShortName())) { + String fmt = org.eclipse.tm.tcf.services.IRegisters.FORMAT_DECIMAL; + String val = nv.getValue().toString(); + ((ObjectDMC)dmc).context.set(fmt, val, new org.eclipse.tm.tcf.services.IRegisters.DoneSet() { + public void doneSet(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + rm.done(); + } + }); + return; + } + } + } + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown mnemonic", null)); //$NON-NLS-1$ + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public void writeRegister(IDMContext dmc, String val, String fmt, RequestMonitor rm) { + writeBitField(dmc, val, fmt, rm); + } + + public void getAvailableFormats(IFormattedDataDMContext dmc, DataRequestMonitor<String[]> rm) { + if (tcf_reg_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Registers service is not available", null)); //$NON-NLS-1$ + } + else if (dmc instanceof ObjectDMC) { + rm.setData(((ObjectDMC)dmc).context.getAvailableFormats()); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public void getFormattedExpressionValue(final FormattedValueDMContext dmc, + final DataRequestMonitor<FormattedValueDMData> rm) { + if (rm.isCanceled()) return; + if (dmc instanceof ValueDMC) { + ValueDMC vmc = (ValueDMC)dmc; + if (vmc.disposed) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + if (!vmc.cache.validate()) { + vmc.cache.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getFormattedExpressionValue(dmc, rm); + } + }); + return; + } + if (vmc.cache.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", vmc.cache.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + rm.setData(vmc.cache.getData()); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + } + rm.done(); + } + + public FormattedValueDMContext getFormattedValueContext(IFormattedDataDMContext dmc, String fmt) { + if (dmc instanceof ObjectDMC) { + ObjectDMC omc = (ObjectDMC)dmc; + ValueDMC res = omc.values.get(fmt); + if (res == null) { + omc.values.put(fmt, res = new ValueDMC(omc, fmt)); + } + return res; + } + return null; + } + + @SuppressWarnings("unchecked") + public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) { + if (dmc instanceof RegisterGroupDMC) { + getRegisterGroupData((RegisterGroupDMC)dmc, (DataRequestMonitor<IRegisterGroupDMData>)rm); + } + else if (dmc instanceof RegisterDMC) { + getRegisterData((RegisterDMC)dmc, (DataRequestMonitor<IRegisterDMData>)rm); + } + else if (dmc instanceof BitFieldDMC) { + getBitFieldData((BitFieldDMC)dmc, (DataRequestMonitor<IBitFieldDMData>)rm); + } + else if (dmc instanceof FormattedValueDMContext) { + getFormattedExpressionValue((FormattedValueDMContext)dmc, (DataRequestMonitor<FormattedValueDMData>)rm); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + @DsfServiceEventHandler + public void eventDispatched(org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent e) { + if (e.getReason() != StateChangeReason.STEP) { + RegistersCache cache = (RegistersCache)((TCFDSFExecutionDMC)e.getDMContext()).registers_cache; + if (cache != null) cache.invalidateRegContents(); + } + } + + @DsfServiceEventHandler + public void eventDispatched(org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent e) { + RegistersCache cache = (RegistersCache)((TCFDSFExecutionDMC)e.getDMContext()).registers_cache; + if (cache != null) cache.invalidateRegContents(); + } + + @DsfServiceEventHandler + public void eventDispatched(org.eclipse.dd.dsf.debug.service.IRunControl.IExitedDMEvent e) { + RegistersCache cache = (RegistersCache)((TCFDSFExecutionDMC)e.getExecutionContext()).registers_cache; + if (cache != null) cache.dispose(); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFRunControl.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFRunControl.java new file mode 100644 index 000000000..0cbe78a87 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFRunControl.java @@ -0,0 +1,1023 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.AbstractDMEvent; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.datamodel.ServiceDMContext; +import org.eclipse.dd.dsf.debug.model.DsfMemoryBlockRetrieval; +import org.eclipse.dd.dsf.service.AbstractDsfService; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IMemoryBlockRetrieval; +import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension; +import org.eclipse.tm.internal.tcf.debug.model.ITCFConstants; +import org.eclipse.tm.internal.tcf.dsf.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.IRunControl; +import org.eclipse.tm.tcf.services.IRunControl.RunControlContext; +import org.osgi.framework.BundleContext; + + +public class TCFDSFRunControl extends AbstractDsfService implements org.eclipse.dd.dsf.debug.service.IRunControl { + + public static class SuspendedEvent extends AbstractDMEvent<IExecutionDMContext> implements ISuspendedDMEvent { + + private final StateChangeReason reason; + + public SuspendedEvent(IExecutionDMContext dmc, String reason) { + super(dmc); + this.reason = toStateChangeReason(reason); + } + + public StateChangeReason getReason() { + return reason; + } + } + + public static class ResumedEvent extends AbstractDMEvent<IExecutionDMContext> implements IResumedDMEvent { + + public ResumedEvent(IExecutionDMContext dmc) { + super(dmc); + } + + public StateChangeReason getReason() { + return StateChangeReason.USER_REQUEST; + } + } + + public class ContainerSuspendedEvent extends AbstractDMEvent<IExecutionDMContext> implements IContainerSuspendedDMEvent { + + private final String trigger_id; + private final StateChangeReason reason; + + public ContainerSuspendedEvent(IExecutionDMContext dmc, String trigger_id, String reason) { + super(dmc); + this.trigger_id = trigger_id; + this.reason = toStateChangeReason(reason); + } + + public IExecutionDMContext getTriggeringContext() { + return cache.get(trigger_id); + } + + public StateChangeReason getReason() { + return reason; + } + } + + public static class ContainerResumedEvent extends AbstractDMEvent<IExecutionDMContext> implements IContainerResumedDMEvent { + + public ContainerResumedEvent(IExecutionDMContext dmc) { + super(dmc); + } + + public StateChangeReason getReason() { + return StateChangeReason.USER_REQUEST; + } + } + + public static class StartedEvent extends AbstractDMEvent<IContainerDMContext> implements IStartedDMEvent { + + private final IExecutionDMContext exe; + + public StartedEvent(IContainerDMContext dmc, IExecutionDMContext exe) { + super(dmc); + this.exe = exe; + } + + public IExecutionDMContext getExecutionContext() { + return exe; + } + } + + public static class ChangedEvent extends AbstractDMEvent<IExecutionDMContext> { + + public ChangedEvent(IExecutionDMContext dmc) { + super(dmc); + } + } + + public static class ExitedEvent extends AbstractDMEvent<IContainerDMContext> implements IExitedDMEvent { + + private final IExecutionDMContext exe; + + public ExitedEvent(IContainerDMContext dmc, IExecutionDMContext exe) { + super(dmc); + this.exe = exe; + } + + public IExecutionDMContext getExecutionContext() { + return exe; + } + } + + private final org.eclipse.tm.tcf.services.IRunControl.RunControlListener run_listener = + new org.eclipse.tm.tcf.services.IRunControl.RunControlListener() { + + public void containerResumed(String[] context_ids) { + for (String id : context_ids) { + ExecutionDMC n = cache.get(id); + if (n != null) n.onContextResumed(); + } + for (String id : context_ids) { + ExecutionDMC n = cache.get(id); + if (n != null && n.context.isValid()) { + RunControlContext c = n.context.getData(); + if (c.isContainer()) { + getSession().dispatchEvent(new ContainerResumedEvent(n), getProperties()); + } + } + } + } + + public void containerSuspended(String trigger_id, String pc, + String reason, Map<String, Object> params, + String[] suspended_ids) { + if (trigger_id != null) { + ExecutionDMC n = cache.get(trigger_id); + if (n != null) n.onContextSuspended(pc, reason, params); + } + for (String id : suspended_ids) { + if (id.equals(trigger_id)) continue; + ExecutionDMC n = cache.get(id); + if (n != null) n.onContainerSuspended(reason); + } + for (String id : suspended_ids) { + ExecutionDMC n = cache.get(id); + if (n != null && n.context.isValid()) { + RunControlContext c = n.context.getData(); + if (c.isContainer()) { + getSession().dispatchEvent(new ContainerSuspendedEvent(n, trigger_id, reason), getProperties()); + } + } + } + } + + public void contextAdded(RunControlContext[] contexts) { + for (RunControlContext ctx : contexts) { + ExecutionDMC n = cache.get(ctx.getParentID()); + if (n != null) n.onContextAdded(ctx); + } + } + + public void contextChanged(RunControlContext[] contexts) { + for (RunControlContext ctx : contexts) { + ExecutionDMC n = cache.get(ctx.getID()); + if (n != null) n.onContextChanged(ctx); + } + } + + public void contextException(String id, String msg) { + ExecutionDMC n = cache.get(id); + if (n != null) n.onContextException(msg); + } + + public void contextRemoved(String[] context_ids) { + for (String id : context_ids) { + ExecutionDMC n = cache.get(id); + if (n != null) n.onContextRemoved(); + } + } + + public void contextResumed(String id) { + ExecutionDMC n = cache.get(id); + if (n != null) n.onContextResumed(); + } + + public void contextSuspended(String id, String pc, String reason, Map<String, Object> params) { + ExecutionDMC n = cache.get(id); + if (n != null) n.onContextSuspended(pc, reason, params); + } + }; + + private static class ExecutionState { + boolean is_suspended; + boolean is_running; + String suspend_pc; + String suspend_reason; + Map<String,Object> suspend_params; + } + + private class ExecutionDMC extends TCFDSFExecutionDMC { + + final String id; + final ExecutionDMC parent; + final IMemoryBlockRetrievalExtension mem_retrieval; + + boolean disposed; + int is_stepping; + int is_resuming; + + final TCFDataCache<RunControlContext> context; + final TCFDataCache<Map<String,ExecutionDMC>> children; + final TCFDataCache<ExecutionState> state; + + public ExecutionDMC(ExecutionDMC parent, final String id) { + super(TCFDSFRunControl.this, parent == null ? + new IDMContext[0] : new IDMContext[] { parent }); + this.parent = parent; + this.id = id; + DsfMemoryBlockRetrieval mr = null; + try { + mr = new DsfMemoryBlockRetrieval(ITCFConstants.ID_TCF_DEBUG_MODEL, this); + } + catch (DebugException e) { + e.printStackTrace(); + }; + mem_retrieval = mr; + context = new TCFDataCache<RunControlContext>(channel) { + @Override + public boolean startDataRetrieval() { + assert command == null; + if (id == null || tcf_run_service == null) { + data = null; + valid = true; + return true; + } + command = tcf_run_service.getContext(id, new IRunControl.DoneGetContext() { + public void doneGetContext(IToken token, Exception err, IRunControl.RunControlContext ctx) { + if (command != token) return; + command = null; + if (err != null) { + error = err; + } + else { + data = ctx; + } + valid = true; + validate(); + } + }); + return false; + } + }; + children = new TCFDataCache<Map<String,ExecutionDMC>>(channel) { + @Override + public boolean startDataRetrieval() { + assert command == null; + if (tcf_run_service == null) { + data = null; + valid = true; + return true; + } + command = tcf_run_service.getChildren(id, new IRunControl.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception err, String[] contexts) { + if (command != token) return; + command = null; + if (err != null) { + data = null; + error = err; + } + else { + if (data == null) data = new HashMap<String,ExecutionDMC>(); + data.clear(); + for (int i = 0; i < contexts.length; i++) { + String id = contexts[i]; + ExecutionDMC n = cache.get(id); + if (n == null) { + n = new ExecutionDMC(ExecutionDMC.this, id); + cache.put(n.id, n); + } + data.put(id, n); + } + } + valid = true; + validate(); + } + }); + return false; + } + }; + state = new TCFDataCache<ExecutionState>(channel) { + @Override + public boolean startDataRetrieval() { + assert command == null; + assert context.isValid(); + RunControlContext c = context.getData(); + if (c == null || !c.hasState()) { + data = null; + valid = true; + return true; + } + command = c.getState(new IRunControl.DoneGetState() { + public void doneGetState(IToken token, Exception err, boolean suspend, String pc, String reason, Map<String,Object> params) { + if (token != command) return; + command = null; + if (err != null) { + data = null; + error = err; + } + else { + data = new ExecutionState(); + data.is_running = !suspend; + data.is_suspended = suspend; + if (suspend) { + data.suspend_pc = pc; + data.suspend_reason = reason; + data.suspend_params = params; + } + } + valid = true; + validate(); + } + }); + return false; + } + }; + } + + @Override + public String toString() { + return baseToString() + ".context[" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public boolean equals(Object obj) { + if (!super.baseEquals(obj)) return false; + String obj_id = ((ExecutionDMC)obj).id; + if (obj_id == null) return id == null; + return obj_id.equals(id); + } + + @Override + public int hashCode() { + if (id == null) return 0; + return id.hashCode(); + } + + @Override + @SuppressWarnings("unchecked") + public Object getAdapter(Class cls) { + Object obj = null; + if (cls == IMemoryBlockRetrieval.class) obj = mem_retrieval; + if (cls == IMemoryBlockRetrievalExtension.class) obj = mem_retrieval; + if (obj == null) obj = super.getAdapter(cls); + return obj; + } + + @Override + public String getTcfContextId() { + return id; + } + + @Override + public void addStateWaitingRequest(IDataRequest req) { + state.addWaitingRequest(req); + } + + @Override + public TCFAddress getPC() { + ExecutionState st = state.getData(); + if (st == null) return null; + if (st.suspend_pc == null) return null; + return new TCFAddress(new BigInteger(st.suspend_pc)); + } + + @Override + public boolean validateState() { + return state.validate(); + } + + @Override + public boolean isDisposed() { + return disposed; + } + + void dispose() { + assert !disposed; + context.cancel(); + children.cancel(); + state.cancel(); + if (children.isValid()) { + Map<String,ExecutionDMC> m = children.getData(); + if (m != null) { + for (ExecutionDMC n : m.values()) n.dispose(); + } + } + cache.remove(id); + disposed = true; + } + + /*--------------------------------------------------------------------------------------*/ + /* Events */ + + void onContextAdded(IRunControl.RunControlContext c) { + String id = c.getID(); + assert !disposed; + assert cache.get(id) == null; + ExecutionDMC n = new ExecutionDMC(this, id); + n.context.reset(c); + if (children.isValid()) { + Map<String,ExecutionDMC> m = children.getData(); + if (m != null) m.put(id, n); + } + cache.put(id, n); + getSession().dispatchEvent(new StartedEvent(this, n), getProperties()); + } + + void onContextChanged(IRunControl.RunControlContext c) { + assert !disposed; + context.reset(c); + getSession().dispatchEvent(new ChangedEvent(this), getProperties()); + } + + void onContextRemoved() { + assert !disposed; + if (parent != null && parent.children.isValid()) { + Map<String,ExecutionDMC> m = parent.children.getData(); + if (m != null) m.remove(id); + } + dispose(); + getSession().dispatchEvent(new ExitedEvent(parent, this), getProperties()); + } + + void onContainerSuspended(String reason) { + assert !disposed; + if (!context.isValid()) return; + RunControlContext rc = context.getData(); + if (rc == null) return; + if (!rc.hasState()) return; + state.reset(); + getSession().dispatchEvent(new SuspendedEvent(this, reason), getProperties()); + } + + void onContextSuspended(String pc, String reason, Map<String,Object> params) { + assert !disposed; + assert !context.isValid() || context.getData().hasState(); + ExecutionState st = new ExecutionState(); + st.is_suspended = true; + st.suspend_pc = pc; + st.suspend_reason = reason; + st.suspend_params = params; + state.reset(st); + getSession().dispatchEvent(new SuspendedEvent(this, reason), getProperties()); + } + + void onContextResumed() { + assert !disposed; + assert !context.isValid() || context.getData().hasState(); + ExecutionState st = new ExecutionState(); + st.is_running = true; + state.reset(st); + getSession().dispatchEvent(new ResumedEvent(this), getProperties()); + } + + void onContextException(String msg) { + assert !disposed; + // TODO onContextException handling + } + } + + private static class ExecutionData implements IExecutionDMData { + + private final StateChangeReason reason; + + ExecutionData(StateChangeReason reason) { + this.reason = reason; + } + + public boolean isValid() { + return true; + } + + public StateChangeReason getStateChangeReason() { + return reason; + } + } + + private static StateChangeReason toStateChangeReason(String s) { + if (s == null) return StateChangeReason.UNKNOWN; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_USER_REQUEST)) return StateChangeReason.USER_REQUEST; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_STEP)) return StateChangeReason.STEP; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_BREAKPOINT)) return StateChangeReason.BREAKPOINT; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_EXCEPTION)) return StateChangeReason.EXCEPTION; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_CONTAINER)) return StateChangeReason.CONTAINER; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_WATCHPOINT)) return StateChangeReason.WATCHPOINT; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SIGNAL)) return StateChangeReason.SIGNAL; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_SHAREDLIB)) return StateChangeReason.SHAREDLIB; + if (s.equals(org.eclipse.tm.tcf.services.IRunControl.REASON_ERROR)) return StateChangeReason.ERROR; + return StateChangeReason.UNKNOWN; + } + + private final IChannel channel; + private final org.eclipse.tm.tcf.services.IRunControl tcf_run_service; + private final Map<String,ExecutionDMC> cache = new HashMap<String,ExecutionDMC>(); + private final ExecutionDMC root_dmc; + private IDMContext service_dmc; + + public TCFDSFRunControl(DsfSession session, IChannel channel, final RequestMonitor monitor) { + super(session); + this.channel = channel; + tcf_run_service = channel.getRemoteService(org.eclipse.tm.tcf.services.IRunControl.class); + if (tcf_run_service != null) tcf_run_service.addListener(run_listener); + service_dmc = new ServiceDMContext(this, "#run_control"); + root_dmc = new ExecutionDMC(null, null); + cache.put(null, root_dmc); + initialize(new RequestMonitor(getExecutor(), monitor) { + @Override + protected void handleOK() { + String[] class_names = { + org.eclipse.dd.dsf.debug.service.IRunControl.class.getName(), + TCFDSFRunControl.class.getName() + }; + register(class_names, new Hashtable<String,String>()); + monitor.done(); + } + }); + } + + @Override + public void shutdown(RequestMonitor monitor) { + if (tcf_run_service != null) tcf_run_service.removeListener(run_listener); + unregister(); + super.shutdown(monitor); + } + + @Override + protected BundleContext getBundleContext() { + return Activator.getBundleContext(); + } + + @SuppressWarnings("unchecked") + public void getModelData(IDMContext dmc, final DataRequestMonitor<?> rm) { + if (dmc instanceof ExecutionDMC) { + final ExecutionDMC ctx = (ExecutionDMC)dmc; + if (!ctx.context.validate()) { + ctx.context.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getModelData(ctx, rm); + } + }); + return; + } + if (ctx.context.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", ctx.context.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + if (ctx.context.getData() == null) { + ExecutionData dt = new ExecutionData(StateChangeReason.UNKNOWN); + ((DataRequestMonitor<IExecutionDMData>)rm).setData(dt); + rm.done(); + return; + } + if (!ctx.context.getData().hasState()) { + ExecutionData dt = new ExecutionData(StateChangeReason.UNKNOWN); + ((DataRequestMonitor<IExecutionDMData>)rm).setData(dt); + rm.done(); + return; + } + if (!ctx.state.validate()) { + ctx.state.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getModelData(ctx, rm); + } + }); + return; + } + if (ctx.state.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", ctx.state.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + if (ctx.state.getData() == null) { + ExecutionData dt = new ExecutionData(StateChangeReason.UNKNOWN); + ((DataRequestMonitor<IExecutionDMData>)rm).setData(dt); + rm.done(); + return; + } + ExecutionData dt = new ExecutionData(toStateChangeReason(ctx.state.getData().suspend_reason)); + ((DataRequestMonitor<IExecutionDMData>)rm).setData(dt); + rm.done(); + } + else if (dmc == service_dmc) { + ((DataRequestMonitor<TCFDSFRunControl>)rm).setData(this); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public IDMContext getServiceContext() { + return service_dmc; + } + + public boolean isValid() { + return true; + } + + public boolean canInstructionStep(IDMContext context) { + if (context instanceof ExecutionDMC) { + ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + return c != null && c.canResume(org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO); + } + } + return false; + } + + public boolean canResume(IDMContext context) { + if (context instanceof ExecutionDMC) { + ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + return c != null && c.canResume(org.eclipse.tm.tcf.services.IRunControl.RM_RESUME); + } + } + return false; + } + + public boolean canStep(IDMContext context) { + if (context instanceof ExecutionDMC) { + ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + if (c != null) { + if (c.canResume(org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO_LINE)) return true; + if (c.canResume(org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO)) return true; + } + } + } + return false; + } + + public boolean canSuspend(IDMContext context) { + if (context instanceof ExecutionDMC) { + ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + return c != null && c.canSuspend(); + } + } + return false; + } + + public TCFDSFExecutionDMC getContext(String id) { + return cache.get(id); + } + + public void getContainerContexts(IContainerDMContext context, final DataRequestMonitor<IExecutionDMContext[]> rm) { + getContexts(context, rm, false); + } + + public void getExecutionContexts(IContainerDMContext context, final DataRequestMonitor<IExecutionDMContext[]> rm) { + getContexts(context, rm, true); + } + + public void getContexts(IContainerDMContext context, + final DataRequestMonitor<IExecutionDMContext[]> rm, final boolean has_state) { + if (context == null) context = root_dmc; + if (context instanceof ExecutionDMC) { + final ExecutionDMC ctx = (ExecutionDMC)context; + TCFDataCache<Map<String,ExecutionDMC>> cache = ctx.children; + if (!cache.validate()) { + cache.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getContexts(ctx, rm, has_state); + } + }); + return; + } + if (cache.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + if (cache.getData() == null) { + rm.setData(new ExecutionDMC[0]); + rm.done(); + return; + } + final Set<IDataRequest> reqs = new HashSet<IDataRequest>(); + for (ExecutionDMC e : cache.getData().values()) { + if (!e.context.validate()) { + IDataRequest req = new IDataRequest() { + public void cancel() { + if (reqs.remove(this) && reqs.isEmpty()) getContexts(ctx, rm, has_state); + } + public void done() { + if (reqs.remove(this) && reqs.isEmpty()) getContexts(ctx, rm, has_state); + } + }; + reqs.add(req); + e.context.addWaitingRequest(req); + } + // TODO DSF service design does not support lazy retrieval of context state (because isSuspened() is not async) + else if (!e.state.validate()) { + IDataRequest req = new IDataRequest() { + public void cancel() { + if (reqs.remove(this) && reqs.isEmpty()) getContexts(ctx, rm, has_state); + } + public void done() { + if (reqs.remove(this) && reqs.isEmpty()) getContexts(ctx, rm, has_state); + } + }; + reqs.add(req); + e.state.addWaitingRequest(req); + } + } + if (reqs.isEmpty()) { + ArrayList<ExecutionDMC> l = new ArrayList<ExecutionDMC>(); + for (ExecutionDMC e : cache.getData().values()) { + assert e.context.isValid(); + RunControlContext c = e.context.getData(); + if (c.hasState() == has_state) l.add(e); + } + rm.setData(l.toArray(new ExecutionDMC[l.size()])); + rm.done(); + } + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public Collection<TCFDSFExecutionDMC> getCachedContexts() { + ArrayList<TCFDSFExecutionDMC> l = new ArrayList<TCFDSFExecutionDMC>(); + for (ExecutionDMC dmc : cache.values()) l.add(dmc); + return l; + } + + public void step(IDMContext context, StepType stepType, final RequestMonitor rm) { + if (context instanceof ExecutionDMC) { + final ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + if (c != null) { + int md = -1; + if (c.canResume(org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO_LINE)) { + switch (stepType) { + case STEP_OVER: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OVER_LINE; + break; + case STEP_INTO: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO_LINE; + break; + case STEP_RETURN: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OUT; + break; + } + } + else { + switch (stepType) { + case STEP_OVER: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OVER; + break; + case STEP_INTO: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO; + break; + case STEP_RETURN: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OUT; + break; + } + } + if (md < 0) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + NOT_SUPPORTED, "Invalid step type", null)); //$NON-NLS-1$ + rm.done(); + } + else { + c.resume(md, 1, new org.eclipse.tm.tcf.services.IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + ctx.is_stepping--; + rm.done(); + } + }); + ctx.is_stepping++; + } + return; + } + } + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void instructionStep(IDMContext context, StepType stepType, final RequestMonitor rm) { + if (context instanceof ExecutionDMC) { + final ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + if (c != null) { + int md = -1; + switch (stepType) { + case STEP_OVER: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OVER; + break; + case STEP_INTO: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_INTO; + break; + case STEP_RETURN: + md = org.eclipse.tm.tcf.services.IRunControl.RM_STEP_OUT; + break; + } + if (md < 0) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + NOT_SUPPORTED, "Invalid step type", null)); //$NON-NLS-1$ + rm.done(); + } + else { + c.resume(md, 1, new org.eclipse.tm.tcf.services.IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + ctx.is_stepping--; + rm.done(); + } + }); + ctx.is_stepping++; + } + return; + } + } + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public boolean isStepping(IDMContext context) { + if (context instanceof ExecutionDMC) { + ExecutionDMC x = (ExecutionDMC)context; + return x.is_stepping > 0; + } + return false; + } + + public void resume(IDMContext context, final RequestMonitor rm) { + if (context instanceof ExecutionDMC) { + final ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + if (c != null) { + c.resume(org.eclipse.tm.tcf.services.IRunControl.RM_RESUME, 1, + new org.eclipse.tm.tcf.services.IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + ctx.is_resuming--; + rm.done(); + } + }); + ctx.is_resuming++; + return; + } + } + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void suspend(IDMContext context, final RequestMonitor rm) { + if (context instanceof ExecutionDMC) { + final ExecutionDMC ctx = (ExecutionDMC)context; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + if (c != null) { + c.suspend(new org.eclipse.tm.tcf.services.IRunControl.DoneCommand() { + public void doneCommand(IToken token, Exception error) { + if (rm.isCanceled()) return; + if (error != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Command error", error)); //$NON-NLS-1$ + } + rm.done(); + } + }); + return; + } + } + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public boolean isSuspended(IDMContext context) { + if (context instanceof ExecutionDMC) { + ExecutionDMC ctx = (ExecutionDMC)context; + boolean r = false; + if (ctx.context.isValid()) { + RunControlContext c = ctx.context.getData(); + if (c != null && c.hasState()) { + if (ctx.is_resuming == 0 && ctx.is_stepping == 0 && ctx.state.isValid()) { + ExecutionState st = ctx.state.getData(); + if (st != null) r = st.is_suspended; + } + } + else if (ctx.children.isValid()) { + Map<String,ExecutionDMC> m = ctx.children.getData(); + if (m != null) { + for (ExecutionDMC e : m.values()) { + if (isSuspended(e)) r = true; + } + } + } + } + return r; + } + return false; + } + + public void getExecutionData(IExecutionDMContext dmc, DataRequestMonitor<IExecutionDMData> rm) { + if (dmc instanceof ExecutionDMC) { + ExecutionDMC ctx = (ExecutionDMC)dmc; + StateChangeReason r = StateChangeReason.UNKNOWN; + if (ctx.state.isValid()) { + ExecutionState st = ctx.state.getData(); + if (st != null && st.suspend_reason != null) { + r = toStateChangeReason(st.suspend_reason); + } + } + rm.setData(new ExecutionData(r)); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Given context: " + dmc + " is not an execution context.", null)); //$NON-NLS-1$ //$NON-NLS-2$ + } + rm.done(); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStack.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStack.java new file mode 100644 index 000000000..67f7c9461 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStack.java @@ -0,0 +1,516 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.cdt.core.IAddress; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.AbstractDMContext; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.datamodel.ServiceDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl; +import org.eclipse.dd.dsf.debug.service.IStack; +import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason; +import org.eclipse.dd.dsf.service.AbstractDsfService; +import org.eclipse.dd.dsf.service.DsfServiceEventHandler; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.tm.internal.tcf.dsf.Activator; +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.services.ILineNumbers; +import org.eclipse.tm.tcf.services.IStackTrace; +import org.eclipse.tm.tcf.services.ILineNumbers.CodeArea; +import org.osgi.framework.BundleContext; + + +public class TCFDSFStack extends AbstractDsfService implements IStack { + + private static final String TOP_FRAME = "TopFrame:"; + + private class TCFFrameDMC extends AbstractDMContext implements IFrameDMContext, Comparable<TCFFrameDMC> { + + final String id; + final TCFDSFExecutionDMC exe_dmc; + final TCFDataCache<TCFFrameData> frame_data; + + int level; + TCFFrameData prev_data; + + public TCFFrameDMC(final TCFDSFExecutionDMC exe_dmc, final String id) { + super(TCFDSFStack.this.getSession().getId(), new IDMContext[] { exe_dmc }); + this.id = id; + this.exe_dmc = exe_dmc; + frame_data = new TCFDataCache<TCFFrameData>(channel) { + + @Override + public boolean startDataRetrieval() { + assert command == null; + if (id == null || tcf_stk_service == null) { + data = null; + valid = true; + return true; + } + if (level == 0) { + assert id.startsWith(TOP_FRAME); + // Top frame is special case: most of its data is stored in CPU registers. + // Other frames are stored in memory - in thread stack area. + return getTopFrame(); + } + command = tcf_stk_service.getContext(new String[]{ id }, new IStackTrace.DoneGetContext() { + public void doneGetContext(IToken token, Exception err, IStackTrace.StackTraceContext[] context) { + if (command != token) return; + command = null; + if (err != null) { + error = err; + data = null; + } + else { + TCFAddress a = null; + Number n = context[0].getReturnAddress(); + if (n != null) a = new TCFAddress(n); + // Optimization: skip source position lookup if same address + if (prev_data != null && prev_data.address.equals(a)) { + data = prev_data; + data.context = context[0]; + data.level = level; + } + else { + data = new TCFFrameData(); + data.context = context[0]; + data.address = a; + data.level = level; + if (!getSourcePos()) return; + } + } + valid = true; + validate(); + } + }); + return false; + } + + private boolean getTopFrame() { + assert level == 0; + if (!exe_dmc.validateState()) { + exe_dmc.addStateWaitingRequest(new IDataRequest() { + public void cancel() { + reset(); + } + public void done() { + validate(); + } + }); + return false; + } + prev_data = data = new TCFFrameData(); + data.address = exe_dmc.getPC(); + data.level = level; + if (!getSourcePos()) return false; + valid = true; + return true; + } + + private boolean getSourcePos() { + if (tcf_lns_service == null) return true; + if (data.address == null) return true; + BigInteger a1 = data.address.getValue(); + BigInteger a2 = data.address.add(1).getValue(); + command = tcf_lns_service.mapToSource(exe_dmc.getTcfContextId(), a1, a2, new ILineNumbers.DoneMapToSource() { + + public void doneMapToSource(IToken token, Exception err, CodeArea[] areas) { + if (command != token) return; + command = null; + if (err != null) { + data.src_pos_error = err; + } + else if (areas != null && areas.length > 0) { + for (ILineNumbers.CodeArea area : areas) { + if (data.code_area == null || area.start_line < data.code_area.start_line) { + data.code_area = area; + } + } + prev_data = data; + } + valid = true; + validate(); + } + }); + return false; + } + }; + } + + public int getLevel() { + return level; + } + + @Override + public boolean equals(Object other) { + return super.baseEquals(other) && ((TCFFrameDMC)other).id.equals(id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public String toString() { + return baseToString() + ".frame[" + id + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + public int compareTo(TCFFrameDMC f) { + if (level < f.level) return -1; + if (level > f.level) return +1; + return 0; + } + } + + private static class TCFFrameData implements IFrameDMData { + + IStackTrace.StackTraceContext context; + IAddress address; + int level; + String function; + Throwable src_pos_error; + ILineNumbers.CodeArea code_area; + + public IAddress getAddress() { + return address; + } + + public String getFunction() { + return function; + } + + public int getLevel() { + return level; + } + + public String getFile() { + if (code_area == null) return null; + return code_area.file; + } + + public int getLine() { + if (code_area == null) return -1; + return code_area.start_line + 1; + } + + public int getColumn() { + if (code_area == null) return -1; + return code_area.start_column + 1; + } + } + + private class FramesCache extends TCFDataCache<Map<String,TCFFrameDMC>> implements TCFDSFExecutionDMC.DataCache { + + private final TCFDSFExecutionDMC dmc; + private final Map<String,TCFFrameDMC> frame_pool; + + FramesCache(IChannel channel, TCFDSFExecutionDMC dmc) { + super(channel); + this.dmc = dmc; + frame_pool = new HashMap<String,TCFFrameDMC>(); + } + + @Override + public boolean startDataRetrieval() { + assert command == null; + if (tcf_stk_service == null) { + data = null; + valid = true; + return true; + } + assert !dmc.isDisposed(); + command = tcf_stk_service.getChildren(dmc.getTcfContextId(), new IStackTrace.DoneGetChildren() { + public void doneGetChildren(IToken token, Exception err, String[] contexts) { + if (command != token) return; + command = null; + if (err != null) { + data = null; + error = err; + } + else { + data = new HashMap<String,TCFFrameDMC>(); + for (int i = 0; i < contexts.length; i++) { + String id = contexts[i]; + TCFFrameDMC n = frame_pool.get(id); + if (n == null) frame_pool.put(id, n = new TCFFrameDMC(dmc, id)); + n.level = contexts.length - i; + data.put(id, n); + } + String id = TOP_FRAME + dmc.getTcfContextId(); + TCFFrameDMC n = frame_pool.get(id); + if (n == null) frame_pool.put(id, n = new TCFFrameDMC(dmc, id)); + n.level = 0; + data.put(id, n); + } + valid = true; + validate(); + } + }); + return false; + } + + void invalidateFrames() { + reset(); + for (TCFFrameDMC dmc : frame_pool.values()) dmc.frame_data.reset(); + } + + void dispose() { + } + } + + private final IChannel channel; + private final IStackTrace tcf_stk_service; + private final ILineNumbers tcf_lns_service; + private IDMContext service_dmc; + + public TCFDSFStack(DsfSession session, IChannel channel, final RequestMonitor monitor) { + super(session); + this.channel = channel; + tcf_stk_service = channel.getRemoteService(IStackTrace.class); + tcf_lns_service = channel.getRemoteService(ILineNumbers.class); + service_dmc = new ServiceDMContext(this, "#stack_trace"); + initialize(new RequestMonitor(getExecutor(), monitor) { + @Override + protected void handleOK() { + String[] class_names = { + IStack.class.getName(), + TCFDSFStack.class.getName() + }; + register(class_names, new Hashtable<String,String>()); + getSession().addServiceEventListener(TCFDSFStack.this, null); + monitor.done(); + } + }); + } + + @Override + public void shutdown(RequestMonitor monitor) { + getSession().removeServiceEventListener(this); + unregister(); + super.shutdown(monitor); + } + + @Override + protected BundleContext getBundleContext() { + return Activator.getBundleContext(); + } + + public IDMContext getServiceContext() { + return service_dmc; + } + + public void getArguments(IDMContext dmc, DataRequestMonitor<IVariableDMContext[]> rm) { + if (dmc instanceof TCFFrameDMC) { + // TODO function arguments + rm.setData(new IVariableDMContext[0]); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getFrameData(final IFrameDMContext dmc, final DataRequestMonitor<IFrameDMData> rm) { + if (dmc instanceof TCFFrameDMC) { + final TCFFrameDMC frame_dmc = (TCFFrameDMC)dmc; + TCFDataCache<TCFFrameData> cache = frame_dmc.frame_data; + if (!cache.validate()) { + cache.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getFrameData(dmc, rm); + } + }); + return; + } + if (cache.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + rm.setData(cache.getData()); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getFrames(final IDMContext dmc, final DataRequestMonitor<IFrameDMContext[]> rm) { + if (tcf_stk_service == null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Stack trace service is not available", null)); //$NON-NLS-1$ + rm.done(); + } + else if (dmc instanceof TCFDSFExecutionDMC) { + TCFDSFExecutionDMC exe = (TCFDSFExecutionDMC)dmc; + if (exe.isDisposed()) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + if (exe.stack_frames_cache == null) exe.stack_frames_cache = new FramesCache(channel, exe); + FramesCache cache = (FramesCache)exe.stack_frames_cache; + if (!cache.validate()) { + cache.addWaitingRequest(new IDataRequest() { + public void cancel() { + rm.setStatus(new Status(IStatus.CANCEL, Activator.PLUGIN_ID, + REQUEST_FAILED, "Canceled", null)); //$NON-NLS-1$ + rm.setCanceled(true); + rm.done(); + } + public void done() { + getFrames(dmc, rm); + } + }); + return; + } + if (cache.getError() != null) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + REQUEST_FAILED, "Data error", cache.getError())); //$NON-NLS-1$ + rm.done(); + return; + } + Map<String,TCFFrameDMC> c = cache.getData(); + TCFFrameDMC[] arr = c.values().toArray(new TCFFrameDMC[c.size()]); + Arrays.sort(arr); + rm.setData(arr); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getLocals(IDMContext dmc, DataRequestMonitor<IVariableDMContext[]> rm) { + if (dmc instanceof TCFFrameDMC) { + // TODO function local variables + rm.setData(new IVariableDMContext[0]); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getStackDepth(DataRequestMonitor<Integer> rm) { + // TODO don't know what getStackDepth() is supposed to return + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + + public void getStackDepth(int maxDepth, DataRequestMonitor<Integer> rm) { + // TODO don't know what getStackDepth() is supposed to return + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + + public void getTopFrame(IDMContext dmc, DataRequestMonitor<IFrameDMContext> rm) { + if (dmc instanceof TCFDSFExecutionDMC) { + TCFDSFExecutionDMC exe = (TCFDSFExecutionDMC)dmc; + if (exe.isDisposed()) { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Disposed DMC", null)); //$NON-NLS-1$ + rm.done(); + return; + } + if (exe.stack_frames_cache == null) exe.stack_frames_cache = new FramesCache(channel, exe); + FramesCache cache = (FramesCache)exe.stack_frames_cache; + String id = TOP_FRAME + exe.getTcfContextId(); + TCFFrameDMC n = cache.frame_pool.get(id); + if (n == null) cache.frame_pool.put(id, n = new TCFFrameDMC(exe, id)); + n.level = 0; + rm.setData(n); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + public void getVariableData(IVariableDMContext variableDmc, DataRequestMonitor<IVariableDMData> rm) { + // TODO model data for local variables + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + + public boolean isStackAvailable(IDMContext dmc) { + return tcf_stk_service != null && dmc instanceof TCFDSFExecutionDMC; + } + + @SuppressWarnings("unchecked") + public void getModelData(IDMContext dmc, DataRequestMonitor<?> rm) { + if (dmc instanceof IFrameDMContext) { + getFrameData((IFrameDMContext)dmc, (DataRequestMonitor<IFrameDMData>)rm); + } + else if (dmc == service_dmc) { + ((DataRequestMonitor<TCFDSFStack>)rm).setData(this); + rm.done(); + } + else { + rm.setStatus(new Status(IStatus.ERROR, Activator.PLUGIN_ID, + INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ + rm.done(); + } + } + + @DsfServiceEventHandler + public void eventDispatched(IRunControl.IResumedDMEvent e) { + if (e.getReason() != StateChangeReason.STEP) { + FramesCache cache = (FramesCache)((TCFDSFExecutionDMC)e.getDMContext()).stack_frames_cache; + if (cache != null) cache.invalidateFrames(); + } + } + + @DsfServiceEventHandler + public void eventDispatched(IRunControl.ISuspendedDMEvent e) { + FramesCache cache = (FramesCache)((TCFDSFExecutionDMC)e.getDMContext()).stack_frames_cache; + if (cache != null) cache.invalidateFrames(); + } + + @DsfServiceEventHandler + public void eventDispatched(IRunControl.IExitedDMEvent e) { + FramesCache cache = (FramesCache)((TCFDSFExecutionDMC)e.getExecutionContext()).stack_frames_cache; + if (cache != null) cache.dispose(); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStepQueueManager.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStepQueueManager.java new file mode 100644 index 000000000..dd5e2042b --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFStepQueueManager.java @@ -0,0 +1,233 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.dd.dsf.concurrent.DsfRunnable; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.DMContexts; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl; +import org.eclipse.dd.dsf.debug.service.IStepQueueManager; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent; +import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason; +import org.eclipse.dd.dsf.debug.service.IRunControl.StepType; +import org.eclipse.dd.dsf.service.AbstractDsfService; +import org.eclipse.dd.dsf.service.DsfServiceEventHandler; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.tm.internal.tcf.dsf.Activator; +import org.osgi.framework.BundleContext; + + +public class TCFDSFStepQueueManager extends AbstractDsfService +implements IStepQueueManager{ + + private static class StepRequest { + StepType fStepType; + boolean fIsInstructionStep; + StepRequest(StepType type, boolean instruction) { + fStepType = type; + fIsInstructionStep = instruction; + } + } + + private IRunControl fRunControl; + private int fQueueDepth = 3; + private Map<IExecutionDMContext,List<StepRequest>> fStepQueues = new HashMap<IExecutionDMContext,List<StepRequest>>(); + private Map<IExecutionDMContext,Boolean> fTimedOutFlags = new HashMap<IExecutionDMContext,Boolean>(); + private Map<IExecutionDMContext,ScheduledFuture<?>> fTimedOutFutures = new HashMap<IExecutionDMContext,ScheduledFuture<?>>(); + + public TCFDSFStepQueueManager(DsfSession session) { + super(session); + } + + /////////////////////////////////////////////////////////////////////////// + // IDsfService + @Override + public void initialize(final RequestMonitor requestMonitor) { + super.initialize( + new RequestMonitor(getExecutor(), requestMonitor) { + @Override + protected void handleOK() { + doInitialize(requestMonitor); + }}); + } + + private void doInitialize(final RequestMonitor requestMonitor) { + fRunControl = getServicesTracker().getService(IRunControl.class); + + getSession().addServiceEventListener(this, null); + register(new String[]{IStepQueueManager.class.getName()}, new Hashtable<String,String>()); + requestMonitor.done(); + } + + @Override + public void shutdown(final RequestMonitor requestMonitor) { + unregister(); + getSession().removeServiceEventListener(this); + super.shutdown(requestMonitor); + } + + /////////////////////////////////////////////////////////////////////////// + // AbstractService + @Override + protected BundleContext getBundleContext() { + return Activator.getBundleContext(); + } + + /////////////////////////////////////////////////////////////////////////// + // IStepQueueManager + public boolean canEnqueueStep(IDMContext ctx) { + IExecutionDMContext execCtx = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class); + return execCtx != null && + ( (fRunControl.isSuspended(execCtx) && fRunControl.canStep(execCtx)) || + (fRunControl.isStepping(execCtx) && !isSteppingTimedOut(execCtx)) ); + } + + // IStepQueueManager + public boolean canEnqueueInstructionStep(IDMContext ctx) { + IExecutionDMContext execCtx = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class); + return execCtx != null && + ( (fRunControl.isSuspended(execCtx) && fRunControl.canInstructionStep(execCtx)) || + (fRunControl.isStepping(execCtx) && !isSteppingTimedOut(execCtx)) ); + } + + public int getPendingStepCount(IDMContext execCtx) { + List<StepRequest> stepQueue = fStepQueues.get(execCtx); + if (stepQueue == null) return 0; + return stepQueue.size(); + } + + public void enqueueStep(IDMContext ctx, StepType stepType) { + IExecutionDMContext execCtx = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class); + if (execCtx != null) { + if (fRunControl.canStep(execCtx)) { + fRunControl.step(execCtx, stepType, new RequestMonitor(getExecutor(), null)); + } else if (canEnqueueStep(execCtx)) { + List<StepRequest> stepQueue = fStepQueues.get(execCtx); + if (stepQueue == null) { + stepQueue = new LinkedList<StepRequest>(); + fStepQueues.put(execCtx, stepQueue); + } + if (stepQueue.size() < fQueueDepth) { + stepQueue.add(new StepRequest(stepType, false)); + } + } + } + } + + public void enqueueInstructionStep(IDMContext ctx, StepType stepType) { + IExecutionDMContext execCtx = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class); + if (execCtx != null) { + if (fRunControl.canInstructionStep(execCtx)) { + fRunControl.instructionStep(execCtx, stepType, new RequestMonitor(getExecutor(), null)); + } + else if (canEnqueueInstructionStep(execCtx)) { + List<StepRequest> stepQueue = fStepQueues.get(execCtx); + if (stepQueue == null) { + stepQueue = new LinkedList<StepRequest>(); + fStepQueues.put(execCtx, stepQueue); + } + if (stepQueue.size() < fQueueDepth) { + stepQueue.add(new StepRequest(stepType, true)); + } + } + } + } + + public boolean isSteppingTimedOut(IDMContext context) { + IExecutionDMContext execCtx = DMContexts.getAncestorOfType(context, IExecutionDMContext.class); + if (execCtx != null) { + return fTimedOutFlags.containsKey(execCtx) ? fTimedOutFlags.get(execCtx) : false; + } + return false; + } + + + public int getStepQueueDepth() { return fQueueDepth; } + public void setStepQueueDepth(int depth) { fQueueDepth = depth; } + + /////////////////////////////////////////////////////////////////////////// + + @DsfServiceEventHandler + public void eventDispatched(ISuspendedDMEvent e) { + // Take care of the stepping time out + fTimedOutFlags.remove(e.getDMContext()); + ScheduledFuture<?> future = fTimedOutFutures.remove(e.getDMContext()); + if (future != null) future.cancel(false); + + // Check if there's a step pending, if so execute it + if (fStepQueues.containsKey(e.getDMContext())) { + List<StepRequest> queue = fStepQueues.get(e.getDMContext()); + StepRequest request = queue.remove(queue.size() - 1); + if (queue.isEmpty()) fStepQueues.remove(e.getDMContext()); + if (request.fIsInstructionStep) { + if (fRunControl.canInstructionStep(e.getDMContext())) { + fRunControl.instructionStep( + e.getDMContext(), request.fStepType, new RequestMonitor(getExecutor(), null)); + } else { + // For whatever reason we can't step anymore, so clear out + // the step queue. + fStepQueues.remove(e.getDMContext()); + } + } else { + if (fRunControl.canStep(e.getDMContext())) { + fRunControl.step(e.getDMContext(), request.fStepType,new RequestMonitor(getExecutor(), null)); + } else { + // For whatever reason we can't step anymore, so clear out + // the step queue. + fStepQueues.remove(e.getDMContext()); + } + } + } + } + + @DsfServiceEventHandler + public void eventDispatched(final IResumedDMEvent e) { + if (e.getReason().equals(StateChangeReason.STEP)) { + fTimedOutFlags.put(e.getDMContext(), Boolean.FALSE); + // We shouldn't have a stepping timeout running unless we get two + // stepping events in a row without a suspended, which would be a + // protocol error. + assert !fTimedOutFutures.containsKey(e.getDMContext()); + fTimedOutFutures.put( + e.getDMContext(), + getExecutor().schedule( + new DsfRunnable() { public void run() { + fTimedOutFutures.remove(e.getDMContext()); + + // Issue the stepping time-out event. + getSession().dispatchEvent( + new ISteppingTimedOutEvent() { + public IExecutionDMContext getDMContext() { return e.getDMContext(); } + }, + getProperties()); + }}, + STEPPING_TIMEOUT, TimeUnit.MILLISECONDS) + ); + + } + } + + @DsfServiceEventHandler + public void eventDispatched(ISteppingTimedOutEvent e) { + fTimedOutFlags.put(e.getDMContext(), Boolean.TRUE); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFThreadDMC.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFThreadDMC.java new file mode 100644 index 000000000..eaf308a9b --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDSFThreadDMC.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import org.eclipse.dd.dsf.datamodel.AbstractDMContext; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.debug.service.INativeProcesses.IThreadDMContext; +import org.eclipse.dd.dsf.service.IDsfService; + +public abstract class TCFDSFThreadDMC extends AbstractDMContext implements IThreadDMContext { + + public TCFDSFThreadDMC(IDsfService service, IDMContext[] parents) { + super(service, parents); + } +} diff --git a/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDataCache.java b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDataCache.java new file mode 100644 index 000000000..e95bb43d4 --- /dev/null +++ b/plugins/org.eclipse.tm.tcf.dsf/src/org/eclipse/tm/internal/tcf/dsf/services/TCFDataCache.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.tm.internal.tcf.dsf.services; + +import java.util.ArrayList; +import java.util.Collection; + +import org.eclipse.tm.tcf.protocol.IChannel; +import org.eclipse.tm.tcf.protocol.IToken; +import org.eclipse.tm.tcf.protocol.Protocol; + + +public abstract class TCFDataCache<V> { + + protected Throwable error; + protected IToken command; + protected boolean valid; + protected V data; + + protected final IChannel channel; + protected final Collection<IDataRequest> waiting_list = new ArrayList<IDataRequest>(); + + public TCFDataCache(IChannel channel) { + assert channel != null; + this.channel = channel; + } + + public void cancel() { + // Cancel current data retrieval command + if (command != null) { + command.cancel(); + command = null; + } + // Cancel waiting data requests + if (!waiting_list.isEmpty()) { + IDataRequest[] arr = waiting_list.toArray(new IDataRequest[waiting_list.size()]); + waiting_list.clear(); + for (IDataRequest r : arr) r.cancel(); + } + } + + public boolean validate() { + assert Protocol.isDispatchThread(); + if (channel.getState() != IChannel.STATE_OPEN) { + error = null; + command = null; + data = null; + valid = true; + return true; + } + if (command != null) { + return false; + } + if (!valid && !startDataRetrieval()) return false; + assert command == null; + if (!waiting_list.isEmpty()) { + IDataRequest[] arr = waiting_list.toArray(new IDataRequest[waiting_list.size()]); + waiting_list.clear(); + for (IDataRequest r : arr) r.done(); + } + return true; + } + + public void addWaitingRequest(IDataRequest req) { + assert !valid; + waiting_list.add(req); + } + + public void reset(V data) { + cancel(); + this.data = data; + error = null; + valid = true; + } + + public void reset() { + cancel(); + error = null; + data = null; + valid = false; + } + + public boolean isValid() { + return valid; + } + + public Throwable getError() { + assert valid; + return error; + } + + public V getData() { + assert valid; + return data; + } + + public abstract boolean startDataRetrieval(); +} |