WL#314: New file handling

Affects: Server-7.1   —   Status: Un-Assigned

To make it possible to easily manipulate filenames and files I suggest that
we should add a new interface (MY_FILE) over file handling. 

Requirements:

- One should be able to use my_b_read/my_b_write directly on the
  MY_FILE structure to get the same speed advantage that IO_CACHE gives
  today.
- It's better to get things done FAST than to loose a couple of bytes
  per open file.
- All my_sys functions that takes filenames or filedescriptors should be
  converted to use MY_FILE.
- Should be coded in C (not C++)
- Strings in MY_FILENAME are NOT null_terminated.
  (This makes it possible to make the filename functions much more efficient).


Advantages

- Simpler and portable filename handling as the filename is split into
  directory, basename and extension
- fn_format() will be much faster (and have a new name!).
- One (clean) interface to files.
- We handle temporary files (mf_cache.c), cached files (mf_io_cache.c),
  and RAID (raid.cc) through the same interface.
- Faster and more portable RAID tables.
- More secure pread/pwrite on windows.


Disadvantages:

- When calling some functions like open/delete/rename one has to first
  create a MY_FILE object, before calling the function.
- A MY_FILE structure will take more space to store than a File.
- By just having one MY_FILE structure, all slots will not be used for
  all file types.
- One call indirection when reading/writing to normal files, instead
  of a normal function call.
- One has to recompile everything when MY_FILE changes.


Proposed MY_FILE structure:
(This is a join of my_file_info and IO_CACHE and RaidFD)

typedef st_my_filename
{
  char *dir;
  char *base;
  char *ext;
  uint16 dir_length, base_length, ext_length;
  uint16 flags;	/* If we should free this on my_close and other flags */
  char buffer[FN_REFLEN];
} MY_FILENAME;

enum en_file_type { UNOPEN = 0, FILE_BY_OPEN, FILE_BY_CREATE,
		 STREAM_BY_FOPEN, STREAM_BY_FDOPEN, FILE_BY_MKSTEMP,
		 FILE_BY_DUP };
enum en_cache_type {READ_CACHE,WRITE_CACHE,READ_FIFO,READ_NET,WRITE_NET};

typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*);

typedef struct st_my_file
{
  File			file
  my_off_t 		pos_in_file,end_of_file;
  ulong			raid_chunksize;			/* 1..n in bytes */
  MY_FILENAME		name;
  int (*read)(struct st_my_file *, byte *, uint, myf myflags);
  int (*pread)(struct st_my_file *, byte *, uint, my_off_t pos, myf myflags);
  int (*write)(struct st_my_file *, byte *, uint);
  int (*pwread)(struct st_my_file *, byte *, uint, my_off_t pos);
  int (*close)(struct st_my_file *);
  int (*lock)(struct st_my_file *, int locktype, my_off_t start,
	       my_off_t length, myf MyFlags);
  int (*chsize)(struct st_my_file *, my_off_t newlength, myf MyFlags);
  int (*fstat)(struct st_my_file *, MY_STAT *stat_area, myf MyFlags);

  /* Most of the following is used for buffered files (old IO_CACHE) */
  byte			*rc_pos,*rc_end,*buffer,*rc_request_pos;
  IO_CACHE_CALLBACK	pre_read, post_read, pre_close;
  void* 		pre_arg;	/* for use by pre/post_read */
  enum en_file_type	file_type;
  enum en_cache_type	cache_type;
  enum st_raid_type	raid_type,
  uint			buffer_length,read_length;
  uint			raid_chunks;
  myf			myflags;	/* Flags used to my_read/my_write */
#if defined(THREAD) && !defined(HAVE_PREAD)  
  pthread_mutex_t	mutex;
#endif
  int			error;
  my_bool	    	seek_not_done;
} MY_FILE;