Resolve various debugger quirks. Fixes #1227

- Prevent the user from executing multiple options at once, resulting in "Execute cannot be used while an asynchronous query is underway********** Error ****" messages

- Stop polling when debugging is complete.

- Don't show the busy cursory when debugging is complete.

- Display info messages properly, and reset them between executions.
This commit is contained in:
Murtuza Zabuawala 2016-11-11 14:25:11 +00:00 committed by Dave Page
parent f405cdf383
commit 6f30cabdbb
3 changed files with 201 additions and 28 deletions

View File

@ -1354,9 +1354,22 @@ def poll_end_execution_result(trans_id):
if conn.connected(): if conn.connected():
statusmsg = conn.status_message() statusmsg = conn.status_message()
if statusmsg and statusmsg == 'SELECT 1':
statusmsg = ''
status, result, col_info = conn.poll() status, result, col_info = conn.poll()
if status == ASYNC_OK and session['functionData'][str(trans_id)]['language'] == 'edbspl': if status == ASYNC_OK and \
not session['functionData'][str(trans_id)]['is_func'] and \
session['functionData'][str(trans_id)]['language'] == 'edbspl':
status = 'Success' status = 'Success'
additional_msgs = conn.messages()
if len(additional_msgs) > 0:
additional_msgs = [msg.strip("\n") for msg in additional_msgs]
additional_msgs = "<br>".join(additional_msgs)
if statusmsg:
statusmsg = additional_msgs + "<br>" + statusmsg
else:
statusmsg = additional_msgs
return make_json_response(success=1, info=gettext("Execution Completed."), return make_json_response(success=1, info=gettext("Execution Completed."),
data={'status': status, 'status_message': statusmsg}) data={'status': status, 'status_message': statusmsg})
if result: if result:
@ -1366,6 +1379,15 @@ def poll_end_execution_result(trans_id):
data={'status': status, 'status_message': result}) data={'status': status, 'status_message': result})
else: else:
status = 'Success' status = 'Success'
additional_msgs = conn.messages()
if len(additional_msgs) > 0:
additional_msgs = [msg.strip("\n") for msg in additional_msgs]
additional_msgs = "<br>".join(additional_msgs)
if statusmsg:
statusmsg = additional_msgs + "<br>" + statusmsg
else:
statusmsg = additional_msgs
columns = [] columns = []
# Check column info is available or not # Check column info is available or not
if col_info is not None and len(col_info) > 0: if col_info is not None and len(col_info) > 0:
@ -1381,6 +1403,17 @@ def poll_end_execution_result(trans_id):
'col_info': columns, 'status_message': statusmsg}) 'col_info': columns, 'status_message': statusmsg})
else: else:
status = 'Busy' status = 'Busy'
additional_msgs = conn.messages()
if len(additional_msgs) > 0:
additional_msgs = [msg.strip("\n") for msg in additional_msgs]
additional_msgs = "<br>".join(additional_msgs)
if statusmsg:
statusmsg = additional_msgs + "<br>" + statusmsg
else:
statusmsg = additional_msgs
return make_json_response(data={
'status': status, 'result': result, 'status_message': statusmsg
})
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.')

View File

@ -67,3 +67,14 @@
.CodeMirror-foldgutter-folded:after { .CodeMirror-foldgutter-folded:after {
content: "\25B6"; content: "\25B6";
} }
/* To make font same as Query tool in messages tab */
.messages {
white-space: pre-wrap;
font-family: monospace;
padding-top: 5px;
padding-left: 10px;
overflow: auto;
height: 100%;
font-size: 0.925em;
}

View File

@ -164,6 +164,9 @@ define(
// Call function to create and update local variables .... // Call function to create and update local variables ....
self.GetStackInformation(trans_id); self.GetStackInformation(trans_id);
if (pgTools.DirectDebug.debug_type) {
self.poll_end_execution_result(trans_id);
}
} }
else if (res.data.status === 'NotConnected') { else if (res.data.status === 'NotConnected') {
Alertify.alert( Alertify.alert(
@ -194,6 +197,13 @@ define(
// Call function to create and update local variables // Call function to create and update local variables
self.AddLocalVariables(res.data.result); self.AddLocalVariables(res.data.result);
self.AddParameters(res.data.result); self.AddParameters(res.data.result);
// If debug function is restarted then again start listener to read the updated messages.
if (pgTools.DirectDebug.debug_restarted) {
if (pgTools.DirectDebug.debug_type) {
self.poll_end_execution_result(trans_id);
}
pgTools.DirectDebug.debug_restarted = false;
}
} }
else if (res.data.status === 'NotConnected') { else if (res.data.status === 'NotConnected') {
Alertify.alert( Alertify.alert(
@ -245,6 +255,12 @@ define(
*/ */
poll_result: function(trans_id) { poll_result: function(trans_id) {
var self = this; var self = this;
// Do we need to poll?
if(!pgTools.DirectDebug.is_polling_required){
return;
}
// Make ajax call to listen the database message // Make ajax call to listen the database message
var baseUrl = "{{ url_for('debugger.index') }}" + "poll_result/" + trans_id; var baseUrl = "{{ url_for('debugger.index') }}" + "poll_result/" + trans_id;
@ -271,6 +287,9 @@ define(
$('.debugger-container').addClass('show_progress'); $('.debugger-container').addClass('show_progress');
}, },
success: function(res) { success: function(res) {
// remove progress cursor
$('.debugger-container').removeClass('show_progress');
if (res.data.status === 'Success') { if (res.data.status === 'Success') {
// If no result then poll again to wait for results. // If no result then poll again to wait for results.
if (res.data.result == null || res.data.result.length == 0) { if (res.data.result == null || res.data.result.length == 0) {
@ -317,8 +336,6 @@ define(
self.GetStackInformation(trans_id); self.GetStackInformation(trans_id);
} }
// remove progress cursor
$('.debugger-container').removeClass('show_progress');
// Enable all the buttons as we got the results // Enable all the buttons as we got the results
self.enable('stop', true); self.enable('stop', true);
self.enable('step_over', true); self.enable('step_over', true);
@ -333,7 +350,8 @@ define(
// If status is Busy then poll the result by recursive call to the poll function // If status is Busy then poll the result by recursive call to the poll function
if (!pgTools.DirectDebug.debug_type) { if (!pgTools.DirectDebug.debug_type) {
pgTools.DirectDebug.docker.startLoading('{{ _('Waiting for another session to invoke the target...') }}'); pgTools.DirectDebug.docker.startLoading('{{ _('Waiting for another session to invoke the target...') }}');
// As we are waiting for another session to invoke the target so disable all the buttons
// As we are waiting for another session to invoke the target,disable all the buttons
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);
@ -363,13 +381,32 @@ define(
}, },
// This function will update messages tab
update_messages: function(msg) {
var old_msgs='', new_msgs='';
old_msgs = pgTools.DirectDebug.messages_panel.$container.find('.messages').html();
if(old_msgs) {
new_msgs = (old_msgs + '\n' + msg)
.replace(/(?:\r\n|\r|\n)/g, '<br />') // Newlines with <br>
.replace(/(<br\ ?\/?>)+/g, '<br />'); // multiple <br> with single <br>
} else {
new_msgs = msg;
}
pgTools.DirectDebug.messages_panel.$container.find('.messages').html(new_msgs);
},
/* /*
For the direct debugging, we need to check weather the functions execution is completed or not. After completion For the direct debugging, we need to check weather the functions execution is completed or not. After completion
of the debugging, we will stop polling the result until new execution starts. of the debugging, we will stop polling the result until new execution starts.
*/ */
poll_end_execution_result: function(trans_id) { poll_end_execution_result: function(trans_id) {
var self = this; var self = this;
//return;
// Do we need to poll?
if(!pgTools.DirectDebug.is_polling_required){
return;
}
// Make ajax call to listen the database message // Make ajax call to listen the database message
var baseUrl = "{{ url_for('debugger.index') }}" + "poll_end_execution_result/" + trans_id; var baseUrl = "{{ url_for('debugger.index') }}" + "poll_end_execution_result/" + trans_id;
@ -411,7 +448,12 @@ define(
); );
// Update the message tab of the debugger // Update the message tab of the debugger
pgTools.DirectDebug.dbmsMessages.$elem.text(res.data.status_message); if (res.data.status_message) {
self.update_messages(res.data.status_message);
}
// remove progress cursor
$('.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 "Continue/Start" button because user can still
// start the same execution again. // start the same execution again.
@ -420,6 +462,9 @@ 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);
// Stop further polling
pgTools.DirectDebug.is_polling_required = false;
} }
else { else {
// Call function to create and update local variables .... // Call function to create and update local variables ....
@ -439,7 +484,12 @@ define(
); );
// Update the message tab of the debugger // Update the message tab of the debugger
pgTools.DirectDebug.messages_panel.$container.find('.messages').text(res.data.status_message); if (res.data.status_message) {
self.update_messages(res.data.status_message);
}
// remove progress cursor
$('.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 "Continue/Start" button because user can still
// start the same execution again. // start the same execution again.
@ -448,12 +498,20 @@ 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);
// Stop further pooling
pgTools.DirectDebug.is_polling_required = false;
} }
} }
} }
else if (res.data.status === 'Busy') { else if (res.data.status === 'Busy') {
// If status is Busy then poll the result by recursive call to the poll function // If status is Busy then poll the result by recursive call to the poll function
//self.poll_end_execution_result(trans_id); self.poll_end_execution_result(trans_id);
// Update the message tab of the debugger
if (res.data.status_message) {
self.update_messages(res.data.status_message);
}
} }
else if (res.data.status === 'NotConnected') { else if (res.data.status === 'NotConnected') {
Alertify.alert( Alertify.alert(
@ -473,9 +531,16 @@ define(
function() { } function() { }
); );
pgTools.DirectDebug.messages_panel.$container.find('.messages').text(res.data.status_message); // Update the message tab of the debugger
if (res.data.status_message) {
self.update_messages(res.data.status_message);
}
pgTools.DirectDebug.messages_panel.focus(); pgTools.DirectDebug.messages_panel.focus();
// remove progress cursor
$('.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 "Continue/Start" button because user can still
// start the same execution again. // start the same execution again.
self.enable('stop', false); self.enable('stop', false);
@ -483,6 +548,10 @@ 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);
// Stop further pooling
pgTools.DirectDebug.is_polling_required = false;
} }
}, },
error: function(e) { error: function(e) {
@ -498,7 +567,17 @@ define(
Restart: function(trans_id) { Restart: function(trans_id) {
var baseUrl = "{{ url_for('debugger.index') }}" + "restart/" + trans_id; var self = this,
baseUrl = "{{ url_for('debugger.index') }}" + "restart/" + trans_id;
self.enable('stop', false);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
self.enable('continue', false);
// Clear msg tab
pgTools.DirectDebug.messages_panel.$container.find('.messages').html('');
$.ajax({ $.ajax({
url: baseUrl, url: baseUrl,
@ -506,6 +585,15 @@ define(
// Restart the same function debugging with previous arguments // Restart the same function debugging with previous arguments
var restart_dbg = res.data.restart_debug ? 1 : 0; var restart_dbg = res.data.restart_debug ? 1 : 0;
// Start pooling again
pgTools.DirectDebug.is_polling_required = true;
self.poll_end_execution_result(trans_id);
self.poll_result(trans_id);
if (restart_dbg) {
pgTools.DirectDebug.debug_restarted = true;
}
/* /*
Need to check if restart debugging really require to open the input dialog ? Need to check if restart debugging really require to open the input dialog ?
If yes then we will get the previous arguments from database and populate the input dialog If yes then we will get the previous arguments from database and populate the input dialog
@ -522,6 +610,9 @@ define(
url: baseUrl, url: baseUrl,
method: 'GET', method: 'GET',
success: function(res) { success: function(res) {
if (pgTools.DirectDebug.debug_type) {
self.poll_end_execution_result(trans_id);
}
}, },
error: function(e) { error: function(e) {
Alertify.alert( Alertify.alert(
@ -546,6 +637,12 @@ define(
// Continue the execution until the next breakpoint // Continue the execution until the next breakpoint
Continue: function(trans_id) { Continue: function(trans_id) {
var self = this; var self = this;
self.enable('stop', false);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
self.enable('continue', false);
//Check first if previous execution was completed or not //Check first if previous execution was completed or not
if (pgTools.DirectDebug.direct_execution_completed && if (pgTools.DirectDebug.direct_execution_completed &&
@ -562,9 +659,6 @@ define(
success: function(res) { success: function(res) {
if (res.data.status) { if (res.data.status) {
self.poll_result(trans_id); self.poll_result(trans_id);
if (pgTools.DirectDebug.debug_type) {
self.poll_end_execution_result(trans_id);
}
} }
else { else {
Alertify.alert( Alertify.alert(
@ -583,6 +677,12 @@ define(
Step_over: function(trans_id) { Step_over: function(trans_id) {
var self = this; var self = this;
self.enable('stop', false);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
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 + "/" + "step_over"; var baseUrl = "{{ url_for('debugger.index') }}" + "execute_query/" + trans_id + "/" + "step_over";
@ -593,9 +693,6 @@ define(
success: function(res) { success: function(res) {
if (res.data.status) { if (res.data.status) {
self.poll_result(trans_id); self.poll_result(trans_id);
if (pgTools.DirectDebug.debug_type) {
self.poll_end_execution_result(trans_id);
}
} }
else { else {
Alertify.alert( Alertify.alert(
@ -613,6 +710,12 @@ define(
Step_into: function(trans_id) { Step_into: function(trans_id) {
var self = this; var self = this;
self.enable('stop', false);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
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 + "/" + "step_into"; var baseUrl = "{{ url_for('debugger.index') }}" + "execute_query/" + trans_id + "/" + "step_into";
@ -623,9 +726,6 @@ define(
success: function(res) { success: function(res) {
if (res.data.status) { if (res.data.status) {
self.poll_result(trans_id); self.poll_result(trans_id);
if (pgTools.DirectDebug.debug_type) {
self.poll_end_execution_result(trans_id);
}
} }
else { else {
Alertify.alert( Alertify.alert(
@ -643,6 +743,12 @@ define(
Stop: function(trans_id) { Stop: function(trans_id) {
var self = this; var self = this;
self.enable('stop', false);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
self.enable('continue', true);
// 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";
@ -665,12 +771,8 @@ define(
); );
//Disable the buttons other than continue button. If user wants to again then it should allow to debug again... //Disable the buttons other than continue button. If user wants to again then it should allow to debug again...
self.enable('stop', false); self.enable('continue', true);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('continue', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
} }
else if (res.data.status === 'NotConnected') { else if (res.data.status === 'NotConnected') {
Alertify.alert( Alertify.alert(
@ -688,6 +790,13 @@ define(
toggle_breakpoint: function(trans_id) { toggle_breakpoint: function(trans_id) {
var self = this; var self = this;
self.enable('stop', false);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
self.enable('continue', false);
var info = pgTools.DirectDebug.editor.lineInfo(self.active_line_no); var info = pgTools.DirectDebug.editor.lineInfo(self.active_line_no);
var baseUrl = ''; var baseUrl = '';
@ -720,6 +829,12 @@ define(
return marker; return marker;
}()); }());
} }
self.enable('stop', true);
self.enable('step_over', true);
self.enable('step_into', true);
self.enable('toggle_breakpoint', true);
self.enable('clear_all_breakpoints', true);
self.enable('continue', true);
} }
else if (res.data.status === 'NotConnected') { else if (res.data.status === 'NotConnected') {
Alertify.alert( Alertify.alert(
@ -736,14 +851,20 @@ define(
}, },
clear_all_breakpoint: function(trans_id) { clear_all_breakpoint: function(trans_id) {
var self = this; var self = this,
br_list = self.GetBreakpointInformation(trans_id);
var br_list = self.GetBreakpointInformation(trans_id);
// If there is no break point to clear then we should return from here. // If there is no break point to clear then we should return from here.
if ((br_list.length == 1) && (br_list[0].linenumber == -1)) if ((br_list.length == 1) && (br_list[0].linenumber == -1))
return; return;
self.enable('stop', false);
self.enable('step_over', false);
self.enable('step_into', false);
self.enable('toggle_breakpoint', false);
self.enable('clear_all_breakpoints', false);
self.enable('continue', false);
var breakpoint_list = new Array(); var breakpoint_list = new Array();
for (i = 0; i < br_list.length; i++) { for (i = 0; i < br_list.length; i++) {
@ -771,6 +892,12 @@ define(
} }
} }
} }
self.enable('stop', true);
self.enable('step_over', true);
self.enable('step_into', true);
self.enable('toggle_breakpoint', true);
self.enable('clear_all_breakpoints', true);
self.enable('continue', true);
}, },
error: function(e) { error: function(e) {
Alertify.alert( Alertify.alert(
@ -1204,6 +1331,8 @@ define(
this.first_time_indirect_debug = false; this.first_time_indirect_debug = false;
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.is_polling_required = true; // Flag to stop unwanted ajax calls
var docker = this.docker = new wcDocker( var docker = this.docker = new wcDocker(
'#container', { '#container', {