~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2002, 2004-2006 MySQL AB
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
	/* Functions to handle fixed-length-records */
17
18
#include "myisamdef.h"
19
20
21
int _mi_write_static_record(MI_INFO *info, const uchar *record)
22
{
23
  uchar temp[8];				/* max pointer length */
24
  if (info->s->state.dellink != HA_OFFSET_ERROR &&
25
      !info->append_insert_at_end)
26
  {
27
    my_off_t filepos=info->s->state.dellink;
28
    info->rec_cache.seek_not_done=1;		/* We have done a seek */
29
    if (info->s->file_read(info, &temp[0],info->s->base.rec_reflength,
30
		info->s->state.dellink+1,
31
		 MYF(MY_NABP)))
32
      goto err;
33
    info->s->state.dellink= _mi_rec_pos(info->s,temp);
34
    info->state->del--;
35
    info->state->empty-=info->s->base.pack_reclength;
36
    if (info->s->file_write(info, record, info->s->base.reclength,
37
		  filepos,
38
		  MYF(MY_NABP)))
39
      goto err;
40
  }
41
  else
42
  {
43
    if (info->state->data_file_length > info->s->base.max_data_file_length-
44
	info->s->base.pack_reclength)
45
    {
46
      my_errno=HA_ERR_RECORD_FILE_FULL;
47
      return(2);
48
    }
49
    if (info->opt_flag & WRITE_CACHE_USED)
50
    {				/* Cash in use */
51
      if (my_b_write(&info->rec_cache, record,
52
		     info->s->base.reclength))
53
	goto err;
54
      if (info->s->base.pack_reclength != info->s->base.reclength)
55
      {
56
	uint length=info->s->base.pack_reclength - info->s->base.reclength;
57
	bzero(temp,length);
58
	if (my_b_write(&info->rec_cache, temp,length))
59
	  goto err;
60
      }
61
    }
62
    else
63
    {
64
      info->rec_cache.seek_not_done=1;		/* We have done a seek */
65
      if (info->s->file_write(info, record, info->s->base.reclength,
66
		    info->state->data_file_length,
67
		    info->s->write_flag))
68
        goto err;
69
      if (info->s->base.pack_reclength != info->s->base.reclength)
70
      {
71
	uint length=info->s->base.pack_reclength - info->s->base.reclength;
72
	bzero(temp,length);
73
	if (info->s->file_write(info, temp,length,
74
		      info->state->data_file_length+
75
		      info->s->base.reclength,
76
		      info->s->write_flag))
77
    goto err;
78
      }
79
    }
80
    info->state->data_file_length+=info->s->base.pack_reclength;
81
    info->s->state.split++;
82
  }
83
  return 0;
84
 err:
85
  return 1;
86
}
87
88
int _mi_update_static_record(MI_INFO *info, my_off_t pos, const uchar *record)
89
{
90
  info->rec_cache.seek_not_done=1;		/* We have done a seek */
91
  return (info->s->file_write(info,
92
                              record, info->s->base.reclength,
93
                              pos,
94
                              MYF(MY_NABP)) != 0);
95
}
96
97
98
int _mi_delete_static_record(MI_INFO *info)
99
{
100
  uchar temp[9];				/* 1+sizeof(uint32) */
101
102
  info->state->del++;
103
  info->state->empty+=info->s->base.pack_reclength;
104
  temp[0]= '\0';			/* Mark that record is deleted */
105
  _mi_dpointer(info,temp+1,info->s->state.dellink);
106
  info->s->state.dellink = info->lastpos;
107
  info->rec_cache.seek_not_done=1;
108
  return (info->s->file_write(info,(uchar*) temp, 1+info->s->rec_reflength,
109
		    info->lastpos, MYF(MY_NABP)) != 0);
110
}
111
112
113
int _mi_cmp_static_record(register MI_INFO *info, register const uchar *old)
114
{
115
  DBUG_ENTER("_mi_cmp_static_record");
116
117
  /* We are going to do changes; dont let anybody disturb */
118
  dont_break();				/* Dont allow SIGHUP or SIGINT */
119
120
  if (info->opt_flag & WRITE_CACHE_USED)
121
  {
122
    if (flush_io_cache(&info->rec_cache))
123
    {
124
      DBUG_RETURN(-1);
125
    }
126
    info->rec_cache.seek_not_done=1;		/* We have done a seek */
127
  }
128
129
  if ((info->opt_flag & READ_CHECK_USED))
130
  {						/* If check isn't disabled  */
131
    info->rec_cache.seek_not_done=1;		/* We have done a seek */
132
    if (info->s->file_read(info, info->rec_buff, info->s->base.reclength,
133
		 info->lastpos,
134
		 MYF(MY_NABP)))
135
      DBUG_RETURN(-1);
136
    if (memcmp(info->rec_buff, old,
137
	       (uint) info->s->base.reclength))
138
    {
139
      DBUG_DUMP("read",old,info->s->base.reclength);
140
      DBUG_DUMP("disk",info->rec_buff,info->s->base.reclength);
141
      my_errno=HA_ERR_RECORD_CHANGED;		/* Record have changed */
142
      DBUG_RETURN(1);
143
    }
144
  }
145
  DBUG_RETURN(0);
146
}
147
148
149
int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
150
			  const uchar *record, my_off_t pos)
151
{
152
  DBUG_ENTER("_mi_cmp_static_unique");
153
154
  info->rec_cache.seek_not_done=1;		/* We have done a seek */
155
  if (info->s->file_read(info, info->rec_buff, info->s->base.reclength,
156
	       pos, MYF(MY_NABP)))
157
    DBUG_RETURN(-1);
158
  DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff,
159
			     def->null_are_equal));
160
}
161
162
163
	/* Read a fixed-length-record */
164
	/* Returns 0 if Ok. */
165
	/*	   1 if record is deleted */
166
	/*	  MY_FILE_ERROR on read-error or locking-error */
167
168
int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
169
			   register uchar *record)
170
{
171
  int error;
172
173
  if (pos != HA_OFFSET_ERROR)
174
  {
175
    if (info->opt_flag & WRITE_CACHE_USED &&
176
	info->rec_cache.pos_in_file <= pos &&
177
	flush_io_cache(&info->rec_cache))
178
      return(-1);
179
    info->rec_cache.seek_not_done=1;		/* We have done a seek */
180
181
    error=info->s->file_read(info, record, info->s->base.reclength,
182
		   pos,MYF(MY_NABP)) != 0;
183
    fast_mi_writeinfo(info);
184
    if (! error)
185
    {
186
      if (!*record)
187
      {
188
	my_errno=HA_ERR_RECORD_DELETED;
189
	return(1);				/* Record is deleted */
190
      }
191
      info->update|= HA_STATE_AKTIV;		/* Record is read */
192
      return(0);
193
    }
194
    return(-1);					/* Error on read */
195
  }
196
  fast_mi_writeinfo(info);			/* No such record */
197
  return(-1);
198
}
199
200
201
202
int _mi_read_rnd_static_record(MI_INFO *info, uchar *buf,
203
			       register my_off_t filepos,
204
			       my_bool skip_deleted_blocks)
205
{
206
  int locked,error,cache_read;
207
  uint cache_length;
208
  MYISAM_SHARE *share=info->s;
209
  DBUG_ENTER("_mi_read_rnd_static_record");
210
211
  cache_read=0;
212
  cache_length=0;
213
  if (info->opt_flag & WRITE_CACHE_USED &&
214
      (info->rec_cache.pos_in_file <= filepos || skip_deleted_blocks) &&
215
      flush_io_cache(&info->rec_cache))
216
    DBUG_RETURN(my_errno);
217
  if (info->opt_flag & READ_CACHE_USED)
218
  {						/* Cache in use */
219
    if (filepos == my_b_tell(&info->rec_cache) &&
220
	(skip_deleted_blocks || !filepos))
221
    {
222
      cache_read=1;				/* Read record using cache */
223
      cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
224
    }
225
    else
226
      info->rec_cache.seek_not_done=1;		/* Filepos is changed */
227
  }
228
  locked=0;
229
  if (info->lock_type == F_UNLCK)
230
  {
231
    if (filepos >= info->state->data_file_length)
232
    {						/* Test if new records */
233
      if (_mi_readinfo(info,F_RDLCK,0))
234
	DBUG_RETURN(my_errno);
235
      locked=1;
236
    }
237
    else
238
    {						/* We don't nead new info */
239
#ifndef UNSAFE_LOCKING
240
      if ((! cache_read || share->base.reclength > cache_length) &&
241
	  share->tot_locks == 0)
242
      {						/* record not in cache */
243
	if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
244
		    MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
245
	  DBUG_RETURN(my_errno);
246
	locked=1;
247
      }
248
#else
249
      info->tmp_lock_type=F_RDLCK;
250
#endif
251
    }
252
  }
253
  if (filepos >= info->state->data_file_length)
254
  {
255
    DBUG_PRINT("test",("filepos: %ld (%ld)  records: %ld  del: %ld",
256
		       (long) filepos/share->base.reclength, (long) filepos,
257
		       (long) info->state->records, (long) info->state->del));
258
    fast_mi_writeinfo(info);
259
    DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE);
260
  }
261
  info->lastpos= filepos;
262
  info->nextpos= filepos+share->base.pack_reclength;
263
264
  if (! cache_read)			/* No cacheing */
265
  {
266
    if ((error=_mi_read_static_record(info,filepos,buf)))
267
    {
268
      if (error > 0)
269
	error=my_errno=HA_ERR_RECORD_DELETED;
270
      else
271
	error=my_errno;
272
    }
273
    DBUG_RETURN(error);
274
  }
275
276
	/* Read record with cacheing */
277
  error=my_b_read(&info->rec_cache,(uchar*) buf,share->base.reclength);
278
  if (info->s->base.pack_reclength != info->s->base.reclength && !error)
279
  {
280
    char tmp[8];				/* Skill fill bytes */
281
    error=my_b_read(&info->rec_cache,(uchar*) tmp,
282
		    info->s->base.pack_reclength - info->s->base.reclength);
283
  }
284
  if (locked)
285
    VOID(_mi_writeinfo(info,0));		/* Unlock keyfile */
286
  if (!error)
287
  {
288
    if (!buf[0])
289
    {						/* Record is removed */
290
      DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
291
    }
292
						/* Found and may be updated */
293
    info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
294
    DBUG_RETURN(0);
295
  }
296
  /* my_errno should be set if rec_cache.error == -1 */
297
  if (info->rec_cache.error != -1 || my_errno == 0)
298
    my_errno=HA_ERR_WRONG_IN_RECORD;
299
  DBUG_RETURN(my_errno);			/* Something wrong (EOF?) */
300
}