~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_test2.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-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
/* Test av isam-databas: stor test */
 
17
 
 
18
#ifndef USE_MY_FUNC             /* We want to be able to dbug this !! */
 
19
#define USE_MY_FUNC
 
20
#endif
 
21
#ifdef DBUG_OFF
 
22
#undef DBUG_OFF
 
23
#endif
 
24
#include "myisamdef.h"
 
25
#include <m_ctype.h>
 
26
#include <my_bit.h>
 
27
 
 
28
#define STANDARD_LENGTH 37
 
29
#define MYISAM_KEYS 6
 
30
#define MAX_PARTS 4
 
31
#if !defined(MSDOS) && !defined(labs)
 
32
#define labs(a) abs(a)
 
33
#endif
 
34
 
 
35
static void get_options(int argc, char *argv[]);
 
36
static uint rnd(uint max_value);
 
37
static void fix_length(uchar *record,uint length);
 
38
static void put_blob_in_record(uchar *blob_pos,char **blob_buffer);
 
39
static void copy_key(struct st_myisam_info *info,uint inx,
 
40
                     uchar *record,uchar *key);
 
41
 
 
42
static  int verbose=0,testflag=0,
 
43
            first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0,
 
44
            rec_pointer_size=0,pack_fields=1,use_log=0,silent=0,
 
45
            opt_quick_mode=0;
 
46
static int pack_seg=HA_SPACE_PACK,pack_type=HA_PACK_KEY,remove_count=-1,
 
47
           create_flag=0;
 
48
static ulong key_cache_size=IO_SIZE*16;
 
49
static uint key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
 
50
 
 
51
static uint keys=MYISAM_KEYS,recant=1000;
 
52
static uint use_blob=0;
 
53
static uint16 key1[1001],key3[5000];
 
54
static uchar record[300],record2[300],key[100],key2[100];
 
55
static uchar read_record[300],read_record2[300],read_record3[300];
 
56
static HA_KEYSEG glob_keyseg[MYISAM_KEYS][MAX_PARTS];
 
57
 
 
58
                /* Test program */
 
59
 
 
60
int main(int argc, char *argv[])
 
61
{
 
62
  uint i;
 
63
  int j,n1,n2,n3,error,k;
 
64
  uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
 
65
       reclength,ant,found_parts;
 
66
  my_off_t lastpos;
 
67
  ha_rows range_records,records;
 
68
  MI_INFO *file;
 
69
  MI_KEYDEF keyinfo[10];
 
70
  MI_COLUMNDEF recinfo[10];
 
71
  MI_ISAMINFO info;
 
72
  const char *filename;
 
73
  char *blob_buffer;
 
74
  MI_CREATE_INFO create_info;
 
75
  MY_INIT(argv[0]);
 
76
 
 
77
  filename= "test2";
 
78
  get_options(argc,argv);
 
79
  if (! async_io)
 
80
    my_disable_async_io=1;
 
81
 
 
82
  reclength=STANDARD_LENGTH+60+(use_blob ? 8 : 0);
 
83
  blob_pos=STANDARD_LENGTH+60;
 
84
  keyinfo[0].seg= &glob_keyseg[0][0];
 
85
  keyinfo[0].seg[0].start=0;
 
86
  keyinfo[0].seg[0].length=6;
 
87
  keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT;
 
88
  keyinfo[0].seg[0].language= default_charset_info->number;
 
89
  keyinfo[0].seg[0].flag=(uint8) pack_seg;
 
90
  keyinfo[0].seg[0].null_bit=0;
 
91
  keyinfo[0].seg[0].null_pos=0;
 
92
  keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
 
93
  keyinfo[0].keysegs=1;
 
94
  keyinfo[0].flag = pack_type;
 
95
  keyinfo[0].block_length= 0;                   /* Default block length */
 
96
  keyinfo[1].seg= &glob_keyseg[1][0];
 
97
  keyinfo[1].seg[0].start=7;
 
98
  keyinfo[1].seg[0].length=6;
 
99
  keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
 
100
  keyinfo[1].seg[0].flag=0;
 
101
  keyinfo[1].seg[0].null_bit=0;
 
102
  keyinfo[1].seg[0].null_pos=0;
 
103
  keyinfo[1].seg[1].start=0;                    /* two part key */
 
104
  keyinfo[1].seg[1].length=6;
 
105
  keyinfo[1].seg[1].type=HA_KEYTYPE_NUM;
 
106
  keyinfo[1].seg[1].flag=HA_REVERSE_SORT;
 
107
  keyinfo[1].seg[1].null_bit=0;
 
108
  keyinfo[1].seg[1].null_pos=0;
 
109
  keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
 
110
  keyinfo[1].keysegs=2;
 
111
  keyinfo[1].flag =0;
 
112
  keyinfo[1].block_length= MI_MIN_KEY_BLOCK_LENGTH;  /* Diff blocklength */
 
113
  keyinfo[2].seg= &glob_keyseg[2][0];
 
114
  keyinfo[2].seg[0].start=12;
 
115
  keyinfo[2].seg[0].length=8;
 
116
  keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
 
117
  keyinfo[2].seg[0].flag=HA_REVERSE_SORT;
 
118
  keyinfo[2].seg[0].null_bit=0;
 
119
  keyinfo[2].seg[0].null_pos=0;
 
120
  keyinfo[2].key_alg=HA_KEY_ALG_BTREE;
 
121
  keyinfo[2].keysegs=1;
 
122
  keyinfo[2].flag =HA_NOSAME;
 
123
  keyinfo[2].block_length= 0;                   /* Default block length */
 
124
  keyinfo[3].seg= &glob_keyseg[3][0];
 
125
  keyinfo[3].seg[0].start=0;
 
126
  keyinfo[3].seg[0].length=reclength-(use_blob ? 8 : 0);
 
127
  keyinfo[3].seg[0].type=HA_KEYTYPE_TEXT;
 
128
  keyinfo[3].seg[0].language=default_charset_info->number;
 
129
  keyinfo[3].seg[0].flag=(uint8) pack_seg;
 
130
  keyinfo[3].seg[0].null_bit=0;
 
131
  keyinfo[3].seg[0].null_pos=0;
 
132
  keyinfo[3].key_alg=HA_KEY_ALG_BTREE;
 
133
  keyinfo[3].keysegs=1;
 
134
  keyinfo[3].flag = pack_type;
 
135
  keyinfo[3].block_length= 0;                   /* Default block length */
 
136
  keyinfo[4].seg= &glob_keyseg[4][0];
 
137
  keyinfo[4].seg[0].start=0;
 
138
  keyinfo[4].seg[0].length=5;
 
139
  keyinfo[4].seg[0].type=HA_KEYTYPE_TEXT;
 
140
  keyinfo[4].seg[0].language=default_charset_info->number;
 
141
  keyinfo[4].seg[0].flag=0;
 
142
  keyinfo[4].seg[0].null_bit=0;
 
143
  keyinfo[4].seg[0].null_pos=0;
 
144
  keyinfo[4].key_alg=HA_KEY_ALG_BTREE;
 
145
  keyinfo[4].keysegs=1;
 
146
  keyinfo[4].flag = pack_type;
 
147
  keyinfo[4].block_length= 0;                   /* Default block length */
 
148
  keyinfo[5].seg= &glob_keyseg[5][0];
 
149
  keyinfo[5].seg[0].start=0;
 
150
  keyinfo[5].seg[0].length=4;
 
151
  keyinfo[5].seg[0].type=HA_KEYTYPE_TEXT;
 
152
  keyinfo[5].seg[0].language=default_charset_info->number;
 
153
  keyinfo[5].seg[0].flag=pack_seg;
 
154
  keyinfo[5].seg[0].null_bit=0;
 
155
  keyinfo[5].seg[0].null_pos=0;
 
156
  keyinfo[5].key_alg=HA_KEY_ALG_BTREE;
 
157
  keyinfo[5].keysegs=1;
 
158
  keyinfo[5].flag = pack_type;
 
159
  keyinfo[5].block_length= 0;                   /* Default block length */
 
160
 
 
161
  recinfo[0].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
 
162
  recinfo[0].length=7;
 
163
  recinfo[0].null_bit=0;
 
164
  recinfo[0].null_pos=0;
 
165
  recinfo[1].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
 
166
  recinfo[1].length=5;
 
167
  recinfo[1].null_bit=0;
 
168
  recinfo[1].null_pos=0;
 
169
  recinfo[2].type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
 
170
  recinfo[2].length=9;
 
171
  recinfo[2].null_bit=0;
 
172
  recinfo[2].null_pos=0;
 
173
  recinfo[3].type=FIELD_NORMAL;
 
174
  recinfo[3].length=STANDARD_LENGTH-7-5-9-4;
 
175
  recinfo[3].null_bit=0;
 
176
  recinfo[3].null_pos=0;
 
177
  recinfo[4].type=pack_fields ? FIELD_SKIP_ZERO : 0;
 
178
  recinfo[4].length=4;
 
179
  recinfo[4].null_bit=0;
 
180
  recinfo[4].null_pos=0;
 
181
  recinfo[5].type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
 
182
  recinfo[5].length=60;
 
183
  recinfo[5].null_bit=0;
 
184
  recinfo[5].null_pos=0;
 
185
  if (use_blob)
 
186
  {
 
187
    recinfo[6].type=FIELD_BLOB;
 
188
    recinfo[6].length=4+portable_sizeof_char_ptr;
 
189
    recinfo[6].null_bit=0;
 
190
    recinfo[6].null_pos=0;
 
191
  }
 
192
 
 
193
  write_count=update=dupp_keys=opt_delete=0;
 
194
  blob_buffer=0;
 
195
 
 
196
  for (i=1000 ; i>0 ; i--) key1[i]=0;
 
197
  for (i=4999 ; i>0 ; i--) key3[i]=0;
 
198
 
 
199
  if (!silent)
 
200
    printf("- Creating isam-file\n");
 
201
  /*  DBUG_PUSH(""); */
 
202
  /* my_delete(filename,MYF(0)); */     /* Remove old locks under gdb */
 
203
  file= 0;
 
204
  bzero((char*) &create_info,sizeof(create_info));
 
205
  create_info.max_rows=(ha_rows) (rec_pointer_size ?
 
206
                                  (1L << (rec_pointer_size*8))/
 
207
                                  reclength : 0);
 
208
  create_info.reloc_rows=(ha_rows) 100;
 
209
  if (mi_create(filename,keys,&keyinfo[first_key],
 
210
                use_blob ? 7 : 6, &recinfo[0],
 
211
                0,(MI_UNIQUEDEF*) 0,
 
212
                &create_info,create_flag))
 
213
    goto err;
 
214
  if (use_log)
 
215
    mi_log(1);
 
216
  if (!(file=mi_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
 
217
    goto err;
 
218
  if (!silent)
 
219
    printf("- Writing key:s\n");
 
220
  if (key_cacheing)
 
221
    init_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size,0,0);
 
222
  if (locking)
 
223
    mi_lock_database(file,F_WRLCK);
 
224
  if (write_cacheing)
 
225
    mi_extra(file,HA_EXTRA_WRITE_CACHE,0);
 
226
  if (opt_quick_mode)
 
227
    mi_extra(file,HA_EXTRA_QUICK,0);
 
228
 
 
229
  for (i=0 ; i < recant ; i++)
 
230
  {
 
231
    n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
 
232
    sprintf((char*) record,"%6d:%4d:%8d:Pos: %4d    ",n1,n2,n3,write_count);
 
233
    int4store(record+STANDARD_LENGTH-4,(long) i);
 
234
    fix_length(record,(uint) STANDARD_LENGTH+rnd(60));
 
235
    put_blob_in_record(record+blob_pos,&blob_buffer);
 
236
    DBUG_PRINT("test",("record: %d",i));
 
237
 
 
238
    if (mi_write(file,record))
 
239
    {
 
240
      if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
 
241
      {
 
242
        printf("Error: %d in write at record: %d\n",my_errno,i);
 
243
        goto err;
 
244
      }
 
245
      if (verbose) printf("   Double key: %d\n",n3);
 
246
    }
 
247
    else
 
248
    {
 
249
      if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
 
250
      {
 
251
        printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
 
252
        goto err;
 
253
      }
 
254
      write_count++; key1[n1]++; key3[n3]=1;
 
255
    }
 
256
 
 
257
    /* Check if we can find key without flushing database */
 
258
    if (i == recant/2)
 
259
    {
 
260
      for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
 
261
      if (!j)
 
262
        for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
 
263
      sprintf((char*) key,"%6d",j);
 
264
      if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
 
265
      {
 
266
        printf("Test in loop: Can't find key: \"%s\"\n",key);
 
267
        goto err;
 
268
      }
 
269
    }
 
270
  }
 
271
  if (testflag==1) goto end;
 
272
 
 
273
  if (write_cacheing)
 
274
  {
 
275
    if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
 
276
    {
 
277
      puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
 
278
      goto end;
 
279
    }
 
280
  }
 
281
  if (key_cacheing)
 
282
    resize_key_cache(dflt_key_cache,key_cache_block_size,key_cache_size*2,0,0);
 
283
 
 
284
  if (!silent)
 
285
    printf("- Delete\n");
 
286
  for (i=0 ; i<recant/10 ; i++)
 
287
  {
 
288
    for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
 
289
    if (j != 0)
 
290
    {
 
291
      sprintf((char*) key,"%6d",j);
 
292
      if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
 
293
      {
 
294
        printf("can't find key1: \"%s\"\n",key);
 
295
        goto err;
 
296
      }
 
297
      if (opt_delete == (uint) remove_count)            /* While testing */
 
298
        goto end;
 
299
      if (mi_delete(file,read_record))
 
300
      {
 
301
        printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
 
302
        goto err;
 
303
      }
 
304
      opt_delete++;
 
305
      key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
 
306
      key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
 
307
    }
 
308
    else
 
309
      puts("Warning: Skipping delete test because no dupplicate keys");
 
310
  }
 
311
  if (testflag==2) goto end;
 
312
 
 
313
  if (!silent)
 
314
    printf("- Update\n");
 
315
  for (i=0 ; i<recant/10 ; i++)
 
316
  {
 
317
    n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
 
318
    sprintf((char*) record2,"%6d:%4d:%8d:XXX: %4d     ",n1,n2,n3,update);
 
319
    int4store(record2+STANDARD_LENGTH-4,(long) i);
 
320
    fix_length(record2,(uint) STANDARD_LENGTH+rnd(60));
 
321
 
 
322
    for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
 
323
    if (j != 0)
 
324
    {
 
325
      sprintf((char*) key,"%6d",j);
 
326
      if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
 
327
      {
 
328
        printf("can't find key1: \"%s\"\n",(char*) key);
 
329
        goto err;
 
330
      }
 
331
      if (use_blob)
 
332
      {
 
333
        if (i & 1)
 
334
          put_blob_in_record(record+blob_pos,&blob_buffer);
 
335
        else
 
336
          bmove(record+blob_pos,read_record+blob_pos,8);
 
337
      }
 
338
      if (mi_update(file,read_record,record2))
 
339
      {
 
340
        if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
 
341
        {
 
342
          printf("error: %d; can't update:\nFrom: \"%s\"\nTo:   \"%s\"\n",
 
343
                 my_errno,read_record,record2);
 
344
          goto err;
 
345
        }
 
346
        if (verbose)
 
347
          printf("Double key when tried to update:\nFrom: \"%s\"\nTo:   \"%s\"\n",record,record2);
 
348
      }
 
349
      else
 
350
      {
 
351
        key1[atoi((char*) read_record+keyinfo[0].seg[0].start)]--;
 
352
        key3[atoi((char*) read_record+keyinfo[2].seg[0].start)]=0;
 
353
        key1[n1]++; key3[n3]=1;
 
354
        update++;
 
355
      }
 
356
    }
 
357
  }
 
358
  if (testflag == 3)
 
359
    goto end;
 
360
 
 
361
  for (i=999, dupp_keys=j=0 ; i>0 ; i--)
 
362
  {
 
363
    if (key1[i] > dupp_keys)
 
364
    {
 
365
      dupp_keys=key1[i]; j=i;
 
366
    }
 
367
  }
 
368
  sprintf((char*) key,"%6d",j);
 
369
  start=keyinfo[0].seg[0].start;
 
370
  length=keyinfo[0].seg[0].length;
 
371
  if (dupp_keys)
 
372
  {
 
373
    if (!silent)
 
374
      printf("- Same key: first - next -> last - prev -> first\n");
 
375
    DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
 
376
    if (verbose) printf("        Using key: \"%s\"  Keys: %d\n",key,dupp_keys);
 
377
 
 
378
    if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
 
379
      goto err;
 
380
    if (mi_rsame(file,read_record2,-1))
 
381
      goto err;
 
382
    if (memcmp(read_record,read_record2,reclength) != 0)
 
383
    {
 
384
      printf("mi_rsame didn't find same record\n");
 
385
      goto end;
 
386
    }
 
387
    info.recpos=mi_position(file);
 
388
    if (mi_rfirst(file,read_record2,0) ||
 
389
        mi_rsame_with_pos(file,read_record2,0,info.recpos) ||
 
390
        memcmp(read_record,read_record2,reclength) != 0)
 
391
    {
 
392
      printf("mi_rsame_with_pos didn't find same record\n");
 
393
      goto end;
 
394
    }
 
395
    {
 
396
      int skr=mi_rnext(file,read_record2,0);
 
397
      if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
 
398
          mi_rprev(file,read_record2,-1) ||
 
399
          memcmp(read_record,read_record2,reclength) != 0)
 
400
      {
 
401
        printf("mi_rsame_with_pos lost position\n");
 
402
        goto end;
 
403
      }
 
404
    }
 
405
    ant=1;
 
406
    while (mi_rnext(file,read_record2,0) == 0 &&
 
407
           memcmp(read_record2+start,key,length) == 0) ant++;
 
408
    if (ant != dupp_keys)
 
409
    {
 
410
      printf("next: Found: %d keys of %d\n",ant,dupp_keys);
 
411
      goto end;
 
412
    }
 
413
    ant=0;
 
414
    while (mi_rprev(file,read_record3,0) == 0 &&
 
415
           bcmp(read_record3+start,key,length) == 0) ant++;
 
416
    if (ant != dupp_keys)
 
417
    {
 
418
      printf("prev: Found: %d records of %d\n",ant,dupp_keys);
 
419
      goto end;
 
420
    }
 
421
 
 
422
    /* Check of mi_rnext_same */
 
423
    if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
 
424
      goto err;
 
425
    ant=1;
 
426
    while (!mi_rnext_same(file,read_record3) && ant < dupp_keys+10)
 
427
      ant++;
 
428
    if (ant != dupp_keys || my_errno != HA_ERR_END_OF_FILE)
 
429
    {
 
430
      printf("mi_rnext_same: Found: %d records of %d\n",ant,dupp_keys);
 
431
      goto end;
 
432
    }
 
433
  }
 
434
 
 
435
  if (!silent)
 
436
    printf("- All keys: first - next -> last - prev -> first\n");
 
437
  DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
 
438
  ant=1;
 
439
  if (mi_rfirst(file,read_record,0))
 
440
  {
 
441
    printf("Can't find first record\n");
 
442
    goto end;
 
443
  }
 
444
  while ((error=mi_rnext(file,read_record3,0)) == 0 && ant < write_count+10)
 
445
    ant++;
 
446
  if (ant != write_count - opt_delete || error != HA_ERR_END_OF_FILE)
 
447
  {
 
448
    printf("next: I found: %d records of %d (error: %d)\n",
 
449
           ant, write_count - opt_delete, error);
 
450
    goto end;
 
451
  }
 
452
  if (mi_rlast(file,read_record2,0) ||
 
453
      bcmp(read_record2,read_record3,reclength))
 
454
  {
 
455
    printf("Can't find last record\n");
 
456
    DBUG_DUMP("record2",(uchar*) read_record2,reclength);
 
457
    DBUG_DUMP("record3",(uchar*) read_record3,reclength);
 
458
    goto end;
 
459
  }
 
460
  ant=1;
 
461
  while (mi_rprev(file,read_record3,0) == 0 && ant < write_count+10)
 
462
    ant++;
 
463
  if (ant != write_count - opt_delete)
 
464
  {
 
465
    printf("prev: I found: %d records of %d\n",ant,write_count);
 
466
    goto end;
 
467
  }
 
468
  if (bcmp(read_record,read_record3,reclength))
 
469
  {
 
470
    printf("Can't find first record\n");
 
471
    goto end;
 
472
  }
 
473
 
 
474
  if (!silent)
 
475
    printf("- Test if: Read first - next - prev - prev - next == first\n");
 
476
  DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
 
477
  if (mi_rfirst(file,read_record,0) ||
 
478
      mi_rnext(file,read_record3,0) ||
 
479
      mi_rprev(file,read_record3,0) ||
 
480
      mi_rprev(file,read_record3,0) == 0 ||
 
481
      mi_rnext(file,read_record3,0))
 
482
      goto err;
 
483
  if (bcmp(read_record,read_record3,reclength) != 0)
 
484
     printf("Can't find first record\n");
 
485
 
 
486
  if (!silent)
 
487
    printf("- Test if: Read last - prev - next - next - prev == last\n");
 
488
  DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
 
489
  if (mi_rlast(file,read_record2,0) ||
 
490
      mi_rprev(file,read_record3,0) ||
 
491
      mi_rnext(file,read_record3,0) ||
 
492
      mi_rnext(file,read_record3,0) == 0 ||
 
493
      mi_rprev(file,read_record3,0))
 
494
      goto err;
 
495
  if (bcmp(read_record2,read_record3,reclength))
 
496
     printf("Can't find last record\n");
 
497
#ifdef NOT_ANYMORE
 
498
  if (!silent)
 
499
    puts("- Test read key-part");
 
500
  strmov(key2,key);
 
501
  for(i=strlen(key2) ; i-- > 1 ;)
 
502
  {
 
503
    key2[i]=0;
 
504
 
 
505
    /* The following row is just to catch some bugs in the key code */
 
506
    bzero((char*) file->lastkey,file->s->base.max_key_length*2);
 
507
    if (mi_rkey(file,read_record,0,key2,(uint) i,HA_READ_PREFIX))
 
508
      goto err;
 
509
    if (bcmp(read_record+start,key,(uint) i))
 
510
    {
 
511
      puts("Didn't find right record");
 
512
      goto end;
 
513
    }
 
514
  }
 
515
#endif
 
516
  if (dupp_keys > 2)
 
517
  {
 
518
    if (!silent)
 
519
      printf("- Read key (first) - next - delete - next -> last\n");
 
520
    DBUG_PRINT("progpos",("first - next - delete - next -> last"));
 
521
    if (mi_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
 
522
      goto err;
 
523
    if (mi_rnext(file,read_record3,0)) goto err;
 
524
    if (mi_delete(file,read_record3)) goto err;
 
525
    opt_delete++;
 
526
    ant=1;
 
527
    while (mi_rnext(file,read_record3,0) == 0 &&
 
528
           bcmp(read_record3+start,key,length) == 0) ant++;
 
529
    if (ant != dupp_keys-1)
 
530
    {
 
531
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
 
532
      goto end;
 
533
    }
 
534
  }
 
535
  if (dupp_keys>4)
 
536
  {
 
537
    if (!silent)
 
538
      printf("- Read last of key - prev - delete - prev -> first\n");
 
539
    DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
 
540
    if (mi_rprev(file,read_record3,0)) goto err;
 
541
    if (mi_rprev(file,read_record3,0)) goto err;
 
542
    if (mi_delete(file,read_record3)) goto err;
 
543
    opt_delete++;
 
544
    ant=1;
 
545
    while (mi_rprev(file,read_record3,0) == 0 &&
 
546
           bcmp(read_record3+start,key,length) == 0) ant++;
 
547
    if (ant != dupp_keys-2)
 
548
    {
 
549
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
 
550
      goto end;
 
551
    }
 
552
  }
 
553
  if (dupp_keys > 6)
 
554
  {
 
555
    if (!silent)
 
556
      printf("- Read first - delete - next -> last\n");
 
557
    DBUG_PRINT("progpos",("first - delete - next -> last"));
 
558
    if (mi_rkey(file,read_record3,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT))
 
559
      goto err;
 
560
    if (mi_delete(file,read_record3)) goto err;
 
561
    opt_delete++;
 
562
    ant=1;
 
563
    if (mi_rnext(file,read_record,0))
 
564
      goto err;                                 /* Skall finnas poster */
 
565
    while (mi_rnext(file,read_record3,0) == 0 &&
 
566
           bcmp(read_record3+start,key,length) == 0) ant++;
 
567
    if (ant != dupp_keys-3)
 
568
    {
 
569
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
 
570
      goto end;
 
571
    }
 
572
 
 
573
    if (!silent)
 
574
      printf("- Read last - delete - prev -> first\n");
 
575
    DBUG_PRINT("progpos",("last - delete - prev -> first"));
 
576
    if (mi_rprev(file,read_record3,0)) goto err;
 
577
    if (mi_delete(file,read_record3)) goto err;
 
578
    opt_delete++;
 
579
    ant=0;
 
580
    while (mi_rprev(file,read_record3,0) == 0 &&
 
581
           bcmp(read_record3+start,key,length) == 0) ant++;
 
582
    if (ant != dupp_keys-4)
 
583
    {
 
584
      printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
 
585
      goto end;
 
586
    }
 
587
  }
 
588
 
 
589
  if (!silent)
 
590
    puts("- Test if: Read rrnd - same");
 
591
  DBUG_PRINT("progpos",("Read rrnd - same"));
 
592
  for (i=0 ; i < write_count ; i++)
 
593
  {
 
594
    if (mi_rrnd(file,read_record,i == 0 ? 0L : HA_OFFSET_ERROR) == 0)
 
595
      break;
 
596
  }
 
597
  if (i == write_count)
 
598
    goto err;
 
599
 
 
600
  bmove(read_record2,read_record,reclength);
 
601
  for (i=min(2,keys) ; i-- > 0 ;)
 
602
  {
 
603
    if (mi_rsame(file,read_record2,(int) i)) goto err;
 
604
    if (bcmp(read_record,read_record2,reclength) != 0)
 
605
    {
 
606
      printf("is_rsame didn't find same record\n");
 
607
      goto end;
 
608
    }
 
609
  }
 
610
  if (!silent)
 
611
    puts("- Test mi_records_in_range");
 
612
  mi_status(file,&info,HA_STATUS_VARIABLE);
 
613
  for (i=0 ; i < info.keys ; i++)
 
614
  {
 
615
    key_range min_key, max_key;
 
616
    if (mi_rfirst(file,read_record,(int) i) ||
 
617
        mi_rlast(file,read_record2,(int) i))
 
618
      goto err;
 
619
    copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
 
620
    copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
 
621
    min_key.key= key;
 
622
    min_key.keypart_map= HA_WHOLE_KEY;
 
623
    min_key.flag= HA_READ_KEY_EXACT;
 
624
    max_key.key= key2;
 
625
    max_key.keypart_map= HA_WHOLE_KEY;
 
626
    max_key.flag= HA_READ_AFTER_KEY;
 
627
 
 
628
    range_records= mi_records_in_range(file,(int) i, &min_key, &max_key);
 
629
    if (range_records < info.records*8/10 ||
 
630
        range_records > info.records*12/10)
 
631
    {
 
632
      printf("mi_records_range returned %ld; Should be about %ld\n",
 
633
             (long) range_records,(long) info.records);
 
634
      goto end;
 
635
    }
 
636
    if (verbose)
 
637
    {
 
638
      printf("mi_records_range returned %ld;  Exact is %ld  (diff: %4.2g %%)\n",
 
639
             (long) range_records, (long) info.records,
 
640
             labs((long) range_records - (long) info.records)*100.0/
 
641
             info.records);
 
642
    }
 
643
  }
 
644
  for (i=0 ; i < 5 ; i++)
 
645
  {
 
646
    for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
 
647
    for (k=rnd(1000)+1 ; k>0 && key1[k] == 0 ; k--) ;
 
648
    if (j != 0 && k != 0)
 
649
    {
 
650
      key_range min_key, max_key;
 
651
      if (j > k)
 
652
        swap_variables(int, j, k);
 
653
      sprintf((char*) key,"%6d",j);
 
654
      sprintf((char*) key2,"%6d",k);
 
655
 
 
656
      min_key.key= key;
 
657
      min_key.length= USE_WHOLE_KEY;
 
658
      min_key.flag= HA_READ_AFTER_KEY;
 
659
      max_key.key= key2;
 
660
      max_key.length= USE_WHOLE_KEY;
 
661
      max_key.flag= HA_READ_BEFORE_KEY;
 
662
      range_records= mi_records_in_range(file, 0, &min_key, &max_key);
 
663
      records=0;
 
664
      for (j++ ; j < k ; j++)
 
665
        records+=key1[j];
 
666
      if ((long) range_records < (long) records*7/10-2 ||
 
667
          (long) range_records > (long) records*14/10+2)
 
668
      {
 
669
        printf("mi_records_range for key: %d returned %lu; Should be about %lu\n",
 
670
               i, (ulong) range_records, (ulong) records);
 
671
        goto end;
 
672
      }
 
673
      if (verbose && records)
 
674
      {
 
675
        printf("mi_records_range returned %lu;  Exact is %lu  (diff: %4.2g %%)\n",
 
676
               (ulong) range_records, (ulong) records,
 
677
               labs((long) range_records-(long) records)*100.0/records);
 
678
 
 
679
      }
 
680
    }
 
681
    }
 
682
 
 
683
  if (!silent)
 
684
    printf("- mi_info\n");
 
685
  mi_status(file,&info,HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
686
  if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
 
687
      || info.keys != keys)
 
688
  {
 
689
    puts("Wrong info from mi_info");
 
690
    printf("Got: records: %lu  delete: %lu  i_keys: %d\n",
 
691
           (ulong) info.records, (ulong) info.deleted, info.keys);
 
692
  }
 
693
  if (verbose)
 
694
  {
 
695
    char buff[80];
 
696
    get_date(buff,3,info.create_time);
 
697
    printf("info: Created %s\n",buff);
 
698
    get_date(buff,3,info.check_time);
 
699
    printf("info: checked %s\n",buff);
 
700
    get_date(buff,3,info.update_time);
 
701
    printf("info: Modified %s\n",buff);
 
702
  }
 
703
 
 
704
  mi_panic(HA_PANIC_WRITE);
 
705
  mi_panic(HA_PANIC_READ);
 
706
  if (mi_is_changed(file))
 
707
    puts("Warning: mi_is_changed reported that datafile was changed");
 
708
 
 
709
  if (!silent)
 
710
    printf("- mi_extra(CACHE) + mi_rrnd.... + mi_extra(NO_CACHE)\n");
 
711
  if (mi_reset(file) || mi_extra(file,HA_EXTRA_CACHE,0))
 
712
  {
 
713
    if (locking || (!use_blob && !pack_fields))
 
714
    {
 
715
      puts("got error from mi_extra(HA_EXTRA_CACHE)");
 
716
      goto end;
 
717
    }
 
718
  }
 
719
  ant=0;
 
720
  while ((error=mi_rrnd(file,record,HA_OFFSET_ERROR)) != HA_ERR_END_OF_FILE &&
 
721
         ant < write_count + 10)
 
722
        ant+= error ? 0 : 1;
 
723
  if (ant != write_count-opt_delete)
 
724
  {
 
725
    printf("rrnd with cache: I can only find: %d records of %d\n",
 
726
           ant,write_count-opt_delete);
 
727
    goto end;
 
728
  }
 
729
  if (mi_extra(file,HA_EXTRA_NO_CACHE,0))
 
730
  {
 
731
    puts("got error from mi_extra(HA_EXTRA_NO_CACHE)");
 
732
    goto end;
 
733
  }
 
734
 
 
735
  ant=0;
 
736
  mi_scan_init(file);
 
737
  while ((error=mi_scan(file,record)) != HA_ERR_END_OF_FILE &&
 
738
         ant < write_count + 10)
 
739
        ant+= error ? 0 : 1;
 
740
  if (ant != write_count-opt_delete)
 
741
  {
 
742
    printf("scan with cache: I can only find: %d records of %d\n",
 
743
           ant,write_count-opt_delete);
 
744
    goto end;
 
745
  }
 
746
 
 
747
  if (testflag == 4) goto end;
 
748
 
 
749
  if (!silent)
 
750
    printf("- Removing keys\n");
 
751
  DBUG_PRINT("progpos",("Removing keys"));
 
752
  lastpos = HA_OFFSET_ERROR;
 
753
  /* DBUG_POP(); */
 
754
  mi_reset(file);
 
755
  found_parts=0;
 
756
  while ((error=mi_rrnd(file,read_record,HA_OFFSET_ERROR)) !=
 
757
         HA_ERR_END_OF_FILE)
 
758
  {
 
759
    info.recpos=mi_position(file);
 
760
    if (lastpos >= info.recpos && lastpos != HA_OFFSET_ERROR)
 
761
    {
 
762
      printf("mi_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
 
763
             (long) lastpos, (long) info.recpos);
 
764
      goto err;
 
765
    }
 
766
    lastpos=info.recpos;
 
767
    if (error == 0)
 
768
    {
 
769
      if (opt_delete == (uint) remove_count)            /* While testing */
 
770
        goto end;
 
771
      if (mi_rsame(file,read_record,-1))
 
772
      {
 
773
        printf("can't find record %lx\n",(long) info.recpos);
 
774
        goto err;
 
775
      }
 
776
      if (use_blob)
 
777
      {
 
778
        ulong blob_length,pos;
 
779
        uchar *ptr;
 
780
        longget(blob_length,read_record+blob_pos+4);
 
781
        ptr=(uchar*) blob_length;
 
782
        longget(blob_length,read_record+blob_pos);
 
783
        for (pos=0 ; pos < blob_length ; pos++)
 
784
        {
 
785
          if (ptr[pos] != (uchar) (blob_length+pos))
 
786
          {
 
787
            printf("found blob with wrong info at %ld\n",(long) lastpos);
 
788
            use_blob=0;
 
789
            break;
 
790
          }
 
791
        }
 
792
      }
 
793
      if (mi_delete(file,read_record))
 
794
      {
 
795
        printf("can't delete record: %6.6s,  delete_count: %d\n",
 
796
               read_record, opt_delete);
 
797
        goto err;
 
798
      }
 
799
      opt_delete++;
 
800
    }
 
801
    else
 
802
      found_parts++;
 
803
  }
 
804
  if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
 
805
    printf("error: %d from mi_rrnd\n",my_errno);
 
806
  if (write_count != opt_delete)
 
807
  {
 
808
    printf("Deleted only %d of %d records (%d parts)\n",opt_delete,write_count,
 
809
           found_parts);
 
810
    goto err;
 
811
  }
 
812
end:
 
813
  if (mi_close(file))
 
814
    goto err;
 
815
  mi_panic(HA_PANIC_CLOSE);                     /* Should close log */
 
816
  if (!silent)
 
817
  {
 
818
    printf("\nFollowing test have been made:\n");
 
819
    printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
 
820
    if (rec_pointer_size)
 
821
      printf("Record pointer size:  %d\n",rec_pointer_size);
 
822
    printf("myisam_block_size:    %lu\n", myisam_block_size);
 
823
    if (key_cacheing)
 
824
    {
 
825
      puts("Key cache used");
 
826
      printf("key_cache_block_size: %u\n", key_cache_block_size);
 
827
      if (write_cacheing)
 
828
        puts("Key cache resized");
 
829
    }
 
830
    if (write_cacheing)
 
831
      puts("Write cacheing used");
 
832
    if (write_cacheing)
 
833
      puts("quick mode");
 
834
    if (async_io && locking)
 
835
      puts("Asyncron io with locking used");
 
836
    else if (locking)
 
837
      puts("Locking used");
 
838
    if (use_blob)
 
839
      puts("blobs used");
 
840
    printf("key cache status: \n\
 
841
blocks used:%10lu\n\
 
842
not flushed:%10lu\n\
 
843
w_requests: %10lu\n\
 
844
writes:     %10lu\n\
 
845
r_requests: %10lu\n\
 
846
reads:      %10lu\n",
 
847
           dflt_key_cache->blocks_used,
 
848
           dflt_key_cache->global_blocks_changed,
 
849
           (ulong) dflt_key_cache->global_cache_w_requests,
 
850
           (ulong) dflt_key_cache->global_cache_write,
 
851
           (ulong) dflt_key_cache->global_cache_r_requests,
 
852
           (ulong) dflt_key_cache->global_cache_read);
 
853
  }
 
854
  end_key_cache(dflt_key_cache,1);
 
855
  if (blob_buffer)
 
856
    my_free(blob_buffer,MYF(0));
 
857
  my_end(silent ? MY_CHECK_ERROR : MY_CHECK_ERROR | MY_GIVE_INFO);
 
858
  return(0);
 
859
err:
 
860
  printf("got error: %d when using MyISAM-database\n",my_errno);
 
861
  if (file)
 
862
    VOID(mi_close(file));
 
863
  return(1);
 
864
} /* main */
 
865
 
 
866
 
 
867
        /* l{ser optioner */
 
868
        /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
 
869
 
 
870
static void get_options(int argc, char **argv)
 
871
{
 
872
  char *pos,*progname;
 
873
 
 
874
  progname= argv[0];
 
875
 
 
876
  while (--argc >0 && *(pos = *(++argv)) == '-' ) {
 
877
    switch(*++pos) {
 
878
    case 'B':
 
879
      pack_type= HA_BINARY_PACK_KEY;
 
880
      break;
 
881
    case 'b':
 
882
      use_blob=1;
 
883
      break;
 
884
    case 'K':                           /* Use key cacheing */
 
885
      key_cacheing=1;
 
886
      if (*++pos)
 
887
        key_cache_size=atol(pos);
 
888
      break;
 
889
    case 'W':                           /* Use write cacheing */
 
890
      write_cacheing=1;
 
891
      if (*++pos)
 
892
        my_default_record_cache_size=atoi(pos);
 
893
      break;
 
894
    case 'd':
 
895
      remove_count= atoi(++pos);
 
896
      break;
 
897
    case 'i':
 
898
      if (*++pos)
 
899
        srand(atoi(pos));
 
900
      break;
 
901
    case 'l':
 
902
      use_log=1;
 
903
      break;
 
904
    case 'L':
 
905
      locking=1;
 
906
      break;
 
907
    case 'A':                           /* use asyncron io */
 
908
      async_io=1;
 
909
      if (*++pos)
 
910
        my_default_record_cache_size=atoi(pos);
 
911
      break;
 
912
    case 'v':                           /* verbose */
 
913
      verbose=1;
 
914
      break;
 
915
    case 'm':                           /* records */
 
916
      if ((recant=atoi(++pos)) < 10)
 
917
      {
 
918
        fprintf(stderr,"record count must be >= 10\n");
 
919
        exit(1);
 
920
      }
 
921
      break;
 
922
    case 'e':                           /* myisam_block_length */
 
923
      if ((myisam_block_size= atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
 
924
          myisam_block_size > MI_MAX_KEY_BLOCK_LENGTH)
 
925
      {
 
926
        fprintf(stderr,"Wrong myisam_block_length\n");
 
927
        exit(1);
 
928
      }
 
929
      myisam_block_size= my_round_up_to_next_power(myisam_block_size);
 
930
      break;
 
931
    case 'E':                           /* myisam_block_length */
 
932
      if ((key_cache_block_size=atoi(++pos)) < MI_MIN_KEY_BLOCK_LENGTH ||
 
933
          key_cache_block_size > MI_MAX_KEY_BLOCK_LENGTH)
 
934
      {
 
935
        fprintf(stderr,"Wrong key_cache_block_size\n");
 
936
        exit(1);
 
937
      }
 
938
      key_cache_block_size= my_round_up_to_next_power(key_cache_block_size);
 
939
      break;
 
940
    case 'f':
 
941
      if ((first_key=atoi(++pos)) < 0 || first_key >= MYISAM_KEYS)
 
942
        first_key=0;
 
943
      break;
 
944
    case 'k':
 
945
      if ((keys=(uint) atoi(++pos)) < 1 ||
 
946
           keys > (uint) (MYISAM_KEYS-first_key))
 
947
        keys=MYISAM_KEYS-first_key;
 
948
      break;
 
949
    case 'P':
 
950
      pack_type=0;                      /* Don't use DIFF_LENGTH */
 
951
      pack_seg=0;
 
952
      break;
 
953
    case 'R':                           /* Length of record pointer */
 
954
      rec_pointer_size=atoi(++pos);
 
955
      if (rec_pointer_size > 7)
 
956
        rec_pointer_size=0;
 
957
      break;
 
958
    case 'S':
 
959
      pack_fields=0;                    /* Static-length-records */
 
960
      break;
 
961
    case 's':
 
962
      silent=1;
 
963
      break;
 
964
    case 't':
 
965
      testflag=atoi(++pos);             /* testmod */
 
966
      break;
 
967
    case 'q':
 
968
      opt_quick_mode=1;
 
969
      break;
 
970
    case 'c':
 
971
      create_flag|= HA_CREATE_CHECKSUM;
 
972
      break;
 
973
    case 'D':
 
974
      create_flag|=HA_CREATE_DELAY_KEY_WRITE;
 
975
      break;
 
976
    case '?':
 
977
    case 'I':
 
978
    case 'V':
 
979
      printf("%s  Ver 1.2 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
 
980
      puts("By Monty, for your professional use\n");
 
981
      printf("Usage: %s [-?AbBcDIKLPRqSsVWltv] [-k#] [-f#] [-m#] [-e#] [-E#] [-t#]\n",
 
982
             progname);
 
983
      exit(0);
 
984
    case '#':
 
985
      DBUG_PUSH (++pos);
 
986
      break;
 
987
    default:
 
988
      printf("Illegal option: '%c'\n",*pos);
 
989
      break;
 
990
    }
 
991
  }
 
992
  return;
 
993
} /* get options */
 
994
 
 
995
        /* Get a random value 0 <= x <= n */
 
996
 
 
997
static uint rnd(uint max_value)
 
998
{
 
999
  return (uint) ((rand() & 32767)/32767.0*max_value);
 
1000
} /* rnd */
 
1001
 
 
1002
 
 
1003
        /* Create a variable length record */
 
1004
 
 
1005
static void fix_length(uchar *rec, uint length)
 
1006
{
 
1007
  bmove(rec+STANDARD_LENGTH,
 
1008
        "0123456789012345678901234567890123456789012345678901234567890",
 
1009
        length-STANDARD_LENGTH);
 
1010
  strfill((char*) rec+length,STANDARD_LENGTH+60-length,' ');
 
1011
} /* fix_length */
 
1012
 
 
1013
 
 
1014
        /* Put maybe a blob in record */
 
1015
 
 
1016
static void put_blob_in_record(uchar *blob_pos, char **blob_buffer)
 
1017
{
 
1018
  ulong i,length;
 
1019
  if (use_blob)
 
1020
  {
 
1021
    if (rnd(10) == 0)
 
1022
    {
 
1023
      if (! *blob_buffer &&
 
1024
          !(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME))))
 
1025
      {
 
1026
        use_blob=0;
 
1027
        return;
 
1028
      }
 
1029
      length=rnd(use_blob);
 
1030
      for (i=0 ; i < length ; i++)
 
1031
        (*blob_buffer)[i]=(char) (length+i);
 
1032
      int4store(blob_pos,length);
 
1033
      memcpy_fixed(blob_pos+4,(char*) blob_buffer,sizeof(char*));
 
1034
    }
 
1035
    else
 
1036
    {
 
1037
      int4store(blob_pos,0);
 
1038
    }
 
1039
  }
 
1040
  return;
 
1041
}
 
1042
 
 
1043
 
 
1044
static void copy_key(MI_INFO *info,uint inx,uchar *rec,uchar *key_buff)
 
1045
{
 
1046
  HA_KEYSEG *keyseg;
 
1047
 
 
1048
  for (keyseg=info->s->keyinfo[inx].seg ; keyseg->type ; keyseg++)
 
1049
  {
 
1050
    memcpy(key_buff,rec+keyseg->start,(size_t) keyseg->length);
 
1051
    key_buff+=keyseg->length;
 
1052
  }
 
1053
  return;
 
1054
}
 
1055
 
 
1056
#include "mi_extrafunc.h"