Changeset ce23cb4


Ignore:
Timestamp:
Oct 26, 2014, 12:46:23 PM (7 years ago)
Author:
Jason Gross <jasongross9@gmail.com>
Parents:
5f3f1e4 (diff), 3d1a2db (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:
Merge 3d1a2dbc8859c7f9fedbc769a8b3f529f40ff85e into 5f3f1e484f3c4b262b481efbd32602853bb41a27
Files:
1 added
9 edited

Legend:

Unmodified
Added
Removed
  • commands.c

    rca1fb26a r71085f0  
    487487              "\n"
    488488              "SEE ALSO: aaway, zaway"),
     489
     490  OWLCMD_ARGS("flush-logs", owl_command_flushlogs, OWL_CTX_ANY,
     491              "flush the queue of messages waiting to be logged",
     492              "flush-logs [-f | --force]",
     493              "If BarnOwl failed to log a file, this command tells\n"
     494              "BarnOwl to try logging the messages that have since\n"
     495              "come in, and to resume logging normally.\n"
     496              "\n"
     497              "Normally, if logging any of these messages fails,\n"
     498              "that message is added to the queue of messages waiting\n"
     499              "to be logged, and any new messages are deferred until\n"
     500              "the next :flush-logs.  If the --force flag is passed,\n"
     501              "any messages on the queue which cannot successfully be\n"
     502              "logged are dropped, and BarnOwl will resume logging\n"
     503              "normally."),
    489504
    490505  OWLCMD_ARGS("load-subs", owl_command_loadsubs, OWL_CTX_ANY,
     
    14331448{
    14341449  owl_function_unsuball();
     1450}
     1451
     1452char *owl_command_flushlogs(int argc, const char *const *argv, const char *buff)
     1453{
     1454  if (argc == 1) {
     1455    owl_log_flush_logs(false);
     1456  } else if (argc == 2) {
     1457    if (!strcmp(argv[1], "-f") || !strcmp(argv[1], "--force")) {
     1458      owl_log_flush_logs(true);
     1459    } else {
     1460      owl_function_makemsg("Invalid flag to flush-logs: %s", argv[1]);
     1461    }
     1462  } else {
     1463    owl_function_makemsg("Wrong number of arguments for flush-logs.");
     1464  }
     1465  return NULL;
    14351466}
    14361467
  • logging.c

    r7dcef03 r3d1a2db  
    1111static GMainLoop *log_loop;
    1212static GThread *logging_thread;
     13bool defer_logs;
     14static GQueue *deferred_entry_queue;
    1315
    1416/* This is now the one function that should be called to log a
     
    151153}
    152154
    153 static void owl_log_error(const char *message)
    154 {
    155   char *data = g_strdup(message);
     155static void owl_log_adminmsg_main_thread(gpointer data)
     156{
     157  owl_function_adminmsg("Logging", (const char*)data);
     158}
     159
     160static void G_GNUC_PRINTF(1, 2) owl_log_error(const char *fmt, ...)
     161{
     162  va_list ap;
     163  char *data;
     164
     165  va_start(ap, fmt);
     166  data = g_strdup_vprintf(fmt, ap);
     167  va_end(ap);
     168
    156169  owl_select_post_task(owl_log_error_main_thread,
    157                        data, g_free, g_main_context_default());
    158 }
    159 
    160 static void owl_log_write_entry(gpointer data)
    161 {
    162   owl_log_entry *msg = (owl_log_entry*)data;
     170                       data, g_free, g_main_context_default());
     171}
     172
     173static void G_GNUC_PRINTF(1, 2) owl_log_adminmsg(const char *fmt, ...)
     174{
     175  va_list ap;
     176  char *data;
     177
     178  va_start(ap, fmt);
     179  data = g_strdup_vprintf(fmt, ap);
     180  va_end(ap);
     181
     182  owl_select_post_task(owl_log_adminmsg_main_thread,
     183                       data, g_free, g_main_context_default());
     184}
     185
     186static CALLER_OWN owl_log_entry *owl_log_new_entry(const char *buffer, const char *filename)
     187{
     188  owl_log_entry *log_msg = g_slice_new(owl_log_entry);
     189  log_msg->message = g_strdup(buffer);
     190  log_msg->filename = g_strdup(filename);
     191  return log_msg;
     192}
     193
     194static void owl_log_deferred_enqueue_message(const char *buffer, const char *filename)
     195{
     196  g_queue_push_tail(deferred_entry_queue, owl_log_new_entry(buffer, filename));
     197}
     198
     199/* write out the entry if possible
     200 * return 0 on success, errno on failure to open
     201 */
     202static int owl_log_try_write_entry(owl_log_entry *msg)
     203{
    163204  FILE *file = NULL;
    164205  file = fopen(msg->filename, "a");
    165206  if (!file) {
    166     owl_log_error("Unable to open file for logging");
    167     return;
     207    return errno;
    168208  }
    169209  fprintf(file, "%s", msg->message);
    170210  fclose(file);
     211  return 0;
    171212}
    172213
     
    181222}
    182223
     224#if GLIB_CHECK_VERSION(2, 32, 0)
     225#else
     226static void owl_log_entry_free_gfunc(gpointer data, gpointer user_data)
     227{
     228  owl_log_entry_free(data);
     229}
     230#endif
     231
     232static void owl_log_file_error(owl_log_entry *msg, int ret)
     233{
     234  owl_log_error("Unable to open file for logging: %s (file %s)",
     235                g_strerror(ret),
     236                msg->filename);
     237}
     238
     239/* If we are deferring log messages, enqueue this entry for writing.
     240 * Otherwise, try to write this log message, and, if it fails with
     241 * EPERM, EACCES, or ETIMEDOUT, go into deferred logging mode and
     242 * queue an admin message.  If it fails with anything else, display an
     243 * error message, but do not go into deferred logging mode. */
     244static void owl_log_eventually_write_entry(gpointer data)
     245{
     246  int ret;
     247  owl_log_entry *msg = (owl_log_entry*)data;
     248  if (defer_logs) {
     249    owl_log_deferred_enqueue_message(msg->message, msg->filename);
     250  } else {
     251    ret = owl_log_try_write_entry(msg);
     252    if (ret == EPERM || ret == EACCES || ret == ETIMEDOUT) {
     253      defer_logs = true;
     254      owl_log_error("Unable to open file for logging (%s): \n"
     255                    "%s.  \n"
     256                    "Consider renewing your tickets.  Logging has been \n"
     257                    "suspended, and your messages will be saved.  To \n"
     258                    "resume logging, use the command :flush-logs.\n\n",
     259                    msg->filename,
     260                    g_strerror(ret));
     261      owl_log_deferred_enqueue_message(msg->message, msg->filename);
     262    } else if (ret != 0) {
     263      owl_log_file_error(msg, ret);
     264    }
     265  }
     266}
     267
     268/* tries to write the deferred log entries */
     269static void owl_log_write_deferred_entries(gpointer data)
     270{
     271  owl_log_entry *entry;
     272  bool drop_failed_logs = *(bool *)data;
     273  int ret;
     274  bool logged_at_least_one_message = false;
     275  bool all_succeeded = true;
     276
     277  defer_logs = false;
     278  while (!g_queue_is_empty(deferred_entry_queue) && !defer_logs) {
     279    logged_at_least_one_message = true;
     280    entry = (owl_log_entry*)g_queue_pop_head(deferred_entry_queue);
     281    if (drop_failed_logs) {
     282      owl_log_eventually_write_entry(entry);
     283    } else {
     284      ret = owl_log_try_write_entry(entry);
     285      if (ret != 0) {
     286        all_succeeded = false;
     287        owl_log_file_error(entry, ret);
     288      }
     289    }
     290    owl_log_entry_free(entry);
     291  }
     292  if (all_succeeded && logged_at_least_one_message) {
     293    owl_log_adminmsg("Logs have been flushed and logging has resumed.");
     294  }
     295}
     296
     297void owl_log_flush_logs(bool drop_failed_logs)
     298{
     299  bool *data = g_new(bool, 1);
     300  *data = drop_failed_logs;
     301
     302  owl_select_post_task(owl_log_write_deferred_entries,
     303                       data,
     304                       g_free,
     305                       log_context);
     306}
     307
    183308void owl_log_enqueue_message(const char *buffer, const char *filename)
    184309{
    185   owl_log_entry *log_msg = NULL;
    186   log_msg = g_slice_new(owl_log_entry);
    187   log_msg->message = g_strdup(buffer);
    188   log_msg->filename = g_strdup(filename);
    189   owl_select_post_task(owl_log_write_entry, log_msg,
     310  owl_log_entry *log_msg = owl_log_new_entry(buffer, filename);
     311  owl_select_post_task(owl_log_eventually_write_entry, log_msg,
    190312                       owl_log_entry_free, log_context);
    191313}
     
    429551static gpointer owl_log_thread_func(gpointer data)
    430552{
     553  log_context = g_main_context_new();
    431554  log_loop = g_main_loop_new(log_context, FALSE);
    432555  g_main_loop_run(log_loop);
     
    434557}
    435558
    436 void owl_log_init(void) 
     559void owl_log_init(void)
    437560{
    438561  log_context = g_main_context_new();
     
    454577  }
    455578#endif
    456  
     579
     580  deferred_entry_queue = g_queue_new();
    457581}
    458582
    459583static void owl_log_quit_func(gpointer data)
    460584{
     585  /* flush the deferred logs queue, trying to write the
     586   * entries to the disk one last time.  Drop any failed
     587   * entries */
     588  bool bool_true = true;
     589  owl_log_write_deferred_entries(&bool_true);
     590#if GLIB_CHECK_VERSION(2, 32, 0)
     591  g_queue_free_full(deferred_entry_queue, owl_log_entry_free);
     592#else
     593  g_queue_foreach(deferred_entry_queue, owl_log_entry_free_gfunc, NULL);
     594  g_queue_free(deferred_entry_queue);
     595#endif
     596
    461597  g_main_loop_quit(log_loop);
    462598}
  • perl/Makefile.am

    ra870319 r4772817  
    99        lib/BarnOwl/Completion/Context.pm \
    1010        lib/BarnOwl/Completion/Util.pm \
     11        lib/BarnOwl/DeferredLogging.pm \
    1112        lib/BarnOwl/Editwin.pm \
    1213        lib/BarnOwl/Help.pm \
  • perl/lib/BarnOwl.pm

    recd4edf r4772817  
    4545use BarnOwl::Completion;
    4646use BarnOwl::Help;
     47use BarnOwl::DeferredLogging;
    4748
    4849use List::Util qw(max);
  • .travis.yml

    r48c09d4 r5f3f1e4  
     1
    12language: perl
    23compiler:
     
    910  - "5.16"
    1011  - "5.18"
    11   - "5.19"
     12  - "5.20"
    1213install:
    1314  - sudo apt-get update -q
  • functions.c

    r7dcef03 rb61ad80  
    12271227  time_t now;
    12281228  va_list ap;
    1229   va_start(ap, fmt);
    12301229
    12311230  if (!owl_global_is_debug_fast(&g))
     
    12421241          (int) getpid(), tmpbuff, now - owl_global_get_starttime(&g));
    12431242  g_free(tmpbuff);
     1243
     1244  va_start(ap, fmt);
    12441245  vfprintf(file, fmt, ap);
     1246  va_end(ap);
     1247
    12451248  putc('\n', file);
    12461249  fflush(file);
    1247 
    1248   va_end(ap);
    12491250}
    12501251
  • util.c

    r7b89e8c rcba6b9c  
    468468  if (fstat(fileno(old), &st) != 0) {
    469469    owl_function_error("Cannot stat %s: %s", filename, strerror(errno));
     470    fclose(old);
    470471    return -1;
    471472  }
     
    473474  /* resolve symlinks, because link() fails on symlinks, at least on AFS */
    474475  actual_filename = owl_util_recursive_resolve_link(filename);
    475   if (actual_filename == NULL)
     476  if (actual_filename == NULL) {
     477    fclose(old);
    476478    return -1; /* resolving the symlink failed, but we already logged this error */
     479  }
    477480
    478481  newfile = g_strdup_printf("%s.new", actual_filename);
  • variable.c

    r7dcef03 r94b9ee0  
    10381038CALLER_OWN char *owl_variable_bool_get_tostring_default(const owl_variable *v, void *dummy)
    10391039{
    1040   bool val = owl_variable_get_bool(v);
    1041   if (val == 0) {
    1042     return g_strdup("off");
    1043   } else if (val == 1) {
    1044     return g_strdup("on");
    1045   } else {
    1046     return g_strdup("<invalid>");
    1047   }
     1040  return g_strdup(owl_variable_get_bool(v) ? "on" : "off");
    10481041}
    10491042
  • zephyr.c

    r7dcef03 r18380fd  
    283283#ifdef HAVE_LIBZEPHYR
    284284  FILE *file;
     285  int fopen_errno;
    285286  char *tmp, *start;
    286287  char *buffer = NULL;
     
    289290  int subSize = 1024;
    290291  int count;
    291   struct stat statbuff;
    292292
    293293  subsfile = owl_zephyr_dotfile(".zephyr.subs", filename);
    294294
    295   if (stat(subsfile, &statbuff) != 0) {
    296     g_free(subsfile);
    297     if (error_on_nofile == 1)
     295  count = 0;
     296  file = fopen(subsfile, "r");
     297  fopen_errno = errno;
     298  g_free(subsfile);
     299  if (!file) {
     300    if (error_on_nofile == 1 || fopen_errno != ENOENT)
    298301      return -1;
    299302    return 0;
    300303  }
    301 
    302   ZResetAuthentication();
    303   count = 0;
    304   file = fopen(subsfile, "r");
    305   g_free(subsfile);
    306   if (!file)
    307     return -1;
    308304
    309305  subs = g_new(ZSubscription_t, subSize);
     
    348344    g_free(buffer);
    349345
     346  ZResetAuthentication();
    350347  return owl_zephyr_loadsubs_helper(subs, count);
    351348#else
     
    412409  char *buffer = NULL;
    413410  int count;
    414   struct stat statbuff;
    415411
    416412  subs = g_new(ZSubscription_t, numSubs);
    417413  subsfile = owl_zephyr_dotfile(".anyone", filename);
    418414
    419   if (stat(subsfile, &statbuff) == -1) {
    420     g_free(subs);
    421     g_free(subsfile);
    422     return 0;
    423   }
    424 
    425   ZResetAuthentication();
    426415  count = 0;
    427416  file = fopen(subsfile, "r");
     
    445434    fclose(file);
    446435  } else {
     436    g_free(subs);
    447437    return 0;
    448438  }
    449439  g_free(buffer);
    450440
     441  ZResetAuthentication();
    451442  return owl_zephyr_loadsubs_helper(subs, count);
    452443#else
Note: See TracChangeset for help on using the changeset viewer.