LTP GCOV extension - code coverage report
Current view: directory - storage/maria - ma_state.c
Test: maria-unit-test.html
Date: 2009-03-04 Instrumented lines: 206
Code covered: 37.4 % Executed lines: 77

       1                 : /* Copyright (C) 2008 Sun AB and Michael Widenius
       2                 : 
       3                 :    This program is free software; you can redistribute it and/or modify
       4                 :    it under the terms of the GNU General Public License as published by
       5                 :    the Free Software Foundation; version 2 of the License.
       6                 : 
       7                 :    This program is distributed in the hope that it will be useful,
       8                 :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9                 :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10                 :    GNU General Public License for more details.
      11                 : 
      12                 :    You should have received a copy of the GNU General Public License
      13                 :    along with this program; if not, write to the Free Software
      14                 :    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
      15                 : 
      16                 : /*
      17                 :   Functions to maintain live statistics for Maria transactional tables
      18                 :   and versioning for not transactional tables
      19                 : 
      20                 :   See WL#3138; Maria - fast "SELECT COUNT(*) FROM t;" and "CHECKSUM TABLE t"
      21                 :   for details about live number of rows and live checksums
      22                 : 
      23                 :   TODO
      24                 :    - Allocate MA_USED_TABLES and MA_HISTORY_STATE from a global pool (to
      25                 :      avoid calls to malloc()
      26                 :    - In trnamn_end_trans_hook(), don't call _ma_remove_not_visible_states()
      27                 :      every time. One could for example call it if there has been more than
      28                 :      10 ended transactions since last time it was called.
      29                 : */
      30                 : 
      31                 : #include "maria_def.h"
      32                 : #include "trnman.h"
      33                 : #include "ma_blockrec.h"
      34                 : 
      35                 : /**
      36                 :    @brief Setup initial start-of-transaction state for a table
      37                 : 
      38                 :    @fn     _ma_setup_live_state
      39                 :    @param info          Maria handler
      40                 : 
      41                 :    @notes
      42                 :      This function ensures that trn->used_tables contains a list of
      43                 :      start and live states for tables that are part of the transaction
      44                 :      and that info->state points to the current live state for the table.
      45                 : 
      46                 :    @TODO
      47                 :      Change trn->table_list to a hash and share->state_history to a binary tree
      48                 : 
      49                 :    @return
      50                 :    @retval 0  ok
      51                 :    @retval 1  error (out of memory)
      52                 : */
      53                 : 
      54                 : my_bool _ma_setup_live_state(MARIA_HA *info)
      55               0 : {
      56               0 :   TRN *trn= info->trn;
      57               0 :   MARIA_SHARE *share= info->s;
      58                 :   MARIA_USED_TABLES *tables;
      59                 :   MARIA_STATE_HISTORY *history;
      60               0 :   DBUG_ENTER("_ma_setup_live_state");
      61                 : 
      62               0 :   for (tables= (MARIA_USED_TABLES*) info->trn->used_tables;
      63               0 :        tables;
      64               0 :        tables= tables->next)
      65                 :   {
      66               0 :     if (tables->share == share)
      67                 :     {
      68                 :       /* Table is already used by transaction */
      69               0 :       goto end;
      70                 :     }
      71                 :   }
      72                 :   /* Table was not used before, create new table state entry */
      73               0 :   if (!(tables= (MARIA_USED_TABLES*) my_malloc(sizeof(*tables),
      74                 :                                                MYF(MY_WME | MY_ZEROFILL))))
      75               0 :     DBUG_RETURN(1);
      76               0 :   tables->next= trn->used_tables;
      77               0 :   trn->used_tables= tables;
      78               0 :   tables->share= share;
      79                 : 
      80               0 :   pthread_mutex_lock(&share->intern_lock);
      81               0 :   share->in_trans++;
      82               0 :   DBUG_PRINT("info", ("share: 0x%lx  in_trans: %d",
      83                 :                       (ulong) share, share->in_trans));
      84                 : 
      85               0 :   history= share->state_history;
      86                 : 
      87                 :   /*
      88                 :     We must keep share locked to ensure that we don't access a history
      89                 :     link that is deleted by concurrently running checkpoint.
      90                 : 
      91                 :     It's enough to compare trids here (instead of calling
      92                 :     tranman_can_read_from) as history->trid is a commit_trid
      93                 :   */
      94               0 :   while (trn->trid <= history->trid)
      95               0 :     history= history->next;
      96               0 :   pthread_mutex_unlock(&share->intern_lock);
      97                 :   /* The current item can't be deleted as it's the first one visible for us */
      98               0 :   tables->state_start=  tables->state_current= history->state;
      99               0 :   tables->state_current.changed= tables->state_current.no_transid= 0;
     100                 : 
     101               0 :   DBUG_PRINT("info", ("records: %ld", (ulong) tables->state_start.records));
     102                 : 
     103               0 : end:
     104               0 :   info->state_start= &tables->state_start;
     105               0 :   info->state= &tables->state_current;
     106                 : 
     107                 :   /*
     108                 :     Mark in transaction state if we are not using transid (versioning)
     109                 :     on rows. If not, then we will in _ma_trnman_end_trans_hook()
     110                 :     ensure that the state is visible for all at end of transaction
     111                 :   */
     112               0 :   tables->state_current.no_transid|= !(info->row_flag & ROW_FLAG_TRANSID);
     113                 : 
     114               0 :   DBUG_RETURN(0);
     115                 : }
     116                 : 
     117                 : 
     118                 : /**
     119                 :    @brief Remove states that are not visible by anyone
     120                 : 
     121                 :    @fn   _ma_remove_not_visible_states()
     122                 :    @param org_history    List to history
     123                 :    @param all            1 if we should delete the first state if it's
     124                 :                          visible for all.  For the moment this is only used
     125                 :                          on close() of table.
     126                 :    @param trnman_is_locked  Set to 1 if we have already a lock on trnman.
     127                 : 
     128                 :    @notes
     129                 :      The assumption is that items in the history list is ordered by
     130                 :      commit_trid.
     131                 : 
     132                 :      A state is not visible anymore if there is no new transaction
     133                 :      that has been started between the commit_trid's of two states
     134                 : 
     135                 :      As long as some states exists, we keep the newest = (last commit)
     136                 :      state as first state in the history.  This is to allow us to just move
     137                 :      the history from the global list to the share when we open the table.
     138                 : 
     139                 :      Note that if 'all' is set trnman_is_locked must be 0, becasue
     140                 :      trnman_get_min_trid() will take a lock on trnman.
     141                 : 
     142                 :    @return
     143                 :    @retval Pointer to new history list
     144                 : */
     145                 : 
     146                 : MARIA_STATE_HISTORY
     147                 : *_ma_remove_not_visible_states(MARIA_STATE_HISTORY *org_history,
     148                 :                                my_bool all,
     149                 :                                my_bool trnman_is_locked)
     150            3226 : {
     151                 :   TrID last_trid;
     152                 :   MARIA_STATE_HISTORY *history, **parent, *next;
     153            3226 :   DBUG_ENTER("_ma_remove_not_visible_states");
     154                 : 
     155            3226 :   if (!org_history)
     156             653 :     DBUG_RETURN(0);                          /* Not versioned table */
     157                 : 
     158            2573 :   last_trid= org_history->trid;
     159            2573 :   parent= &org_history->next;
     160            2573 :   for (history= org_history->next; history; history= next)
     161                 :   {
     162               0 :     next= history->next;
     163               0 :     if (!trnman_exists_active_transactions(history->trid, last_trid,
     164                 :                                            trnman_is_locked))
     165                 :     {
     166               0 :       DBUG_PRINT("info", ("removing history->trid: %lu  next: %lu",
     167                 :                           (ulong) history->trid, (ulong) last_trid));
     168               0 :       my_free(history, MYF(0));
     169               0 :       continue;
     170                 :     }
     171               0 :     *parent= history;
     172               0 :     parent= &history->next;
     173               0 :     last_trid= history->trid;
     174                 :   }
     175            2573 :   *parent= 0;
     176                 : 
     177            2573 :   if (all && parent == &org_history->next)
     178                 :   {
     179                 :     /* There is only one state left. Delete this if it's visible for all */
     180            2493 :     if (last_trid < trnman_get_min_trid())
     181                 :     {
     182            2493 :       my_free(org_history, MYF(0));
     183            2493 :       org_history= 0;
     184                 :     }
     185                 :   }
     186            2573 :   DBUG_RETURN(org_history);
     187                 : }
     188                 : 
     189                 : 
     190                 : /**
     191                 :    @brief Remove not used state history
     192                 : 
     193                 :    @param share          Maria table information
     194                 :    @param all            1 if we should delete the first state if it's
     195                 :                          visible for all.  For the moment this is only used
     196                 :                          on close() of table.
     197                 : 
     198                 :    @notes
     199                 :    share and trnman are not locked.
     200                 : 
     201                 :    We must first lock trnman and then share->intern_lock. This is becasue
     202                 :    _ma_trnman_end_trans_hook() has a lock on trnman and then
     203                 :    takes share->intern_lock.
     204                 : */
     205                 : 
     206                 : void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share,
     207                 :                                              my_bool all)
     208            3226 : {
     209                 :   my_bool is_lock_trman;
     210            3226 :   if ((is_lock_trman= trman_is_inited()))
     211             710 :     trnman_lock();
     212                 : 
     213            3226 :   pthread_mutex_lock(&share->intern_lock);
     214            3226 :   share->state_history=  _ma_remove_not_visible_states(share->state_history,
     215                 :                                                        all, 1);
     216            3226 :   pthread_mutex_unlock(&share->intern_lock);
     217            3226 :   if (is_lock_trman)
     218             710 :     trnman_unlock();
     219                 : }
     220                 : 
     221                 : 
     222                 : /*
     223                 :   Free state history information from share->history and reset information
     224                 :   to current state.
     225                 : 
     226                 :   @notes
     227                 :   Used after repair as then all rows are visible for everyone
     228                 : */
     229                 : 
     230                 : void _ma_reset_state(MARIA_HA *info)
     231             110 : {
     232             110 :   MARIA_SHARE *share= info->s;
     233             110 :   MARIA_STATE_HISTORY *history= share->state_history;
     234                 : 
     235             110 :   if (history)
     236                 :   {
     237                 :     MARIA_STATE_HISTORY *next;
     238                 : 
     239                 :     /* Set the current history to current state */
     240              44 :     share->state_history->state= share->state.state;
     241                 :     /* Set current table handler to point to new history state */
     242              44 :     info->state= info->state_start= &share->state_history->state;
     243              44 :     for (history= history->next ; history ; history= next)
     244                 :     {
     245               0 :       next= history->next;
     246               0 :       my_free(history, MYF(0));
     247                 :     }
     248              44 :     share->state_history->next= 0;
     249              44 :     share->state_history->trid= 0;              /* Visibile for all */
     250                 :   }
     251                 : }
     252                 : 
     253                 : 
     254                 : /****************************************************************************
     255                 :   The following functions are called by thr_lock() in threaded applications
     256                 :   for not transactional tables
     257                 : ****************************************************************************/
     258                 : 
     259                 : /*
     260                 :   Create a copy of the current status for the table
     261                 : 
     262                 :   SYNOPSIS
     263                 :     _ma_get_status()
     264                 :     param               Pointer to Myisam handler
     265                 :     concurrent_insert   Set to 1 if we are going to do concurrent inserts
     266                 :                         (THR_WRITE_CONCURRENT_INSERT was used)
     267                 : */
     268                 : 
     269                 : void _ma_get_status(void* param, my_bool concurrent_insert)
     270               0 : {
     271               0 :   MARIA_HA *info=(MARIA_HA*) param;
     272               0 :   DBUG_ENTER("_ma_get_status");
     273               0 :   DBUG_PRINT("info",("key_file: %ld  data_file: %ld  concurrent_insert: %d",
     274                 :                      (long) info->s->state.state.key_file_length,
     275                 :                      (long) info->s->state.state.data_file_length,
     276                 :                      concurrent_insert));
     277                 : #ifndef DBUG_OFF
     278               0 :   if (info->state->key_file_length > info->s->state.state.key_file_length ||
     279                 :       info->state->data_file_length > info->s->state.state.data_file_length)
     280               0 :     DBUG_PRINT("warning",("old info:  key_file: %ld  data_file: %ld",
     281                 :                           (long) info->state->key_file_length,
     282                 :                           (long) info->state->data_file_length));
     283                 : #endif
     284               0 :   info->state_save= info->s->state.state;
     285               0 :   info->state= &info->state_save;
     286               0 :   info->state->changed= 0;
     287               0 :   info->append_insert_at_end= concurrent_insert;
     288               0 :   DBUG_VOID_RETURN;
     289                 : }
     290                 : 
     291                 : 
     292                 : void _ma_update_status(void* param)
     293               0 : {
     294               0 :   MARIA_HA *info=(MARIA_HA*) param;
     295                 :   /*
     296                 :     Because someone may have closed the table we point at, we only
     297                 :     update the state if its our own state.  This isn't a problem as
     298                 :     we are always pointing at our own lock or at a read lock.
     299                 :     (This is enforced by thr_multi_lock.c)
     300                 :   */
     301               0 :   if (info->state == &info->state_save)
     302                 :   {
     303               0 :     MARIA_SHARE *share= info->s;
     304                 : #ifndef DBUG_OFF
     305               0 :     DBUG_PRINT("info",("updating status:  key_file: %ld  data_file: %ld",
     306                 :                        (long) info->state->key_file_length,
     307                 :                        (long) info->state->data_file_length));
     308               0 :     if (info->state->key_file_length < share->state.state.key_file_length ||
     309                 :         info->state->data_file_length < share->state.state.data_file_length)
     310               0 :       DBUG_PRINT("warning",("old info:  key_file: %ld  data_file: %ld",
     311                 :                             (long) share->state.state.key_file_length,
     312                 :                             (long) share->state.state.data_file_length));
     313                 : #endif
     314                 :     /*
     315                 :       we are going to modify the state without lock's log, this would break
     316                 :       recovery if done with a transactional table.
     317                 :     */
     318               0 :     DBUG_ASSERT(!info->s->base.born_transactional);
     319               0 :     share->state.state= *info->state;
     320               0 :     info->state= &share->state.state;
     321                 :   }
     322               0 :   info->append_insert_at_end= 0;
     323                 : }
     324                 : 
     325                 : 
     326                 : void _ma_restore_status(void *param)
     327               0 : {
     328               0 :   MARIA_HA *info= (MARIA_HA*) param;
     329               0 :   info->state= &info->s->state.state;
     330               0 :   info->append_insert_at_end= 0;
     331                 : }
     332                 : 
     333                 : 
     334                 : void _ma_copy_status(void* to, void *from)
     335               0 : {
     336               0 :   ((MARIA_HA*) to)->state= &((MARIA_HA*) from)->state_save;
     337                 : }
     338                 : 
     339                 : 
     340                 : void _ma_reset_update_flag(void *param,
     341                 :                            my_bool concurrent_insert __attribute__((unused)))
     342               0 : {
     343               0 :   MARIA_HA *info=(MARIA_HA*) param;
     344               0 :   info->state->changed= 0;
     345                 : }
     346                 : 
     347                 : 
     348                 : /**
     349                 :    @brief Check if should allow concurrent inserts
     350                 : 
     351                 :    @implementation
     352                 :      Allow concurrent inserts if we don't have a hole in the table or
     353                 :      if there is no active write lock and there is active read locks and
     354                 :      maria_concurrent_insert == 2. In this last case the new
     355                 :      row('s) are inserted at end of file instead of filling up the hole.
     356                 : 
     357                 :      The last case is to allow one to inserts into a heavily read-used table
     358                 :      even if there is holes.
     359                 : 
     360                 :    @notes
     361                 :      If there is a an rtree indexes in the table, concurrent inserts are
     362                 :      disabled in maria_open()
     363                 : 
     364                 :   @return
     365                 :   @retval 0  ok to use concurrent inserts
     366                 :   @retval 1  not ok
     367                 : */
     368                 : 
     369                 : my_bool _ma_check_status(void *param)
     370               0 : {
     371               0 :   MARIA_HA *info=(MARIA_HA*) param;
     372                 :   /*
     373                 :     The test for w_locks == 1 is here because this thread has already done an
     374                 :     external lock (in other words: w_locks == 1 means no other threads has
     375                 :     a write lock)
     376                 :   */
     377               0 :   DBUG_PRINT("info",("dellink: %ld  r_locks: %u  w_locks: %u",
     378                 :                      (long) info->s->state.dellink, (uint) info->s->r_locks,
     379                 :                      (uint) info->s->w_locks));
     380               0 :   return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
     381                 :                      (maria_concurrent_insert == 2 && info->s->r_locks &&
     382                 :                       info->s->w_locks == 1));
     383                 : }
     384                 : 
     385                 : 
     386                 : /**
     387                 :    @brief write hook at end of trans to store status for all used table
     388                 : 
     389                 :    @Notes
     390                 :    This function must be called under trnman_lock in trnman_end_trn()
     391                 :    because of the following reasons:
     392                 :    - After trnman_end_trn() is called, the current transaction will be
     393                 :    regarded as committed and all used tables state_history will be
     394                 :    visible to other transactions.  To do this, we loop over all used
     395                 :    tables and create/update a history entries that contains the correct
     396                 :    state_history for them.
     397                 : */
     398                 : 
     399                 : my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
     400                 :                                   my_bool active_transactions)
     401             770 : {
     402             770 :   my_bool error= 0;
     403                 :   MARIA_USED_TABLES *tables, *next;
     404             770 :   DBUG_ENTER("_ma_trnman_end_trans_hook");
     405                 :   
     406             770 :   for (tables= (MARIA_USED_TABLES*) trn->used_tables;
     407            1540 :        tables;
     408               0 :        tables= next)
     409                 :   {
     410               0 :     MARIA_SHARE *share= tables->share;
     411               0 :     next= tables->next;
     412               0 :     if (commit)
     413                 :     {
     414                 :       MARIA_STATE_HISTORY *history;
     415                 : 
     416               0 :       pthread_mutex_lock(&share->intern_lock);
     417                 : 
     418                 :       /* We only have to update history state if something changed */
     419               0 :       if (tables->state_current.changed)
     420                 :       {
     421               0 :         if (tables->state_current.no_transid)
     422                 :         {
     423                 :           /*
     424                 :             The change was done without using transid on rows (like in
     425                 :             bulk insert). In this case this thread is the only one
     426                 :             that is using the table and all rows will be visble
     427                 :             for all transactions.
     428                 :           */
     429               0 :           _ma_reset_history(share);
     430                 :         }
     431                 :         else
     432                 :         {
     433               0 :           if (active_transactions && share->now_transactional &&
     434                 :               trnman_exists_active_transactions(share->state_history->trid,
     435                 :                                                 trn->commit_trid, 1))
     436                 :           {
     437                 :             /*
     438                 :               There exist transactions that are still using the current
     439                 :               share->state_history.  Create a new history item for this
     440                 :               commit and add it first in the state_history list. This
     441                 :               ensures that all history items are stored in the list in
     442                 :               decresing trid order.
     443                 :             */
     444               0 :             if (!(history= my_malloc(sizeof(*history), MYF(MY_WME))))
     445                 :             {
     446                 :               /* purecov: begin inspected */
     447               0 :               error= 1;
     448               0 :               pthread_mutex_unlock(&share->intern_lock);
     449               0 :               my_free(tables, MYF(0));
     450               0 :               continue;
     451                 :               /* purecov: end */
     452                 :             }
     453               0 :             history->state= share->state_history->state;
     454               0 :             history->next= share->state_history;
     455               0 :             share->state_history= history;
     456                 :           }
     457                 :           else
     458                 :           {
     459                 :             /* Previous history can't be seen by anyone, reuse old memory */
     460               0 :             history= share->state_history;
     461               0 :             DBUG_PRINT("info", ("removing history->trid: %lu  new: %lu",
     462                 :                                 (ulong) history->trid,
     463                 :                                 (ulong) trn->commit_trid));
     464                 :           }
     465                 : 
     466               0 :           history->state.records+= (tables->state_current.records -
     467                 :                                     tables->state_start.records);
     468               0 :           history->state.checksum+= (tables->state_current.checksum -
     469                 :                                      tables->state_start.checksum);
     470               0 :           history->trid= trn->commit_trid;
     471                 : 
     472               0 :           if (history->next)
     473                 :           {
     474                 :             /* Remove not visible states */
     475               0 :             share->state_history= _ma_remove_not_visible_states(history, 0, 1);
     476                 :           }
     477               0 :           DBUG_PRINT("info", ("share: 0x%lx  in_trans: %d",
     478                 :                               (ulong) share, share->in_trans));
     479                 :         }
     480                 :       }
     481               0 :       share->in_trans--;
     482               0 :       pthread_mutex_unlock(&share->intern_lock);
     483                 :     }
     484                 :     else
     485                 :     {
     486                 : #ifndef DBUG_OFF
     487                 :       /*
     488                 :         We need to keep share->in_trans correct in the debug library
     489                 :         because of the assert in maria_close()
     490                 :       */
     491               0 :       pthread_mutex_lock(&share->intern_lock);
     492               0 :       share->in_trans--;
     493               0 :       pthread_mutex_unlock(&share->intern_lock);
     494                 : #endif
     495                 :     }
     496               0 :     my_free(tables, MYF(0));
     497                 :   }
     498             770 :   trn->used_tables= 0;
     499             770 :   DBUG_RETURN(error);
     500                 : }
     501                 : 
     502                 : 
     503                 : /**
     504                 :    Remove table from trnman_list
     505                 : 
     506                 :    @notes
     507                 :      This is used when we unlock a table from a group of locked tables
     508                 :      just before doing a rename or drop table.
     509                 : 
     510                 :      share->internal_lock must be locked when function is called
     511                 : */
     512                 : 
     513                 : void _ma_remove_table_from_trnman(MARIA_SHARE *share, TRN *trn)
     514               0 : {
     515                 :   MARIA_USED_TABLES *tables, **prev;
     516               0 :   DBUG_ENTER("_ma_remove_table_from_trnman");
     517               0 :   DBUG_PRINT("enter", ("share: 0x%lx  in_trans: %d",
     518                 :                        (ulong) share, share->in_trans));
     519                 : 
     520               0 :   safe_mutex_assert_owner(&share->intern_lock);
     521                 :   
     522               0 :   for (prev= (MARIA_USED_TABLES**) &trn->used_tables, tables= *prev;
     523               0 :        tables;
     524               0 :        tables= *prev)
     525                 :   {
     526               0 :     if (tables->share == share)
     527                 :     {
     528               0 :       *prev= tables->next;
     529               0 :       share->in_trans--;
     530               0 :       DBUG_PRINT("info", ("in_trans: %d", share->in_trans));
     531               0 :       my_free(tables, MYF(0));
     532               0 :       break;
     533                 :     }
     534               0 :     prev= &tables->next;
     535                 :   }
     536               0 :   DBUG_VOID_RETURN;
     537                 : }
     538                 : 
     539                 : 
     540                 : 
     541                 : /****************************************************************************
     542                 :   The following functions are called by thr_lock() in threaded applications
     543                 :   for transactional tables.
     544                 : ****************************************************************************/
     545                 : 
     546                 : /*
     547                 :   Create a copy of the current status for the table
     548                 : 
     549                 :   SYNOPSIS
     550                 :     _ma_get_status()
     551                 :     param               Pointer to Myisam handler
     552                 :     concurrent_insert   Set to 1 if we are going to do concurrent inserts
     553                 :                         (THR_WRITE_CONCURRENT_INSERT was used)
     554                 : */
     555                 : 
     556                 : void _ma_block_get_status(void* param, my_bool concurrent_insert)
     557             143 : {
     558             143 :   MARIA_HA *info=(MARIA_HA*) param;
     559             143 :   DBUG_ENTER("_ma_block_get_status");
     560             143 :   DBUG_PRINT("info", ("concurrent_insert %d", concurrent_insert));
     561             143 :   info->row_base_length= info->s->base_length;
     562             143 :   info->row_flag= info->s->base.default_row_flag;
     563             143 :   if (concurrent_insert)
     564                 :   {
     565             143 :     DBUG_ASSERT(info->lock.type == TL_WRITE_CONCURRENT_INSERT);
     566             143 :     info->row_flag|= ROW_FLAG_TRANSID;
     567             143 :     info->row_base_length+= TRANSID_SIZE;
     568                 :   }
     569                 :   else
     570                 :   {
     571               0 :     DBUG_ASSERT(info->lock.type != TL_WRITE_CONCURRENT_INSERT);
     572                 :   }
     573                 : 
     574             143 :   if (info->s->lock_key_trees)
     575                 :   {
     576                 :     /*
     577                 :       Assume for now that this doesn't fail (It can only fail in
     578                 :       out of memory conditions)
     579                 :       TODO: Fix this by having one extra state pre-allocated
     580                 :     */
     581               0 :     (void) _ma_setup_live_state(info);
     582                 :   }
     583             143 :   DBUG_VOID_RETURN;
     584                 : }
     585                 : 
     586                 : 
     587                 : void _ma_block_update_status(void *param __attribute__((unused)))
     588             135 : {
     589                 : }
     590                 : 
     591                 : void _ma_block_restore_status(void *param __attribute__((unused)))
     592               0 : {
     593                 : }
     594                 : 
     595                 : 
     596                 : /**
     597                 :   Check if should allow concurrent inserts
     598                 : 
     599                 :   @return
     600                 :   @retval 0  ok to use concurrent inserts
     601                 :   @retval 1  not ok
     602                 : */
     603                 : 
     604                 : my_bool _ma_block_check_status(void *param __attribute__((unused)))
     605               0 : {
     606               0 :   return (my_bool) 0;
     607                 : }
     608                 : 
     609                 : 
     610                 : /**
     611                 :   Enable/disable versioning
     612                 : */
     613                 : 
     614                 : void maria_versioning(MARIA_HA *info, my_bool versioning)
     615             253 : {
     616                 :   /* For now, this is a hack */
     617             253 :   if (info->s->have_versioning)
     618                 :   {
     619                 :     enum thr_lock_type save_lock_type;
     620                 :     /* Assume is a non threaded application (for now) */
     621             143 :     info->s->lock_key_trees= 0;
     622                 :     /* Set up info->lock.type temporary for _ma_block_get_status() */
     623             143 :     save_lock_type= info->lock.type;
     624             143 :     info->lock.type= versioning ? TL_WRITE_CONCURRENT_INSERT : TL_WRITE;
     625             143 :     _ma_block_get_status((void*) info, versioning);
     626             143 :     info->lock.type= save_lock_type;
     627                 :   }
     628                 : }
     629                 : 
     630                 : 
     631                 : /**
     632                 :    Update data_file_length to new length
     633                 : 
     634                 :    NOTES
     635                 :      Only used by block records
     636                 : */
     637                 : 
     638                 : void _ma_set_share_data_file_length(MARIA_SHARE *share, ulonglong new_length)
     639            5610 : {
     640            5610 :   pthread_mutex_lock(&share->intern_lock);
     641            5610 :   if (share->state.state.data_file_length < new_length)
     642            5610 :     share->state.state.data_file_length= new_length;
     643            5610 :   pthread_mutex_unlock(&share->intern_lock);
     644                 : }
     645                 : 
     646                 : 
     647                 : /**
     648                 :    Copy state information that where updated while the table was used
     649                 :    in not transactional mode
     650                 : */
     651                 : 
     652                 : void _ma_copy_nontrans_state_information(MARIA_HA *info)
     653             575 : {
     654             575 :   info->s->state.state.records=          info->state->records;
     655             575 :   info->s->state.state.checksum=         info->state->checksum;
     656                 : }
     657                 : 
     658                 : 
     659                 : void _ma_reset_history(MARIA_SHARE *share)
     660             575 : {
     661                 :   MARIA_STATE_HISTORY *history, *next;
     662             575 :   DBUG_ENTER("_ma_reset_history");
     663                 : 
     664             575 :   share->state_history->trid= 0;          /* Visibly by all */
     665             575 :   share->state_history->state= share->state.state;
     666             575 :   history= share->state_history->next;
     667             575 :   share->state_history->next= 0;
     668                 : 
     669             575 :   for (; history; history= next)
     670                 :   {
     671               0 :     next= history->next;
     672               0 :     my_free(history, MYF(0));
     673                 :   }
     674             575 :   DBUG_VOID_RETURN;
     675                 : }
     676                 : 
     677                 : 
     678                 : /****************************************************************************
     679                 :   Virtual functions to check if row is visible
     680                 : ****************************************************************************/
     681                 : 
     682                 : /**
     683                 :    Row is always visible
     684                 :    This is for tables without concurrent insert
     685                 : */
     686                 : 
     687                 : my_bool _ma_row_visible_always(MARIA_HA *info __attribute__((unused)))
     688          227793 : {
     689          227793 :   return 1;
     690                 : }
     691                 : 
     692                 : 
     693                 : /**
     694                 :    Row visibility for non transactional tables with concurrent insert
     695                 : 
     696                 :    @implementation
     697                 :    When we got our table lock, we saved the current
     698                 :    data_file_length. Concurrent inserts always go to the end of the
     699                 :    file. So we can test if the found key references a new record.
     700                 : */
     701                 : 
     702                 : my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info)
     703               0 : {
     704               0 :   return info->cur_row.lastpos < info->state->data_file_length;
     705                 : }
     706                 : 
     707                 : 
     708                 : /**
     709                 :    Row visibility for transactional tables with versioning
     710                 : 
     711                 : 
     712                 :    @TODO
     713                 :    Add test if found key was marked deleted and it was deleted by
     714                 :    us. In that case we should return 0
     715                 : */
     716                 : 
     717                 : my_bool _ma_row_visible_transactional_table(MARIA_HA *info)
     718           48887 : {
     719           48887 :   return trnman_can_read_from(info->trn, info->cur_row.trid);
     720                 : }

Generated by: LTP GCOV extension version 1.4