# HG changeset patch
# User Abhishek Kulkarni <[EMAIL PROTECTED]>
# Date 1223199649 21600
# Node ID bff0d23271408117225dfa48f67b108c3da9c678
# Parent  66e2cc7728c349d370a94b0591a6eec51bd5c4bf
Use the zlib adler32 function for rolling checksum.

This patch uses the zlib adler32 function to calculate the checksum of the 
files.
Instead of calculating the checksum during file setup stage, we use the rolling 
hash technique to compute the checksum
while the server serves the files to the clients. This reduces the server setup 
time from almost zero to a few seconds.
The clients compute their checksum while downloading the file which also 
reduces the time in which the file is available
to the clients

Signed-off-by: Abhishek Kulkarni <[EMAIL PROTECTED]>

diff --git a/xget/Makefile b/xget/Makefile
--- a/xget/Makefile
+++ b/xget/Makefile
@@ -2,13 +2,12 @@ SYSNAME!=uname
 SYSNAME!=uname
 INCDIR=../include
 CFLAGS=-Wall -g -I $(INCDIR) -DSYSNAME=$(SYSNAME)
-LFLAGS=-L. -L../libstrutil -lstrutil -L../libspclient -lspclient -L../libspfs 
-lspfs -lm
+LFLAGS=-L. -L../libstrutil -lstrutil -L../libspclient -lspclient -L../libspfs 
-lspfs -lm -lz
 HFILES=$(INCDIR)/spfs.h $(INCDIR)/spclient.h $(INCDIR)/xcpu.h 
$(INCDIR)/strutil.h xget.h
 
 CMD=xget
 OFILES=\
        xget.o\
-       crc32.o\
 
 all: $(CMD)
 
@@ -16,7 +15,7 @@ xget: $(OFILES) $(HFILES) Makefile
        $(CC) -o xget $(CFLAGS) $(OFILES) $(LFLAGS)
 
 xget.static: $(OFILES) $(HFILES) Makefile
-       $(CC) -static -o xget.static $(CFLAGS) $(OFILES) $(LFLAGS) -lm
+       $(CC) -static -o xget.static $(CFLAGS) $(OFILES) $(LFLAGS) -lm -lz
 
 install:
        mkdir -p $(INSTALLPREFIX)/sbin
diff --git a/xget/crc32.c b/xget/crc32.c
deleted file mode 100644
--- a/xget/crc32.c
+++ /dev/null
@@ -1,118 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <limits.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <dirent.h>
-#include <regex.h>
-#include <math.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-
-#include "spfs.h"
-
-#define CRC_MAX_READ 640000
-
-//crc32 and crc32 were taken from: 
http://fxr.watson.org/fxr/source/libkern/crc32.c
-
-static u32      crc32_tab[] = {
-       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
-       0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
-       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
-       0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
-       0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
-       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
-       0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
-       0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
-       0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
-       0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
-       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
-       0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
-       0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
-       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
-       0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
-       0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
-       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
-       0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
-       0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
-       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
-       0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
-       0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
-       0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
-       0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
-       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
-       0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
-       0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
-       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
-       0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
-       0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
-       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-u32
-crc32(const void *buf, size_t size)
-{
-       const u8 *p = buf;
-       u32 crc;
-       
-       crc = ~0U;
-       while (size--)
-               crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
-       return crc ^ ~0U;
-}
-
-u32 
-fcrc32(int fd, u64 size)
-{
-        u8 *buf, *p=NULL;
-       u32 crc=~0U;
-       u64 totalbytes, bytes_read;
-
-       totalbytes = bytes_read = 0;
-        if (!( buf = sp_malloc(CRC_MAX_READ)))
-         goto crc_error;
-
-        while ((bytes_read = read(fd, buf, CRC_MAX_READ)) > 0){
-               p = buf;
-               totalbytes += bytes_read;
-               while (bytes_read--)
-                       crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
-       }//while
-
-       if (bytes_read < 0 || totalbytes != size) {
-               sp_uerror(errno);
-               goto crc_error;
-       }
-
-       free(buf);
-       return crc ^ ~0U;
-
-crc_error:
-        if (buf) 
-         free(buf);
-        return 0xFF ; //??
-}
diff --git a/xget/xget.c b/xget/xget.c
--- a/xget/xget.c
+++ b/xget/xget.c
@@ -22,6 +22,7 @@
 #include <unistd.h>
 #include <sys/time.h>
 #include <sys/mman.h>
+#include <zlib.h>
 
 #include "spfs.h"
 #include "spclient.h"
@@ -358,7 +359,7 @@ fileretry(File *f, u64 offset)
                goto error;
        } 
 
-       f->retries++;           
+       f->retries++; 
        if ((file_finalize(f, 1)) < 0)
                goto error;
 
@@ -367,6 +368,8 @@ fileretry(File *f, u64 offset)
                f->datafd = NULL;
        }
 
+        f->checksum = adler32(0L, Z_NULL, 0);
+        f->checksum_ptr = 0;
        f->progress = time(NULL);
        f->finished = 0;
        if (offset == 0)
@@ -474,15 +477,16 @@ tick(void)
                fdone = 1;
                for(f = files; f != NULL; f = f->next) {
 //                     debug(Dbgfn, "tick\n");
+                        
+                       if (f->finished && (f->finished = matchsum(f))) 
+                                file_finalize(f, 0);                        
+                        
                        if (f->finished<0) {
                                debug(Dbgclntfn, "File: %s checksum did not 
match, retrying\n",
                                      f->nname);
                                if (fileretry(f, 0) < 0)
                                        return -1;
                        }
-
-                       if (f->finished == 1)
-                               file_finalize(f, 0);
                        
                        if(f->finished == 2)
                                continue;
@@ -887,6 +891,7 @@ filealloc(Spfile *parent, char *nname, c
        f->availfid = NULL;
        f->datafd = NULL;
        f->checksum = checksum;
+        f->checksum_ptr = 0;        
        f->finished = 0;
        f->progress = time(NULL);
        f->retries = 0;
@@ -917,7 +922,6 @@ localfileread(Spfile *parent, char *file
        Spfile *dir, *ret;
        DIR *dirstr;
        struct dirent *de;
-       int fd;
        u32 checksum, npmode;
        Spuser *usr;
        Spgroup *grp;
@@ -944,18 +948,13 @@ localfileread(Spfile *parent, char *file
        }
 
        if (S_ISREG(st.st_mode)) {
-               if ((fd = open(filename, O_RDONLY)) == -1) {
-                       sp_uerror(errno);
-                       goto error;
-               }
-               
-               checksum = fcrc32(fd, st.st_size);
+                
+               checksum = adler32(0L, Z_NULL, 0);                
                f = filealloc(parent, name, filename, st.st_size, st.st_size,  
                              st.st_mtime, checksum, npmode, usr, grp);
                if (!f)
-                       goto error;
+                       return NULL;
 
-               close(fd);
                debug(Dbgsrvfn, "Added file: %s\n", f->dir->name);
                ret = f->dir;
        } else if (S_ISDIR(st.st_mode)) {
@@ -992,11 +991,6 @@ localfileread(Spfile *parent, char *file
        }
        
        return ret;
-
-error:
-       if (fd > -1)
-               close(fd);
-       return NULL;
 }
 
 static void
@@ -1035,6 +1029,11 @@ respondreqs(File *f)
                        
                        if ((n = read(fd, buf, count)) < 0)
                                goto error;
+
+                        if (req->offset == f->checksum_ptr) {
+                                f->checksum = adler32(f->checksum, (const 
Bytef *)buf, n);
+                                f->checksum_ptr += n;
+                        }
                        
                        close(fd);
                        if (n < count)
@@ -1072,7 +1071,6 @@ netreadcb(Spcfd *fd, void *a)
 {
        int n, lfd, readsize;
        File *f;
-       u32 checksum;
        u8 *buf;
        struct stat *st;
        
@@ -1118,6 +1116,11 @@ netreadcb(Spcfd *fd, void *a)
                xget_uerror(errno);
                goto error;
        }
+
+        if (f->datalen == f->checksum_ptr) {
+                f->checksum = adler32(f->checksum, (const Bytef *)buf, n);
+                f->checksum_ptr += n;
+        }        
                
        f->datalen += n;
        if (f->datalen >= f->datasize) {
@@ -1128,11 +1131,7 @@ netreadcb(Spcfd *fd, void *a)
                        goto error;
                }
 
-               checksum = fcrc32(lfd, f->datasize);
-               if (checksum == f->checksum) 
-                       f->finished = 1;
-               else 
-                       f->finished = -1;
+                f->finished = 5;
        }
 
        f->progress = time(NULL);
@@ -1152,17 +1151,48 @@ error:
 }
 
 static int
+matchsum(File *f)
+{
+        Spcfid *checksumfid = NULL;
+        u32 checksum;
+        char *buf;
+        int blen, n;
+        
+        blen = strlen(f->nname) + 16;
+       if (blen < 128)
+               blen = 128;
+       buf = sp_malloc(blen);
+       if (!buf)
+               return -1;
+
+        sprintf(buf, "%s/checksum", f->nname);
+       checksumfid = spc_open(f->fs, buf, Oread);
+       if (!checksumfid)
+               return -1;
+
+       n = spc_read(checksumfid, (u8 *) buf, blen, 0);
+       if (n < 0)
+               return -1;
+
+       buf[n] = '\0';
+       checksum = strtoul(buf, NULL, 0);
+       spc_close(checksumfid);
+        free(buf);
+        return (f->checksum == checksum)?1:-1;
+}
+
+
+static int
 netfileread(Spfile *dir, char *lname, char *nname, u64 len, int mtime, 
            u32 npmode, Spuser *usr, Spgroup *grp)
 {
-       int n, blen, checksum;
+       int n, blen;
        char *buf, *fname, *redirto;
-       Spcfid *datafid, *checksumfid, *availfid, *redirfid;
+       Spcfid *datafid, *availfid, *redirfid;
        Spcfsys *redirfs;
        File *file;
        
        datafid = NULL;
-       checksumfid = NULL;
        availfid = NULL;
        redirfid = NULL;
        redirfs = NULL;
@@ -1174,18 +1204,6 @@ netfileread(Spfile *dir, char *lname, ch
        if (!buf)
                return -1;
 
-       sprintf(buf, "%s/checksum", nname);
-       checksumfid = spc_open(masterfs, buf, Oread);
-       if (!checksumfid)
-               goto error;
-
-       n = spc_read(checksumfid, (u8 *) buf, blen, 0);
-       if (n < 0)
-               goto error;
-
-       buf[n] = '\0';
-       checksum = strtoul(buf, NULL, 0);
-       spc_close(checksumfid);
        fname = strrchr(nname, '/');
        if (!fname)
                fname = nname;
@@ -1238,13 +1256,13 @@ netfileread(Spfile *dir, char *lname, ch
 
        snprintf(buf, blen, "%d %s", port, redirto);
        n = spc_write(availfid, (u8 *) buf, strlen(buf) + 1, 0);
-       if (n < 0) {
-               goto error;
-       }
+       if (n < 0)
+               goto error;     
 
        file->fs = redirfs;
        file->datafid = datafid;
-       file->checksum = checksum;
+       file->checksum = adler32(0L, Z_NULL, 0);
+        file->checksum_ptr = 0;
        file->datafd = spcfd_add(file->datafid, netreadcb, file, 0);
        file->availfid = availfid;
        free(buf);
@@ -1254,9 +1272,6 @@ error:
 error:
        if (datafid)
                spc_close(datafid);
-
-       if (checksumfid)
-               spc_close(checksumfid);
 
        if (availfid)
                spc_close(availfid);
diff --git a/xget/xget.h b/xget/xget.h
--- a/xget/xget.h
+++ b/xget/xget.h
@@ -48,6 +48,7 @@ struct File {
        File*   next;
        File*   prev;
        u32     checksum;
+        u64    checksum_ptr;        
        int     finished;
        time_t  progress;
        int     retries;
@@ -112,5 +113,4 @@ static File     *filealloc(Spfile *paren
                           u64 datasize, u64 datalen, u32 mtime, u32 checksum, 
                           u32 mode, Spuser *user, Spgroup *group);
 static int      file_finalize(File *f, int write);
-u32 crc32(const void *buf, size_t size);
-u32 fcrc32(int fd, u64 size);
+static int     matchsum(File *f);

Reply via email to