00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "myisam_priv.h"
00024 #include <drizzled/charset.h>
00025 #include <drizzled/util/test.h>
00026
00027 using namespace std;
00028 using namespace drizzled;
00029
00030
00031
00032 int mi_lock_database(MI_INFO *info, int lock_type)
00033 {
00034 int error;
00035 uint32_t count;
00036 MYISAM_SHARE *share=info->s;
00037 #if defined(FULL_LOG) || defined(_lint)
00038 uint32_t flag;
00039 #endif
00040
00041 if (!info->s->in_use)
00042 info->s->in_use= new list<Session *>;
00043
00044 if (lock_type == F_EXTRA_LCK)
00045 {
00046 ++share->w_locks;
00047 ++share->tot_locks;
00048 info->lock_type= lock_type;
00049 info->s->in_use->push_front(info->in_use);
00050 return(0);
00051 }
00052 #if defined(FULL_LOG) || defined(_lint)
00053 flag=0;
00054 #endif
00055
00056 error=0;
00057 if (share->kfile >= 0)
00058 {
00059 switch (lock_type) {
00060 case F_UNLCK:
00061 if (info->lock_type == F_RDLCK)
00062 count= --share->r_locks;
00063 else
00064 count= --share->w_locks;
00065 --share->tot_locks;
00066 if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
00067 {
00068 if (info->rec_cache.end_io_cache())
00069 {
00070 error=errno;
00071 mi_print_error(info->s, HA_ERR_CRASHED);
00072 mi_mark_crashed(info);
00073 }
00074 }
00075 if (!count)
00076 {
00077 if (share->changed && !share->w_locks)
00078 {
00079 if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
00080 (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
00081 {
00082 mi_remap_file(info, info->s->state.state.data_file_length);
00083 info->s->nonmmaped_inserts= 0;
00084 }
00085 share->state.process= share->last_process=share->this_process;
00086 share->state.unique= info->last_unique= info->this_unique;
00087 share->state.update_count= info->last_loop= ++info->this_loop;
00088 if (mi_state_info_write(share->kfile, &share->state, 1))
00089 error=errno;
00090 share->changed=0;
00091 share->not_flushed=1;
00092 if (error)
00093 {
00094 mi_print_error(info->s, HA_ERR_CRASHED);
00095 mi_mark_crashed(info);
00096 }
00097 }
00098 #if defined(FULL_LOG) || defined(_lint)
00099 if (info->lock_type != F_EXTRA_LCK)
00100 {
00101 if (share->r_locks)
00102 {
00103 flag=1;
00104 }
00105 else if (!share->w_locks)
00106 {
00107 flag=1;
00108 }
00109 }
00110 #endif
00111 }
00112 info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
00113 info->lock_type= F_UNLCK;
00114 info->s->in_use->remove(info->in_use);
00115 break;
00116 case F_RDLCK:
00117 if (info->lock_type == F_WRLCK)
00118 {
00119
00120
00121
00122
00123
00124
00125 #if defined(FULL_LOG) || defined(_lint)
00126 if (share->w_locks == 1)
00127 {
00128 flag=1;
00129 }
00130 #endif
00131 share->w_locks--;
00132 share->r_locks++;
00133 info->lock_type=lock_type;
00134 break;
00135 }
00136 if (!share->r_locks && !share->w_locks)
00137 {
00138 #if defined(FULL_LOG) || defined(_lint)
00139 flag=1;
00140 #endif
00141 if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
00142 {
00143 error=errno;
00144 break;
00145 }
00146 if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
00147 {
00148 error=errno;
00149 errno=error;
00150 break;
00151 }
00152 }
00153 _mi_test_if_changed(info);
00154 share->r_locks++;
00155 share->tot_locks++;
00156 info->lock_type=lock_type;
00157 info->s->in_use->push_front(info->in_use);
00158 break;
00159 case F_WRLCK:
00160 if (info->lock_type == F_RDLCK)
00161 {
00162 if (share->r_locks == 1)
00163 {
00164 #if defined(FULL_LOG) || defined(_lint)
00165 flag=1;
00166 #endif
00167 share->r_locks--;
00168 share->w_locks++;
00169 info->lock_type=lock_type;
00170 break;
00171 }
00172 }
00173 if (!(share->options & HA_OPTION_READ_ONLY_DATA))
00174 {
00175 if (!share->w_locks)
00176 {
00177 #if defined(FULL_LOG) || defined(_lint)
00178 flag=1;
00179 #endif
00180 if (!share->r_locks)
00181 {
00182 if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
00183 {
00184 error=errno;
00185 errno=error;
00186 break;
00187 }
00188 }
00189 }
00190 }
00191 _mi_test_if_changed(info);
00192
00193 info->lock_type=lock_type;
00194 share->w_locks++;
00195 share->tot_locks++;
00196 info->s->in_use->push_front(info->in_use);
00197 break;
00198 default:
00199 break;
00200 }
00201 }
00202 #ifdef __WIN__
00203 else
00204 {
00205
00206
00207
00208
00209
00210
00211 if( info->owned_by_merge && (info->s)->kfile < 0 )
00212 {
00213 error = HA_ERR_NO_SUCH_TABLE;
00214 }
00215 }
00216 #endif
00217 #if defined(FULL_LOG) || defined(_lint)
00218 lock_type|=(int) (flag << 8);
00219 myisam_log_command(MI_LOG_LOCK,info,(unsigned char*) &lock_type,sizeof(lock_type),
00220 error);
00221 #endif
00222 return(error);
00223 }
00224
00225
00226
00227
00228
00229
00230 int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
00231 {
00232 if (info->lock_type == F_UNLCK)
00233 {
00234 MYISAM_SHARE *share=info->s;
00235 if (!share->tot_locks)
00236 {
00237 if (mi_state_info_read_dsk(share->kfile, &share->state, 1))
00238 {
00239 int error=errno ? errno : -1;
00240 errno=error;
00241 return(1);
00242 }
00243 }
00244 if (check_keybuffer)
00245 _mi_test_if_changed(info);
00246 }
00247 else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
00248 {
00249 errno=EACCES;
00250 return(-1);
00251 }
00252 return(0);
00253 }
00254
00255
00256
00257
00258
00259
00260
00261 int _mi_writeinfo(register MI_INFO *info, uint32_t operation)
00262 {
00263 int error,olderror;
00264 MYISAM_SHARE *share=info->s;
00265
00266 error=0;
00267 if (share->tot_locks == 0)
00268 {
00269 olderror=errno;
00270 if (operation)
00271 {
00272 share->state.process= share->last_process= share->this_process;
00273 share->state.unique= info->last_unique= info->this_unique;
00274 share->state.update_count= info->last_loop= ++info->this_loop;
00275 if ((error=mi_state_info_write(share->kfile, &share->state, 1)))
00276 olderror=errno;
00277 }
00278 errno=olderror;
00279 }
00280 else if (operation)
00281 share->changed= 1;
00282 return(error);
00283 }
00284
00285
00286
00287
00288
00289 int _mi_test_if_changed(register MI_INFO *info)
00290 {
00291 MYISAM_SHARE *share=info->s;
00292 if (share->state.process != share->last_process ||
00293 share->state.unique != info->last_unique ||
00294 share->state.update_count != info->last_loop)
00295 {
00296 share->last_process=share->state.process;
00297 info->last_unique= share->state.unique;
00298 info->last_loop= share->state.update_count;
00299 info->update|= HA_STATE_WRITTEN;
00300 info->data_changed= 1;
00301 return 1;
00302 }
00303 return (!(info->update & HA_STATE_AKTIV) ||
00304 (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
00305 HA_STATE_KEY_CHANGED)));
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 int _mi_mark_file_changed(MI_INFO *info)
00327 {
00328 unsigned char buff[3];
00329 register MYISAM_SHARE *share=info->s;
00330
00331 if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
00332 {
00333 share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
00334 STATE_NOT_OPTIMIZED_KEYS);
00335 if (!share->global_changed)
00336 {
00337 share->global_changed=1;
00338 share->state.open_count++;
00339 }
00340 if (!share->temporary)
00341 {
00342 mi_int2store(buff,share->state.open_count);
00343 buff[2]=1;
00344 return(my_pwrite(share->kfile,buff,sizeof(buff),
00345 sizeof(share->state.header),
00346 MYF(MY_NABP)));
00347 }
00348 }
00349 return(0);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358 int _mi_decrement_open_count(MI_INFO *info)
00359 {
00360 unsigned char buff[2];
00361 register MYISAM_SHARE *share=info->s;
00362 int lock_error=0,write_error=0;
00363 if (share->global_changed)
00364 {
00365 uint32_t old_lock=info->lock_type;
00366 share->global_changed=0;
00367 lock_error=mi_lock_database(info,F_WRLCK);
00368
00369 if (share->state.open_count > 0)
00370 {
00371 share->state.open_count--;
00372 mi_int2store(buff,share->state.open_count);
00373 write_error=my_pwrite(share->kfile,buff,sizeof(buff),
00374 sizeof(share->state.header),
00375 MYF(MY_NABP));
00376 }
00377 if (!lock_error)
00378 lock_error=mi_lock_database(info,old_lock);
00379 }
00380 return test(lock_error || write_error);
00381 }