ARB
AW_root_debug.cxx
Go to the documentation of this file.
1 // =========================================================== //
2 // //
3 // File : AW_root_debug.cxx //
4 // Purpose : //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in May 2009 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // =========================================================== //
11 
12 #include "aw_window.hxx"
13 #include "aw_Xm.hxx"
14 #include "aw_window_Xm.hxx"
15 #include "aw_root.hxx"
16 #include "aw_msg.hxx"
17 
18 #include <arbdbt.h>
19 #include <arb_strarray.h>
20 
21 #include <vector>
22 #include <iterator>
23 #include <string>
24 #include <algorithm>
25 
26 // do includes above (otherwise depends depend on DEBUG)
27 
28 #if defined(DEBUG)
29 // --------------------------------------------------------------------------------
30 
31 using namespace std;
32 
33 typedef vector<string> CallbackArray;
34 typedef CallbackArray::const_iterator CallbackIter;
35 
36 static GB_HASH *dontCallHash = NULp;
37 static GB_HASH *alreadyCalledHash = NULp;
38 
39 static void forgetCalledCallbacks() {
40  if (alreadyCalledHash) GBS_free_hash(alreadyCalledHash);
41  alreadyCalledHash = GBS_create_hash(2500, GB_MIND_CASE);
42 }
43 
44 static void auto_dontcall1(const char *key, long value, void *cl_hash) {
45  if (strncmp(key, "ARB_NT/", 7) == 0) {
46  GB_HASH *autodontCallHash = (GB_HASH*)cl_hash;
47  GBS_write_hash(autodontCallHash, GBS_global_string("ARB_NT_1/%s", key+7), value);
48  }
49 }
50 static void auto_dontcall2(const char *key, long value, void *) {
51  GBS_write_hash(dontCallHash, key, value);
52 }
53 
54 static void forget_dontCallHash() {
55  if (dontCallHash) {
56  GBS_free_hash(dontCallHash);
57  GBS_free_hash(alreadyCalledHash);
58  dontCallHash = NULp;
59  }
60 }
61 
62 static void build_dontCallHash() {
63  aw_assert(!dontCallHash);
64  dontCallHash = GBS_create_hash(100, GB_MIND_CASE);
65  forgetCalledCallbacks();
66 
67  atexit(forget_dontCallHash);
68 
69  // avoid program termination/restart/etc.
70  GBS_write_hash(dontCallHash, "ARB_NT/QUIT", 1);
71  GBS_write_hash(dontCallHash, "quit", 1);
72  GBS_write_hash(dontCallHash, "new_arb", 1);
73  GBS_write_hash(dontCallHash, "restart_arb", 1);
74  GBS_write_hash(dontCallHash, "ARB_EDIT4/QUIT", 1);
75  GBS_write_hash(dontCallHash, "ARB_INTRO/CANCEL", 1);
76  GBS_write_hash(dontCallHash, "ARB_MERGE/QUIT", 1);
77  GBS_write_hash(dontCallHash, "ARB_MERGE/quit", 1);
78  GBS_write_hash(dontCallHash, "NEIGHBOUR_JOINING/CLOSE", 1);
79  GBS_write_hash(dontCallHash, "MERGE_SELECT_DATABASES/QUIT", 1);
80  GBS_write_hash(dontCallHash, "quitnstart", 1);
81  GBS_write_hash(dontCallHash, "PARS_PROPS/ABORT", 1);
82  GBS_write_hash(dontCallHash, "ARB_PHYLO/QUIT", 1);
83  GBS_write_hash(dontCallHash, "SELECT_ALIGNMENT/ABORT", 1);
84 
85  // avoid start of some external programs:
86 #if 1
87  GBS_write_hash(dontCallHash, "GDE__User__Start_a_slave_ARB_on_a_foreign_host_/GO", 2);
88  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/REMOVE_SUPERFLUOUS_ENTRIES_IN_NAMES_FILE", 2);
89  GBS_write_hash(dontCallHash, "GDE__Print__Pretty_print_sequences_slow_/GO", 2);
90 
91  GBS_write_hash(dontCallHash, "ARB_NT/EDIT_SEQUENCES", 2);
92  GBS_write_hash(dontCallHash, "merge_from", 2);
93  GBS_write_hash(dontCallHash, "CPR_MAIN/HELP", 2);
94  GBS_write_hash(dontCallHash, "HELP/BROWSE", 2);
95  GBS_write_hash(dontCallHash, "mailing_list", 2);
96  GBS_write_hash(dontCallHash, "bug_report", 2);
97  GBS_write_hash(dontCallHash, "HELP/EDIT", 2);
98  GBS_write_hash(dontCallHash, "MACROS/EDIT", 2);
99  GBS_write_hash(dontCallHash, "MACROS/EXECUTE", 2);
100  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/EDIT_NAMES_FILE", 2);
101  GBS_write_hash(dontCallHash, "arb_dist", 2);
102  GBS_write_hash(dontCallHash, "arb_pars", 2);
103  GBS_write_hash(dontCallHash, "arb_pars_quick", 2);
104  GBS_write_hash(dontCallHash, "arb_phyl", 2);
105  GBS_write_hash(dontCallHash, "count_different_chars", 2);
106  GBS_write_hash(dontCallHash, "corr_mutat_analysis", 2);
107  GBS_write_hash(dontCallHash, "export_to_ARB", 2);
108  GBS_write_hash(dontCallHash, "new2_arb_edit4", 2);
109  GBS_write_hash(dontCallHash, "new_arb_edit4", 2);
110  GBS_write_hash(dontCallHash, "primer_design", 2);
111  GBS_write_hash(dontCallHash, "xterm", 2);
112  GBS_write_hash(dontCallHash, "SUBMIT_REG/SEND", 2);
113  GBS_write_hash(dontCallHash, "SUBMIT_BUG/SEND", 2);
114  GBS_write_hash(dontCallHash, "PRINT_CANVAS/PRINT", 2);
115  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/CREATE_TEMPLATE", 2);
116  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/EDIT_LOG", 2);
117  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/CREATE_TEMPLATE", 2);
118  GBS_write_hash(dontCallHash, "SELECT_CONFIGURATION/START", 2);
119  GBS_write_hash(dontCallHash, "EXPORT_TREE_AS_XFIG/START_XFIG", 2);
120  GBS_write_hash(dontCallHash, "EXPORT_NDS_OF_MARKED/PRINT", 2);
121  GBS_write_hash(dontCallHash, "ALIGNER_V2/GO", 2);
122  GBS_write_hash(dontCallHash, "SINA/Start", 2);
123 #endif
124 
125  // avoid saving
126  GBS_write_hash(dontCallHash, "save_changes", 3);
127  GBS_write_hash(dontCallHash, "save_props", 3);
128  GBS_write_hash(dontCallHash, "save_alitype_props", 3);
129  GBS_write_hash(dontCallHash, "save_alispecific_props", 3);
130  GBS_write_hash(dontCallHash, "save_DB1", 3);
131  GBS_write_hash(dontCallHash, "SAVE_DB/SAVE", 3);
132  GBS_write_hash(dontCallHash, "ARB_NT/SAVE", 3);
133  GBS_write_hash(dontCallHash, "ARB_NT/SAVE_AS", 3);
134  GBS_write_hash(dontCallHash, "ARB_NT/QUICK_SAVE_AS", 3);
135 
136  GBS_write_hash(dontCallHash, "ARB_MERGE/save_DB1", 3);
137 
138  GBS_write_hash(dontCallHash, "User1_search_1/SAVE", 3);
139  GBS_write_hash(dontCallHash, "User2_search_1/SAVE", 3);
140  GBS_write_hash(dontCallHash, "Probe_search_1/SAVE", 3);
141  GBS_write_hash(dontCallHash, "Primer_local_search_1/SAVE", 3);
142  GBS_write_hash(dontCallHash, "Primer_region_search_1/SAVE", 3);
143  GBS_write_hash(dontCallHash, "Primer_global_search_1/SAVE", 3);
144  GBS_write_hash(dontCallHash, "Signature_local_search_1/SAVE", 3);
145  GBS_write_hash(dontCallHash, "Signature_region_search_1/SAVE", 3);
146  GBS_write_hash(dontCallHash, "Signature_global_search_1/SAVE", 3);
147 
148  // avoid confusion by recording, executing or deleting macros
149  GBS_write_hash(dontCallHash, "MACROS/DELETE", 1);
150  GBS_write_hash(dontCallHash, "MACROS/EDIT", 1);
151  GBS_write_hash(dontCallHash, "MACROS/EXECUTE", 1);
152  GBS_write_hash(dontCallHash, "MACROS/macro_record", 1);
153 
154 #if 1
155  // @@@ crashing - fix later
156  GBS_write_hash(dontCallHash, "ARB_NT/view_probe_group_result", 4);
157  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/CHECK_SERVER", 4);
158  GBS_write_hash(dontCallHash, "ARB_EDIT4/SECEDIT", 4);
159  GBS_write_hash(dontCallHash, "sec_edit", 4);
160  GBS_write_hash(dontCallHash, "ARB_EDIT4/RNA3D", 4);
161  GBS_write_hash(dontCallHash, "rna3d", 4);
162  GBS_write_hash(dontCallHash, "reload_config", 4);
163  GBS_write_hash(dontCallHash, "LOAD_OLD_CONFIGURATION/LOAD", 4);
164  GBS_write_hash(dontCallHash, "table_admin", 4); // disabled in userland atm
165  GBS_write_hash(dontCallHash, "PARS_PROPS/GO", 4); // has already been executed (designed to run only once)
166  GBS_write_hash(dontCallHash, "ARB_PARSIMONY/POP", 4); // pop does not work correctly in all cases (see #528)
167  GBS_write_hash(dontCallHash, "new_win", 4); // 2nd editor window (blocked by #429)
168  GBS_write_hash(dontCallHash, "ARB_NT/UNDO", 4); // doesn't crash, but caused following commands to crash
169 #endif
170 
171  // do not open 2nd ARB_NT window (to buggy)
172  GBS_write_hash(dontCallHash, "new_window", 4);
173 
174 #if 1
175  // @@@ test callbacks asking questions again later
176  GBS_write_hash(dontCallHash, "ARB_NT/tree_scale_lengths", 5);
177  GBS_write_hash(dontCallHash, "CREATE_USER_MASK/CREATE", 5);
178  GBS_write_hash(dontCallHash, "GDE__Import__Import_sequences_using_Readseq_slow_/GO", 5);
179  GBS_write_hash(dontCallHash, "INFO_OF_ALIGNMENT/DELETE", 5);
180  GBS_write_hash(dontCallHash, "LOAD_SELECTION_BOX/LOAD", 5);
181  GBS_write_hash(dontCallHash, "MULTI_PROBE/CREATE_NEW_SEQUENCE", 5);
182  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/KILL_ALL_SERVERS", 5);
183  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/KILL_SERVER", 5);
184  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/UPDATE_SERVER", 5);
185  GBS_write_hash(dontCallHash, "REALIGN_DNA/REALIGN", 5);
186  // GBS_write_hash(dontCallHash, "SPECIES_QUERY/DELETE_LISTED", 5);
187  GBS_write_hash(dontCallHash, "SPECIES_QUERY/DELETE_LISTED_spec", 5);
188  GBS_write_hash(dontCallHash, "SPECIES_QUERY/SAVELOAD_CONFIG_spec", 5);
189  GBS_write_hash(dontCallHash, "SPECIES_SELECTIONS/RENAME", 5);
190  GBS_write_hash(dontCallHash, "SPECIES_SELECTIONS/STORE_0", 5);
191  GBS_write_hash(dontCallHash, "del_marked", 5);
192  GBS_write_hash(dontCallHash, "create_group", 5);
193  GBS_write_hash(dontCallHash, "dcs_threshold", 5);
194  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/DELETE_OLD_NAMES_FILE", 5);
195  GBS_write_hash(dontCallHash, "detail_col_stat", 5);
196  // merge tool:
197  GBS_write_hash(dontCallHash, "MERGE_TRANSFER_SPECIES/DELETE_LISTED_db1", 5);
198  GBS_write_hash(dontCallHash, "MERGE_TRANSFER_SPECIES/DELETE_LISTED_db2", 5);
199  GBS_write_hash(dontCallHash, "MERGE_CONFIGS/DELETE CONFIG_DB1", 5);
200  GBS_write_hash(dontCallHash, "MERGE_CONFIGS/DELETE CONFIG_DB2", 5);
201  GBS_write_hash(dontCallHash, "MERGE_SAI/DELETE_SAI_DB1", 5);
202  GBS_write_hash(dontCallHash, "MERGE_SAI/DELETE_SAI_DB2", 5);
203 #endif
204 
205  // don't call some close-callbacks
206  // (needed when they perform cleanup that makes other callbacks from the same window fail)
207  GBS_write_hash(dontCallHash, "ARB_IMPORT/CLOSE", 6);
208 
209  GB_HASH *autodontCallHash = GBS_create_hash(100, GB_MIND_CASE);
210  GBS_hash_do_const_loop(dontCallHash, auto_dontcall1, autodontCallHash);
211  GBS_hash_do_const_loop(autodontCallHash, auto_dontcall2, dontCallHash);
212  GBS_free_hash(autodontCallHash);
213 }
214 
215 class StringVectorArray : public ConstStrArray {
216  CallbackArray array;
217 public:
218  StringVectorArray(const CallbackArray& a)
219  : array(a)
220  {
221  reserve(a.size());
222  for (CallbackArray::iterator id = array.begin(); id != array.end(); ++id) {
223  put(id->c_str());
224  }
225  }
226 };
227 
228 inline bool exclude_key(const char *key) {
229  if (strncmp(key, "FILTER_SELECT_", 14) == 0) {
230  if (strstr(key, "/2filter/2filter/2filter/")) {
231  return true;
232  }
233  }
234  else {
235  if (strstr(key, "SAVELOAD_CONFIG")) return true;
236  }
237  return false;
238 }
239 
240 inline bool is_wanted_callback(const char *key) {
241  return
242  GBS_read_hash(alreadyCalledHash, key) == 0 && // dont call twice
243  !exclude_key(key); // skip some problematic callbacks
244 }
245 
246 static int sortedByCallbackLocation(const char *k0, long v0, const char *k1, long v1) {
247  AW_cb *cbs0 = reinterpret_cast<AW_cb*>(v0);
248  AW_cb *cbs1 = reinterpret_cast<AW_cb*>(v1);
249 
250  int cmp = cbs0->compare(*cbs1);
251  if (!cmp) cmp = strcmp(k0, k1);
252 
253  return cmp;
254 }
255 
256 // ------------------------
257 // get_action_ids
258 
259 static void add_wanted_callbacks(const char *key, long /*val*/, void *cl_callbacks) {
260  if (is_wanted_callback(key)) {
261  CallbackArray *callbacks = reinterpret_cast<CallbackArray*>(cl_callbacks);
262  callbacks->push_back(string(key));
263  }
264 }
265 
266 ConstStrArray *AW_root::get_action_ids() {
267  if (!dontCallHash) build_dontCallHash();
268  CallbackArray callbacks;
269  GBS_hash_do_const_sorted_loop(prvt->action_hash, add_wanted_callbacks, GBS_HCF_sortedByKey, &callbacks);
270  return new StringVectorArray(callbacks);
271 }
272 
273 // --------------------------
274 // callallcallbacks
275 
276 size_t AW_root::callallcallbacks(int mode) {
277  // mode == -2 -> mark all as called
278  // mode == -1 -> forget called
279  // mode == 0 -> call all in alpha-order
280  // mode == 1 -> call all in reverse alpha-order
281  // mode == 2 -> call all in code-order
282  // mode == 3 -> call all in reverse code-order
283  // mode == 4 -> call all in random order
284  // mode & 8 -> repeat until no uncalled callbacks left
285 
286  size_t count = GBS_hash_elements(prvt->action_hash);
287  size_t callCount = 0;
288 
289  aw_message(GBS_global_string("Found %zi callbacks", count));
290 
291  if (!dontCallHash) build_dontCallHash();
292 
293  if (mode>0 && (mode&8)) {
294  aw_message("Calling callbacks iterated");
295  for (int iter = 1; ; ++iter) { // forever
296  size_t thisCount = callallcallbacks(mode&~8); // call all in wanted order
297  aw_message(GBS_global_string("%zu callbacks were called (iteration %i)", thisCount, iter));
298  if (!thisCount) {
299  aw_message("No uncalled callbacks left");
300  break;
301  }
302 
303  callCount += thisCount;
304  }
305  }
306  else if (mode == -1) {
307  forgetCalledCallbacks();
308  }
309  else {
310  CallbackArray callbacks;
311  switch (mode) {
312  case 0:
313  case 1:
314  GBS_hash_do_const_sorted_loop(prvt->action_hash, add_wanted_callbacks, GBS_HCF_sortedByKey, &callbacks);
315  break;
316  case 2:
317  case 3:
318  GBS_hash_do_const_sorted_loop(prvt->action_hash, add_wanted_callbacks, sortedByCallbackLocation, &callbacks);
319  break;
320  case -2:
321  aw_message("Marking all callbacks as \"called\"");
322  FALLTHROUGH;
323  case 4:
324  GBS_hash_do_const_loop(prvt->action_hash, add_wanted_callbacks, &callbacks);
325  break;
326  default:
327  aw_assert(0);
328  break;
329  }
330 
331  switch (mode) {
332  case -2:
333  case 0:
334  case 2: break; // use this order
335  case 1:
336  case 3: reverse(callbacks.begin(), callbacks.end()); break; // use reverse order
337  case 4: random_shuffle(callbacks.begin(), callbacks.end()); break; // use random order
338  default: aw_assert(0); break; // unknown mode
339  }
340 
341  count = callbacks.size();
342  aw_message(GBS_global_string("%zu callbacks were not called yet", count));
343 
344  CallbackIter end = callbacks.end();
345 
346  for (int pass = 1; pass <= 2; ++pass) {
347  size_t curr = 1;
348  CallbackIter cb = callbacks.begin();
349 
350  for (; cb != end; ++cb) {
351  const char *remote_command = cb->c_str();
352  const char *remote_command_name = remote_command;
353  {
354  const char *slash = strrchr(remote_command, '/');
355  if (slash) remote_command_name = slash+1;
356  }
357 
358  char firstNameChar = remote_command_name[0];
359  bool this_pass = firstNameChar == '-' ? (pass == 2) : (pass == 1);
360 
361  if (this_pass) {
362  GBS_write_hash(alreadyCalledHash, remote_command, 1); // don't call twice
363 
364  if (mode != -2) { // -2 means "only mark as called"
365  AW_cb *cbs = (AW_cb *)GBS_read_hash(prvt->action_hash, remote_command);
366  bool skipcb = firstNameChar == '!' || GBS_read_hash(dontCallHash, remote_command);
367 
368  if (!skipcb) {
369  if (cbs->contains(AnyWinCB(AW_help_entry_pressed))) skipcb = true;
370  }
371 
372  if (skipcb) {
373  fprintf(stderr, "Skipped callback %zu/%zu (%s)\n", curr, count, remote_command);
374  }
375  else {
376  fprintf(stderr, "Calling back %zu/%zu (%s)\n", curr, count, remote_command);
377 
378  GB_clear_error();
379 
380  cbs->run_callbacks();
381  callCount++;
382  process_pending_events();
383 
384  if (GB_have_error()) {
385  fprintf(stderr, "Unhandled error in '%s': %s\n", remote_command, GB_await_error());
386  }
387  }
388  }
389  }
390  else {
391  if (pass == 1) {
392  fprintf(stderr, "Delayed callback %zu/%zu (%s)\n", curr, count, remote_command);
393  }
394  }
395 
396  curr++;
397  }
398 
399  if (pass == 1) fprintf(stderr, "Executing delayed callbacks:\n");
400  }
401 
402  aw_message(GBS_global_string("%zu callbacks are marked as called now", GBS_hash_elements(alreadyCalledHash)));
403  }
404 
405  return callCount;
406 }
407 
408 // --------------------------------------------------------------------------------
409 #endif // DEBUG
410 
void GBS_hash_do_const_sorted_loop(const GB_HASH *hs, gb_hash_const_loop_type func, gbs_hash_compare_function sorter, void *client_data)
Definition: adhash.cxx:641
const char * id
Definition: AliAdmin.cxx:17
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
Definition: adhash.cxx:454
static list< ArbDisconnectCallback > callbacks
Definition: app.cxx:21
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
bool GB_have_error()
Definition: arb_msg.cxx:338
STL namespace.
void GBS_free_hash(GB_HASH *hs)
Definition: adhash.cxx:538
#define cb(action)
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
bool contains(AnyWinCB g)
void GBS_hash_do_const_loop(const GB_HASH *hs, gb_hash_const_loop_type func, void *client_data)
Definition: adhash.cxx:559
int compare(const AW_cb &other) const
Definition: aw_window.hxx:152
void GB_clear_error()
Definition: arb_msg.cxx:354
#define aw_assert(bed)
Definition: aw_position.hxx:29
size_t GBS_hash_elements(const GB_HASH *hs)
Definition: adhash.cxx:570
#define cmp(h1, h2)
Definition: admap.cxx:50
WindowCallbackSimple AnyWinCB
Definition: aw_window.hxx:120
void AW_help_entry_pressed(AW_window *aww)
Definition: AW_root.cxx:38
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
int GBS_HCF_sortedByKey(const char *k0, long dummy_1x, const char *k1, long dummy_2x)
Definition: adhash.cxx:653
#define NULp
Definition: cxxforward.h:116
#define FALLTHROUGH
Definition: cxxforward.h:136
void run_callbacks()
long GBS_read_hash(const GB_HASH *hs, const char *key)
Definition: adhash.cxx:392
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)
Definition: adhash.cxx:253