int main(int argc,char *argv[])
{
  int error=0;
  uint keylen, keylen2=0, inx, doc_cnt=0;
  float weight= 1.0;
  double gws, min_gws=0, avg_gws=0;
  MARIA_HA *info;
  char buf[MAX_LEN], buf2[MAX_LEN], buf_maxlen[MAX_LEN], buf_min_gws[MAX_LEN];
  ulong total=0, maxlen=0, uniq=0, max_doc_cnt=0;
  struct { MARIA_HA *info; } aio0, *aio=&aio0; /* for GWS_IN_USE */

  MY_INIT(argv[0]);
  if ((error= handle_options(&argc, &argv, my_long_options, get_one_option)))
    exit(error);
  maria_init();
  if (count || dump)
    verbose=0;
  if (!count && !dump && !lstats && !query)
    stats=1;

  if (verbose)
    setbuf(stdout,NULL);

  if (argc < 2)
    usage();

  {
    char *end;
    inx= (uint) strtoll(argv[1], &end, 10);
    if (*end)
      usage();
  }

  init_pagecache(maria_pagecache, PAGE_BUFFER_INIT, 0, 0,
                 MARIA_KEY_BLOCK_LENGTH, 0, MY_WME);

  if (!(info=maria_open(argv[0], O_RDONLY,
                        HA_OPEN_ABORT_IF_LOCKED|HA_OPEN_FROM_SQL_LAYER)))
  {
    error=my_errno;
    goto err;
  }

  *buf2=0;
  aio->info=info;

  if ((inx >= info->s->base.keys) ||
      !(info->s->keyinfo[inx].flag & HA_FULLTEXT))
  {
    printf("Key %d in table %s is not a FULLTEXT key\n", inx,
           info->s->open_file_name.str);
    goto err;
  }

  maria_lock_database(info, F_EXTRA_LCK);

  info->cur_row.lastpos= HA_OFFSET_ERROR;
  info->update|= HA_STATE_PREV_FOUND;

  while (!(error=maria_rnext(info,NULL,inx)))
  {
    FT_WEIGTH subkeys;
    keylen=*(info->lastkey_buff);

    subkeys.i= ft_sintXkorr(info->lastkey_buff + keylen + 1);
    if (subkeys.i >= 0)
      weight= subkeys.f;

#ifdef HAVE_SNPRINTF
    snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey_buff+1);
#else
    sprintf(buf,"%.*s",(int) keylen,info->lastkey_buff+1);
#endif
    my_casedn_str(default_charset_info,buf);
    total++;
    lengths[keylen]++;

    if (count || stats)
    {
      if (strcmp(buf, buf2))
      {
        if (*buf2)
        {
          uniq++;
          avg_gws+=gws=GWS_IN_USE;
          if (count)
            printf("%9u %20.7f %s\n",doc_cnt,gws,buf2);
          if (maxlen<keylen2)
          {
            maxlen=keylen2;
            strmov(buf_maxlen, buf2);
          }
          if (max_doc_cnt < doc_cnt)
          {
            max_doc_cnt=doc_cnt;
            strmov(buf_min_gws, buf2);
            min_gws=gws;
          }
        }
        strmov(buf2, buf);
        keylen2=keylen;
        doc_cnt=0;
      }
      doc_cnt+= (subkeys.i >= 0 ? 1 : -subkeys.i);
    }
    if (dump)
    {
      if (subkeys.i >= 0)
        printf("%9lx %20.7f %s\n", (long) info->cur_row.lastpos,weight,buf);
      else
        printf("%9lx => %17d %s\n",(long) info->cur_row.lastpos,-subkeys.i,
               buf);
    }
    if (verbose && (total%HOW_OFTEN_TO_WRITE)==0)
      printf("%10ld\r",total);
  }
  maria_lock_database(info, F_UNLCK);

  if (count || stats)
  {
    if (*buf2)
    {
      uniq++;
      avg_gws+=gws=GWS_IN_USE;
      if (count)
        printf("%9u %20.7f %s\n",doc_cnt,gws,buf2);
      if (maxlen<keylen2)
      {
        maxlen=keylen2;
        strmov(buf_maxlen, buf2);
      }
      if (max_doc_cnt < doc_cnt)
      {
        max_doc_cnt=doc_cnt;
        strmov(buf_min_gws, buf2);
        min_gws=gws;
      }
    }
  }

  if (stats)
  {
    count=0;
    for (inx=0;inx<256;inx++)
    {
      count+=lengths[inx];
      if ((ulong) count >= total/2)
        break;
    }
    printf("Total rows: %lu\nTotal words: %lu\n"
           "Unique words: %lu\nLongest word: %lu chars (%s)\n"
           "Median length: %u\n"
           "Average global weight: %f\n"
           "Most common word: %lu times, weight: %f (%s)\n",
           (long) info->state->records, total, uniq, maxlen, buf_maxlen,
           inx, avg_gws/uniq, max_doc_cnt, min_gws, buf_min_gws);
  }
  if (lstats)
  {
    count=0;
    for (inx=0; inx<256; inx++)
    {
      count+=lengths[inx];
      if (count && lengths[inx])
        printf("%3u: %10lu %5.2f%% %20lu %4.1f%%\n", inx,
               (ulong) lengths[inx],100.0*lengths[inx]/total,(ulong) count,
               100.0*count/total);
    }
  }

err:
  if (error && error != HA_ERR_END_OF_FILE)
    printf("got error %d\n",my_errno);
  if (info)
    maria_close(info);
  maria_end();
  return 0;
}
Example #2
0
int main(int argc, char **argv)
{
  LSN lsn;
  char **default_argv;
  uint warnings_count;
  MY_INIT(argv[0]);

  maria_data_root= (char *)".";
  load_defaults("my", load_default_groups, &argc, &argv);
  default_argv= argv;
  get_options(&argc, &argv);

  maria_in_recovery= TRUE;

  if (maria_init())
  {
    fprintf(stderr, "Can't init Aria engine (%d)\n", errno);
    goto err;
  }
  maria_block_size= 0;                          /* Use block size from file */
  /* we don't want to create a control file, it MUST exist */
  if (ma_control_file_open(FALSE, TRUE))
  {
    fprintf(stderr, "Can't open control file (%d)\n", errno);
    goto err;
  }
  if (last_logno == FILENO_IMPOSSIBLE)
  {
    fprintf(stderr, "Can't find any log\n");
    goto err;
  }
  if (init_pagecache(maria_pagecache, opt_page_buffer_size, 0, 0,
                     maria_block_size, MY_WME) == 0)
  {
    fprintf(stderr, "Got error in init_pagecache() (errno: %d)\n", errno);
    goto err;
  }
  /*
    If log handler does not find the "last_logno" log it will return error,
    which is good.
    But if it finds a log and this log was crashed, it will create a new log,
    which is useless. TODO: start log handler in read-only mode.
  */
  if (init_pagecache(maria_log_pagecache, opt_translog_buffer_size,
                     0, 0, TRANSLOG_PAGE_SIZE, MY_WME) == 0 ||
      translog_init(maria_data_root, TRANSLOG_FILE_SIZE,
                    0, 0, maria_log_pagecache, TRANSLOG_DEFAULT_FLAGS,
                    opt_display_only))
  {
    fprintf(stderr, "Can't init loghandler (%d)\n", errno);
    goto err;
  }

  if (opt_display_only)
    printf("You are using --display-only, NOTHING will be written to disk\n");

  lsn= translog_first_lsn_in_log();
  if (lsn == LSN_ERROR)
  {
    fprintf(stderr, "Opening transaction log failed\n");
    goto end;
  }
  if (lsn == LSN_IMPOSSIBLE)
  {
     fprintf(stdout, "The transaction log is empty\n");
  }
  if (opt_start_from_checkpoint && !opt_start_from_lsn &&
      last_checkpoint_lsn != LSN_IMPOSSIBLE)
  {
    lsn= LSN_IMPOSSIBLE;             /* LSN set in maria_apply_log() */
    fprintf(stdout, "Starting from checkpoint (%lu,0x%lx)\n",
            LSN_IN_PARTS(last_checkpoint_lsn));
  }
  else
    fprintf(stdout, "The transaction log starts from lsn (%lu,0x%lx)\n",
            LSN_IN_PARTS(lsn));

  if (opt_start_from_lsn)
  {
    if (opt_start_from_lsn < (ulonglong) lsn)
    {
      fprintf(stderr, "start_from_lsn is too small. Aborting\n");
      maria_end();
      goto err;
    }
    lsn= (LSN) opt_start_from_lsn;
    fprintf(stdout, "Starting reading log from lsn (%lu,0x%lx)\n",
            LSN_IN_PARTS(lsn));
  }

  if (opt_end_lsn != LSN_IMPOSSIBLE)
  {
    /* We can't apply undo if we use end_lsn */
    opt_apply_undo= 0;
  }

  fprintf(stdout, "TRACE of the last aria_read_log\n");
  if (maria_apply_log(lsn, opt_end_lsn, opt_apply ?  MARIA_LOG_APPLY :
                      (opt_check ? MARIA_LOG_CHECK :
                       MARIA_LOG_DISPLAY_HEADER), opt_silent ? NULL : stdout,
                      opt_apply_undo, FALSE, FALSE, &warnings_count))
    goto err;
  if (warnings_count == 0)
    fprintf(stdout, "%s: SUCCESS\n", my_progname_short);
  else
    fprintf(stdout, "%s: DOUBTFUL (%u warnings, check previous output)\n",
            my_progname_short, warnings_count);

end:
  maria_end();
  free_tmpdir(&maria_chk_tmpdir);
  free_defaults(default_argv);
  my_end(0);
  exit(0);
  return 0;				/* No compiler warning */

err:
  /* don't touch anything more, in case we hit a bug */
  fprintf(stderr, "%s: FAILED\n", my_progname_short);
  free_tmpdir(&maria_chk_tmpdir);
  free_defaults(default_argv);
  exit(1);
}
Example #3
0
static int run_test(const char *filename)
{
  MARIA_HA *file;
  int i,j= 0,error,deleted,rec_length,uniques=0;
  uint offset_to_key;
  ha_rows found,row_count;
  uchar record[MAX_REC_LENGTH],key[MAX_REC_LENGTH],read_record[MAX_REC_LENGTH];
  MARIA_UNIQUEDEF uniquedef;
  MARIA_CREATE_INFO create_info;

  if (die_in_middle_of_transaction)
    null_fields= 1;

  bzero((char*) recinfo,sizeof(recinfo));
  bzero((char*) &create_info,sizeof(create_info));

  /* First define 2 columns */
  create_info.null_bytes= 1;
  recinfo[0].type= key_field;
  recinfo[0].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
		      key_length);
  if (key_field == FIELD_VARCHAR)
    recinfo[0].length+= HA_VARCHAR_PACKLENGTH(key_length);
  recinfo[1].type=extra_field;
  recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24);
  if (extra_field == FIELD_VARCHAR)
    recinfo[1].length+= HA_VARCHAR_PACKLENGTH(recinfo[1].length);
  recinfo[1].null_bit= null_fields ? 2 : 0;

  if (opt_unique)
  {
    recinfo[2].type=FIELD_CHECK;
    recinfo[2].length=MARIA_UNIQUE_HASH_LENGTH;
  }
  rec_length= recinfo[0].length + recinfo[1].length + recinfo[2].length +
    create_info.null_bytes;

  if (key_type == HA_KEYTYPE_VARTEXT1 &&
      key_length > 255)
    key_type= HA_KEYTYPE_VARTEXT2;

  /* Define a key over the first column */
  keyinfo[0].seg=keyseg;
  keyinfo[0].keysegs=1;
  keyinfo[0].block_length= 0;                   /* Default block length */
  keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[0].seg[0].type= key_type;
  keyinfo[0].seg[0].flag= pack_seg;
  keyinfo[0].seg[0].start=1;
  keyinfo[0].seg[0].length=key_length;
  keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0;
  keyinfo[0].seg[0].null_pos=0;
  keyinfo[0].seg[0].language= default_charset_info->number;
  if (pack_seg & HA_BLOB_PART)
  {
    keyinfo[0].seg[0].bit_start=4;		/* Length of blob length */
  }
  keyinfo[0].flag = (uint8) (pack_keys | unique_key);

  bzero((uchar*) flags,sizeof(flags));
  if (opt_unique)
  {
    uint start;
    uniques=1;
    bzero((char*) &uniquedef,sizeof(uniquedef));
    bzero((char*) uniqueseg,sizeof(uniqueseg));
    uniquedef.seg=uniqueseg;
    uniquedef.keysegs=2;

    /* Make a unique over all columns (except first NULL fields) */
    for (i=0, start=1 ; i < 2 ; i++)
    {
      uniqueseg[i].start=start;
      start+=recinfo[i].length;
      uniqueseg[i].length=recinfo[i].length;
      uniqueseg[i].language= default_charset_info->number;
    }
    uniqueseg[0].type= key_type;
    uniqueseg[0].null_bit= null_fields ? 2 : 0;
    uniqueseg[1].type= HA_KEYTYPE_TEXT;
    if (extra_field == FIELD_BLOB)
    {
      uniqueseg[1].length=0;			/* The whole blob */
      uniqueseg[1].bit_start=4;			/* long blob */
      uniqueseg[1].flag|= HA_BLOB_PART;
    }
    else if (extra_field == FIELD_VARCHAR)
    {
      uniqueseg[1].flag|= HA_VAR_LENGTH_PART;
      uniqueseg[1].type= (HA_VARCHAR_PACKLENGTH(recinfo[1].length-1) == 1 ?
                          HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2);
    }
  }
  else
    uniques=0;

  offset_to_key= MY_TEST(null_fields);
  if (key_field == FIELD_BLOB || key_field == FIELD_VARCHAR)
    offset_to_key+= 2;

  if (!silent)
    printf("- Creating maria file\n");
  create_info.max_rows=(ulong) (rec_pointer_size ?
				(1L << (rec_pointer_size*8))/40 :
				0);
  create_info.transactional= transactional;
  if (maria_create(filename, record_type, 1, keyinfo,2+opt_unique,recinfo,
		uniques, &uniquedef, &create_info,
		create_flag))
    goto err;
  if (!(file=maria_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
    goto err;
  if (!silent)
    printf("- Writing key:s\n");

  if (maria_begin(file))
    goto err;
  if (opt_versioning)
    maria_versioning(file, 1);
  my_errno=0;
  row_count=deleted=0;
  for (i=49 ; i>=1 ; i-=2 )
  {
    if (insert_count-- == 0)
    {
      if (testflag)
        break;
      maria_close(file);
      exit(0);
    }
    j=i%25 +1;
    create_record(record,j);
    error=maria_write(file,record);
    if (!error)
      row_count++;
    flags[j]=1;
    if (verbose || error)
      printf("J= %2d  maria_write: %d  errno: %d\n", j,error,my_errno);
  }

  if (maria_commit(file) || maria_begin(file))
    goto err;

  if (checkpoint == 1 && ma_checkpoint_execute(CHECKPOINT_MEDIUM, FALSE))
    goto err;

  if (testflag == 1)
    goto end;

  /* Insert 2 rows with null values */
  if (null_fields)
  {
    create_record(record,0);
    error=maria_write(file,record);
    if (!error)
      row_count++;
    if (verbose || error)
      printf("J= NULL  maria_write: %d  errno: %d\n", error,my_errno);
    error=maria_write(file,record);
    if (!error)
      row_count++;
    if (verbose || error)
      printf("J= NULL  maria_write: %d  errno: %d\n", error,my_errno);
    flags[0]=2;
  }

  if (checkpoint == 2 && ma_checkpoint_execute(CHECKPOINT_MEDIUM, FALSE))
    goto err;

  if (testflag == 2)
  {
    printf("Terminating after inserts\n");
    goto end;
  }

  if (maria_commit(file) || maria_begin(file))
    goto err;

  if (!skip_update)
  {
    if (opt_unique)
    {
      if (!silent)
	printf("- Checking unique constraint\n");
      create_record(record,j);                  /* Check last created row */
      if (!maria_write(file,record) || my_errno != HA_ERR_FOUND_DUPP_UNIQUE)
      {
	printf("unique check failed\n");
      }
    }
    if (!silent)
      printf("- Updating rows\n");

    /* Update first last row to force extend of file */
    if (maria_rsame(file,read_record,-1))
    {
      printf("Can't find last row with maria_rsame\n");
    }
    else
    {
      memcpy(record,read_record,rec_length);
      update_record(record);
      if (maria_update(file,read_record,record))
      {
	printf("Can't update last row: %.*s\n",
	       keyinfo[0].seg[0].length,read_record+1);
      }
    }

    /* Read through all rows and update them */
    maria_scan_init(file);

    found=0;
    while ((error= maria_scan(file,read_record)) == 0)
    {
      if (--update_count == 0) { maria_close(file); exit(0) ; }
      memcpy(record,read_record,rec_length);
      update_record(record);
      if (maria_update(file,read_record,record))
      {
	printf("Can't update row: %.*s, error: %d\n",
	       keyinfo[0].seg[0].length,record+1,my_errno);
      }
      found++;
    }
    if (found != row_count)
      printf("Found %ld of %ld rows\n", (ulong) found, (ulong) row_count);
    maria_scan_end(file);
  }

  if (checkpoint == 3 && ma_checkpoint_execute(CHECKPOINT_MEDIUM, FALSE))
    goto err;

  if (testflag == 3)
  {
    printf("Terminating after updates\n");
    goto end;
  }
  if (!silent)
    printf("- Reopening file\n");
  if (maria_commit(file))
    goto err;
  if (maria_close(file))
    goto err;
  if (!(file=maria_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
    goto err;
  if (maria_begin(file))
    goto err;
  if (opt_versioning)
    maria_versioning(file, 1);
  if (!skip_delete)
  {
    if (!silent)
      printf("- Removing keys\n");

    for (i=0 ; i <= 10 ; i++)
    {
      /*
        If you want to debug the problem in ma_test_recovery with BLOBs
        (see @todo there), you can break out of the loop after just one
        delete, it is enough, like this:
        if (i==1) break;
      */
      /* testing */
      if (remove_count-- == 0)
      {
        fprintf(stderr,
                "delete-rows number of rows deleted; Going down hard!\n");
        goto end;
      }
      j=i*2;
      if (!flags[j])
	continue;
      create_key(key,j);
      my_errno=0;
      if ((error = maria_rkey(file, read_record, 0, key,
                              HA_WHOLE_KEY, HA_READ_KEY_EXACT)))
      {
	if (verbose || (flags[j] >= 1 ||
			(error && my_errno != HA_ERR_KEY_NOT_FOUND)))
	  printf("key: '%.*s'  maria_rkey:  %3d  errno: %3d\n",
		 (int) key_length,key+offset_to_key,error,my_errno);
      }
      else
      {
	error=maria_delete(file,read_record);
	if (verbose || error)
	  printf("key: '%.*s'  maria_delete: %3d  errno: %3d\n",
		 (int) key_length, key+offset_to_key, error, my_errno);
	if (! error)
	{
	  deleted++;
	  flags[j]--;
	}
      }
    }
  }

  if (checkpoint == 4 && ma_checkpoint_execute(CHECKPOINT_MEDIUM, FALSE))
    goto err;

  if (testflag == 4)
  {
    printf("Terminating after deletes\n");
    goto end;
  }

  if (!silent)
    printf("- Reading rows with key\n");
  record[1]= 0;                                 /* For nicer printf */

  if (record_type == NO_RECORD)
    maria_extra(file, HA_EXTRA_KEYREAD, 0);

  for (i=0 ; i <= 25 ; i++)
  {
    create_key(key,i);
    my_errno=0;
    error=maria_rkey(file,read_record,0,key,HA_WHOLE_KEY,HA_READ_KEY_EXACT);
    if (verbose ||
	(error == 0 && flags[i] == 0 && unique_key) ||
	(error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
    {
      printf("key: '%.*s'  maria_rkey: %3d  errno: %3d  record: %s\n",
	     (int) key_length,key+offset_to_key,error,my_errno,record+1);
    }
  }
  if (record_type == NO_RECORD)
  {
    maria_extra(file, HA_EXTRA_NO_KEYREAD, 0);
    goto end;
  }

  if (!silent)
    printf("- Reading rows with position\n");

  if (maria_scan_init(file))
  {
    fprintf(stderr, "maria_scan_init failed\n");
    goto err;
  }

  for (i=1,found=0 ; i <= 30 ; i++)
  {
    my_errno=0;
    if ((error= maria_scan(file, read_record)) == HA_ERR_END_OF_FILE)
    {
      if (found != row_count-deleted)
	printf("Found only %ld of %ld rows\n", (ulong) found,
	       (ulong) (row_count - deleted));
      break;
    }
    if (!error)
      found++;
    if (verbose || (error != 0 && error != HA_ERR_RECORD_DELETED &&
		    error != HA_ERR_END_OF_FILE))
    {
      printf("pos: %2d  maria_rrnd: %3d  errno: %3d  record: %s\n",
	     i-1,error,my_errno,read_record+1);
    }
  }
  maria_scan_end(file);

end:
  if (die_in_middle_of_transaction)
  {
    /* As commit record is not done, UNDO entries needs to be rolled back */
    switch (die_in_middle_of_transaction) {
    case 1:
      /*
        Flush changed pages go to disk. That will also flush log. Recovery
        will skip REDOs and apply UNDOs.
      */
      _ma_flush_table_files(file, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
                            FLUSH_RELEASE, FLUSH_RELEASE);
      break;
    case 2:
      /*
        Just flush log. Pages are likely to not be on disk. Recovery will
        then execute REDOs and UNDOs.
      */
      if (translog_flush(file->trn->undo_lsn))
        goto err;
      break;
    case 3:
      /*
        Flush nothing. Pages and log are likely to not be on disk. Recovery
        will then do nothing.
      */
      break;
    case 4:
      /*
        Flush changed data pages go to disk. Changed index pages are not
        flushed. Recovery will skip some REDOs and apply UNDOs.
      */
      _ma_flush_table_files(file, MARIA_FLUSH_DATA, FLUSH_RELEASE,
                            FLUSH_RELEASE);
      /*
        We have to flush log separately as the redo for the last key page
        may not be flushed
      */
      if (translog_flush(file->trn->undo_lsn))
        goto err;
      break;
    }
    printf("Dying on request without maria_commit()/maria_close()\n");
    sf_leaking_memory= 1;
    exit(0);
  }

  if (maria_commit(file))
    goto err;
  if (maria_close(file))
    goto err;
  maria_end();
  my_uuid_end();
  my_end(MY_CHECK_ERROR);

  return (0);
err:
  printf("got error: %3d when using maria-database\n",my_errno);
  return 1;			/* skip warning */
}
Example #4
0
int main(int argc,char **argv)
{
  int status,wait_ret;
  uint i=0;
  MARIA_KEYDEF keyinfo[10];
  MARIA_COLUMNDEF recinfo[10];
  HA_KEYSEG keyseg[10][2];
  MY_INIT(argv[0]);
  get_options(argc,argv);

  fprintf(stderr, "WARNING! this program is to test 'external locking'"
          " (when several processes share a table through file locking)"
          " which is not supported by Maria at all; expect errors."
          " We may soon remove this program.\n");
  maria_init();
  bzero((char*) keyinfo,sizeof(keyinfo));
  bzero((char*) recinfo,sizeof(recinfo));
  bzero((char*) keyseg,sizeof(keyseg));
  keyinfo[0].seg= &keyseg[0][0];
  keyinfo[0].seg[0].start=0;
  keyinfo[0].seg[0].length=8;
  keyinfo[0].seg[0].type=HA_KEYTYPE_TEXT;
  keyinfo[0].seg[0].flag=HA_SPACE_PACK;
  keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[0].keysegs=1;
  keyinfo[0].flag = (uint8) HA_PACK_KEY;
  keyinfo[0].block_length= 0;                   /* Default block length */
  keyinfo[1].seg= &keyseg[1][0];
  keyinfo[1].seg[0].start=8;
  keyinfo[1].seg[0].length=4;		/* Long is always 4 in maria */
  keyinfo[1].seg[0].type=HA_KEYTYPE_LONG_INT;
  keyinfo[1].seg[0].flag=0;
  keyinfo[1].key_alg=HA_KEY_ALG_BTREE;
  keyinfo[1].keysegs=1;
  keyinfo[1].flag =HA_NOSAME;
  keyinfo[1].block_length= 0;                   /* Default block length */

  recinfo[0].type=0;
  recinfo[0].length=sizeof(record.id);
  recinfo[1].type=0;
  recinfo[1].length=sizeof(record.nr);
  recinfo[2].type=0;
  recinfo[2].length=sizeof(record.text);

  puts("- Creating maria-file");
  my_delete(filename,MYF(0));		/* Remove old locks under gdb */
  if (maria_create(filename,BLOCK_RECORD, 2, &keyinfo[0],2,&recinfo[0],0,
                   (MARIA_UNIQUEDEF*) 0, (MARIA_CREATE_INFO*) 0,0))
    exit(1);

  rnd_init(0);
  printf("- Starting %d processes\n",forks); fflush(stdout);
  for (i=0 ; i < forks; i++)
  {
    if (!fork())
    {
      start_test(i+1);
      sleep(1);
      return 0;
    }
    rnd(1);
  }

  for (i=0 ; i < forks ; i++)
    while ((wait_ret=wait(&status)) && wait_ret == -1);
  maria_end();
  return 0;
}