diff --git a/lib/galaxy/web/base/controller.py b/lib/galaxy/web/base/controller.py index 006cec81a98..8548edeb766 100644 --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -540,18 +540,19 @@ class UsesHistoryDatasetAssociationMixin: def get_hda_dict( self, trans, hda ): """Return full details of this HDA in dictionary form. """ + #precondition: the user's access to this hda has already been checked + #TODO:?? postcondition: all ids are encoded (is this really what we want at this level?) hda_dict = hda.get_api_value( view='element' ) - history = hda.history hda_dict[ 'api_type' ] = "file" # Add additional attributes that depend on trans can hence must be added here rather than at the model level. - can_access_hda = trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ) - can_access_hda = ( trans.user_is_admin() or can_access_hda ) - hda_dict[ 'accessible' ] = can_access_hda + + #NOTE: access is an expensive operation - removing it and adding the precondition of access is already checked + hda_dict[ 'accessible' ] = True # ---- return here if deleted AND purged OR can't access purged = ( hda.purged or hda.dataset.purged ) - if ( hda.deleted and purged ) or not can_access_hda: + if ( hda.deleted and purged ): #TODO: get_api_value should really go AFTER this - only summary data return trans.security.encode_dict_ids( hda_dict ) @@ -559,7 +560,7 @@ class UsesHistoryDatasetAssociationMixin: hda_dict[ 'file_name' ] = hda.file_name hda_dict[ 'download_url' ] = url_for( 'history_contents_display', - history_id = trans.security.encode_id( history.id ), + history_id = trans.security.encode_id( hda.history.id ), history_content_id = trans.security.encode_id( hda.id ) ) # indeces, assoc. metadata files, etc. @@ -592,6 +593,72 @@ class UsesHistoryDatasetAssociationMixin: return trans.security.encode_dict_ids( hda_dict ) + def profile_get_hda_dict( self, trans, hda ): + """Profiles returning full details of this HDA in dictionary form. + """ + from galaxy.util.debugging import SimpleProfiler + profiler = SimpleProfiler() + profiler.start() + + hda_dict = hda.get_api_value( view='element' ) + profiler.report( '\t\t get_api_value' ) + history = hda.history + hda_dict[ 'api_type' ] = "file" + + # Add additional attributes that depend on trans can hence must be added here rather than at the model level. + can_access_hda = trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), hda.dataset ) + can_access_hda = ( trans.user_is_admin() or can_access_hda ) + hda_dict[ 'accessible' ] = can_access_hda + profiler.report( '\t\t accessible' ) + + # ---- return here if deleted AND purged OR can't access + purged = ( hda.purged or hda.dataset.purged ) + if ( hda.deleted and purged ) or not can_access_hda: + #TODO: get_api_value should really go AFTER this - only summary data + return ( profiler, trans.security.encode_dict_ids( hda_dict ) ) + + if trans.user_is_admin() or trans.app.config.expose_dataset_path: + hda_dict[ 'file_name' ] = hda.file_name + profiler.report( '\t\t file_name' ) + + hda_dict[ 'download_url' ] = url_for( 'history_contents_display', + history_id = trans.security.encode_id( history.id ), + history_content_id = trans.security.encode_id( hda.id ) ) + profiler.report( '\t\t download_url' ) + + # indeces, assoc. metadata files, etc. + meta_files = [] + for meta_type in hda.metadata.spec.keys(): + if isinstance( hda.metadata.spec[ meta_type ].param, FileParameter ): + meta_files.append( dict( file_type=meta_type ) ) + if meta_files: + hda_dict[ 'meta_files' ] = meta_files + profiler.report( '\t\t meta_files' ) + + # currently, the viz reg is optional - handle on/off + if trans.app.visualizations_registry: + hda_dict[ 'visualizations' ] = trans.app.visualizations_registry.get_visualizations( trans, hda ) + else: + hda_dict[ 'visualizations' ] = hda.get_visualizations() + profiler.report( '\t\t visualizations' ) + #TODO: it may also be wiser to remove from here and add as API call that loads the visualizations + # when the visualizations button is clicked (instead of preloading/pre-checking) + + # ---- return here if deleted + if hda.deleted and not purged: + return ( profiler, trans.security.encode_dict_ids( hda_dict ) ) + + # if a tool declares 'force_history_refresh' in its xml, when the hda -> ready, reload the history panel + # expensive + if( ( hda.state in [ 'running', 'queued' ] ) + and ( hda.creating_job and hda.creating_job.tool_id ) ): + tool_used = trans.app.toolbox.get_tool( hda.creating_job.tool_id ) + if tool_used and tool_used.force_history_refresh: + hda_dict[ 'force_history_refresh' ] = True + profiler.report( '\t\t force_history_refresh' ) + + return ( profiler, trans.security.encode_dict_ids( hda_dict ) ) + def get_hda_dict_with_error( self, trans, hda, error_msg='' ): return trans.security.encode_dict_ids({ 'id' : hda.id, diff --git a/lib/galaxy/webapps/galaxy/api/history_contents.py b/lib/galaxy/webapps/galaxy/api/history_contents.py index 1e90dd300b0..d2190e4b61b 100644 --- a/lib/galaxy/webapps/galaxy/api/history_contents.py +++ b/lib/galaxy/webapps/galaxy/api/history_contents.py @@ -54,7 +54,6 @@ class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociatio hda_dict = self.get_hda_dict( trans, hda ) hda_dict[ 'display_types' ] = self.get_old_display_applications( trans, hda ) hda_dict[ 'display_apps' ] = self.get_display_apps( trans, hda ) - #rval.append( self.get_hda_dict( trans, hda ) ) rval.append( hda_dict ) except Exception, exc: @@ -115,6 +114,7 @@ class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociatio check_ownership=False, check_accessible=True ) else: + #TODO: do we really need the history? history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True, deleted=False ) hda = self.get_history_dataset_association( trans, history, id, diff --git a/lib/galaxy/webapps/galaxy/controllers/root.py b/lib/galaxy/webapps/galaxy/controllers/root.py index 4c64e7a199f..0fc1275457d 100644 --- a/lib/galaxy/webapps/galaxy/controllers/root.py +++ b/lib/galaxy/webapps/galaxy/controllers/root.py @@ -212,6 +212,7 @@ class RootController( BaseUIController, UsesHistoryMixin, UsesHistoryDatasetAsso history_dictionary = {} hda_dictionaries = [] + import pprint try: history = trans.get_history( create=True ) profiler.report( 'trans.get_history' ) @@ -221,8 +222,10 @@ class RootController( BaseUIController, UsesHistoryMixin, UsesHistoryDatasetAsso for hda in hdas: try: - hda_dictionaries.append( self.get_hda_dict( trans, hda ) ) + ( hda_profiler, hda_dict ) = self.profile_get_hda_dict( trans, hda ) + profiler.reports.extend( hda_profiler.get_reports() ) profiler.report( '\t hda -> dictionary (%s)' %( hda.name ) ) + hda_dictionaries.append( hda_dict ) except Exception, exc: # don't fail entire list if hda err's, record and move on