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