Exemplo n.º 1
0
size_t cleanup_dirname(register char *to, const char *from)
{
  reg5 size_t length;
  reg2 char * pos;
  reg3 char * from_ptr;
  reg4 char * start;
  char parent[5],				/* for "FN_PARENTDIR" */
       buff[FN_REFLEN + 1],*end_parentdir;
#ifdef BACKSLASH_MBTAIL
  CHARSET_INFO *fs= fs_character_set();
#endif
  DBUG_ENTER("cleanup_dirname");
  DBUG_PRINT("enter",("from: '%s'",from));

  start=buff;
  from_ptr=(char *) from;
#ifdef FN_DEVCHAR
  if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0)
  {						/* Skip device part */
    length=(size_t) (pos-from_ptr)+1;
    start=strnmov(buff,from_ptr,length); from_ptr+=length;
  }
#endif

  parent[0]=FN_LIBCHAR;
  length=(size_t) (strmov(parent+1,FN_PARENTDIR)-parent);
  for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++)
  {
#ifdef BACKSLASH_MBTAIL
    uint l;
    if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2)))
    {
      for (l-- ; l ; *++pos= *from_ptr++, l--);
      start= pos + 1; /* Don't look inside multi-byte char */
      continue;
    }
#endif
    if (*pos == '/')
      *pos = FN_LIBCHAR;
    if (*pos == FN_LIBCHAR)
    {
      if ((size_t) (pos-start) > length && memcmp(pos-length,parent,length) == 0)
      {						/* If .../../; skip prev */
	pos-=length;
	if (pos != start)
	{					 /* not /../ */
	  pos--;
	  if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR))
	  {
	    if (!home_dir)
	    {
	      pos+=length+1;			/* Don't unpack ~/.. */
	      continue;
	    }
	    pos=strmov(buff,home_dir)-1;	/* Unpacks ~/.. */
	    if (*pos == FN_LIBCHAR)
	      pos--;				/* home ended with '/' */
	  }
	  if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR))
	  {
	    if (my_getwd(curr_dir,FN_REFLEN,MYF(0)))
	    {
	      pos+=length+1;			/* Don't unpack ./.. */
	      continue;
	    }
	    pos=strmov(buff,curr_dir)-1;	/* Unpacks ./.. */
	    if (*pos == FN_LIBCHAR)
	      pos--;				/* home ended with '/' */
	  }
	  end_parentdir=pos;
	  while (pos >= start && *pos != FN_LIBCHAR)	/* remove prev dir */
	    pos--;
          if (pos[1] == FN_HOMELIB ||
              (pos >= start && memcmp(pos, parent, length) == 0))
	  {					/* Don't remove ~user/ */
	    pos=strmov(end_parentdir+1,parent);
	    *pos=FN_LIBCHAR;
	    continue;
	  }
	}
      }
      else if ((size_t) (pos-start) == length-1 &&
	       !memcmp(start,parent+1,length-1))
	start=pos;				/* Starts with "../" */
      else if (pos-start > 0 && pos[-1] == FN_LIBCHAR)
      {
#ifdef FN_NETWORK_DRIVES
	if (pos-start != 1)
#endif
	  pos--;			/* Remove dupplicate '/' */
      }
      else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR)
	pos-=2;					/* Skip /./ */
      else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR)
      {					/* Found ..../~/  */
	buff[0]=FN_HOMELIB;
	buff[1]=FN_LIBCHAR;
	start=buff; pos=buff+1;
      }
    }
  }
  (void) strmov(to,buff);
  DBUG_PRINT("exit",("to: '%s'",to));
  DBUG_RETURN((size_t) (pos-buff));
} /* cleanup_dirname */
Exemplo n.º 2
0
File create_temp_file(char *to, const char *dir, const char *prefix,
                      int mode __attribute__((unused)),
                      myf MyFlags __attribute__((unused)))
{
    File file= -1;
#ifdef __WIN__
    TCHAR path_buf[MAX_PATH-14];
#endif

    DBUG_ENTER("create_temp_file");
    DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix));
#if defined (__WIN__)

    /*
      Use GetTempPath to determine path for temporary files.
      This is because the documentation for GetTempFileName
      has the following to say about this parameter:
      "If this parameter is NULL, the function fails."
    */
    if (!dir)
    {
        if(GetTempPath(sizeof(path_buf), path_buf) > 0)
            dir = path_buf;
    }
    /*
      Use GetTempFileName to generate a unique filename, create
      the file and release it's handle
       - uses up to the first three letters from prefix
    */
    if (GetTempFileName(dir, prefix, 0, to) == 0)
        DBUG_RETURN(-1);

    DBUG_PRINT("info", ("name: %s", to));

    /*
      Open the file without the "open only if file doesn't already exist"
      since the file has already been created by GetTempFileName
    */
    if ((file= my_open(to,  (mode & ~O_EXCL), MyFlags)) < 0)
    {
        /* Open failed, remove the file created by GetTempFileName */
        int tmp= my_errno;
        (void) my_delete(to, MYF(0));
        my_errno= tmp;
    }

#elif defined(HAVE_MKSTEMP)
    {
        char prefix_buff[30];
        uint pfx_len;
        File org_file;

        pfx_len= (uint) (strmov(strnmov(prefix_buff,
                                        prefix ? prefix : "tmp.",
                                        sizeof(prefix_buff)-7),"XXXXXX") -
                         prefix_buff);
        if (!dir && ! (dir =getenv("TMPDIR")))
            dir=DEFAULT_TMPDIR;
        if (strlen(dir)+ pfx_len > FN_REFLEN-2)
        {
            errno=my_errno= ENAMETOOLONG;
            DBUG_RETURN(file);
        }
        strmov(convert_dirname(to,dir,NullS),prefix_buff);
        org_file=mkstemp(to);
        if (mode & O_TEMPORARY)
            (void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
        file=my_register_filename(org_file, to, FILE_BY_MKSTEMP,
                                  EE_CANTCREATEFILE, MyFlags);
        /* If we didn't manage to register the name, remove the temp file */
        if (org_file >= 0 && file < 0)
        {
            int tmp=my_errno;
            close(org_file);
            (void) my_delete(to, MYF(MY_WME | ME_NOINPUT));
            my_errno=tmp;
        }
    }
#elif defined(HAVE_TEMPNAM)
    {
        extern char **environ;

        char *res,**old_env,*temp_env[1];
        if (dir && !dir[0])
        {   /* Change empty string to current dir */
            to[0]= FN_CURLIB;
            to[1]= 0;
            dir=to;
        }

        old_env= (char**) environ;
        if (dir)
        {   /* Don't use TMPDIR if dir is given */
            environ=(const char**) temp_env;
            temp_env[0]=0;
        }

        if ((res=tempnam((char*) dir, (char*) prefix)))
        {
            strmake(to,res,FN_REFLEN-1);
            (*free)(res);
            file=my_create(to,0,
                           (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW |
                                  O_TEMPORARY | O_SHORT_LIVED),
                           MYF(MY_WME));

        }
        else
        {
            DBUG_PRINT("error",("Got error: %d from tempnam",errno));
        }

        environ=(const char**) old_env;
    }
#else
#error No implementation found for create_temp_file
#endif
    if (file >= 0)
        thread_safe_increment(my_tmp_file_created,&THR_LOCK_open);
    DBUG_RETURN(file);
}
Exemplo n.º 3
0
static int search_default_file_with_ext(Process_option_func opt_handler,
                                        void *handler_ctx,
                                        const char *dir,
                                        const char *ext,
                                        const char *config_file,
                                        int recursion_level)
{
  char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
  char *value, option[4096], tmp[FN_REFLEN];
  static const char includedir_keyword[]= "includedir";
  static const char include_keyword[]= "include";
  const int max_recursion_level= 10;
  FILE *fp;
  uint line=0;
  my_bool found_group=0;
  uint i;
  MY_DIR *search_dir;
  FILEINFO *search_file;

  if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3)
    return 0;					/* Ignore wrong paths */
  if (dir)
  {
    end=convert_dirname(name, dir, NullS);
    if (dir[0] == FN_HOMELIB)		/* Add . to filenames in home */
      *end++='.';
    strxmov(end,config_file,ext,NullS);
  }
  else
  {
    strmov(name,config_file);
  }
  fn_format(name,name,"","",4);
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
  {
    MY_STAT stat_info;
    if (!my_stat(name,&stat_info,MYF(0)))
      return 1;
    /*
      Ignore world-writable regular files.
      This is mainly done to protect us to not read a file created by
      the mysqld server, but the check is still valid in most context. 
    */
    if ((stat_info.st_mode & S_IWOTH) &&
	(stat_info.st_mode & S_IFMT) == S_IFREG)
    {
      fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
              name);
      return 0;
    }
  }
#endif
  if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
    return 1;					/* Ignore wrong files */

  while (fgets(buff, sizeof(buff) - 1, fp))
  {
    line++;
    /* Ignore comment and empty lines */
    for (ptr= buff; my_isspace(&my_charset_latin1, *ptr); ptr++)
    {}

    if (*ptr == '#' || *ptr == ';' || !*ptr)
      continue;

    /* Configuration File Directives */
    if ((*ptr == '!'))
    {
      if (recursion_level >= max_recursion_level)
      {
        for (end= ptr + strlen(ptr) - 1; 
             my_isspace(&my_charset_latin1, *(end - 1));
             end--)
        {}
        end[0]= 0;
        fprintf(stderr,
                "Warning: skipping '%s' directive as maximum include"
                "recursion level was reached in file %s at line %d\n",
                ptr, name, line);
        continue;
      }

      /* skip over `!' and following whitespace */
      for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++)
      {}

      if ((!strncmp(ptr, includedir_keyword,
                    sizeof(includedir_keyword) - 1)) &&
          my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1]))
      {
	if (!(ptr= get_argument(includedir_keyword,
                                sizeof(includedir_keyword),
                                ptr, name, line)))
	  goto err;

        if (!(search_dir= my_dir(ptr, MYF(MY_WME))))
          goto err;

        for (i= 0; i < (uint) search_dir->number_off_files; i++)
        {
          search_file= search_dir->dir_entry + i;
          ext= fn_ext(search_file->name);

          /* check extension */
          for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
          {
            if (!strcmp(ext, *tmp_ext))
              break;
          }

          if (*tmp_ext)
          {
            fn_format(tmp, search_file->name, ptr, "",
                      MY_UNPACK_FILENAME | MY_SAFE_PATH);

            search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
                                         recursion_level + 1);
          }
        }

        my_dirend(search_dir);
      }
      else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) &&
               my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1]))
      {
	if (!(ptr= get_argument(include_keyword,
                                sizeof(include_keyword), ptr,
                                name, line)))
	  goto err;

        search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
                                     recursion_level + 1);
      }

      continue;
    }

    if (*ptr == '[')				/* Group name */
    {
      found_group=1;
      if (!(end=(char *) strchr(++ptr,']')))
      {
	fprintf(stderr,
		"error: Wrong group definition in config file: %s at line %d\n",
		name,line);
	goto err;
      }
      for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;/* Remove end space */
      end[0]=0;

      strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
      continue;
    }
    if (!found_group)
    {
      fprintf(stderr,
	      "error: Found option without preceding group in config file: %s at line: %d\n",
	      name,line);
      goto err;
    }
    
   
    end= remove_end_comment(ptr);
    if ((value= strchr(ptr, '=')))
      end= value;				/* Option without argument */
    for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
    if (!value)
    {
      strmake(strmov(option,"--"),ptr,(uint) (end-ptr));
      if (opt_handler(handler_ctx, curr_gr, option))
        goto err;
    }
    else
    {
      /* Remove pre- and end space */
      char *value_end;
      for (value++ ; my_isspace(&my_charset_latin1,*value); value++) ;
      value_end=strend(value);
      /*
	We don't have to test for value_end >= value as we know there is
	an '=' before
      */
      for ( ; my_isspace(&my_charset_latin1,value_end[-1]) ; value_end--) ;
      if (value_end < value)			/* Empty string */
	value_end=value;

      /* remove quotes around argument */
      if ((*value == '\"' || *value == '\'') && /* First char is quote */
          (value + 1 < value_end ) && /* String is longer than 1 */
          *value == value_end[-1] ) /* First char is equal to last char */
      {
	value++;
	value_end--;
      }
      ptr=strnmov(strmov(option,"--"),ptr,(uint) (end-ptr));
      *ptr++= '=';

      for ( ; value != value_end; value++)
      {
	if (*value == '\\' && value != value_end-1)
	{
	  switch(*++value) {
	  case 'n':
	    *ptr++='\n';
	    break;
	  case 't':
	    *ptr++= '\t';
	    break;
	  case 'r':
	    *ptr++ = '\r';
	    break;
	  case 'b':
	    *ptr++ = '\b';
	    break;
	  case 's':
	    *ptr++= ' ';			/* space */
	    break;
	  case '\"':
	    *ptr++= '\"';
	    break;
	  case '\'':
	    *ptr++= '\'';
	    break;
	  case '\\':
	    *ptr++= '\\';
	    break;
	  default:				/* Unknown; Keep '\' */
	    *ptr++= '\\';
	    *ptr++= *value;
	    break;
	  }
	}
	else
	  *ptr++= *value;
      }
      *ptr=0;
      if (opt_handler(handler_ctx, curr_gr, option))
        goto err;
    }
  }
  my_fclose(fp,MYF(0));
  return(0);

 err:
  my_fclose(fp,MYF(0));
  return -1;					/* Fatal error */
}
Exemplo n.º 4
0
int my_setwd(const char *dir, myf MyFlags)
{
  int res;
  size_s length;
  my_string start,pos;
#if defined(VMS) || defined(MSDOS) || defined(OS2)
  char buff[FN_REFLEN];
#endif
  DBUG_ENTER("my_setwd");
  DBUG_PRINT("my",("dir: '%s'  MyFlags %d", dir, MyFlags));

  start=(my_string) dir;
#if defined(MSDOS) || defined(OS2) /* OS2/MSDOS chdir can't change drive */
#if !defined(_DDL) && !defined(WIN32)
  if ((pos=(char*) strchr(dir,FN_DEVCHAR)) != 0)
  {
    uint drive,drives;

    pos++;				/* Skipp FN_DEVCHAR */
    drive=(uint) (toupper(dir[0])-'A'+1); drives= (uint) -1;
    if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32)
    {
#ifdef OS2
      _chdrive(drive);
      drives = _getdrive();
#else
      _dos_setdrive(drive,&drives);
      _dos_getdrive(&drives);
#endif
    }
    if (drive != drives)
    {
      *pos='\0';			/* Dir is now only drive */
      my_errno=errno;
      my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),dir,ENOENT);
      DBUG_RETURN(-1);
    }
    dir=pos;				/* drive changed, change now path */
  }
#endif
  if (*((pos=strend(dir)-1)) == FN_LIBCHAR && pos != dir)
  {
    strmov(buff,dir)[-1]=0;			/* Remove last '/' */
    dir=buff;
  }
#endif /* MSDOS*/
  if (! dir[0] || (dir[0] == FN_LIBCHAR && dir[1] == 0))
    dir=FN_ROOTDIR;
#ifdef VMS
  {
    pos=strmov(buff,dir);
    if (pos[-1] != FN_LIBCHAR)
    {
      pos[0]=FN_LIBCHAR;		/* Mark as directory */
      pos[1]=0;
    }
    system_filename(buff,buff);		/* Change to VMS format */
    dir=buff;
  }
#endif /* VMS */
  if ((res=chdir((char*) dir)) != 0)
  {
    my_errno=errno;
    if (MyFlags & MY_WME)
      my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),start,errno);
  }
  else
  {
    if (test_if_hard_path(start))
    {						/* Hard pathname */
      pos=strmake(&curr_dir[0],start,(size_s) FN_REFLEN-1);
      if (pos[-1] != FN_LIBCHAR)
      {
	length=(uint) (pos-(char*) curr_dir);
	curr_dir[length]=FN_LIBCHAR;		/* must end with '/' */
	curr_dir[length+1]='\0';
      }
    }
    else
      curr_dir[0]='\0';				/* Don't save name */
  }
  DBUG_RETURN(res);
} /* my_setwd */
Exemplo n.º 5
0
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;
    MI_INFO *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 {
        MI_INFO *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);
    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_key_cache(dflt_key_cache, MI_KEY_BLOCK_LENGTH, KEY_BUFFER_INIT, 0, 0, 0, 0);

    if (!(info=mi_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->filename);
        goto err;
    }

    mi_lock_database(info, F_EXTRA_LCK);

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

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

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

#ifdef HAVE_SNPRINTF
        snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
#else
        sprintf(buf,"%.*s",(int) keylen,info->lastkey+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->lastpos,weight,buf);
            else
                printf("%9lx => %17d %s\n",(long) info->lastpos,-subkeys.i,buf);
        }
        if (verbose && (total%HOW_OFTEN_TO_WRITE)==0)
            printf("%10ld\r",total);
    }
    mi_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)
        mi_close(info);
    return 0;
}
Exemplo n.º 6
0
char * fn_format(char * to, const char *name, const char *dir,
		    const char *extension, uint flag)
{
  char dev[FN_REFLEN], buff[FN_REFLEN], *pos, *startpos;
  const char *ext;
  size_t length;
  size_t dev_length;
  DBUG_ENTER("fn_format");
  DBUG_ASSERT(name != NULL);
  DBUG_ASSERT(extension != NULL);
  DBUG_PRINT("enter",("name: %s  dir: %s  extension: %s  flag: %d",
		       name,dir,extension,flag));

  /* Copy and skip directory */
  name+=(length=dirname_part(dev, (startpos=(char *) name), &dev_length));
  if (length == 0 || (flag & MY_REPLACE_DIR))
  {
    DBUG_ASSERT(dir != NULL);
    /* Use given directory */
    convert_dirname(dev,dir,NullS);		/* Fix to this OS */
  }
  else if ((flag & MY_RELATIVE_PATH) && !test_if_hard_path(dev))
  {
    DBUG_ASSERT(dir != NULL);
    /* Put 'dir' before the given path */
    strmake(buff,dev,sizeof(buff)-1);
    pos=convert_dirname(dev,dir,NullS);
    strmake(pos,buff,sizeof(buff)-1- (int) (pos-dev));
  }

  if (flag & MY_PACK_FILENAME)
    pack_dirname(dev,dev);			/* Put in ./.. and ~/.. */
  if (flag & MY_UNPACK_FILENAME)
    (void) unpack_dirname(dev,dev);		/* Replace ~/.. with dir */

  if (!(flag & MY_APPEND_EXT) &&
      (pos= (char*) strchr(name,FN_EXTCHAR)) != NullS)
  {
    if ((flag & MY_REPLACE_EXT) == 0)		/* If we should keep old ext */
    {
      length=strlength(name);			/* Use old extension */
      ext = "";
    }
    else
    {
      length= (size_t) (pos-(char*) name);	/* Change extension */
      ext= extension;
    }
  }
  else
  {
    length=strlength(name);			/* No ext, use the now one */
    ext=extension;
  }

  if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN )
  {
    /* To long path, return original or NULL */
    size_t tmp_length;
    if (flag & MY_SAFE_PATH)
      DBUG_RETURN(NullS);
    tmp_length= strlength(startpos);
    DBUG_PRINT("error",("dev: '%s'  ext: '%s'  length: %u",dev,ext,
                        (uint) length));
    (void) strmake(to, startpos, MY_MIN(tmp_length, FN_REFLEN-1));
  }
  else
  {
    if (to == startpos)
    {
      bmove(buff,(uchar*) name,length);		/* Save name for last copy */
      name=buff;
    }
    pos=strmake(strmov(to,dev),name,length);
    (void) strmov(pos,ext);			/* Don't convert extension */
  }
  /*
    If MY_RETURN_REAL_PATH and MY_RESOLVE_SYMLINK is given, only do
    realpath if the file is a symbolic link
  */
  if (flag & MY_RETURN_REAL_PATH)
    (void) my_realpath(to, to, MYF(flag & MY_RESOLVE_SYMLINKS ?
				   MY_RESOLVE_LINK: 0));
  else if (flag & MY_RESOLVE_SYMLINKS)
  {
    strmov(buff,to);
    (void) my_readlink(to, buff, MYF(0));
  }
  DBUG_RETURN(to);
} /* fn_format */
static int examine_log(char * file_name, char **table_names)
{
  uint command,result,files_open;
  ulong access_time,length;
  my_off_t filepos;
  int lock_command,mi_result;
  char isam_file_name[FN_REFLEN],llbuff[21],llbuff2[21];
  uchar head[20];
  uchar*	buff;
  struct test_if_open_param open_param;
  IO_CACHE cache;
  File file;
  FILE *write_file;
  enum ha_extra_function extra_command;
  TREE tree;
  struct file_info file_info,*curr_file_info;
  DBUG_ENTER("examine_log");

  if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0)
    DBUG_RETURN(1);
  write_file=0;
  if (write_filename)
  {
    if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME))))
    {
      my_close(file,MYF(0));
      DBUG_RETURN(1);
    }
  }

  init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
  bzero((uchar*) com_count,sizeof(com_count));
  init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,
	    (tree_element_free) file_info_free, NULL,
            MYF(MY_TREE_WITH_DELETE));
  (void) init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
                        0, 0, 0, 0);

  files_open=0; access_time=0;
  while (access_time++ != number_of_commands &&
	 !my_b_read(&cache,(uchar*) head,9))
  {
    isamlog_filepos=my_b_tell(&cache)-9L;
    file_info.filenr= mi_uint2korr(head+1);
    isamlog_process=file_info.process=(long) mi_uint4korr(head+3);
    if (!opt_processes)
      file_info.process=0;
    result= mi_uint2korr(head+7);
    if ((curr_file_info=(struct file_info*) tree_search(&tree, &file_info,
							tree.custom_arg)))
    {
      curr_file_info->accessed=access_time;
      if (update && curr_file_info->used && curr_file_info->closed)
      {
	if (reopen_closed_file(&tree,curr_file_info))
	{
	  command=sizeof(com_count)/sizeof(com_count[0][0])/3;
	  result=0;
	  goto com_err;
	}
      }
    }
    command=(uint) head[0];
    if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 &&
	(!table_names[0] || (curr_file_info && curr_file_info->used)))
    {
      com_count[command][0]++;
      if (result)
	com_count[command][1]++;
    }
    switch ((enum myisam_log_commands) command) {
    case MI_LOG_OPEN:
      if (!table_names[0])
      {
	com_count[command][0]--;		/* Must be counted explicite */
	if (result)
	  com_count[command][1]--;
      }

      if (curr_file_info)
	printf("\nWarning: %s is opened with same process and filenumber\n"
               "Maybe you should use the -P option ?\n",
	       curr_file_info->show_name);
      if (my_b_read(&cache,(uchar*) head,2))
	goto err;
      buff= 0;
      file_info.name=0;
      file_info.show_name=0;
      file_info.record=0;
      if (read_string(&cache, &buff, (uint) mi_uint2korr(head)))
	goto err;
      {
	uint i;
	char *pos,*to;

	/* Fix if old DOS files to new format */
	for (pos=file_info.name=(char*)buff; (pos=strchr(pos,'\\')) ; pos++)
	  *pos= '/';

	pos=file_info.name;
	for (i=0 ; i < prefix_remove ; i++)
	{
	  char *next;
	  if (!(next=strchr(pos,'/')))
	    break;
	  pos=next+1;
	}
	to=isam_file_name;
	if (filepath)
	  to=convert_dirname(isam_file_name,filepath,NullS);
	strmov(to,pos);
	fn_ext(isam_file_name)[0]=0;	/* Remove extension */
      }
      open_param.name=file_info.name;
      open_param.max_id=0;
      (void) tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param,
		     left_root_right);
      file_info.id=open_param.max_id+1;
      /*
       * In the line below +10 is added to accomodate '<' and '>' chars
       * plus '\0' at the end, so that there is place for 7 digits.
       * It is  improbable that same table can have that many entries in 
       * the table cache.
       * The additional space is needed for the sprintf commands two lines
       * below.
       */ 
      file_info.show_name=my_memdup(isam_file_name,
				    (uint) strlen(isam_file_name)+10,
				    MYF(MY_WME));
      if (file_info.id > 1)
	sprintf(strend(file_info.show_name),"<%d>",file_info.id);
      file_info.closed=1;
      file_info.accessed=access_time;
      file_info.used=1;
      if (table_names[0])
      {
	char **name;
	file_info.used=0;
	for (name=table_names ; *name ; name++)
	{
	  if (!strcmp(*name,isam_file_name))
	    file_info.used=1;			/* Update/log only this */
	}
      }
      if (update && file_info.used)
      {
	if (files_open >= max_files)
	{
	  if (close_some_file(&tree))
	    goto com_err;
	  files_open--;
	}
	if (!(file_info.isam= mi_open(isam_file_name,O_RDWR,
				      HA_OPEN_WAIT_IF_LOCKED)))
	  goto com_err;
	if (!(file_info.record=my_malloc(file_info.isam->s->base.reclength,
					 MYF(MY_WME))))
	  goto end;
	files_open++;
	file_info.closed=0;
      }
      (void) tree_insert(&tree, (uchar*) &file_info, 0, tree.custom_arg);
      if (file_info.used)
      {
	if (verbose && !record_pos_file)
	  printf_log("%s: open -> %d",file_info.show_name, file_info.filenr);
	com_count[command][0]++;
	if (result)
	  com_count[command][1]++;
      }
      break;
    case MI_LOG_CLOSE:
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s -> %d",FILENAME(curr_file_info),
	       command_name[command],result);
      if (curr_file_info)
      {
	if (!curr_file_info->closed)
	  files_open--;
        (void) tree_delete(&tree, (uchar*) curr_file_info, 0, tree.custom_arg);
      }
      break;
    case MI_LOG_EXTRA:
      if (my_b_read(&cache,(uchar*) head,1))
	goto err;
      extra_command=(enum ha_extra_function) head[0];
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info),
		   command_name[command], (int) extra_command,result);
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (mi_extra(curr_file_info->isam, extra_command, 0) != (int) result)
	{
	  fflush(stdout);
	  (void) fprintf(stderr,
		       "Warning: error %d, expected %d on command %s at %s\n",
		       my_errno,result,command_name[command],
		       llstr(isamlog_filepos,llbuff));
	  fflush(stderr);
	}
      }
      break;
    case MI_LOG_DELETE:
      if (my_b_read(&cache,(uchar*) head,8))
	goto err;
      filepos=mi_sizekorr(head);
      if (verbose && (!record_pos_file ||
		      ((record_pos == filepos || record_pos == NO_FILEPOS) &&
		       !cmp_filename(curr_file_info,record_pos_file))) &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info),
		   command_name[command],(long) filepos,result);
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
	{
	  if (!recover)
	    goto com_err;
	  if (verbose)
	    printf_log("error: Didn't find row to delete with mi_rrnd");
	  com_count[command][2]++;		/* Mark error */
	}
	mi_result=mi_delete(curr_file_info->isam,curr_file_info->record);
	if ((mi_result == 0 && result) ||
	    (mi_result && (uint) my_errno != result))
	{
	  if (!recover)
	    goto com_err;
	  if (mi_result)
	    com_count[command][2]++;		/* Mark error */
	  if (verbose)
	    printf_log("error: Got result %d from mi_delete instead of %d",
		       mi_result, result);
	}
      }
      break;
    case MI_LOG_WRITE:
    case MI_LOG_UPDATE:
      if (my_b_read(&cache,(uchar*) head,12))
	goto err;
      filepos=mi_sizekorr(head);
      length=mi_uint4korr(head+8);
      buff=0;
      if (read_string(&cache,&buff,(uint) length))
	goto err;
      if ((!record_pos_file ||
	  ((record_pos == filepos || record_pos == NO_FILEPOS) &&
	   !cmp_filename(curr_file_info,record_pos_file))) &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
      {
	if (write_file &&
	    (my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP))))
	  goto end;
	if (verbose)
	  printf_log("%s: %s at %ld, length=%ld -> %d",
		     FILENAME(curr_file_info),
		     command_name[command], filepos,length,result);
      }
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (curr_file_info->isam->s->base.blobs)
	  fix_blob_pointers(curr_file_info->isam,buff);
	if ((enum myisam_log_commands) command == MI_LOG_UPDATE)
	{
	  if (mi_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
	  {
	    if (!recover)
	    {
	      result=0;
	      goto com_err;
	    }
	    if (verbose)
	      printf_log("error: Didn't find row to update with mi_rrnd");
	    if (recover == 1 || result ||
		find_record_with_key(curr_file_info,buff))
	    {
	      com_count[command][2]++;		/* Mark error */
	      break;
	    }
	  }
	  mi_result=mi_update(curr_file_info->isam,curr_file_info->record,
			      buff);
	  if ((mi_result == 0 && result) ||
	      (mi_result && (uint) my_errno != result))
	  {
	    if (!recover)
	      goto com_err;
	    if (verbose)
	      printf_log("error: Got result %d from mi_update instead of %d",
			 mi_result, result);
	    if (mi_result)
	      com_count[command][2]++;		/* Mark error */
	  }
	}
	else
	{
	  mi_result=mi_write(curr_file_info->isam,buff);
	  if ((mi_result == 0 && result) ||
	      (mi_result && (uint) my_errno != result))
	  {
	    if (!recover)
	      goto com_err;
	    if (verbose)
	      printf_log("error: Got result %d from mi_write instead of %d",
			 mi_result, result);
	    if (mi_result)
	      com_count[command][2]++;		/* Mark error */
	  }
	  if (!recover && filepos != curr_file_info->isam->lastpos)
	  {
	    printf("error: Wrote at position: %s, should have been %s",
		   llstr(curr_file_info->isam->lastpos,llbuff),
		   llstr(filepos,llbuff2));
	    goto end;
	  }
	}
      }
      my_free(buff);
      break;
    case MI_LOG_LOCK:
      if (my_b_read(&cache,(uchar*) head,sizeof(lock_command)))
	goto err;
      memcpy(&lock_command, head, sizeof(lock_command));
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info),
		   command_name[command],lock_command,result);
      if (update && curr_file_info && !curr_file_info->closed)
      {
	if (mi_lock_database(curr_file_info->isam,lock_command) !=
	    (int) result)
	  goto com_err;
      }
      break;
    case MI_LOG_DELETE_ALL:
      if (verbose && !record_pos_file &&
	  (!table_names[0] || (curr_file_info && curr_file_info->used)))
	printf_log("%s: %s -> %d\n",FILENAME(curr_file_info),
		   command_name[command],result);
      break;
    default:
      fflush(stdout);
      (void) fprintf(stderr,
		   "Error: found unknown command %d in logfile, aborted\n",
		   command);
      fflush(stderr);
      goto end;
    }
  }
  end_key_cache(dflt_key_cache,1);
  delete_tree(&tree);
  (void) end_io_cache(&cache);
  (void) my_close(file,MYF(0));
  if (write_file && my_fclose(write_file,MYF(MY_WME)))
    DBUG_RETURN(1);
  DBUG_RETURN(0);

 err:
  fflush(stdout);
  (void) fprintf(stderr,"Got error %d when reading from logfile\n",my_errno);
  fflush(stderr);
  goto end;
 com_err:
  fflush(stdout);
  (void) fprintf(stderr,"Got error %d, expected %d on command %s at %s\n",
	       my_errno,result,command_name[command],
	       llstr(isamlog_filepos,llbuff));
  fflush(stderr);
 end:
  end_key_cache(dflt_key_cache, 1);
  delete_tree(&tree);
  (void) end_io_cache(&cache);
  (void) my_close(file,MYF(0));
  if (write_file)
    (void) my_fclose(write_file,MYF(MY_WME));
  DBUG_RETURN(1);
}
Exemplo n.º 8
0
int test_update(MARIA_HA *file,int id,int lock_type)
{
  uint i,lock,found,next,prev,update;
  uint32 tmp;
  char find[4];
  struct record new_record;

  lock=0;
  if (rnd(2) == 0 || lock_type == F_RDLCK)
  {
    lock=1;
    if (maria_lock_database(file,F_WRLCK))
    {
      if (lock_type == F_RDLCK && my_errno == EDEADLK)
      {
	printf("%2d: write:  deadlock\n",id); fflush(stdout);
	return 0;
      }
      fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
      return 1;
    }
  }
  bzero((char*) &new_record,sizeof(new_record));
  strmov((char*) new_record.text,"Updated");

  found=next=prev=update=0;
  for (i=0 ; i < 100 ; i++)
  {
    tmp=rnd(100000);
    int4store(find,tmp);
    if (!maria_rkey(file,record.id,1,(uchar*) find, HA_WHOLE_KEY,
                    HA_READ_KEY_EXACT))
      found++;
    else
    {
      if (my_errno != HA_ERR_KEY_NOT_FOUND)
      {
	fprintf(stderr,"%2d: Got error %d from read in update\n",id,my_errno);
	return 1;
      }
      else if (!maria_rnext(file,record.id,1))
	next++;
      else
      {
	if (my_errno != HA_ERR_END_OF_FILE)
	{
	  fprintf(stderr,"%2d: Got error %d from rnext in update\n",
		  id,my_errno);
	  return 1;
	}
	else if (!maria_rprev(file,record.id,1))
	  prev++;
	else
	{
	  if (my_errno != HA_ERR_END_OF_FILE)
	  {
	    fprintf(stderr,"%2d: Got error %d from rnext in update\n",
		    id,my_errno);
	    return 1;
	  }
	  continue;
	}
      }
    }
    memcpy(new_record.id,record.id,sizeof(record.id));
    tmp=rnd(20000)+40000;
    int4store(new_record.nr,tmp);
    if (!maria_update(file,record.id,new_record.id))
      update++;
    else
    {
      if (my_errno != HA_ERR_RECORD_CHANGED &&
	  my_errno != HA_ERR_RECORD_DELETED &&
	  my_errno != HA_ERR_FOUND_DUPP_KEY)
      {
	fprintf(stderr,"%2d: Got error %d from update\n",id,my_errno);
	return 1;
      }
    }
  }
  if (lock)
  {
    if (maria_lock_database(file,F_UNLCK))
    {
      fprintf(stderr,"Can't unlock table,id, error%d\n",my_errno);
      return 1;
    }
  }
  printf("%2d: update: %5d\n",id,update); fflush(stdout);
  return 0;
}
Exemplo n.º 9
0
int main(int argc, char *argv[])
{
  register uint i,j;
  uint ant,n1,n2,n3;
  uint write_count,update,opt_delete,check2,dupp_keys,found_key;
  int error;
  ulong pos;
  unsigned long key_check;
  uchar record[128],record2[128],record3[128],key[10];
  const char *filename,*filename2;
  HP_INFO *file,*file2;
  HP_SHARE *tmp_share;
  HP_KEYDEF keyinfo[MAX_KEYS];
  HA_KEYSEG keyseg[MAX_KEYS*5];
  HEAP_PTR UNINIT_VAR(position);
  HP_CREATE_INFO hp_create_info;
  CHARSET_INFO *cs= &my_charset_latin1;
  my_bool unused;
  MY_INIT(argv[0]);		/* init my_sys library & pthreads */

  filename= "test2";
  filename2= "test2_2";
  file=file2=0;
  get_options(argc,argv);

  bzero(&hp_create_info, sizeof(hp_create_info));
  hp_create_info.max_table_size= 1024L*1024L;
  hp_create_info.keys= keys;
  hp_create_info.keydef= keyinfo;
  hp_create_info.reclength= reclength;
  hp_create_info.max_records= (ulong) flag*100000L;
  hp_create_info.min_records= (ulong) recant/2;

  write_count=update=opt_delete=0;
  key_check=0;

  keyinfo[0].seg=keyseg;
  keyinfo[0].keysegs=1;
  keyinfo[0].flag= 0;
  keyinfo[0].algorithm= HA_KEY_ALG_HASH;
  keyinfo[0].seg[0].type=HA_KEYTYPE_BINARY;
  keyinfo[0].seg[0].start=0;
  keyinfo[0].seg[0].length=6;
  keyinfo[0].seg[0].null_bit=0;
  keyinfo[0].seg[0].charset=cs;
  keyinfo[1].seg=keyseg+1;
  keyinfo[1].keysegs=2;
  keyinfo[1].flag=0;
  keyinfo[1].algorithm= HA_KEY_ALG_HASH;
  keyinfo[1].seg[0].type=HA_KEYTYPE_BINARY;
  keyinfo[1].seg[0].start=7;
  keyinfo[1].seg[0].length=6;
  keyinfo[1].seg[0].null_bit=0;
  keyinfo[1].seg[0].charset=cs;
  keyinfo[1].seg[1].type=HA_KEYTYPE_TEXT;
  keyinfo[1].seg[1].start=0;			/* key in two parts */
  keyinfo[1].seg[1].length=6;
  keyinfo[1].seg[1].null_bit=0;
  keyinfo[1].seg[1].charset=cs;
  keyinfo[2].seg=keyseg+3;
  keyinfo[2].keysegs=1;
  keyinfo[2].flag=HA_NOSAME;
  keyinfo[2].algorithm= HA_KEY_ALG_HASH;
  keyinfo[2].seg[0].type=HA_KEYTYPE_BINARY;
  keyinfo[2].seg[0].start=12;
  keyinfo[2].seg[0].length=8;
  keyinfo[2].seg[0].null_bit=0;
  keyinfo[2].seg[0].charset=cs;
  keyinfo[3].seg=keyseg+4;
  keyinfo[3].keysegs=1;
  keyinfo[3].flag=HA_NOSAME;
  keyinfo[3].algorithm= HA_KEY_ALG_HASH;
  keyinfo[3].seg[0].type=HA_KEYTYPE_BINARY;
  keyinfo[3].seg[0].start=37;
  keyinfo[3].seg[0].length=1;
  keyinfo[3].seg[0].null_bit=1;
  keyinfo[3].seg[0].null_pos=38;
  keyinfo[3].seg[0].charset=cs;

  bzero((char*) key1,sizeof(key1));
  bzero((char*) key3,sizeof(key3));

  printf("- Creating heap-file\n");
  if (heap_create(filename, &hp_create_info, &tmp_share, &unused) ||
      !(file= heap_open(filename, 2)))
    goto err;
  signal(SIGINT,endprog);

  printf("- Writing records:s\n");
  strmov((char*) record,"          ..... key");

  for (i=0 ; i < recant ; i++)
  {
    n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*5,MAX_RECORDS));
    make_record(record,n1,n2,n3,"Pos",write_count);

    if (heap_write(file,record))
    {
      if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
      {
	printf("Error: %d in write at record: %d\n",my_errno,i);
	goto err;
      }
      if (verbose) printf("   Double key: %d\n",n3);
    }
    else
    {
      if (key3[n3] == 1)
      {
	printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
	goto err;
      }
      write_count++; key1[n1]++; key3[n3]=1;
      key_check+=n1;
    }
    if (testflag == 1 && heap_check_heap(file,0))
    {
      puts("Heap keys crashed");
      goto err;
    }
  }
  if (testflag == 1)
    goto end;
  if (heap_check_heap(file,0))
  {
    puts("Heap keys crashed");
    goto err;
  }

  printf("- Delete\n");
  for (i=0 ; i < write_count/10 ; i++)
  {
    for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
    if (j != 0)
    {
      sprintf((char*) key,"%6d",j);
      if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT))
      {
	printf("can't find key1: \"%s\"\n",(char*) key);
	goto err;
      }
      if (heap_delete(file,record))
      {
	printf("error: %d; can't delete record: \"%s\"\n", my_errno,(char*) record);
	goto err;
      }
      opt_delete++;
      key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
      key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
      key_check-=atoi((char*) record);
      if (testflag == 2 && heap_check_heap(file,0))
      {
	puts("Heap keys crashed");
	goto err;
      }
    }
    else
      puts("Warning: Skipping delete test because no dupplicate keys");
  }
  if (testflag==2) goto end;
  if (heap_check_heap(file,0))
  {
    puts("Heap keys crashed");
    goto err;
  }

  printf("- Update\n");
  for (i=0 ; i < write_count/10 ; i++)
  {
    n1=rnd(1000); n2=rnd(100); n3=rnd(min(recant*2,MAX_RECORDS));
    make_record(record2, n1, n2, n3, "XXX", update);
    if (rnd(2) == 1)
    {
      if (heap_scan_init(file))
	goto err;
      j=rnd(write_count-opt_delete);
      while ((error=heap_scan(file,record) == HA_ERR_RECORD_DELETED) ||
	     (!error && j))
      {
	if (!error)
	  j--;
      }
      if (error)
	goto err;
    }
    else
    {
      for (j=rnd(1000)+1 ; j>0 && key1[j] == 0 ; j--) ;
      if (!key1[j])
	continue;
      sprintf((char*) key,"%6d",j);
      if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT))
      {
	printf("can't find key1: \"%s\"\n",(char*) key);
	goto err;
      }
    }
    if (heap_update(file,record,record2))
    {
      if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
      {
	printf("error: %d; can't update:\nFrom: \"%s\"\nTo:   \"%s\"\n",
	       my_errno,(char*) record, (char*) record2);
	goto err;
      }
      if (verbose)
	printf("Double key when tried to update:\nFrom: \"%s\"\nTo:   \"%s\"\n",
               (char*) record, (char*) record2);
    }
    else
    {
      key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
      key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
      key1[n1]++; key3[n3]=1;
      update++;
      key_check=key_check-atoi((char*) record)+n1;
    }
    if (testflag == 3 && heap_check_heap(file,0))
    {
      puts("Heap keys crashed");
      goto err;
    }
  }
  if (testflag == 3) goto end;
  if (heap_check_heap(file,0))
  {
    puts("Heap keys crashed");
    goto err;
  }

  for (i=999, dupp_keys=found_key=0 ; i>0 ; i--)
  {
    if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; }
    sprintf((char*) key,"%6d",found_key);
  }

  if (dupp_keys > 3)
  {
    if (!silent)
      printf("- Read first key - next - delete - next -> last\n");
    DBUG_PRINT("progpos",("first - next - delete - next -> last"));

    if (heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT))
      goto err;
    if (heap_rnext(file,record3)) goto err;
    if (heap_delete(file,record3)) goto err;
    key_check-=atoi((char*) record3);
    key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
    key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
    opt_delete++;
    ant=2;
    while ((error=heap_rnext(file,record3)) == 0 ||
	   error == HA_ERR_RECORD_DELETED)
      if (! error)
	ant++;
    if (ant != dupp_keys)
    {
      printf("next: I can only find: %d records of %d\n",
	     ant,dupp_keys);
      goto end;
    }
    dupp_keys--;
    if (heap_check_heap(file,0))
    {
      puts("Heap keys crashed");
      goto err;
    }

    if (!silent)
      printf("- Read last key - delete - prev - prev - opt_delete - prev -> first\n");

    if (heap_rlast(file,record3,0)) goto err;
    if (heap_delete(file,record3)) goto err;
    key_check-=atoi((char*) record3);
    key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
    key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
    opt_delete++;
    if (heap_rprev(file,record3) || heap_rprev(file,record3))
      goto err;
    if (heap_delete(file,record3)) goto err;
    key_check-=atoi((char*) record3);
    key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
    key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
    opt_delete++;
    ant=3;
    while ((error=heap_rprev(file,record3)) == 0 ||
	   error == HA_ERR_RECORD_DELETED)
    {
      if (! error)
	ant++;
    }
    if (ant != dupp_keys)
    {
      printf("next: I can only find: %d records of %d\n",
	     ant,dupp_keys);
      goto end;
    }
    dupp_keys-=2;
    if (heap_check_heap(file,0))
    {
      puts("Heap keys crashed");
      goto err;
    }
  }
  else
    puts("Warning: Not enough duplicated keys:  Skipping delete key check");

  if (!silent)
    printf("- Read (first) - next - delete - next -> last\n");
  DBUG_PRINT("progpos",("first - next - delete - next -> last"));

  if (heap_scan_init(file))
    goto err;
  while ((error=heap_scan(file,record3) == HA_ERR_RECORD_DELETED)) ;
  if (error)
    goto err;
  if (heap_delete(file,record3)) goto err;
  key_check-=atoi((char*) record3);
  opt_delete++;
  key1[atoi((char*) record+keyinfo[0].seg[0].start)]--;
  key3[atoi((char*) record+keyinfo[2].seg[0].start)]=0;
  ant=0;
  while ((error=heap_scan(file,record3)) == 0 ||
	 error == HA_ERR_RECORD_DELETED)
    if (! error)
      ant++;
  if (ant != write_count-opt_delete)
  {
    printf("next: Found: %d records of %d\n",ant,write_count-opt_delete);
    goto end;
  }
  if (heap_check_heap(file,0))
  {
    puts("Heap keys crashed");
    goto err;
  }

  puts("- Test if: Read rrnd - same - rkey - same");
  DBUG_PRINT("progpos",("Read rrnd - same"));
  pos=rnd(write_count-opt_delete-5)+5;
  heap_scan_init(file);
  i=5;
  while ((error=heap_scan(file,record)) == HA_ERR_RECORD_DELETED ||
	 (error == 0 && pos))
  {
    if (!error)
      pos--;
    if (i-- == 0)
    {
      bmove(record3,record,reclength);
      position=heap_position(file);
    }
  }
  if (error)
    goto err;
  bmove(record2,record,reclength);
  if (heap_rsame(file,record,-1) || heap_rsame(file,record2,2))
    goto err;
  if (memcmp(record2,record,reclength))
  {
    puts("heap_rsame didn't find right record");
    goto end;
  }

  puts("- Test of read through position");
  if (heap_rrnd(file,record,position))
    goto err;
  if (memcmp(record3,record,reclength))
  {
    puts("heap_frnd didn't find right record");
    goto end;
  }

  printf("- heap_info\n");
  {
    HEAPINFO info;
    heap_info(file,&info,0);
    /* We have to test with opt_delete +1 as this may be the case if the last
       inserted row was a duplicate key */
    if (info.records != write_count-opt_delete ||
	(info.deleted != opt_delete && info.deleted != opt_delete+1))
    {
      puts("Wrong info from heap_info");
      printf("Got: records: %ld(%d)  deleted: %ld(%d)\n",
	     info.records,write_count-opt_delete,info.deleted,opt_delete);
    }
  }

#ifdef OLD_HEAP_VERSION
  {
    uint check;
    printf("- Read through all records with rnd\n");
    if (heap_extra(file,HA_EXTRA_RESET) || heap_extra(file,HA_EXTRA_CACHE))
    {
      puts("got error from heap_extra");
      goto end;
    }
    ant=check=0;
    while ((error=heap_rrnd(file,record,(ulong) -1)) != HA_ERR_END_OF_FILE &&
	   ant < write_count + 10)
    {
      if (!error)
      {
	ant++;
	check+=calc_check(record,reclength);
      }
    }
    if (ant != write_count-opt_delete)
    {
      printf("rrnd: I can only find: %d records of %d\n", ant,
	     write_count-opt_delete);
      goto end;
    }
    if (heap_extra(file,HA_EXTRA_NO_CACHE))
    {
      puts("got error from heap_extra(HA_EXTRA_NO_CACHE)");
      goto end;
    }
  }
#endif

  printf("- Read through all records with scan\n");
  if (heap_reset(file) || heap_extra(file,HA_EXTRA_CACHE))
  {
    puts("got error from heap_extra");
    goto end;
  }
  ant=check2=0;
  heap_scan_init(file);
  while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE &&
	 ant < write_count + 10)
  {
    if (!error)
    {
      ant++;
      check2+=calc_check(record,reclength);
    }
  }
  if (ant != write_count-opt_delete)
  {
    printf("scan: I can only find: %d records of %d\n", ant,
	   write_count-opt_delete);
    goto end;
  }
#ifdef OLD_HEAP_VERSION
  if (check != check2)
  {
    puts("scan: Checksum didn't match reading with rrnd");
    goto end;
  }
#endif


  if (heap_extra(file,HA_EXTRA_NO_CACHE))
  {
    puts("got error from heap_extra(HA_EXTRA_NO_CACHE)");
    goto end;
  }

  for (i=999, dupp_keys=found_key=0 ; i>0 ; i--)
  {
    if (key1[i] > dupp_keys) { dupp_keys=key1[i]; found_key=i; }
    sprintf((char*) key,"%6d",found_key);
  }
  printf("- Read through all keys with first-next-last-prev\n");
  ant=0;
  for (error=heap_rkey(file,record,0,key,6, HA_READ_KEY_EXACT);
      ! error ;
       error=heap_rnext(file,record))
    ant++;
  if (ant != dupp_keys)
  {
    printf("first-next: I can only find: %d records of %d\n", ant,
	   dupp_keys);
    goto end;
  }

  ant=0;
  for (error=heap_rlast(file,record,0) ;
      ! error ;
      error=heap_rprev(file,record))
  {
    ant++;
    check2+=calc_check(record,reclength);
  }
  if (ant != dupp_keys)
  {
    printf("last-prev: I can only find: %d records of %d\n", ant,
	   dupp_keys);
    goto end;
  }

  if (testflag == 4) goto end;

  printf("- Reading through all rows through keys\n");
  if (!(file2=heap_open(filename, 2)))
    goto err;
  if (heap_scan_init(file))
    goto err;
  while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE)
  {
    if (error == 0)
    {
      if (heap_rkey(file2,record2,2,record+keyinfo[2].seg[0].start,8,
		    HA_READ_KEY_EXACT))
      {
	printf("can't find key3: \"%.8s\"\n",
	       record+keyinfo[2].seg[0].start);
	goto err;
      }
    }
  }
  heap_close(file2);

  printf("- Creating output heap-file 2\n");
  hp_create_info.keys= 1;
  hp_create_info.max_records= 0;
  hp_create_info.min_records= 0;
  if (heap_create(filename2, &hp_create_info, &tmp_share, &unused) ||
      !(file2= heap_open_from_share_and_register(tmp_share, 2)))
    goto err;

  printf("- Copying and removing records\n");
  if (heap_scan_init(file))
    goto err;
  while ((error=heap_scan(file,record)) != HA_ERR_END_OF_FILE)
  {
    if (error == 0)
    {
      if (heap_write(file2,record))
	goto err;
      key_check-=atoi((char*) record);
      write_count++;
      if (heap_delete(file,record))
	goto err;
      opt_delete++;
    }
    pos++;
  }
  printf("- Checking heap tables\n");
  if (heap_check_heap(file,1) || heap_check_heap(file2,1))
  {
    puts("Heap keys crashed");
    goto err;
  }

  if (my_errno != HA_ERR_END_OF_FILE)
    printf("error: %d from heap_rrnd\n",my_errno);
  if (key_check)
    printf("error: Some read got wrong: check is %ld\n",(long) key_check);

end:
  printf("\nFollowing test have been made:\n");
  printf("Write records: %d\nUpdate records: %d\nDelete records: %d\n", write_count,update,opt_delete);
  heap_clear(file);
  if (heap_close(file) || (file2 && heap_close(file2)))
    goto err;
  heap_delete_table(filename2);
  hp_panic(HA_PANIC_CLOSE);
  my_end(MY_GIVE_INFO);
  return(0);
err:
  printf("Got error: %d when using heap-database\n",my_errno);
  (void) heap_close(file);
  return(1);
} /* main */
Exemplo n.º 10
0
int modify_defaults_file(const char *file_location, const char *option,
                         const char *option_value,
                         const char *section_name, int remove_option)
{
  FILE *cnf_file;
  MY_STAT file_stat;
  char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
  size_t opt_len= 0, optval_len= 0, sect_len;
  uint nr_newlines= 0, buffer_size;
  my_bool in_section= FALSE, opt_applied= 0;
  uint reserve_extended;
  uint new_opt_len;
  int reserve_occupied= 0;
  DBUG_ENTER("modify_defaults_file");

  if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0))))
    DBUG_RETURN(2);

  /* my_fstat doesn't use the flag parameter */
  if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
    goto malloc_err;

  if (option && option_value)
  {
    opt_len= strlen(option);
    optval_len= strlen(option_value);
  }

  new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN;

  /* calculate the size of the buffer we need */
  reserve_extended= (opt_len +
                     1 +                        /* For '=' char */
                     optval_len +               /* Option value len */
                     NEWLINE_LEN +              /* Space for newline */
                     RESERVE);                  /* Some additional space */

  buffer_size= (file_stat.st_size +
                1);                             /* The ending zero */

  /*
    Reserve space to read the contents of the file and some more
    for the option we want to add.
  */
  if (!(file_buffer= (char*) my_malloc(buffer_size + reserve_extended,
                                       MYF(MY_WME))))
    goto malloc_err;

  sect_len= strlen(section_name);

  for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); )
  {
    /* Skip over whitespaces */
    for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr);
	 src_ptr++)
    {}

    if (!*src_ptr) /* Empty line */
    {
      nr_newlines++;
      continue;
    }

    /* correct the option (if requested) */
    if (option && in_section && !strncmp(src_ptr, option, opt_len) &&
        (*(src_ptr + opt_len) == '=' ||
         my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) ||
         *(src_ptr + opt_len) == '\0'))
    {
      char *old_src_ptr= src_ptr;
      src_ptr= strend(src_ptr+ opt_len);        /* Find the end of the line */

      /* could be negative */
      reserve_occupied+= (int) new_opt_len - (int) (src_ptr - old_src_ptr);
      if (reserve_occupied >= (int) reserve_extended)
      {
        reserve_extended= (uint) reserve_occupied + RESERVE;
        if (!(file_buffer= (char*) my_realloc(file_buffer, buffer_size +
                                              reserve_extended,
                                              MYF(MY_WME|MY_FREE_ON_ERROR))))
          goto malloc_err;
      }
      opt_applied= 1;
      dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
    }
    else
    {
      /*
        If we are going to the new group and have an option to apply, do
        it now. If we are removing a single option or the whole section
        this will only trigger opt_applied flag.
      */

      if (in_section && !opt_applied && *src_ptr == '[')
      {
        dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
        opt_applied= 1;           /* set the flag to do write() later */
        reserve_occupied= new_opt_len+ opt_len + 1 + NEWLINE_LEN;
      }

      for (; nr_newlines; nr_newlines--)
        dst_ptr= strmov(dst_ptr, NEWLINE);

      /* Skip the section if MY_REMOVE_SECTION was given */
      if (!in_section || remove_option != MY_REMOVE_SECTION)
        dst_ptr= strmov(dst_ptr, linebuff);
    }
    /* Look for a section */
    if (*src_ptr == '[')
    {
      /* Copy the line to the buffer */
      if (!strncmp(++src_ptr, section_name, sect_len))
      {
        src_ptr+= sect_len;
        /* Skip over whitespaces. They are allowed after section name */
        for (; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++)
        {}

        if (*src_ptr != ']')
        {
          in_section= FALSE;
          continue; /* Missing closing parenthesis. Assume this was no group */
        }

        if (remove_option == MY_REMOVE_SECTION)
          dst_ptr= dst_ptr - strlen(linebuff);

        in_section= TRUE;
      }
      else
        in_section= FALSE; /* mark that this section is of no interest to us */
    }
  }

  /*
    File ended. Apply an option or set opt_applied flag (in case of
    MY_REMOVE_SECTION) so that the changes are saved. Do not do anything
    if we are removing non-existent option.
  */

  if (!opt_applied && in_section && (remove_option != MY_REMOVE_OPTION))
  {
    /* New option still remains to apply at the end */
    if (!remove_option && *(dst_ptr - 1) != '\n')
      dst_ptr= strmov(dst_ptr, NEWLINE);
    dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
    opt_applied= 1;
  }
  for (; nr_newlines; nr_newlines--)
    dst_ptr= strmov(dst_ptr, NEWLINE);

  if (opt_applied)
  {
    /* Don't write the file if there are no changes to be made */
    if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
                  MYF(MY_WME)) ||
        my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
        my_fwrite(cnf_file, (uchar*) file_buffer, (size_t) (dst_ptr - file_buffer),
                  MYF(MY_NABP)))
      goto err;
  }
  if (my_fclose(cnf_file, MYF(MY_WME)))
    DBUG_RETURN(1);

  my_free(file_buffer, MYF(0));
  DBUG_RETURN(0);

err:
  my_free(file_buffer, MYF(0));
malloc_err:
  my_fclose(cnf_file, MYF(0));
  DBUG_RETURN(1); /* out of resources */
}