List:Commits« Previous MessageNext Message »
From:stewart Date:October 11 2007 8:45am
Subject:[patch 1/8] WL4081: Copy azio for NDB
View as plain text  
Only copy the files directly from ARCHIVE engine.

Index: ndb-work/storage/ndb/include/util/azlib.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ndb-work/storage/ndb/include/util/azlib.h	2007-09-24 17:26:58.388401288 +0200
@@ -0,0 +1,342 @@
+/*
+  This libary has been modified for use by the MySQL Archive Engine.
+     -Brian Aker
+*/
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.3, July 18th, 2005
+
+  Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@stripped          madler@stripped
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#include <zlib.h>
+
+#include "../../mysys/mysys_priv.h"
+#include <my_dir.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/* Start of MySQL Specific Information */
+
+/*
+  ulonglong + ulonglong + ulonglong + ulonglong + uchar
+*/
+#define AZMETA_BUFFER_SIZE sizeof(unsigned long long) \
+  + sizeof(unsigned long long) + sizeof(unsigned long long) + sizeof(unsigned long long)
\
+  + sizeof(unsigned int) + sizeof(unsigned int) \
+  + sizeof(unsigned int) + sizeof(unsigned int) \
+  + sizeof(unsigned char)
+
+#define AZHEADER_SIZE 29
+
+#define AZ_MAGIC_POS 0
+#define AZ_VERSION_POS 1
+#define AZ_MINOR_VERSION_POS 2
+#define AZ_BLOCK_POS 3
+#define AZ_STRATEGY_POS 4
+#define AZ_FRM_POS 5
+#define AZ_FRM_LENGTH_POS 9
+#define AZ_META_POS 13
+#define AZ_META_LENGTH_POS 17
+#define AZ_START_POS 21
+#define AZ_ROW_POS 29
+#define AZ_FLUSH_POS 37
+#define AZ_CHECK_POS 45
+#define AZ_AUTOINCREMENT_POS 53
+#define AZ_LONGEST_POS 61
+#define AZ_SHORTEST_POS 65
+#define AZ_COMMENT_POS 69
+#define AZ_COMMENT_LENGTH_POS 73
+#define AZ_DIRTY_POS 77
+
+
+/*
+  Flags for state
+*/
+#define AZ_STATE_CLEAN 0
+#define AZ_STATE_DIRTY 1
+#define AZ_STATE_SAVED 2
+#define AZ_STATE_CRASHED 3
+
+/*
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+     This library can optionally read and write gzip streams in memory as well.
+
+     The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+#define AZ_BUFSIZE_READ 32768
+#define AZ_BUFSIZE_WRITE 16384
+
+
+typedef struct azio_stream {
+  z_stream stream;
+  int      z_err;   /* error code for last stream operation */
+  int      z_eof;   /* set if end of input file */
+  File     file;   /* .gz file */
+  Byte     inbuf[AZ_BUFSIZE_READ];  /* input buffer */
+  Byte     outbuf[AZ_BUFSIZE_WRITE]; /* output buffer */
+  uLong    crc;     /* crc32 of uncompressed data */
+  char     *msg;    /* error message */
+  int      transparent; /* 1 if input file is not a .gz file */
+  char     mode;    /* 'w' or 'r' */
+  my_off_t  start;   /* start of compressed data in file (header skipped) */
+  my_off_t  in;      /* bytes into deflate or inflate */
+  my_off_t  out;     /* bytes out of deflate or inflate */
+  int      back;    /* one character push-back */
+  int      last;    /* true if push-back is last character */
+  unsigned char version;   /* Version */
+  unsigned char minor_version;   /* Version */
+  unsigned int block_size;   /* Block Size */
+  unsigned long long check_point;   /* Last position we checked */
+  unsigned long long forced_flushes;   /* Forced Flushes */
+  unsigned long long rows;   /* rows */
+  unsigned long long auto_increment;   /* auto increment field */
+  unsigned int longest_row;   /* Longest row */
+  unsigned int shortest_row;   /* Shortest row */
+  unsigned char dirty;   /* State of file */
+  unsigned int frm_start_pos;   /* Position for start of FRM */
+  unsigned int frm_length;   /* Position for start of FRM */
+  unsigned int comment_start_pos;   /* Position for start of comment */
+  unsigned int comment_length;   /* Position for start of comment */
+} azio_stream;
+
+                        /* basic functions */
+
+extern int azopen(azio_stream *s, const char *path, int Flags);
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h", or 'R' for run-length encoding
+   as in "wb1R". (See the description of deflateInit2 for more information
+   about the strategy parameter.)
+
+     azopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     azopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+int azdopen(azio_stream *s,File fd, int Flags); 
+/*
+     azdopen() associates a azio_stream with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in azopen.
+     The next call of gzclose on the returned azio_stream will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use azdopen(dup(fd), mode).
+     azdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+
+extern unsigned int azread ( azio_stream *s, voidp buf, unsigned int len, int *error);
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+extern unsigned int azwrite (azio_stream *s, voidpc buf, unsigned int len);
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   azwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+
+extern int azflush(azio_stream *file, int flush);
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+extern my_off_t azseek (azio_stream *file,
+                                      my_off_t offset, int whence);
+/*
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+extern int azrewind(azio_stream *file);
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+extern my_off_t aztell(azio_stream *file);
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+extern int azclose(azio_stream *file);
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+extern int azwrite_frm (azio_stream *s, char *blob, unsigned int length);
+extern int azread_frm (azio_stream *s, char *blob);
+extern int azwrite_comment (azio_stream *s, char *blob, unsigned int length);
+extern int azread_comment (azio_stream *s, char *blob);
+
+#ifdef	__cplusplus
+}
+#endif
Index: ndb-work/storage/ndb/src/common/util/azio.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ndb-work/storage/ndb/src/common/util/azio.c	2007-09-24 17:26:58.392401484 +0200
@@ -0,0 +1,871 @@
+/*
+  azio is a modified version of gzio. It  makes use of mysys and removes mallocs.
+    -Brian Aker
+*/
+
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ */
+
+/* @(#) $Id$ */
+
+#include "azlib.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+static int const az_magic[3] = {0xfe, 0x03, 0x01}; /* az magic header */
+
+/* gzip flag uchar */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define RESERVED     0xE0 /* bits 5..7: reserved */
+
+int az_open(azio_stream *s, const char *path, int Flags, File  fd);
+int do_flush(azio_stream *file, int flush);
+int    get_byte(azio_stream *s);
+void   check_header(azio_stream *s);
+void write_header(azio_stream *s);
+int    destroy(azio_stream *s);
+void putLong(File file, uLong x);
+uLong  getLong(azio_stream *s);
+void read_header(azio_stream *s, unsigned char *buffer);
+
+/* ===========================================================================
+  Opens a gzip (.gz) file for reading or writing. The mode parameter
+  is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+  or path name (if fd == -1).
+  az_open returns NULL if the file could not be opened or if there was
+  insufficient memory to allocate the (de)compression state; errno
+  can be checked to distinguish the two cases (if errno is zero, the
+  zlib error is Z_MEM_ERROR).
+*/
+int az_open (azio_stream *s, const char *path, int Flags, File fd)
+{
+  int err;
+  int level = Z_DEFAULT_COMPRESSION; /* compression level */
+  int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+
+  s->stream.zalloc = (alloc_func)0;
+  s->stream.zfree = (free_func)0;
+  s->stream.opaque = (voidpf)0;
+  memset(s->inbuf, 0, AZ_BUFSIZE_READ);
+  memset(s->outbuf, 0, AZ_BUFSIZE_WRITE);
+  s->stream.next_in = s->inbuf;
+  s->stream.next_out = s->outbuf;
+  s->stream.avail_in = s->stream.avail_out = 0;
+  s->z_err = Z_OK;
+  s->z_eof = 0;
+  s->in = 0;
+  s->out = 0;
+  s->back = EOF;
+  s->crc = crc32(0L, Z_NULL, 0);
+  s->transparent = 0;
+  s->mode = 'r';
+  s->version = (unsigned char)az_magic[1]; /* this needs to be a define to version */
+  s->version = (unsigned char)az_magic[2]; /* minor version */
+
+  /*
+    We do our own version of append by nature. 
+    We must always have write access to take card of the header.
+  */
+  DBUG_ASSERT(Flags | O_APPEND);
+  DBUG_ASSERT(Flags | O_WRONLY);
+
+  if (Flags & O_RDWR) 
+    s->mode = 'w';
+
+  if (s->mode == 'w') 
+  {
+    err = deflateInit2(&(s->stream), level,
+                       Z_DEFLATED, -MAX_WBITS, 8, strategy);
+    /* windowBits is passed < 0 to suppress zlib header */
+
+    s->stream.next_out = s->outbuf;
+    if (err != Z_OK)
+    {
+      destroy(s);
+      return Z_NULL;
+    }
+  } else {
+    s->stream.next_in  = s->inbuf;
+
+    err = inflateInit2(&(s->stream), -MAX_WBITS);
+    /* windowBits is passed < 0 to tell that there is no zlib header.
+     * Note that in this case inflate *requires* an extra "dummy" byte
+     * after the compressed stream in order to complete decompression and
+     * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+     * present after the compressed stream.
+   */
+    if (err != Z_OK)
+    {
+      destroy(s);
+      return Z_NULL;
+    }
+  }
+  s->stream.avail_out = AZ_BUFSIZE_WRITE;
+
+  errno = 0;
+  s->file = fd < 0 ? my_open(path, Flags, MYF(0)) : fd;
+
+  if (s->file < 0 ) 
+  {
+    destroy(s);
+    return Z_NULL;
+  }
+
+  if (Flags & O_CREAT || Flags & O_TRUNC) 
+  {
+    s->rows= 0;
+    s->forced_flushes= 0;
+    s->shortest_row= 0;
+    s->longest_row= 0;
+    s->auto_increment= 0;
+    s->check_point= 0;
+    s->comment_start_pos= 0;
+    s->comment_length= 0;
+    s->frm_start_pos= 0;
+    s->frm_length= 0;
+    s->dirty= 1; /* We create the file dirty */
+    s->start = AZHEADER_SIZE + AZMETA_BUFFER_SIZE;
+    write_header(s);
+    my_seek(s->file, 0, MY_SEEK_END, MYF(0));
+  }
+  else if (s->mode == 'w') 
+  {
+    uchar buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
+    my_pread(s->file, buffer, AZHEADER_SIZE + AZMETA_BUFFER_SIZE, 0,
+             MYF(0));
+    read_header(s, buffer); /* skip the .az header */
+    my_seek(s->file, 0, MY_SEEK_END, MYF(0));
+  }
+  else
+  {
+    check_header(s); /* skip the .az header */
+  }
+
+  return 1;
+}
+
+
+void write_header(azio_stream *s)
+{
+  char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
+  char *ptr= buffer;
+
+  s->block_size= AZ_BUFSIZE_WRITE;
+  s->version = (unsigned char)az_magic[1];
+  s->minor_version = (unsigned char)az_magic[2];
+
+
+  /* Write a very simple .az header: */
+  memset(buffer, 0, AZHEADER_SIZE + AZMETA_BUFFER_SIZE);
+  *(ptr + AZ_MAGIC_POS)= az_magic[0];
+  *(ptr + AZ_VERSION_POS)= (unsigned char)s->version;
+  *(ptr + AZ_MINOR_VERSION_POS)= (unsigned char)s->minor_version;
+  *(ptr + AZ_BLOCK_POS)= (unsigned char)(s->block_size/1024); /* Reserved for block
size */
+  *(ptr + AZ_STRATEGY_POS)= (unsigned char)Z_DEFAULT_STRATEGY; /* Compression Type */
+
+  int4store(ptr + AZ_FRM_POS, s->frm_start_pos); /* FRM Block */
+  int4store(ptr + AZ_FRM_LENGTH_POS, s->frm_length); /* FRM Block */
+  int4store(ptr + AZ_COMMENT_POS, s->comment_start_pos); /* COMMENT Block */
+  int4store(ptr + AZ_COMMENT_LENGTH_POS, s->comment_length); /* COMMENT Block */
+  int4store(ptr + AZ_META_POS, 0); /* Meta Block */
+  int4store(ptr + AZ_META_LENGTH_POS, 0); /* Meta Block */
+  int8store(ptr + AZ_START_POS, (unsigned long long)s->start); /* Start of Data Block
Index Block */
+  int8store(ptr + AZ_ROW_POS, (unsigned long long)s->rows); /* Start of Data Block
Index Block */
+  int8store(ptr + AZ_FLUSH_POS, (unsigned long long)s->forced_flushes); /* Start of
Data Block Index Block */
+  int8store(ptr + AZ_CHECK_POS, (unsigned long long)s->check_point); /* Start of Data
Block Index Block */
+  int8store(ptr + AZ_AUTOINCREMENT_POS, (unsigned long long)s->auto_increment); /*
Start of Data Block Index Block */
+  int4store(ptr+ AZ_LONGEST_POS , s->longest_row); /* Longest row */
+  int4store(ptr+ AZ_SHORTEST_POS, s->shortest_row); /* Shorest row */
+  int4store(ptr+ AZ_FRM_POS, 
+            AZHEADER_SIZE + AZMETA_BUFFER_SIZE); /* FRM position */
+  *(ptr + AZ_DIRTY_POS)= (unsigned char)s->dirty; /* Start of Data Block Index Block
*/
+
+  /* Always begin at the begining, and end there as well */
+  my_pwrite(s->file, (uchar*) buffer, AZHEADER_SIZE + AZMETA_BUFFER_SIZE, 0,
+            MYF(0));
+}
+
+/* ===========================================================================
+  Opens a gzip (.gz) file for reading or writing.
+*/
+int azopen(azio_stream *s, const char *path, int Flags)
+{
+  return az_open(s, path, Flags, -1);
+}
+
+/* ===========================================================================
+  Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+  to mimic the behavio(u)r of fdopen.
+*/
+int azdopen(azio_stream *s, File fd, int Flags)
+{
+  if (fd < 0) return 0;
+
+  return az_open (s, NULL, Flags, fd);
+}
+
+/* ===========================================================================
+  Read a byte from a azio_stream; update next_in and avail_in. Return EOF
+  for end of file.
+  IN assertion: the stream s has been sucessfully opened for reading.
+*/
+int get_byte(s)
+  azio_stream *s;
+{
+  if (s->z_eof) return EOF;
+  if (s->stream.avail_in == 0) 
+  {
+    errno = 0;
+    s->stream.avail_in = my_read(s->file, (uchar *)s->inbuf, AZ_BUFSIZE_READ,
MYF(0));
+    if (s->stream.avail_in == 0) 
+    {
+      s->z_eof = 1;
+      /* if (ferror(s->file)) s->z_err = Z_ERRNO; */
+      return EOF;
+    }
+    s->stream.next_in = s->inbuf;
+  }
+  s->stream.avail_in--;
+  return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+  Check the gzip header of a azio_stream opened for reading. Set the stream
+  mode to transparent if the gzip magic header is not present; set s->err
+  to Z_DATA_ERROR if the magic header is present but the rest of the header
+  is incorrect.
+  IN assertion: the stream s has already been created sucessfully;
+  s->stream.avail_in is zero for the first time, but may be non-zero
+  for concatenated .gz files.
+*/
+void check_header(azio_stream *s)
+{
+  int method; /* method uchar */
+  int flags;  /* flags uchar */
+  uInt len;
+  int c;
+
+  /* Assure two bytes in the buffer so we can peek ahead -- handle case
+    where first byte of header is at the end of the buffer after the last
+    gzip segment */
+  len = s->stream.avail_in;
+  if (len < 2) {
+    if (len) s->inbuf[0] = s->stream.next_in[0];
+    errno = 0;
+    len = (uInt)my_read(s->file, (uchar *)s->inbuf + len, AZ_BUFSIZE_READ >>
len, MYF(0));
+    if (len == 0) s->z_err = Z_ERRNO;
+    s->stream.avail_in += len;
+    s->stream.next_in = s->inbuf;
+    if (s->stream.avail_in < 2) {
+      s->transparent = s->stream.avail_in;
+      return;
+    }
+  }
+
+  /* Peek ahead to check the gzip magic header */
+  if ( s->stream.next_in[0] == gz_magic[0]  && s->stream.next_in[1] ==
gz_magic[1])
+  {
+    s->stream.avail_in -= 2;
+    s->stream.next_in += 2;
+    s->version= (unsigned char)2;
+
+    /* Check the rest of the gzip header */
+    method = get_byte(s);
+    flags = get_byte(s);
+    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+      s->z_err = Z_DATA_ERROR;
+      return;
+    }
+
+    /* Discard time, xflags and OS code: */
+    for (len = 0; len < 6; len++) (void)get_byte(s);
+
+    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+      len  =  (uInt)get_byte(s);
+      len += ((uInt)get_byte(s))<<8;
+      /* len is garbage if EOF but the loop below will quit anyway */
+      while (len-- != 0 && get_byte(s) != EOF) ;
+    }
+    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+      while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
+      while ((c = get_byte(s)) != 0 && c != EOF) ;
+    }
+    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
+      for (len = 0; len < 2; len++) (void)get_byte(s);
+    }
+    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+    s->start = my_tell(s->file, MYF(0)) - s->stream.avail_in;
+  }
+  else if ( s->stream.next_in[0] == az_magic[0]  && s->stream.next_in[1] ==
az_magic[1])
+  {
+    unsigned char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
+
+    for (len = 0; len < (AZHEADER_SIZE + AZMETA_BUFFER_SIZE); len++) 
+      buffer[len]= get_byte(s);
+    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+    read_header(s, buffer);
+    for (; len < s->start; len++) 
+      get_byte(s);
+  }
+  else
+  {
+    s->z_err = Z_OK;
+
+    return;
+  }
+}
+
+void read_header(azio_stream *s, unsigned char *buffer)
+{
+  if (buffer[0] == az_magic[0]  && buffer[1] == az_magic[1])
+  {
+    s->version= (unsigned int)buffer[AZ_VERSION_POS];
+    s->minor_version= (unsigned int)buffer[AZ_MINOR_VERSION_POS];
+    s->block_size= 1024 * buffer[AZ_BLOCK_POS];
+    s->start= (unsigned long long)uint8korr(buffer + AZ_START_POS);
+    s->rows= (unsigned long long)uint8korr(buffer + AZ_ROW_POS);
+    s->check_point= (unsigned long long)uint8korr(buffer + AZ_CHECK_POS);
+    s->forced_flushes= (unsigned long long)uint8korr(buffer + AZ_FLUSH_POS);
+    s->auto_increment= (unsigned long long)uint8korr(buffer + AZ_AUTOINCREMENT_POS);
+    s->longest_row= (unsigned int)uint4korr(buffer + AZ_LONGEST_POS);
+    s->shortest_row= (unsigned int)uint4korr(buffer + AZ_SHORTEST_POS);
+    s->frm_start_pos= (unsigned int)uint4korr(buffer + AZ_FRM_POS);
+    s->frm_length= (unsigned int)uint4korr(buffer + AZ_FRM_LENGTH_POS);
+    s->comment_start_pos= (unsigned int)uint4korr(buffer + AZ_COMMENT_POS);
+    s->comment_length= (unsigned int)uint4korr(buffer + AZ_COMMENT_LENGTH_POS);
+    s->dirty= (unsigned int)buffer[AZ_DIRTY_POS];
+  }
+  else
+  {
+    DBUG_ASSERT(buffer[0] == az_magic[0]  && buffer[1] == az_magic[1]);
+    return;
+  }
+}
+
+/* ===========================================================================
+ * Cleanup then free the given azio_stream. Return a zlib error code.
+ Try freeing in the reverse order of allocations.
+ */
+int destroy (s)
+  azio_stream *s;
+{
+  int err = Z_OK;
+
+  if (s->stream.state != NULL) 
+  {
+    if (s->mode == 'w') 
+      err = deflateEnd(&(s->stream));
+    else if (s->mode == 'r') 
+      err = inflateEnd(&(s->stream));
+  }
+
+  if (s->file > 0 && my_close(s->file, MYF(0))) 
+      err = Z_ERRNO;
+
+  s->file= -1;
+
+  if (s->z_err < 0) err = s->z_err;
+
+  return err;
+}
+
+/* ===========================================================================
+  Reads the given number of uncompressed bytes from the compressed file.
+  azread returns the number of bytes actually read (0 for end of file).
+*/
+unsigned int ZEXPORT azread ( azio_stream *s, voidp buf, unsigned int len, int *error)
+{
+  Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+  Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+  *error= 0;
+
+  if (s->mode != 'r')
+  { 
+    *error= Z_STREAM_ERROR;
+    return 0;
+  }
+
+  if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)
+  { 
+    *error= s->z_err;
+    return 0;
+  }
+
+  if (s->z_err == Z_STREAM_END)  /* EOF */
+  { 
+    return 0;
+  }
+
+  next_out = (Byte*)buf;
+  s->stream.next_out = (Bytef*)buf;
+  s->stream.avail_out = len;
+
+  if (s->stream.avail_out && s->back != EOF) {
+    *next_out++ = s->back;
+    s->stream.next_out++;
+    s->stream.avail_out--;
+    s->back = EOF;
+    s->out++;
+    start++;
+    if (s->last) {
+      s->z_err = Z_STREAM_END;
+      { 
+        return 1;
+      }
+    }
+  }
+
+  while (s->stream.avail_out != 0) {
+
+    if (s->transparent) {
+      /* Copy first the lookahead bytes: */
+      uInt n = s->stream.avail_in;
+      if (n > s->stream.avail_out) n = s->stream.avail_out;
+      if (n > 0) {
+        memcpy(s->stream.next_out, s->stream.next_in, n);
+        next_out += n;
+        s->stream.next_out = (Bytef *)next_out;
+        s->stream.next_in   += n;
+        s->stream.avail_out -= n;
+        s->stream.avail_in  -= n;
+      }
+      if (s->stream.avail_out > 0) 
+      {
+        s->stream.avail_out -=
+          (uInt)my_read(s->file, (uchar *)next_out, s->stream.avail_out, MYF(0));
+      }
+      len -= s->stream.avail_out;
+      s->in  += len;
+      s->out += len;
+      if (len == 0) s->z_eof = 1;
+      { 
+        return len;
+      }
+    }
+    if (s->stream.avail_in == 0 && !s->z_eof) {
+
+      errno = 0;
+      s->stream.avail_in = (uInt)my_read(s->file, (uchar *)s->inbuf,
AZ_BUFSIZE_READ, MYF(0));
+      if (s->stream.avail_in == 0) 
+      {
+        s->z_eof = 1;
+      }
+      s->stream.next_in = (Bytef *)s->inbuf;
+    }
+    s->in += s->stream.avail_in;
+    s->out += s->stream.avail_out;
+    s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+    s->in -= s->stream.avail_in;
+    s->out -= s->stream.avail_out;
+
+    if (s->z_err == Z_STREAM_END) {
+      /* Check CRC and original size */
+      s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+      start = s->stream.next_out;
+
+      if (getLong(s) != s->crc) {
+        s->z_err = Z_DATA_ERROR;
+      } else {
+        (void)getLong(s);
+        /* The uncompressed length returned by above getlong() may be
+         * different from s->out in case of concatenated .gz files.
+         * Check for such files:
+       */
+        check_header(s);
+        if (s->z_err == Z_OK) 
+        {
+          inflateReset(&(s->stream));
+          s->crc = crc32(0L, Z_NULL, 0);
+        }
+      }
+    }
+    if (s->z_err != Z_OK || s->z_eof) break;
+  }
+  s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+  if (len == s->stream.avail_out &&
+      (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
+  {
+    *error= s->z_err;
+
+    return 0;
+  }
+
+  return (len - s->stream.avail_out);
+}
+
+
+/* ===========================================================================
+  Writes the given number of uncompressed bytes into the compressed file.
+  azwrite returns the number of bytes actually written (0 in case of error).
+*/
+unsigned int azwrite (azio_stream *s, voidpc buf, unsigned int len)
+{
+  s->stream.next_in = (Bytef*)buf;
+  s->stream.avail_in = len;
+
+  s->rows++;
+
+  while (s->stream.avail_in != 0) 
+  {
+    if (s->stream.avail_out == 0) 
+    {
+
+      s->stream.next_out = s->outbuf;
+      if (my_write(s->file, (uchar *)s->outbuf, AZ_BUFSIZE_WRITE, 
+                   MYF(0)) != AZ_BUFSIZE_WRITE) 
+      {
+        s->z_err = Z_ERRNO;
+        break;
+      }
+      s->stream.avail_out = AZ_BUFSIZE_WRITE;
+    }
+    s->in += s->stream.avail_in;
+    s->out += s->stream.avail_out;
+    s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+    s->in -= s->stream.avail_in;
+    s->out -= s->stream.avail_out;
+    if (s->z_err != Z_OK) break;
+  }
+  s->crc = crc32(s->crc, (const Bytef *)buf, len);
+
+  if (len > s->longest_row)
+    s->longest_row= len;
+
+  if (len < s->shortest_row || !(s->shortest_row))
+    s->shortest_row= len;
+
+  return (unsigned int)(len - s->stream.avail_in);
+}
+
+
+/* ===========================================================================
+  Flushes all pending output into the compressed file. The parameter
+  flush is as in the deflate() function.
+*/
+int do_flush (azio_stream *s, int flush)
+{
+  uInt len;
+  int done = 0;
+  my_off_t afterwrite_pos;
+
+  if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+  s->stream.avail_in = 0; /* should be zero already anyway */
+
+  for (;;) 
+  {
+    len = AZ_BUFSIZE_WRITE - s->stream.avail_out;
+
+    if (len != 0) 
+    {
+      s->check_point= my_tell(s->file, MYF(0));
+      if ((uInt)my_write(s->file, (uchar *)s->outbuf, len, MYF(0)) != len) 
+      {
+        s->z_err = Z_ERRNO;
+        return Z_ERRNO;
+      }
+      s->stream.next_out = s->outbuf;
+      s->stream.avail_out = AZ_BUFSIZE_WRITE;
+    }
+    if (done) break;
+    s->out += s->stream.avail_out;
+    s->z_err = deflate(&(s->stream), flush);
+    s->out -= s->stream.avail_out;
+
+    /* Ignore the second of two consecutive flushes: */
+    if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
+
+    /* deflate has finished flushing only when it hasn't used up
+     * all the available space in the output buffer:
+   */
+    done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+
+    if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+  }
+
+  if (flush == Z_FINISH)
+    s->dirty= AZ_STATE_CLEAN; /* Mark it clean, we should be good now */
+  else
+    s->dirty= AZ_STATE_SAVED; /* Mark it clean, we should be good now */
+
+  afterwrite_pos= my_tell(s->file, MYF(0));
+  write_header(s);
+  my_seek(s->file, afterwrite_pos, SEEK_SET, MYF(0));
+
+  return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+int ZEXPORT azflush (s, flush)
+  azio_stream *s;
+  int flush;
+{
+  int err;
+
+  if (s->mode == 'r') 
+  {
+    unsigned char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
+    my_pread(s->file, (uchar*) buffer, AZHEADER_SIZE + AZMETA_BUFFER_SIZE, 0,
+             MYF(0));
+    read_header(s, buffer); /* skip the .az header */
+
+    return Z_OK;
+  }
+  else
+  {
+    s->forced_flushes++;
+    err= do_flush(s, flush);
+
+    if (err) return err;
+    my_sync(s->file, MYF(0));
+    return  s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+  }
+}
+
+/* ===========================================================================
+  Rewinds input file.
+*/
+int azrewind (s)
+  azio_stream *s;
+{
+  if (s == NULL || s->mode != 'r') return -1;
+
+  s->z_err = Z_OK;
+  s->z_eof = 0;
+  s->back = EOF;
+  s->stream.avail_in = 0;
+  s->stream.next_in = (Bytef *)s->inbuf;
+  s->crc = crc32(0L, Z_NULL, 0);
+  if (!s->transparent) (void)inflateReset(&s->stream);
+  s->in = 0;
+  s->out = 0;
+  return my_seek(s->file, (int)s->start, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR;
+}
+
+/* ===========================================================================
+  Sets the starting position for the next azread or azwrite on the given
+  compressed file. The offset represents a number of bytes in the
+  azseek returns the resulting offset location as measured in bytes from
+  the beginning of the uncompressed stream, or -1 in case of error.
+  SEEK_END is not implemented, returns error.
+  In this version of the library, azseek can be extremely slow.
+*/
+my_off_t azseek (s, offset, whence)
+  azio_stream *s;
+  my_off_t offset;
+  int whence;
+{
+
+  if (s == NULL || whence == SEEK_END ||
+      s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
+    return -1L;
+  }
+
+  if (s->mode == 'w') 
+  {
+    if (whence == SEEK_SET) 
+      offset -= s->in;
+
+    /* At this point, offset is the number of zero bytes to write. */
+    /* There was a zmemzero here if inbuf was null -Brian */
+    while (offset > 0)  
+    {
+      uInt size = AZ_BUFSIZE_WRITE;
+      if (offset < AZ_BUFSIZE_WRITE) size = (uInt)offset;
+
+      size = azwrite(s, s->inbuf, size);
+      if (size == 0) return -1L;
+
+      offset -= size;
+    }
+    return s->in;
+  }
+  /* Rest of function is for reading only */
+
+  /* compute absolute position */
+  if (whence == SEEK_CUR) {
+    offset += s->out;
+  }
+
+  if (s->transparent) {
+    /* map to my_seek */
+    s->back = EOF;
+    s->stream.avail_in = 0;
+    s->stream.next_in = (Bytef *)s->inbuf;
+    if (my_seek(s->file, offset, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) return -1L;
+
+    s->in = s->out = offset;
+    return offset;
+  }
+
+  /* For a negative seek, rewind and use positive seek */
+  if (offset >= s->out) {
+    offset -= s->out;
+  } else if (azrewind(s)) {
+    return -1L;
+  }
+  /* offset is now the number of bytes to skip. */
+
+  if (offset && s->back != EOF) {
+    s->back = EOF;
+    s->out++;
+    offset--;
+    if (s->last) s->z_err = Z_STREAM_END;
+  }
+  while (offset > 0)  {
+    int error;
+    unsigned int size = AZ_BUFSIZE_READ;
+    if (offset < AZ_BUFSIZE_READ) size = (int)offset;
+
+    size = azread(s, s->outbuf, size, &error);
+    if (error <= 0) return -1L;
+    offset -= size;
+  }
+  return s->out;
+}
+
+/* ===========================================================================
+  Returns the starting position for the next azread or azwrite on the
+  given compressed file. This position represents a number of bytes in the
+  uncompressed data stream.
+*/
+my_off_t ZEXPORT aztell (file)
+  azio_stream *file;
+{
+  return azseek(file, 0L, SEEK_CUR);
+}
+
+
+/* ===========================================================================
+  Outputs a long in LSB order to the given file
+*/
+void putLong (File file, uLong x)
+{
+  int n;
+  uchar buffer[1];
+
+  for (n = 0; n < 4; n++) 
+  {
+    buffer[0]= (int)(x & 0xff);
+    my_write(file, buffer, 1, MYF(0));
+    x >>= 8;
+  }
+}
+
+/* ===========================================================================
+  Reads a long in LSB order from the given azio_stream. Sets z_err in case
+  of error.
+*/
+uLong getLong (azio_stream *s)
+{
+  uLong x = (uLong)get_byte(s);
+  int c;
+
+  x += ((uLong)get_byte(s))<<8;
+  x += ((uLong)get_byte(s))<<16;
+  c = get_byte(s);
+  if (c == EOF) s->z_err = Z_DATA_ERROR;
+  x += ((uLong)c)<<24;
+  return x;
+}
+
+/* ===========================================================================
+  Flushes all pending output if necessary, closes the compressed file
+  and deallocates all the (de)compression state.
+*/
+int azclose (azio_stream *s)
+{
+
+  if (s == NULL) return Z_STREAM_ERROR;
+  
+  if (s->file < 1) return Z_OK;
+
+  if (s->mode == 'w') 
+  {
+    if (do_flush(s, Z_FINISH) != Z_OK)
+      return destroy(s);
+
+    putLong(s->file, s->crc);
+    putLong(s->file, (uLong)(s->in & 0xffffffff));
+    s->dirty= AZ_STATE_CLEAN;
+    s->check_point= my_tell(s->file, MYF(0));
+    write_header(s);
+  }
+
+  return destroy(s);
+}
+
+/*
+  Though this was added to support MySQL's FRM file, anything can be 
+  stored in this location.
+*/
+int azwrite_frm(azio_stream *s, char *blob, unsigned int length)
+{
+  if (s->mode == 'r') 
+    return 1;
+
+  if (s->rows > 0) 
+    return 1;
+
+  s->frm_start_pos= (uint) s->start;
+  s->frm_length= length;
+  s->start+= length;
+
+  my_pwrite(s->file, (uchar*) blob, s->frm_length, s->frm_start_pos, MYF(0));
+
+  write_header(s);
+  my_seek(s->file, 0, MY_SEEK_END, MYF(0));
+
+  return 0;
+}
+
+int azread_frm(azio_stream *s, char *blob)
+{
+  my_pread(s->file, (uchar*) blob, s->frm_length, s->frm_start_pos, MYF(0));
+
+  return 0;
+}
+
+
+/*
+  Simple comment field
+*/
+int azwrite_comment(azio_stream *s, char *blob, unsigned int length)
+{
+  if (s->mode == 'r') 
+    return 1;
+
+  if (s->rows > 0) 
+    return 1;
+
+  s->comment_start_pos= (uint) s->start;
+  s->comment_length= length;
+  s->start+= length;
+
+  my_pwrite(s->file, (uchar*) blob, s->comment_length, s->comment_start_pos,
+            MYF(0));
+
+  write_header(s);
+  my_seek(s->file, 0, MY_SEEK_END, MYF(0));
+
+  return 0;
+}
+
+int azread_comment(azio_stream *s, char *blob)
+{
+  my_pread(s->file, (uchar*) blob, s->comment_length, s->comment_start_pos,
+           MYF(0));
+
+  return 0;
+}

--
Stewart Smith
Thread
[patch 0/8] WL4081 NDB Compressed LCP and Backupstewart11 Oct
  • [patch 4/8] WL4081: read compressed backup filesstewart11 Oct
  • [patch 3/8] WL4081: Add compressed file support to AsyncFile (azio) and support compressed backups.stewart11 Oct
  • [patch 1/8] WL4081: Copy azio for NDBstewart11 Oct
  • [patch 6/8] WL4081: Add support to AsyncFile for reading zlib compressed files.stewart11 Oct
  • [patch 5/8] WL4081: add support for *storing* compressed LCPstewart11 Oct
  • [patch 8/8] WL4081 Futz with mtr ndb config to enable compressed lcp, backup and O_DIRECTstewart11 Oct
  • [patch 7/8] WL4081 Allow use of direct IO (O_DIRECT) with aziostewart11 Oct
  • [patch 2/8] WL4081: Make azio build for NDBstewart11 Oct
  • Re: [patch 0/8] WL4081 NDB Compressed LCP and BackupStewart Smith11 Oct