~ubuntu-branches/ubuntu/maverick/mysql-5.1/maverick-proposed

« back to all changes in this revision

Viewing changes to sql/log.cc

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 14:16:05 UTC
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: package-import@ubuntu.com-20120222141605-nxlu9yzc6attylc2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
 
1
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
1217
1217
    file_log= file_log_handler->get_mysql_log();
1218
1218
    break;
1219
1219
  default:
1220
 
    assert(0);                                  // Impossible
 
1220
    MY_ASSERT_UNREACHABLE();
1221
1221
  }
1222
1222
 
1223
1223
  if (!(*tmp_opt))
1628
1628
  DBUG_RETURN(error);
1629
1629
}
1630
1630
 
 
1631
/**
 
1632
  Cleanup the cache.
 
1633
 
 
1634
  @param thd   The client thread that wants to clean up the cache.
 
1635
*/
 
1636
void MYSQL_BIN_LOG::reset_gathered_updates(THD *thd)
 
1637
{
 
1638
  binlog_trx_data *const trx_data=
 
1639
    (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
 
1640
 
 
1641
  trx_data->reset();
 
1642
}
 
1643
 
1631
1644
void MYSQL_BIN_LOG::set_write_error(THD *thd)
1632
1645
{
1633
1646
  DBUG_ENTER("MYSQL_BIN_LOG::set_write_error");
1699
1712
 
1700
1713
  String log_query;
1701
1714
  if (log_query.append(STRING_WITH_LEN("SAVEPOINT ")) ||
1702
 
      log_query.append(thd->lex->ident.str, thd->lex->ident.length))
 
1715
      log_query.append("`") ||
 
1716
      log_query.append(thd->lex->ident.str, thd->lex->ident.length) ||
 
1717
      log_query.append("`"))
1703
1718
    DBUG_RETURN(1);
1704
1719
  int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
1705
1720
  Query_log_event qinfo(thd, log_query.c_ptr_safe(), log_query.length(),
1721
1736
  {
1722
1737
    String log_query;
1723
1738
    if (log_query.append(STRING_WITH_LEN("ROLLBACK TO ")) ||
1724
 
        log_query.append(thd->lex->ident.str, thd->lex->ident.length))
 
1739
        log_query.append("`") ||
 
1740
        log_query.append(thd->lex->ident.str, thd->lex->ident.length) ||
 
1741
        log_query.append("`"))
1725
1742
      DBUG_RETURN(1);
1726
1743
    int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED);
1727
1744
    Query_log_event qinfo(thd, log_query.c_ptr_safe(), log_query.length(),
1837
1854
 
1838
1855
static int find_uniq_filename(char *name)
1839
1856
{
1840
 
  long                  number;
 
1857
  long                  number= 0;
1841
1858
  uint                  i;
1842
1859
  char                  buff[FN_REFLEN];
1843
1860
  struct st_my_dir     *dir_info;
1854
1871
  *end='.';
1855
1872
  length= (size_t) (end-start+1);
1856
1873
 
1857
 
  if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))
 
1874
  if ((DBUG_EVALUATE_IF("error_unique_log_filename", 1, 
 
1875
      !(dir_info = my_dir(buff,MYF(MY_DONT_SORT))))))
1858
1876
  {                                             // This shouldn't happen
1859
1877
    strmov(end,".1");                           // use name+1
1860
 
    DBUG_RETURN(0);
 
1878
    DBUG_RETURN(1);
1861
1879
  }
1862
1880
  file_info= dir_info->dir_entry;
1863
1881
  for (i=dir_info->number_off_files ; i-- ; file_info++)
1864
1882
  {
1865
 
    if (bcmp((uchar*) file_info->name, (uchar*) start, length) == 0 &&
 
1883
    if (memcmp(file_info->name, start, length) == 0 &&
1866
1884
        test_if_number(file_info->name+length, &number,0))
1867
1885
    {
1868
1886
      set_if_bigger(max_found,(ulong) number);
1871
1889
  my_dirend(dir_info);
1872
1890
 
1873
1891
  *end++='.';
1874
 
  sprintf(end,"%06ld",max_found+1);
1875
 
  DBUG_RETURN(0);
 
1892
  DBUG_RETURN((sprintf(end,"%06ld",max_found+1) < 0));
1876
1893
}
1877
1894
 
1878
1895
 
2084
2101
    {
2085
2102
      if (find_uniq_filename(new_name))
2086
2103
      {
 
2104
        my_printf_error(ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE),
 
2105
                        MYF(ME_FATALERROR), log_name);
2087
2106
        sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name);
2088
2107
        return 1;
2089
2108
      }
2580
2599
      sync_purge_index_file() ||
2581
2600
      DBUG_EVALUATE_IF("fault_injection_registering_index", 1, 0))
2582
2601
  {
 
2602
    /**
 
2603
        TODO: although this was introduced to appease valgrind
 
2604
              when injecting emulated faults using fault_injection_registering_index
 
2605
              it may be good to consider what actually happens when
 
2606
              open_purge_index_file succeeds but register or sync fails.
 
2607
 
 
2608
              Perhaps we might need the code below in MYSQL_LOG_BIN::cleanup
 
2609
              for "real life" purposes as well? 
 
2610
     */
 
2611
    DBUG_EXECUTE_IF("fault_injection_registering_index", {
 
2612
      if (my_b_inited(&purge_index_file))
 
2613
      {
 
2614
        end_io_cache(&purge_index_file);
 
2615
        my_close(purge_index_file.file, MYF(0));
 
2616
      }
 
2617
    });
 
2618
 
2583
2619
    sql_print_error("MSYQL_BIN_LOG::open failed to sync the index file.");
2584
2620
    DBUG_RETURN(1);
2585
2621
  }
2586
 
  DBUG_EXECUTE_IF("crash_create_non_critical_before_update_index", abort(););
 
2622
  DBUG_EXECUTE_IF("crash_create_non_critical_before_update_index", DBUG_SUICIDE(););
2587
2623
#endif
2588
2624
 
2589
2625
  write_error= 0;
2680
2716
    if (write_file_name_to_index_file)
2681
2717
    {
2682
2718
#ifdef HAVE_REPLICATION
2683
 
      DBUG_EXECUTE_IF("crash_create_critical_before_update_index", abort(););
 
2719
      DBUG_EXECUTE_IF("crash_create_critical_before_update_index", DBUG_SUICIDE(););
2684
2720
#endif
2685
2721
 
2686
2722
      DBUG_ASSERT(my_b_inited(&index_file) != 0);
2699
2735
        goto err;
2700
2736
 
2701
2737
#ifdef HAVE_REPLICATION
2702
 
      DBUG_EXECUTE_IF("crash_create_after_update_index", abort(););
 
2738
      DBUG_EXECUTE_IF("crash_create_after_update_index", DBUG_SUICIDE(););
2703
2739
#endif
2704
2740
    }
2705
2741
  }
2953
2989
  DBUG_ENTER("reset_logs");
2954
2990
 
2955
2991
  ha_reset_logs(thd);
2956
 
  /*
2957
 
    We need to get both locks to be sure that no one is trying to
2958
 
    write to the index log file.
2959
 
  */
2960
 
  pthread_mutex_lock(&LOCK_log);
2961
 
  pthread_mutex_lock(&LOCK_index);
2962
2992
 
2963
2993
  /*
2964
2994
    The following mutex is needed to ensure that no threads call
2966
2996
    thread. If the transaction involved MyISAM tables, it should go
2967
2997
    into binlog even on rollback.
2968
2998
  */
2969
 
  VOID(pthread_mutex_lock(&LOCK_thread_count));
 
2999
  pthread_mutex_lock(&LOCK_thread_count);
 
3000
 
 
3001
  /*
 
3002
    We need to get both locks to be sure that no one is trying to
 
3003
    write to the index log file.
 
3004
  */
 
3005
  pthread_mutex_lock(&LOCK_log);
 
3006
  pthread_mutex_lock(&LOCK_index);
2970
3007
 
2971
3008
  /* Save variables so that we can reopen the log */
2972
3009
  save_name=name;
3020
3057
  }
3021
3058
 
3022
3059
  /* Start logging with a new file */
3023
 
  close(LOG_CLOSE_INDEX);
 
3060
  close(LOG_CLOSE_INDEX | LOG_CLOSE_TO_BE_OPENED);
3024
3061
  if ((error= my_delete_allow_opened(index_file_name, MYF(0)))) // Reset (open will update)
3025
3062
  {
3026
3063
    if (my_errno == ENOENT) 
3049
3086
  if (!thd->slave_thread)
3050
3087
    need_start_event=1;
3051
3088
  if (!open_index_file(index_file_name, 0, FALSE))
3052
 
    open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE);
 
3089
    if ((error= open(save_name, log_type, 0, io_cache_type, no_auto_events, max_size, 0, FALSE)))
 
3090
      goto err;
3053
3091
  my_free((uchar*) save_name, MYF(0));
3054
3092
 
3055
3093
err:
3151
3189
  /* Store where we are in the new file for the execution thread */
3152
3190
  flush_relay_log_info(rli);
3153
3191
 
3154
 
  DBUG_EXECUTE_IF("crash_before_purge_logs", abort(););
 
3192
  DBUG_EXECUTE_IF("crash_before_purge_logs", DBUG_SUICIDE(););
3155
3193
 
3156
3194
  pthread_mutex_lock(&rli->log_space_lock);
3157
3195
  rli->relay_log.purge_logs(to_purge_if_included, included,
3279
3317
      break;
3280
3318
  }
3281
3319
 
3282
 
  DBUG_EXECUTE_IF("crash_purge_before_update_index", abort(););
 
3320
  DBUG_EXECUTE_IF("crash_purge_before_update_index", DBUG_SUICIDE(););
3283
3321
 
3284
3322
  if ((error= sync_purge_index_file()))
3285
3323
  {
3294
3332
    goto err;
3295
3333
  }
3296
3334
 
3297
 
  DBUG_EXECUTE_IF("crash_purge_critical_after_update_index", abort(););
 
3335
  DBUG_EXECUTE_IF("crash_purge_critical_after_update_index", DBUG_SUICIDE(););
3298
3336
 
3299
3337
err:
3300
3338
  /* Read each entry from purge_index_file and delete the file. */
3304
3342
                    " that would be purged.");
3305
3343
  close_purge_index_file();
3306
3344
 
3307
 
  DBUG_EXECUTE_IF("crash_purge_non_critical_after_update_index", abort(););
 
3345
  DBUG_EXECUTE_IF("crash_purge_non_critical_after_update_index", DBUG_SUICIDE(););
3308
3346
 
3309
3347
  if (need_mutex)
3310
3348
    pthread_mutex_unlock(&LOCK_index);
3711
3749
  incapsulation 3) allows external access to the class without
3712
3750
  a lock (which is not possible with private new_file_without_locking
3713
3751
  method).
 
3752
 
 
3753
  @retval
 
3754
    nonzero - error
3714
3755
*/
3715
3756
 
3716
 
void MYSQL_BIN_LOG::new_file()
 
3757
int MYSQL_BIN_LOG::new_file()
3717
3758
{
3718
 
  new_file_impl(1);
 
3759
  return new_file_impl(1);
3719
3760
}
3720
3761
 
3721
 
 
3722
 
void MYSQL_BIN_LOG::new_file_without_locking()
 
3762
/*
 
3763
  @retval
 
3764
    nonzero - error
 
3765
 */
 
3766
int MYSQL_BIN_LOG::new_file_without_locking()
3723
3767
{
3724
 
  new_file_impl(0);
 
3768
  return new_file_impl(0);
3725
3769
}
3726
3770
 
3727
3771
 
3730
3774
 
3731
3775
  @param need_lock              Set to 1 if caller has not locked LOCK_log
3732
3776
 
 
3777
  @retval
 
3778
    nonzero - error
 
3779
 
3733
3780
  @note
3734
3781
    The new file name is stored last in the index file
3735
3782
*/
3736
3783
 
3737
 
void MYSQL_BIN_LOG::new_file_impl(bool need_lock)
 
3784
int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
3738
3785
{
3739
 
  char new_name[FN_REFLEN], *new_name_ptr, *old_name;
 
3786
  int error= 0, close_on_error= FALSE;
 
3787
  char new_name[FN_REFLEN], *new_name_ptr, *old_name, *file_to_open;
3740
3788
 
3741
3789
  DBUG_ENTER("MYSQL_BIN_LOG::new_file_impl");
3742
3790
  if (!is_open())
3743
3791
  {
3744
3792
    DBUG_PRINT("info",("log is closed"));
3745
 
    DBUG_VOID_RETURN;
 
3793
    DBUG_RETURN(error);
3746
3794
  }
3747
3795
 
3748
3796
  if (need_lock)
3780
3828
    We have to do this here and not in open as we want to store the
3781
3829
    new file name in the current binary log file.
3782
3830
  */
3783
 
  if (generate_new_name(new_name, name))
 
3831
  if ((error= generate_new_name(new_name, name)))
3784
3832
    goto end;
3785
3833
  new_name_ptr=new_name;
3786
3834
 
3794
3842
      */
3795
3843
      Rotate_log_event r(new_name+dirname_length(new_name),
3796
3844
                         0, LOG_EVENT_OFFSET, is_relay_log ? Rotate_log_event::RELAY_LOG : 0);
3797
 
      r.write(&log_file);
 
3845
      if(DBUG_EVALUATE_IF("fault_injection_new_file_rotate_event", (error=close_on_error=TRUE), FALSE) ||
 
3846
         (error= r.write(&log_file)))
 
3847
      {
 
3848
        DBUG_EXECUTE_IF("fault_injection_new_file_rotate_event", errno=2;);
 
3849
        close_on_error= TRUE;
 
3850
        my_printf_error(ER_ERROR_ON_WRITE, ER(ER_CANT_OPEN_FILE), MYF(ME_FATALERROR), name, errno);
 
3851
        goto end;
 
3852
      }
3798
3853
      bytes_written += r.data_written;
3799
3854
    }
3800
3855
    /*
3822
3877
  */
3823
3878
 
3824
3879
  /* reopen index binlog file, BUG#34582 */
3825
 
  if (!open_index_file(index_file_name, 0, FALSE))
3826
 
    open(old_name, log_type, new_name_ptr,
3827
 
         io_cache_type, no_auto_events, max_size, 1, FALSE);
 
3880
  file_to_open= index_file_name;
 
3881
  error= open_index_file(index_file_name, 0, FALSE);
 
3882
  if (!error)
 
3883
  {
 
3884
    /* reopen the binary log file. */
 
3885
    file_to_open= new_name_ptr;
 
3886
    error= open(old_name, log_type, new_name_ptr, io_cache_type,
 
3887
                no_auto_events, max_size, 1, FALSE);
 
3888
  }
 
3889
 
 
3890
  /* handle reopening errors */
 
3891
  if (error)
 
3892
  {
 
3893
    my_printf_error(ER_CANT_OPEN_FILE, ER(ER_CANT_OPEN_FILE), 
 
3894
                    MYF(ME_FATALERROR), file_to_open, error);
 
3895
    close_on_error= TRUE;
 
3896
  }
 
3897
 
3828
3898
  my_free(old_name,MYF(0));
3829
3899
 
3830
3900
end:
 
3901
 
 
3902
  if (error && close_on_error /* rotate or reopen failed */)
 
3903
  {
 
3904
    /* 
 
3905
      Close whatever was left opened.
 
3906
 
 
3907
      We are keeping the behavior as it exists today, ie,
 
3908
      we disable logging and move on (see: BUG#51014).
 
3909
 
 
3910
      TODO: as part of WL#1790 consider other approaches:
 
3911
       - kill mysql (safety);
 
3912
       - try multiple locations for opening a log file;
 
3913
       - switch server to protected/readonly mode
 
3914
       - ...
 
3915
    */
 
3916
    close(LOG_CLOSE_INDEX);
 
3917
    sql_print_error("Could not open %s for logging (error %d). "
 
3918
                     "Turning logging off for the whole duration "
 
3919
                     "of the MySQL server process. To turn it on "
 
3920
                     "again: fix the cause, shutdown the MySQL "
 
3921
                     "server and restart it.", 
 
3922
                     new_name_ptr, errno);
 
3923
  }
 
3924
 
3831
3925
  if (need_lock)
3832
3926
    pthread_mutex_unlock(&LOCK_log);
3833
3927
  pthread_mutex_unlock(&LOCK_index);
3834
3928
 
3835
 
  DBUG_VOID_RETURN;
 
3929
  DBUG_RETURN(error);
3836
3930
}
3837
3931
 
3838
3932
 
3855
3949
  bytes_written+= ev->data_written;
3856
3950
  DBUG_PRINT("info",("max_size: %lu",max_size));
3857
3951
  if ((uint) my_b_append_tell(&log_file) > max_size)
3858
 
    new_file_without_locking();
3859
 
 
 
3952
    error= new_file_without_locking();
3860
3953
err:
3861
3954
  pthread_mutex_unlock(&LOCK_log);
3862
3955
  signal_update();                              // Safe as we don't call close
3885
3978
  } while ((buf=va_arg(args,const char*)) && (len=va_arg(args,uint)));
3886
3979
  DBUG_PRINT("info",("max_size: %lu",max_size));
3887
3980
  if ((uint) my_b_append_tell(&log_file) > max_size)
3888
 
    new_file_without_locking();
3889
 
 
 
3981
    error= new_file_without_locking();
3890
3982
err:
3891
3983
  if (!error)
3892
3984
    signal_update();
4235
4327
      if (!error)
4236
4328
      {
4237
4329
        signal_update();
4238
 
        rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
 
4330
        error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
4239
4331
      }
4240
4332
    }
4241
4333
 
4431
4523
      if (flush_and_sync())
4432
4524
        goto err;
4433
4525
      signal_update();
4434
 
      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
 
4526
      if ((error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED)))
 
4527
        goto err;
 
4528
      
4435
4529
    }
4436
4530
    error=0;
4437
4531
 
4514
4608
  return FALSE;
4515
4609
}
4516
4610
 
4517
 
void MYSQL_BIN_LOG::rotate_and_purge(uint flags)
 
4611
/**
 
4612
  @note
 
4613
    If rotation fails, for instance the server was unable 
 
4614
    to create a new log file, we still try to write an 
 
4615
    incident event to the current log.
 
4616
 
 
4617
  @retval
 
4618
    nonzero - error 
 
4619
*/
 
4620
int MYSQL_BIN_LOG::rotate_and_purge(uint flags)
4518
4621
{
 
4622
  int error= 0;
 
4623
  DBUG_ENTER("MYSQL_BIN_LOG::rotate_and_purge");
4519
4624
#ifdef HAVE_REPLICATION
4520
4625
  bool check_purge= false;
4521
4626
#endif
4524
4629
  if ((flags & RP_FORCE_ROTATE) ||
4525
4630
      (my_b_tell(&log_file) >= (my_off_t) max_size))
4526
4631
  {
4527
 
    new_file_without_locking();
 
4632
    if ((error= new_file_without_locking()))
 
4633
      /** 
 
4634
         Be conservative... There are possible lost events (eg, 
 
4635
         failing to log the Execute_load_query_log_event
 
4636
         on a LOAD DATA while using a non-transactional
 
4637
         table)!
 
4638
 
 
4639
         We give it a shot and try to write an incident event anyway
 
4640
         to the current log. 
 
4641
      */
 
4642
      if (!write_incident(current_thd, FALSE))
 
4643
        flush_and_sync();
 
4644
 
4528
4645
#ifdef HAVE_REPLICATION
4529
4646
    check_purge= true;
4530
4647
#endif
4531
4648
  }
4532
4649
  if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED))
4533
4650
    pthread_mutex_unlock(&LOCK_log);
4534
 
 
4535
4651
#ifdef HAVE_REPLICATION
4536
4652
  /*
4537
4653
    NOTE: Run purge_logs wo/ holding LOCK_log
4538
4654
          as it otherwise will deadlock in ndbcluster_binlog_index_purge_file
4539
4655
  */
4540
 
  if (check_purge && expire_logs_days)
 
4656
  if (!error && check_purge && expire_logs_days)
4541
4657
  {
4542
4658
    time_t purge_time= my_time(0) - expire_logs_days*24*60*60;
4543
4659
    if (purge_time >= 0)
4544
4660
      purge_logs_before_date(purge_time);
4545
4661
  }
4546
4662
#endif
 
4663
  DBUG_RETURN(error);
4547
4664
}
4548
4665
 
4549
4666
uint MYSQL_BIN_LOG::next_file_id()
4730
4847
{
4731
4848
  uint error= 0;
4732
4849
  DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
 
4850
 
 
4851
  if (!is_open())
 
4852
    DBUG_RETURN(error);
 
4853
 
4733
4854
  LEX_STRING const write_error_msg=
4734
4855
    { C_STRING_WITH_LEN("error writing to the binary log") };
4735
4856
  Incident incident= INCIDENT_LOST_EVENTS;
4742
4863
    if (!error && !(error= flush_and_sync()))
4743
4864
    {
4744
4865
      signal_update();
4745
 
      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
 
4866
      error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
4746
4867
    }
4747
4868
    pthread_mutex_unlock(&LOCK_log);
4748
4869
  }
4815
4936
                          DBUG_PRINT("info", ("error writing binlog cache: %d",
4816
4937
                                               write_error));
4817
4938
                        DBUG_PRINT("info", ("crashing before writing xid"));
4818
 
                        abort();
 
4939
                        DBUG_SUICIDE();
4819
4940
                      });
4820
4941
 
4821
4942
      if ((write_error= write_cache(cache, false, false)))
4829
4950
 
4830
4951
      if (flush_and_sync())
4831
4952
        goto err;
4832
 
      DBUG_EXECUTE_IF("half_binlogged_transaction", abort(););
 
4953
      DBUG_EXECUTE_IF("half_binlogged_transaction", DBUG_SUICIDE(););
4833
4954
      if (cache->error)                         // Error on read
4834
4955
      {
4835
4956
        sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
4854
4975
      pthread_mutex_unlock(&LOCK_prep_xids);
4855
4976
    }
4856
4977
    else
4857
 
      rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
 
4978
      if (rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED))
 
4979
        goto err;
4858
4980
  }
4859
4981
  VOID(pthread_mutex_unlock(&LOCK_log));
4860
4982
 
5050
5172
}
5051
5173
 
5052
5174
 
 
5175
/*
 
5176
  Change the file associated with two output streams. Used to
 
5177
  redirect stdout and stderr to a file. The streams are reopened
 
5178
  only for appending (writing at end of file).
 
5179
*/
 
5180
extern "C" my_bool reopen_fstreams(const char *filename,
 
5181
                                   FILE *outstream, FILE *errstream)
 
5182
{
 
5183
  if (outstream && !my_freopen(filename, "a", outstream))
 
5184
    return TRUE;
 
5185
 
 
5186
  if (errstream && !my_freopen(filename, "a", errstream))
 
5187
    return TRUE;
 
5188
 
 
5189
  /* The error stream must be unbuffered. */
 
5190
  if (errstream)
 
5191
    setbuf(errstream, NULL);
 
5192
 
 
5193
  return FALSE;
 
5194
}
 
5195
 
 
5196
 
 
5197
/*
 
5198
  Unfortunately, there seems to be no good way
 
5199
  to restore the original streams upon failure.
 
5200
*/
 
5201
static bool redirect_std_streams(const char *file)
 
5202
{
 
5203
  if (reopen_fstreams(file, stdout, stderr))
 
5204
    return TRUE;
 
5205
 
 
5206
  setbuf(stderr, NULL);
 
5207
  return FALSE;
 
5208
}
 
5209
 
 
5210
 
5053
5211
bool flush_error_log()
5054
5212
{
5055
 
  bool result=0;
 
5213
  bool result= 0;
5056
5214
  if (opt_error_log)
5057
5215
  {
5058
 
    char err_renamed[FN_REFLEN], *end;
5059
 
    end= strmake(err_renamed,log_error_file,FN_REFLEN-5);
5060
 
    strmov(end, "-old");
5061
5216
    VOID(pthread_mutex_lock(&LOCK_error_log));
5062
 
#ifdef __WIN__
5063
 
    char err_temp[FN_REFLEN+5];
5064
 
    /*
5065
 
     On Windows is necessary a temporary file for to rename
5066
 
     the current error file.
5067
 
    */
5068
 
    strxmov(err_temp, err_renamed,"-tmp",NullS);
5069
 
    (void) my_delete(err_temp, MYF(0)); 
5070
 
    if (freopen(err_temp,"a+",stdout))
5071
 
    {
5072
 
      int fd;
5073
 
      size_t bytes;
5074
 
      uchar buf[IO_SIZE];
5075
 
 
5076
 
      freopen(err_temp,"a+",stderr);
5077
 
      setbuf(stderr, NULL);
5078
 
      (void) my_delete(err_renamed, MYF(0));
5079
 
      my_rename(log_error_file,err_renamed,MYF(0));
5080
 
      if (freopen(log_error_file,"a+",stdout))
5081
 
      {
5082
 
        freopen(log_error_file,"a+",stderr);
5083
 
        setbuf(stderr, NULL);
5084
 
      }
5085
 
 
5086
 
      if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
5087
 
      {
5088
 
        while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) &&
5089
 
               bytes != MY_FILE_ERROR)
5090
 
          my_fwrite(stderr, buf, bytes, MYF(0));
5091
 
        my_close(fd, MYF(0));
5092
 
      }
5093
 
      (void) my_delete(err_temp, MYF(0)); 
5094
 
    }
5095
 
    else
5096
 
     result= 1;
5097
 
#else
5098
 
   my_rename(log_error_file,err_renamed,MYF(0));
5099
 
   if (freopen(log_error_file,"a+",stdout))
5100
 
   {
5101
 
     FILE *reopen;
5102
 
     reopen= freopen(log_error_file,"a+",stderr);
5103
 
     setbuf(stderr, NULL);
5104
 
   }
5105
 
   else
5106
 
     result= 1;
5107
 
#endif
 
5217
    if (redirect_std_streams(log_error_file))
 
5218
      result= 1;
5108
5219
    VOID(pthread_mutex_unlock(&LOCK_error_log));
5109
5220
  }
5110
 
   return result;
 
5221
  return result;
5111
5222
}
5112
5223
 
5113
5224
void MYSQL_BIN_LOG::signal_update()
5153
5264
#endif /* __NT__ */
5154
5265
 
5155
5266
 
5156
 
/**
5157
 
  Prints a printf style message to the error log and, under NT, to the
5158
 
  Windows event log.
5159
 
 
5160
 
  This function prints the message into a buffer and then sends that buffer
5161
 
  to other functions to write that message to other logging sources.
5162
 
 
5163
 
  @param event_type          Type of event to write (Error, Warning, or Info)
5164
 
  @param format              Printf style format of message
5165
 
  @param args                va_list list of arguments for the message
5166
 
 
5167
 
  @returns
5168
 
    The function always returns 0. The return value is present in the
5169
 
    signature to be compatible with other logging routines, which could
5170
 
    return an error (e.g. logging to the log tables)
5171
 
*/
5172
 
 
5173
5267
#ifndef EMBEDDED_LIBRARY
5174
 
static void print_buffer_to_file(enum loglevel level, const char *buffer)
 
5268
static void print_buffer_to_file(enum loglevel level, const char *buffer,
 
5269
                                 size_t length)
5175
5270
{
5176
5271
  time_t skr;
5177
5272
  struct tm tm_tmp;
5185
5280
  localtime_r(&skr, &tm_tmp);
5186
5281
  start=&tm_tmp;
5187
5282
 
5188
 
  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
 
5283
  fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %.*s\n",
5189
5284
          start->tm_year % 100,
5190
5285
          start->tm_mon+1,
5191
5286
          start->tm_mday,
5194
5289
          start->tm_sec,
5195
5290
          (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
5196
5291
           "Warning" : "Note"),
5197
 
          buffer);
 
5292
          (int) length, buffer);
5198
5293
 
5199
5294
  fflush(stderr);
5200
5295
 
5202
5297
  DBUG_VOID_RETURN;
5203
5298
}
5204
5299
 
5205
 
 
 
5300
/**
 
5301
  Prints a printf style message to the error log and, under NT, to the
 
5302
  Windows event log.
 
5303
 
 
5304
  This function prints the message into a buffer and then sends that buffer
 
5305
  to other functions to write that message to other logging sources.
 
5306
 
 
5307
  @param level          The level of the msg significance
 
5308
  @param format         Printf style format of message
 
5309
  @param args           va_list list of arguments for the message
 
5310
 
 
5311
  @returns
 
5312
    The function always returns 0. The return value is present in the
 
5313
    signature to be compatible with other logging routines, which could
 
5314
    return an error (e.g. logging to the log tables)
 
5315
*/
5206
5316
int vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
5207
5317
{
5208
5318
  char   buff[1024];
5210
5320
  DBUG_ENTER("vprint_msg_to_log");
5211
5321
 
5212
5322
  length= my_vsnprintf(buff, sizeof(buff), format, args);
5213
 
  print_buffer_to_file(level, buff);
 
5323
  print_buffer_to_file(level, buff, length);
5214
5324
 
5215
5325
#ifdef __NT__
5216
5326
  print_buffer_to_nt_eventlog(level, buff, length, sizeof(buff));
5218
5328
 
5219
5329
  DBUG_RETURN(0);
5220
5330
}
5221
 
#endif /*EMBEDDED_LIBRARY*/
 
5331
#endif /* EMBEDDED_LIBRARY */
5222
5332
 
5223
5333
 
5224
5334
void sql_print_error(const char *format, ...) 
5617
5727
  cookie points directly to the memory where xid was logged.
5618
5728
*/
5619
5729
 
5620
 
void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
 
5730
int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
5621
5731
{
5622
5732
  PAGE *p=pages+(cookie/tc_log_page_size);
5623
5733
  my_xid *x=(my_xid *)(data+cookie);
5635
5745
  if (p->waiters == 0)                 // the page is in pool and ready to rock
5636
5746
    pthread_cond_signal(&COND_pool);   // ping ... for overflow()
5637
5747
  pthread_mutex_unlock(&p->lock);
 
5748
  return 0;
5638
5749
}
5639
5750
 
5640
5751
void TC_LOG_MMAP::close()
5876
5987
  DBUG_RETURN(!binlog_end_trans(thd, trx_data, &xle, TRUE));
5877
5988
}
5878
5989
 
5879
 
void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
 
5990
int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
5880
5991
{
 
5992
  DBUG_ENTER("TC_LOG_BINLOG::unlog");
5881
5993
  pthread_mutex_lock(&LOCK_prep_xids);
5882
5994
  DBUG_ASSERT(prepared_xids > 0);
5883
5995
  if (--prepared_xids == 0) {
5885
5997
    pthread_cond_signal(&COND_prep_xids);
5886
5998
  }
5887
5999
  pthread_mutex_unlock(&LOCK_prep_xids);
5888
 
  rotate_and_purge(0);     // as ::write() did not rotate
 
6000
  DBUG_RETURN(rotate_and_purge(0));     // as ::write() did not rotate
5889
6001
}
5890
6002
 
5891
6003
int TC_LOG_BINLOG::recover(IO_CACHE *log, Format_description_log_event *fdle)