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, "NEIGHBOUR_JOINING/CLOSE", 1);
77  GBS_write_hash(dontCallHash, "MERGE_SELECT_DATABASES/QUIT", 1);
78  GBS_write_hash(dontCallHash, "quitnstart", 1);
79  GBS_write_hash(dontCallHash, "PARS_PROPS/ABORT", 1);
80  GBS_write_hash(dontCallHash, "ARB_PHYLO/QUIT", 1);
81  GBS_write_hash(dontCallHash, "SELECT_ALIGNMENT/ABORT", 1);
82 
83  // avoid start of some external programs:
84 #if 1
85  GBS_write_hash(dontCallHash, "GDE__User__Start_a_slave_ARB_on_a_foreign_host_/GO", 2);
86  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/REMOVE_SUPERFLUOUS_ENTRIES_IN_NAMES_FILE", 2);
87  GBS_write_hash(dontCallHash, "GDE__Print__Pretty_print_sequences_slow_/GO", 2);
88 
89  GBS_write_hash(dontCallHash, "ARB_NT/EDIT_SEQUENCES", 2);
90  GBS_write_hash(dontCallHash, "merge_from", 2);
91  GBS_write_hash(dontCallHash, "CPR_MAIN/HELP", 2);
92  GBS_write_hash(dontCallHash, "HELP/BROWSE", 2);
93  GBS_write_hash(dontCallHash, "mailing_list", 2);
94  GBS_write_hash(dontCallHash, "bug_report", 2);
95  GBS_write_hash(dontCallHash, "HELP/EDIT", 2);
96  GBS_write_hash(dontCallHash, "MACROS/EDIT", 2);
97  GBS_write_hash(dontCallHash, "MACROS/EXECUTE", 2);
98  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/EDIT_NAMES_FILE", 2);
99  GBS_write_hash(dontCallHash, "arb_dist", 2);
100  GBS_write_hash(dontCallHash, "arb_pars", 2);
101  GBS_write_hash(dontCallHash, "arb_pars_quick", 2);
102  GBS_write_hash(dontCallHash, "arb_phyl", 2);
103  GBS_write_hash(dontCallHash, "count_different_chars", 2);
104  GBS_write_hash(dontCallHash, "corr_mutat_analysis", 2);
105  GBS_write_hash(dontCallHash, "export_to_ARB", 2);
106  GBS_write_hash(dontCallHash, "new2_arb_edit4", 2);
107  GBS_write_hash(dontCallHash, "new_arb_edit4", 2);
108  GBS_write_hash(dontCallHash, "primer_design", 2);
109  GBS_write_hash(dontCallHash, "xterm", 2);
110  GBS_write_hash(dontCallHash, "SUBMIT_REG/SEND", 2);
111  GBS_write_hash(dontCallHash, "SUBMIT_BUG/SEND", 2);
112  GBS_write_hash(dontCallHash, "PRINT_CANVAS/PRINT", 2);
113  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/CREATE_TEMPLATE", 2);
114  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/EDIT_LOG", 2);
115  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/CREATE_TEMPLATE", 2);
116  GBS_write_hash(dontCallHash, "SELECT_CONFIGURATION/START", 2);
117  GBS_write_hash(dontCallHash, "EXPORT_TREE_AS_XFIG/START_XFIG", 2);
118  GBS_write_hash(dontCallHash, "EXPORT_NDS_OF_MARKED/PRINT", 2);
119  GBS_write_hash(dontCallHash, "ALIGNER_V2/GO", 2);
120  GBS_write_hash(dontCallHash, "SINA/Start", 2);
121 #endif
122 
123  // avoid saving
124  GBS_write_hash(dontCallHash, "save_changes", 3);
125  GBS_write_hash(dontCallHash, "save_props", 3);
126  GBS_write_hash(dontCallHash, "save_alitype_props", 3);
127  GBS_write_hash(dontCallHash, "save_alispecific_props", 3);
128  GBS_write_hash(dontCallHash, "save_DB1", 3);
129  GBS_write_hash(dontCallHash, "SAVE_DB/SAVE", 3);
130  GBS_write_hash(dontCallHash, "ARB_NT/SAVE", 3);
131  GBS_write_hash(dontCallHash, "ARB_NT/SAVE_AS", 3);
132  GBS_write_hash(dontCallHash, "ARB_NT/QUICK_SAVE_AS", 3);
133 
134  GBS_write_hash(dontCallHash, "User1_search_1/SAVE", 3);
135  GBS_write_hash(dontCallHash, "User2_search_1/SAVE", 3);
136  GBS_write_hash(dontCallHash, "Probe_search_1/SAVE", 3);
137  GBS_write_hash(dontCallHash, "Primer_local_search_1/SAVE", 3);
138  GBS_write_hash(dontCallHash, "Primer_region_search_1/SAVE", 3);
139  GBS_write_hash(dontCallHash, "Primer_global_search_1/SAVE", 3);
140  GBS_write_hash(dontCallHash, "Signature_local_search_1/SAVE", 3);
141  GBS_write_hash(dontCallHash, "Signature_region_search_1/SAVE", 3);
142  GBS_write_hash(dontCallHash, "Signature_global_search_1/SAVE", 3);
143 
144  // avoid confusion by recording, executing or deleting macros
145  GBS_write_hash(dontCallHash, "MACROS/DELETE", 1);
146  GBS_write_hash(dontCallHash, "MACROS/EDIT", 1);
147  GBS_write_hash(dontCallHash, "MACROS/EXECUTE", 1);
148  GBS_write_hash(dontCallHash, "MACROS/macro_record", 1);
149 
150 #if 1
151  // @@@ crashing - fix later
152  GBS_write_hash(dontCallHash, "ARB_NT/view_probe_group_result", 4);
153  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/CHECK_SERVER", 4);
154  GBS_write_hash(dontCallHash, "ARB_EDIT4/SECEDIT", 4);
155  GBS_write_hash(dontCallHash, "sec_edit", 4);
156  GBS_write_hash(dontCallHash, "ARB_EDIT4/RNA3D", 4);
157  GBS_write_hash(dontCallHash, "rna3d", 4);
158  GBS_write_hash(dontCallHash, "reload_config", 4);
159  GBS_write_hash(dontCallHash, "LOAD_OLD_CONFIGURATION/LOAD", 4);
160  GBS_write_hash(dontCallHash, "table_admin", 4); // disabled in userland atm
161  GBS_write_hash(dontCallHash, "PARS_PROPS/GO", 4); // has already been executed (designed to run only once)
162  GBS_write_hash(dontCallHash, "ARB_PARSIMONY/POP", 4); // pop does not work correctly in all cases (see #528)
163  GBS_write_hash(dontCallHash, "new_win", 4); // 2nd editor window (blocked by #429)
164  GBS_write_hash(dontCallHash, "ARB_NT/UNDO", 4); // doesn't crash, but caused following commands to crash
165 #endif
166 
167  // do not open 2nd ARB_NT window (to buggy)
168  GBS_write_hash(dontCallHash, "new_window", 4);
169 
170 #if 1
171  // @@@ test callbacks asking questions again later
172  GBS_write_hash(dontCallHash, "ARB_NT/tree_scale_lengths", 5);
173  GBS_write_hash(dontCallHash, "CREATE_USER_MASK/CREATE", 5);
174  GBS_write_hash(dontCallHash, "GDE__Import__Import_sequences_using_Readseq_slow_/GO", 5);
175  GBS_write_hash(dontCallHash, "INFO_OF_ALIGNMENT/DELETE", 5);
176  GBS_write_hash(dontCallHash, "LOAD_SELECTION_BOX/LOAD", 5);
177  GBS_write_hash(dontCallHash, "MULTI_PROBE/CREATE_NEW_SEQUENCE", 5);
178  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/KILL_ALL_SERVERS", 5);
179  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/KILL_SERVER", 5);
180  GBS_write_hash(dontCallHash, "PT_SERVER_ADMIN/UPDATE_SERVER", 5);
181  GBS_write_hash(dontCallHash, "REALIGN_DNA/REALIGN", 5);
182  // GBS_write_hash(dontCallHash, "SPECIES_QUERY/DELETE_LISTED", 5);
183  GBS_write_hash(dontCallHash, "SPECIES_QUERY/DELETE_LISTED_spec", 5);
184  GBS_write_hash(dontCallHash, "SPECIES_QUERY/SAVELOAD_CONFIG_spec", 5);
185  GBS_write_hash(dontCallHash, "SPECIES_SELECTIONS/RENAME", 5);
186  GBS_write_hash(dontCallHash, "SPECIES_SELECTIONS/STORE_0", 5);
187  GBS_write_hash(dontCallHash, "del_marked", 5);
188  GBS_write_hash(dontCallHash, "create_group", 5);
189  GBS_write_hash(dontCallHash, "dcs_threshold", 5);
190  GBS_write_hash(dontCallHash, "NAME_SERVER_ADMIN/DELETE_OLD_NAMES_FILE", 5);
191  GBS_write_hash(dontCallHash, "detail_col_stat", 5);
192 #endif
193 
194  // don't call some close-callbacks
195  // (needed when they perform cleanup that makes other callbacks from the same window fail)
196  GBS_write_hash(dontCallHash, "ARB_IMPORT/CLOSE", 6);
197 
198  GB_HASH *autodontCallHash = GBS_create_hash(100, GB_MIND_CASE);
199  GBS_hash_do_const_loop(dontCallHash, auto_dontcall1, autodontCallHash);
200  GBS_hash_do_const_loop(autodontCallHash, auto_dontcall2, dontCallHash);
201  GBS_free_hash(autodontCallHash);
202 }
203 
204 class StringVectorArray : public ConstStrArray {
205  CallbackArray array;
206 public:
207  StringVectorArray(const CallbackArray& a)
208  : array(a)
209  {
210  reserve(a.size());
211  for (CallbackArray::iterator id = array.begin(); id != array.end(); ++id) {
212  put(id->c_str());
213  }
214  }
215 };
216 
217 inline bool exclude_key(const char *key) {
218  if (strncmp(key, "FILTER_SELECT_", 14) == 0) {
219  if (strstr(key, "/2filter/2filter/2filter/")) {
220  return true;
221  }
222  }
223  else {
224  if (strstr(key, "SAVELOAD_CONFIG")) return true;
225  }
226  return false;
227 }
228 
229 inline bool is_wanted_callback(const char *key) {
230  return
231  GBS_read_hash(alreadyCalledHash, key) == 0 && // dont call twice
232  !exclude_key(key); // skip some problematic callbacks
233 }
234 
235 static int sortedByCallbackLocation(const char *k0, long v0, const char *k1, long v1) {
236  AW_cb *cbs0 = reinterpret_cast<AW_cb*>(v0);
237  AW_cb *cbs1 = reinterpret_cast<AW_cb*>(v1);
238 
239  int cmp = cbs0->compare(*cbs1);
240  if (!cmp) cmp = strcmp(k0, k1);
241 
242  return cmp;
243 }
244 
245 // ------------------------
246 // get_action_ids
247 
248 static void add_wanted_callbacks(const char *key, long /*val*/, void *cl_callbacks) {
249  if (is_wanted_callback(key)) {
250  CallbackArray *callbacks = reinterpret_cast<CallbackArray*>(cl_callbacks);
251  callbacks->push_back(string(key));
252  }
253 }
254 
255 ConstStrArray *AW_root::get_action_ids() {
256  if (!dontCallHash) build_dontCallHash();
257  CallbackArray callbacks;
258  GBS_hash_do_const_sorted_loop(prvt->action_hash, add_wanted_callbacks, GBS_HCF_sortedByKey, &callbacks);
259  return new StringVectorArray(callbacks);
260 }
261 
262 // --------------------------
263 // callallcallbacks
264 
265 size_t AW_root::callallcallbacks(int mode) {
266  // mode == -2 -> mark all as called
267  // mode == -1 -> forget called
268  // mode == 0 -> call all in alpha-order
269  // mode == 1 -> call all in reverse alpha-order
270  // mode == 2 -> call all in code-order
271  // mode == 3 -> call all in reverse code-order
272  // mode == 4 -> call all in random order
273  // mode & 8 -> repeat until no uncalled callbacks left
274 
275  size_t count = GBS_hash_elements(prvt->action_hash);
276  size_t callCount = 0;
277 
278  aw_message(GBS_global_string("Found %zi callbacks", count));
279 
280  if (!dontCallHash) build_dontCallHash();
281 
282  if (mode>0 && (mode&8)) {
283  aw_message("Calling callbacks iterated");
284  for (int iter = 1; ; ++iter) { // forever
285  size_t thisCount = callallcallbacks(mode&~8); // call all in wanted order
286  aw_message(GBS_global_string("%zu callbacks were called (iteration %i)", thisCount, iter));
287  if (!thisCount) {
288  aw_message("No uncalled callbacks left");
289  break;
290  }
291 
292  callCount += thisCount;
293  }
294  }
295  else if (mode == -1) {
296  forgetCalledCallbacks();
297  }
298  else {
299  CallbackArray callbacks;
300  switch (mode) {
301  case 0:
302  case 1:
303  GBS_hash_do_const_sorted_loop(prvt->action_hash, add_wanted_callbacks, GBS_HCF_sortedByKey, &callbacks);
304  break;
305  case 2:
306  case 3:
307  GBS_hash_do_const_sorted_loop(prvt->action_hash, add_wanted_callbacks, sortedByCallbackLocation, &callbacks);
308  break;
309  case -2:
310  aw_message("Marking all callbacks as \"called\"");
311  FALLTHROUGH;
312  case 4:
313  GBS_hash_do_const_loop(prvt->action_hash, add_wanted_callbacks, &callbacks);
314  break;
315  default:
316  aw_assert(0);
317  break;
318  }
319 
320  switch (mode) {
321  case -2:
322  case 0:
323  case 2: break; // use this order
324  case 1:
325  case 3: reverse(callbacks.begin(), callbacks.end()); break; // use reverse order
326  case 4: random_shuffle(callbacks.begin(), callbacks.end()); break; // use random order
327  default: aw_assert(0); break; // unknown mode
328  }
329 
330  count = callbacks.size();
331  aw_message(GBS_global_string("%zu callbacks were not called yet", count));
332 
333  CallbackIter end = callbacks.end();
334 
335  for (int pass = 1; pass <= 2; ++pass) {
336  size_t curr = 1;
337  CallbackIter cb = callbacks.begin();
338 
339  for (; cb != end; ++cb) {
340  const char *remote_command = cb->c_str();
341  const char *remote_command_name = remote_command;
342  {
343  const char *slash = strrchr(remote_command, '/');
344  if (slash) remote_command_name = slash+1;
345  }
346 
347  char firstNameChar = remote_command_name[0];
348  bool this_pass = firstNameChar == '-' ? (pass == 2) : (pass == 1);
349 
350  if (this_pass) {
351  GBS_write_hash(alreadyCalledHash, remote_command, 1); // don't call twice
352 
353  if (mode != -2) { // -2 means "only mark as called"
354  AW_cb *cbs = (AW_cb *)GBS_read_hash(prvt->action_hash, remote_command);
355  bool skipcb = firstNameChar == '!' || GBS_read_hash(dontCallHash, remote_command);
356 
357  if (!skipcb) {
358  if (cbs->contains(AnyWinCB(AW_help_entry_pressed))) skipcb = true;
359  }
360 
361  if (skipcb) {
362  fprintf(stderr, "Skipped callback %zu/%zu (%s)\n", curr, count, remote_command);
363  }
364  else {
365  fprintf(stderr, "Calling back %zu/%zu (%s)\n", curr, count, remote_command);
366 
367  GB_clear_error();
368 
369  cbs->run_callbacks();
370  callCount++;
371  process_pending_events();
372 
373  if (GB_have_error()) {
374  fprintf(stderr, "Unhandled error in '%s': %s\n", remote_command, GB_await_error());
375  }
376  }
377  }
378  }
379  else {
380  if (pass == 1) {
381  fprintf(stderr, "Delayed callback %zu/%zu (%s)\n", curr, count, remote_command);
382  }
383  }
384 
385  curr++;
386  }
387 
388  if (pass == 1) fprintf(stderr, "Executing delayed callbacks:\n");
389  }
390 
391  aw_message(GBS_global_string("%zu callbacks are marked as called now", GBS_hash_elements(alreadyCalledHash)));
392  }
393 
394  return callCount;
395 }
396 
397 // --------------------------------------------------------------------------------
398 #endif // DEBUG
399 
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
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:37
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:130
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