~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
  if (info->opt_flag & WRITE_CACHE_USED)
118
  {
119
    if (flush_io_cache(&info->rec_cache))
120
    {
121
      DBUG_RETURN(-1);
122
    }
123
    info->rec_cache.seek_not_done=1;		/* We have done a seek */
124
  }
125
126
  if ((info->opt_flag & READ_CHECK_USED))
127
  {						/* If check isn't disabled  */
128
    info->rec_cache.seek_not_done=1;		/* We have done a seek */
129
    if (info->s->file_read(info, info->rec_buff, info->s->base.reclength,
130
		 info->lastpos,
131
		 MYF(MY_NABP)))
132
      DBUG_RETURN(-1);
133
    if (memcmp(info->rec_buff, old,
134
	       (uint) info->s->base.reclength))
135
    {
136
      DBUG_DUMP("read",old,info->s->base.reclength);
137
      DBUG_DUMP("disk",info->rec_buff,info->s->base.reclength);
138
      my_errno=HA_ERR_RECORD_CHANGED;		/* Record have changed */
139
      DBUG_RETURN(1);
140
    }
141
  }
142
  DBUG_RETURN(0);
143
}
144
145
146
int _mi_cmp_static_unique(MI_INFO *info, MI_UNIQUEDEF *def,
147
			  const uchar *record, my_off_t pos)
148
{
149
  DBUG_ENTER("_mi_cmp_static_unique");
150
151
  info->rec_cache.seek_not_done=1;		/* We have done a seek */
152
  if (info->s->file_read(info, info->rec_buff, info->s->base.reclength,
153
	       pos, MYF(MY_NABP)))
154
    DBUG_RETURN(-1);
155
  DBUG_RETURN(mi_unique_comp(def, record, info->rec_buff,
156
			     def->null_are_equal));
157
}
158
159
160
	/* Read a fixed-length-record */
161
	/* Returns 0 if Ok. */
162
	/*	   1 if record is deleted */
163
	/*	  MY_FILE_ERROR on read-error or locking-error */
164
165
int _mi_read_static_record(register MI_INFO *info, register my_off_t pos,
166
			   register uchar *record)
167
{
168
  int error;
169
170
  if (pos != HA_OFFSET_ERROR)
171
  {
172
    if (info->opt_flag & WRITE_CACHE_USED &&
173
	info->rec_cache.pos_in_file <= pos &&
174
	flush_io_cache(&info->rec_cache))
175
      return(-1);
176
    info->rec_cache.seek_not_done=1;		/* We have done a seek */
177
178
    error=info->s->file_read(info, record, info->s->base.reclength,
179
		   pos,MYF(MY_NABP)) != 0;
180
    fast_mi_writeinfo(info);
181
    if (! error)
182
    {
183
      if (!*record)
184
      {
185
	my_errno=HA_ERR_RECORD_DELETED;
186
	return(1);				/* Record is deleted */
187
      }
188
      info->update|= HA_STATE_AKTIV;		/* Record is read */
189
      return(0);
190
    }
191
    return(-1);					/* Error on read */
192
  }
193
  fast_mi_writeinfo(info);			/* No such record */
194
  return(-1);
195
}
196
197
198
199
int _mi_read_rnd_static_record(MI_INFO *info, uchar *buf,
200
			       register my_off_t filepos,
201
			       my_bool skip_deleted_blocks)
202
{
203
  int locked,error,cache_read;
204
  uint cache_length;
205
  MYISAM_SHARE *share=info->s;
206
  DBUG_ENTER("_mi_read_rnd_static_record");
207
208
  cache_read=0;
209
  cache_length=0;
210
  if (info->opt_flag & WRITE_CACHE_USED &&
211
      (info->rec_cache.pos_in_file <= filepos || skip_deleted_blocks) &&
212
      flush_io_cache(&info->rec_cache))
213
    DBUG_RETURN(my_errno);
214
  if (info->opt_flag & READ_CACHE_USED)
215
  {						/* Cache in use */
216
    if (filepos == my_b_tell(&info->rec_cache) &&
217
	(skip_deleted_blocks || !filepos))
218
    {
219
      cache_read=1;				/* Read record using cache */
220
      cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
221
    }
222
    else
223
      info->rec_cache.seek_not_done=1;		/* Filepos is changed */
224
  }
225
  locked=0;
226
  if (info->lock_type == F_UNLCK)
227
  {
228
    if (filepos >= info->state->data_file_length)
229
    {						/* Test if new records */
230
      if (_mi_readinfo(info,F_RDLCK,0))
231
	DBUG_RETURN(my_errno);
232
      locked=1;
233
    }
234
    else
235
    {						/* We don't nead new info */
236
#ifndef UNSAFE_LOCKING
237
      if ((! cache_read || share->base.reclength > cache_length) &&
238
	  share->tot_locks == 0)
239
      {						/* record not in cache */
240
	if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
241
		    MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
242
	  DBUG_RETURN(my_errno);
243
	locked=1;
244
      }
245
#else
246
      info->tmp_lock_type=F_RDLCK;
247
#endif
248
    }
249
  }
250
  if (filepos >= info->state->data_file_length)
251
  {
252
    DBUG_PRINT("test",("filepos: %ld (%ld)  records: %ld  del: %ld",
253
		       (long) filepos/share->base.reclength, (long) filepos,
254
		       (long) info->state->records, (long) info->state->del));
255
    fast_mi_writeinfo(info);
256
    DBUG_RETURN(my_errno=HA_ERR_END_OF_FILE);
257
  }
258
  info->lastpos= filepos;
259
  info->nextpos= filepos+share->base.pack_reclength;
260
261
  if (! cache_read)			/* No cacheing */
262
  {
263
    if ((error=_mi_read_static_record(info,filepos,buf)))
264
    {
265
      if (error > 0)
266
	error=my_errno=HA_ERR_RECORD_DELETED;
267
      else
268
	error=my_errno;
269
    }
270
    DBUG_RETURN(error);
271
  }
272
273
	/* Read record with cacheing */
274
  error=my_b_read(&info->rec_cache,(uchar*) buf,share->base.reclength);
275
  if (info->s->base.pack_reclength != info->s->base.reclength && !error)
276
  {
277
    char tmp[8];				/* Skill fill bytes */
278
    error=my_b_read(&info->rec_cache,(uchar*) tmp,
279
		    info->s->base.pack_reclength - info->s->base.reclength);
280
  }
281
  if (locked)
282
    VOID(_mi_writeinfo(info,0));		/* Unlock keyfile */
283
  if (!error)
284
  {
285
    if (!buf[0])
286
    {						/* Record is removed */
287
      DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
288
    }
289
						/* Found and may be updated */
290
    info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
291
    DBUG_RETURN(0);
292
  }
293
  /* my_errno should be set if rec_cache.error == -1 */
294
  if (info->rec_cache.error != -1 || my_errno == 0)
295
    my_errno=HA_ERR_WRONG_IN_RECORD;
296
  DBUG_RETURN(my_errno);			/* Something wrong (EOF?) */
297
}