Improve the debugger's default page layout, and prevent attempts to continue debugging after the user has stopped. Fixes #2512, Fixes #2511

This commit is contained in:
Murtuza Zabuawala
2017-07-03 15:14:45 +01:00
committed by Dave Page
parent 1977a5fcda
commit 2d5e55964a
4 changed files with 93 additions and 48 deletions

View File

@@ -524,7 +524,7 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
'newBrowserTab': new_browser_tab}) 'newBrowserTab': new_browser_tab})
@blueprint.route('/close/<int:trans_id>', methods=["GET"]) @blueprint.route('/close/<int:trans_id>', methods=["DELETE"])
def close(trans_id): def close(trans_id):
""" """
close(trans_id) close(trans_id)
@@ -849,10 +849,16 @@ def execute_debugger_query(trans_id, query_type):
template_path = 'debugger/sql/v2' template_path = 'debugger/sql/v2'
if conn.connected(): if conn.connected():
sql = render_template("/".join([template_path, query_type + ".sql"]), session_id=obj['session_id']) sql = render_template(
# As the query type is continue or step_into or step_over then we may get result after some time so poll the "/".join([template_path, query_type + ".sql"]),
# result. We need to update the frame id variable when user move the next step for debugging. session_id=obj['session_id']
if query_type == 'continue' or query_type == 'step_into' or query_type == 'step_over': )
# As the query type is continue or step_into or step_over then we
# may get result after some time so poll the result.
# We need to update the frame id variable when user move the next
# step for debugging.
if query_type == 'continue' or query_type == 'step_into' or \
query_type == 'step_over':
# We should set the frame_id to 0 when execution starts. # We should set the frame_id to 0 when execution starts.
if obj['frame_id'] != 0: if obj['frame_id'] != 0:
session_obj = debugger_data[str(trans_id)] session_obj = debugger_data[str(trans_id)]
@@ -860,29 +866,30 @@ def execute_debugger_query(trans_id, query_type):
update_session_debugger_transaction(trans_id, session_obj) update_session_debugger_transaction(trans_id, session_obj)
status, result = conn.execute_async(sql) status, result = conn.execute_async(sql)
return make_json_response(data={'status': status, 'result': result}) return make_json_response(
data={'status': status, 'result': result}
)
elif query_type == 'abort_target': elif query_type == 'abort_target':
status, result = conn.execute_dict(sql) status, result = conn.execute_dict(sql)
manager.release(did=obj['database_id'], conn_id=obj['conn_id'])
# Delete the existing debugger data in session variable
del session['debuggerData'][str(trans_id)]
del session['functionData'][str(trans_id)]
if not status: if not status:
return internal_server_error(errormsg=result) return internal_server_error(errormsg=result)
else: else:
return make_json_response(info=gettext('Target Aborted.'), data={'status': status, 'result': result}) return make_json_response(
info=gettext('Debugging aborted successfully.'),
data={'status': 'Success', 'result': result}
)
else: else:
status, result = conn.execute_dict(sql) status, result = conn.execute_dict(sql)
if not status: if not status:
return internal_server_error(errormsg=result) return internal_server_error(errormsg=result)
else: else:
status = False result = gettext('Not connected to server or connection '
result = gettext('Not connected to server or connection with the server has been closed.') 'with the server has been closed.')
return internal_server_error(errormsg=result)
return make_json_response(data={'status': 'Success', 'result': result['rows']}) return make_json_response(
data={'status': 'Success', 'result': result['rows']}
)
@blueprint.route('/messages/<int:trans_id>/', methods=["GET"]) @blueprint.route('/messages/<int:trans_id>/', methods=["GET"])
@@ -915,9 +922,12 @@ def messages(trans_id):
status, result = conn.poll() status, result = conn.poll()
notify = conn.messages() notify = conn.messages()
if notify: if notify:
# In notice message we need to find "PLDBGBREAK" string to find the port number to attach. # In notice message we need to find "PLDBGBREAK" string to find the
# Notice message returned by the server is "NOTICE: PLDBGBREAK:7". # port number to attach.
# From the above message we need to find out port number as "7" so below logic will find 7 as port number # Notice message returned by the server is
# "NOTICE: PLDBGBREAK:7".
# From the above message we need to find out port number
# as "7" so below logic will find 7 as port number
# and attach listened to that port number # and attach listened to that port number
offset = notify[0].find('PLDBGBREAK') offset = notify[0].find('PLDBGBREAK')
str_len = len('PLDBGBREAK') str_len = len('PLDBGBREAK')
@@ -935,11 +945,18 @@ def messages(trans_id):
status = 'Busy' status = 'Busy'
else: else:
status = 'Busy' status = 'Busy'
else:
status = 'NotConnected'
result = gettext('Not connected to server or connection with the server has been closed.')
return make_json_response(data={'status': status, 'result': port_number}) return make_json_response(
data={'status': status, 'result': port_number}
)
else:
result = gettext(
'Not connected to server or connection with the '
'server has been closed.'
)
return internal_server_error(errormsg=str(result))
@blueprint.route('/start_execution/<int:trans_id>/<int:port_num>', methods=['GET']) @blueprint.route('/start_execution/<int:trans_id>/<int:port_num>', methods=['GET'])
@@ -1422,7 +1439,10 @@ def poll_end_execution_result(trans_id):
if str(trans_id) not in debugger_data: if str(trans_id) not in debugger_data:
return make_json_response( return make_json_response(
data={'status': 'NotConnected', data={'status': 'NotConnected',
'result': gettext('Not connected to server or connection with the server has been closed.')} 'result': gettext(
'Not connected to server or connection with the '
'server has been closed.')
}
) )
obj = debugger_data[str(trans_id)] obj = debugger_data[str(trans_id)]
@@ -1447,18 +1467,23 @@ def poll_end_execution_result(trans_id):
else: else:
statusmsg = additional_msgs statusmsg = additional_msgs
return make_json_response(success=1, info=gettext("Execution Completed."), return make_json_response(
data={'status': status, 'status_message': statusmsg}) success=1, info=gettext("Execution Completed."),
data={'status': status, 'status_message': statusmsg}
)
if result: if result:
if 'ERROR' in result: if 'ERROR' in result:
status = 'ERROR' status = 'ERROR'
return make_json_response(info=gettext("Execution completed with error"), return make_json_response(
data={'status': status, 'status_message': result}) info=gettext("Execution completed with error"),
data={'status': status, 'status_message': result}
)
else: else:
status = 'Success' status = 'Success'
additional_msgs = conn.messages() additional_msgs = conn.messages()
if len(additional_msgs) > 0: if len(additional_msgs) > 0:
additional_msgs = [msg.strip("\n") for msg in additional_msgs] additional_msgs = [msg.strip("\n")
for msg in additional_msgs]
additional_msgs = "\n".join(additional_msgs) additional_msgs = "\n".join(additional_msgs)
if statusmsg: if statusmsg:
statusmsg = additional_msgs + "\n" + statusmsg statusmsg = additional_msgs + "\n" + statusmsg
@@ -1467,9 +1492,11 @@ def poll_end_execution_result(trans_id):
columns, result = convert_data_to_dict(conn, result) columns, result = convert_data_to_dict(conn, result)
return make_json_response(success=1, info=gettext("Execution Completed."), return make_json_response(
data={'status': status, 'result': result, success=1, info=gettext("Execution Completed."),
'col_info': columns, 'status_message': statusmsg}) data={'status': status, 'result': result,
'col_info': columns, 'status_message': statusmsg}
)
else: else:
status = 'Busy' status = 'Busy'
additional_msgs = conn.messages() additional_msgs = conn.messages()
@@ -1485,7 +1512,8 @@ def poll_end_execution_result(trans_id):
}) })
else: else:
status = 'NotConnected' status = 'NotConnected'
result = gettext('Not connected to server or connection with the server has been closed.') result = gettext('Not connected to server or connection with the '
'server has been closed.')
return make_json_response(data={'status': status, 'result': result}) return make_json_response(data={'status': status, 'result': result})

View File

@@ -11,7 +11,7 @@ try {
window.onbeforeunload = function(ev) { window.onbeforeunload = function(ev) {
$.ajax({ $.ajax({
url: "{{ url_for('debugger.index') }}close/{{ uniqueId }}", url: "{{ url_for('debugger.index') }}close/{{ uniqueId }}",
method: 'GET' method: 'DELETE'
}); });
}; };
}, },

View File

@@ -269,7 +269,7 @@ define([
var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId;
$.ajax({ $.ajax({
url: closeUrl, url: closeUrl,
method: 'GET' method: 'DELETE'
}); });
}); });
} }
@@ -366,7 +366,7 @@ define([
var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId; var closeUrl = "{{ url_for('debugger.index') }}" + "close/" + res.data.debuggerTransId;
$.ajax({ $.ajax({
url: closeUrl, url: closeUrl,
method: 'GET' method: 'DELETE'
}); });
}); });
} }

View File

@@ -543,7 +543,10 @@ define([
//Set the alertify message to inform the user that execution is completed with error. //Set the alertify message to inform the user that execution is completed with error.
var alertifyWrapper = new AlertifyWrapper(); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.error(res.info, 3);
if(!pgTools.DirectDebug.is_user_aborted_debugging) {
alertifyWrapper.error(res.info, 3);
}
// Update the message tab of the debugger // Update the message tab of the debugger
if (res.data.status_message) { if (res.data.status_message) {
@@ -555,14 +558,21 @@ define([
// remove progress cursor // remove progress cursor
$('.debugger-container').removeClass('show_progress'); $('.debugger-container').removeClass('show_progress');
// Execution completed so disable the buttons other than "Continue/Start" button because user can still // Execution completed so disable the buttons other than
// start the same execution again. // "Continue/Start" button because user can still start the
// same execution again.
self.enable('stop', false); self.enable('stop', false);
self.enable('step_over', false); self.enable('step_over', false);
self.enable('step_into', false); self.enable('step_into', false);
self.enable('toggle_breakpoint', false); self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false); self.enable('clear_all_breakpoints', false);
self.enable('continue', true); // If debugging is stopped by user then do not enable
// continue/restart button
if(!pgTools.DirectDebug.is_user_aborted_debugging)
{
self.enable('continue', true);
pgTools.DirectDebug.is_user_aborted_debugging = false;
}
// Stop further pooling // Stop further pooling
pgTools.DirectDebug.is_polling_required = false; pgTools.DirectDebug.is_polling_required = false;
@@ -600,6 +610,7 @@ define([
var restart_dbg = res.data.restart_debug ? 1 : 0; var restart_dbg = res.data.restart_debug ? 1 : 0;
// Start pooling again // Start pooling again
pgTools.DirectDebug.polling_timeout_idle = false;
pgTools.DirectDebug.is_polling_required = true; pgTools.DirectDebug.is_polling_required = true;
self.poll_end_execution_result(trans_id); self.poll_end_execution_result(trans_id);
self.poll_result(trans_id); self.poll_result(trans_id);
@@ -768,7 +779,7 @@ define([
self.enable('step_into', false); self.enable('step_into', false);
self.enable('toggle_breakpoint', false); self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false); self.enable('clear_all_breakpoints', false);
self.enable('continue', true); self.enable('continue', false);
// Make ajax call to listen the database message // Make ajax call to listen the database message
var baseUrl = "{{ url_for('debugger.index') }}" + "execute_query/" + trans_id + "/" + "abort_target"; var baseUrl = "{{ url_for('debugger.index') }}" + "execute_query/" + trans_id + "/" + "abort_target";
@@ -781,14 +792,19 @@ define([
// Call function to create and update local variables .... // Call function to create and update local variables ....
pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background'); pgTools.DirectDebug.editor.removeLineClass(self.active_line_no, 'wrap', 'CodeMirror-activeline-background');
pgTools.DirectDebug.direct_execution_completed = true; pgTools.DirectDebug.direct_execution_completed = true;
pgTools.DirectDebug.is_user_aborted_debugging = true;
//Set the alertify message to inform the user that execution is completed. // Stop further pooling
pgTools.DirectDebug.is_polling_required = false;
// Restarting debugging in the same transaction do not work
// We will give same behaviour as pgAdmin3 and disable all buttons
self.enable('continue', false);
// Set the alertify message to inform the user that execution
// is completed.
var alertifyWrapper = new AlertifyWrapper(); var alertifyWrapper = new AlertifyWrapper();
alertifyWrapper.success(res.info, 3); alertifyWrapper.success(res.info, 3);
//Disable the buttons other than continue button. If user wants to again then it should allow to debug again...
self.enable('continue', true);
} }
else if (res.data.status === 'NotConnected') { else if (res.data.status === 'NotConnected') {
Alertify.alert( Alertify.alert(
@@ -1353,6 +1369,7 @@ define([
this.direct_execution_completed = false; this.direct_execution_completed = false;
this.polling_timeout_idle = false; this.polling_timeout_idle = false;
this.debug_restarted = false; this.debug_restarted = false;
this.is_user_aborted_debugging = false;
this.is_polling_required = true; // Flag to stop unwanted ajax calls this.is_polling_required = true; // Flag to stop unwanted ajax calls
var docker = this.docker = new wcDocker( var docker = this.docker = new wcDocker(
@@ -1495,7 +1512,7 @@ define([
intializePanels: function() { intializePanels: function() {
var self = this; var self = this;
this.registerPanel( this.registerPanel(
'code', false, '100%', '100%', 'code', false, '100%', '50%',
function(panel) { function(panel) {
// Create the parameters panel to display the arguments of the functions // Create the parameters panel to display the arguments of the functions