Commit a2720e18 authored by Rob Latham's avatar Rob Latham
Browse files

[svn-r8558] back out all the "same romio region" work, now that it lives on...

[svn-r8558] back out all the "same romio region" work, now that it lives on the "romio_ident_regions" branch
parent 4134c2eb
......@@ -19,10 +19,6 @@
#include "ad_bgl_pset.h"
#include "ad_bgl_aggrs.h"
#ifdef HAVE_SPI_KERNEL_INTERFACE_H
#include <spi/kernel_interface.h>
#endif
#ifdef PROFILE
#include "mpe.h"
#endif
......@@ -91,9 +87,6 @@ extern void ADIOI_Calc_my_off_len(ADIO_File fd, int bufcount, MPI_Datatype
ADIO_Offset *end_offset_ptr, int
*contig_access_count_ptr);
static int ADIOI_too_much_memory_for_alltoallv(int nprocs,
int * send_size, int *recv_size);
void ADIOI_BGL_ReadStridedColl(ADIO_File fd, void *buf, int count,
MPI_Datatype datatype, int file_ptr_type,
ADIO_Offset offset, ADIO_Status *status, int
......@@ -253,28 +246,6 @@ void ADIOI_BGL_ReadStridedColl(ADIO_File fd, void *buf, int count,
return;
}
/* one more check: if we have a "everyone reads the same data" workload (a
* config file, an initial mesh dataset, etc), then the full two-phase
* algorithm is overkill and we should just read-and-broadcast */
if (ADIOI_allsame_access(fd, count, datatype)) {
if (myrank == fd->hints->ranklist[0]) {
ADIO_ReadContig(fd, buf, count, datatype, file_ptr_type,
offset, status, error_code);
}
MPI_Bcast(buf, count, datatype, fd->hints->ranklist[0], fd->comm);
#ifdef HAVE_STATUS_SET_BYTES
MPI_Type_size(datatype, &size);
bufsize = size * count;
MPIR_Status_set_bytes(status, datatype, bufsize);
ADIOI_Free(offset_list);
ADIOI_Free(len_list);
ADIOI_Free(st_offsets);
ADIOI_Free(end_offsets);
#endif
return;
}
#if BGL_PROFILE
BGLMPIO_T_CIO_SET_GET( 0, r, 1, 1, 1, BGLMPIO_CIO_FD_PART, BGLMPIO_CIO_PATANA )
#endif
......@@ -1070,30 +1041,11 @@ static void ADIOI_R_Exchange_data_alltoallv(
int len;
int *sdispls, *rdispls;
char *all_recv_buf, *all_send_buf;
int my_too_big, too_big;
/* exchange send_size info so that each process knows how much to
receive from whom and how much memory to allocate. */
MPI_Alltoall(send_size, 1, MPI_INT, recv_size, 1, MPI_INT, fd->comm);
/* we now have enough information to know how much memory we will allocate
* for this routine */
my_too_big = ADIOI_too_much_memory_for_alltoallv(nprocs,
send_size, recv_size);
MPI_Allreduce(&my_too_big, &too_big, 1, MPI_INT, MPI_MAX, fd->comm);
if (too_big) {
/* fall back to point-to-point */
ADIOI_R_Exchange_data(fd, buf, flat_buf,
offset_list, len_list, send_size, recv_size,
count, start_pos, partial_send, recd_from_proc,
nprocs, myrank, buftype_is_contig,
contig_access_count, min_st_offset,
fd_size, fd_start, fd_end,
others_req, iter, buftype_extent, buf_idx);
return;
}
nprocs_recv = 0;
for (i=0; i<nprocs; i++) if (recv_size[i]) { nprocs_recv++; break; }
......@@ -1193,25 +1145,3 @@ static void ADIOI_R_Exchange_data_alltoallv(
ADIOI_Free( rdispls );
return;
}
static int ADIOI_too_much_memory_for_alltoallv(int nprocs,
int * send_size, int *recv_size) {
unsigned int threshold;
#ifdef HAVE_KERNEL_GETMEMORYSIZE
Kernel_GetMemorySize(KERNEL_MEMSIZE_ESTHEAPAVAIL, &threshold);
#else
threshold = 1024*1024*128;
#endif
int i, mem_required=0;
for (i=0; i< nprocs; i++)
/* the 'stail' and 'rtail' arrays */
mem_required += recv_size[i] + send_size[i];
/* the sdispl, recv_buf, and rdispls arrays */
mem_required += nprocs*sizeof(int)*3;
if (mem_required > threshold) return 1;
return 0;
}
......@@ -35,8 +35,7 @@ AD_OBJECTS = ad_close.o ad_init.o ad_end.o ad_open.o flatten.o \
ad_write_nolock.o \
ad_coll_exch_new.o ad_coll_build_req_new.o ad_io_coll.o \
ad_aggregate_new.o heap-sort.o \
ad_opencoll.o ad_opencoll_scalable.o ad_opencoll_failsafe.o ad_features.o \
hash_type.o same_dtype.o lookup3.o
ad_opencoll.o ad_opencoll_scalable.o ad_opencoll_failsafe.o ad_features.o
all: $(LIBNAME)
@if [ "@ENABLE_SHLIB@" != "none" ] ; then \
......
......@@ -93,15 +93,6 @@ void ADIO_Close(ADIO_File fd, int *error_code)
}
ADIOI_Free(fd->filename);
if (fd->etype_hash_key != MPI_KEYVAL_INVALID) {
MPI_Type_delete_attr(fd->etype, fd->etype_hash_key);
MPI_Keyval_free(&(fd->etype_hash_key));
}
if (fd->ftype_hash_key != MPI_KEYVAL_INVALID) {
MPI_Type_delete_attr(fd->filetype, fd->ftype_hash_key);
MPI_Keyval_free(&(fd->ftype_hash_key));
}
MPI_Type_get_envelope(fd->etype, &i, &j, &k, &combiner);
if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->etype));
......@@ -111,7 +102,6 @@ void ADIO_Close(ADIO_File fd, int *error_code)
MPI_Type_get_envelope(fd->filetype, &i, &j, &k, &combiner);
if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->filetype));
MPI_Info_free(&(fd->info));
/* memory for fd is freed in MPI_File_close */
......
......@@ -59,9 +59,6 @@ MPI_File ADIO_Open(MPI_Comm orig_comm,
fd->filetype = filetype; /* MPI_BYTE by default */
fd->etype_size = 1; /* default etype is MPI_BYTE */
fd->etype_hash_key = MPI_KEYVAL_INVALID; /* will be set in file view (if called) */
fd->ftype_hash_key = MPI_KEYVAL_INVALID;
fd->file_realm_st_offs = NULL;
fd->file_realm_types = NULL;
......
......@@ -51,6 +51,7 @@ static void ADIOI_Fill_user_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node
ADIO_Offset *fd_end,
MPI_Aint buftype_extent);
void ADIOI_GEN_ReadStridedColl(ADIO_File fd, void *buf, int count,
MPI_Datatype datatype, int file_ptr_type,
ADIO_Offset offset, ADIO_Status *status, int
......@@ -168,29 +169,6 @@ void ADIOI_GEN_ReadStridedColl(ADIO_File fd, void *buf, int count,
return;
}
/* one more check: if we have a "everyone reads the same data" workload (a
* config file, an initial mesh dataset, etc), then the full two-phase
* algorithm is overkill and we should just read-and-broadcast */
if (ADIOI_allsame_access(fd, count, datatype, offset)) {
*error_code = MPI_SUCCESS;
if (myrank == fd->hints->ranklist[0]) {
ADIO_ReadContig(fd, buf, count, datatype, file_ptr_type,
offset, status, error_code);
}
MPI_Bcast(buf, count, datatype, fd->hints->ranklist[0], fd->comm);
#ifdef HAVE_STATUS_SET_BYTES
MPI_Type_size(datatype, &size);
bufsize = size * count;
MPIR_Status_set_bytes(status, datatype, bufsize);
#endif
ADIOI_Free(offset_list);
ADIOI_Free(len_list);
ADIOI_Free(st_offsets);
ADIOI_Free(end_offsets);
return;
}
/* We're going to perform aggregation of I/O. Here we call
* ADIOI_Calc_file_domains() to determine what processes will handle I/O
* to what regions. We pass nprocs_for_coll into this function; it is
......@@ -1086,4 +1064,3 @@ static void ADIOI_Fill_user_buffer(ADIO_File fd, void *buf, ADIOI_Flatlist_node
ADIOI_Free(done_from_proc);
ADIOI_Free(recv_buf_idx);
}
......@@ -8,27 +8,6 @@
#include "adio.h"
#include "adio_extern.h"
int hash_copy_fn(MPI_Datatype oldtype, int type_keyval, void *extra_state,
void * attr_val_in, void *attr_val_out, int *flag)
{
((ADIOI_hashed_dtype *)attr_val_in)->ref_count +=1;
*((ADIOI_hashed_dtype **)attr_val_out) = (ADIOI_hashed_dtype *)attr_val_in;
*flag = 1;
return MPI_SUCCESS;
}
int hash_delete_fn(MPI_Datatype type, int type_keyval,
void *attr_val, void *extra_state)
{
ADIOI_hashed_dtype *hash;
hash = (ADIOI_hashed_dtype *)attr_val;
hash->ref_count -= 1;
if (hash->ref_count == 0) {
ADIOI_Free(hash);
}
return MPI_SUCCESS;
}
/* this used to be implemented in every file system as an fcntl. It makes
* deferred open easier if we know ADIO_Fcntl will always need a file to really
* be open. set_view doesn't modify anything related to the open files.
......@@ -37,8 +16,6 @@ void ADIO_Set_view(ADIO_File fd, ADIO_Offset disp, MPI_Datatype etype,
MPI_Datatype filetype, MPI_Info info, int *error_code)
{
int combiner, i, j, k, err, filetype_is_contig;
int key;
ADIOI_hashed_dtype *etype_hash, *ftype_hash;
MPI_Datatype copy_etype, copy_filetype;
ADIOI_Flatlist_node *flat_file;
/* free copies of old etypes and filetypes and delete flattened
......@@ -80,25 +57,6 @@ void ADIO_Set_view(ADIO_File fd, ADIO_Offset disp, MPI_Datatype etype,
MPI_Type_size(fd->etype, &(fd->etype_size));
fd->disp = disp;
etype_hash = ADIOI_Calloc(1, sizeof(ADIOI_hashed_dtype));
etype_hash->ref_count = 1;
ADIOI_dtype_hash(fd->etype, etype_hash);
MPI_Type_create_keyval(hash_copy_fn, hash_delete_fn,
&key, etype_hash);
fd->etype_hash_key = key;
MPI_Type_set_attr(fd->etype, key, etype_hash);
ftype_hash = ADIOI_Calloc(1, sizeof(ADIOI_hashed_dtype));
ftype_hash->ref_count = 1;
ADIOI_dtype_hash(fd->filetype, ftype_hash);
MPI_Type_create_keyval(hash_copy_fn, hash_delete_fn,
&key, ftype_hash);
fd->ftype_hash_key = key;
MPI_Type_set_attr(fd->filetype, key, ftype_hash);
/* reset MPI-IO file pointer to point to the first byte that can
be accessed in this view. */
......
This diff is collapsed.
This diff is collapsed.
/* -*- Mode: C; c-basic-offset:4 ; -*- */
/*
*
* Copyright (C) 2011 UChicago/Argonne, LLC
* See COPYRIGHT notice in top-level directory.
*/
#include <adio.h>
/* build_answer_array: instead of doing 4 allreduces (or 8 since we don't have
* equality), stuff all these values into an array:
*
* ---------------------------------------------------------
* |disp|reqsize|offset|ehash[0]|ehash[1]|fhash[0]|fhash[1]|
* ---------------------------------------------------------
*/
static ADIO_Offset * build_answer_array(ADIO_Offset disp, ADIO_Offset reqsize,
ADIO_Offset offset,
ADIOI_hashed_dtype *etype_hash, ADIOI_hashed_dtype *ftype_hash, int *nitems)
{
ADIO_Offset *tmp_array;
int i, idx=0;
tmp_array = ADIOI_Calloc(1 + 1 + 1 + ADIOI_HASH_COUNT + ADIOI_HASH_COUNT,
sizeof(ADIO_Offset));
tmp_array[idx++] = disp;
tmp_array[idx++] = reqsize;
tmp_array[idx++] = offset;
for (i=0; i< ADIOI_HASH_COUNT; i++) {
tmp_array[idx++] = etype_hash->hash[i];
}
for (i=0; i< ADIOI_HASH_COUNT; i++) {
tmp_array[idx++] = ftype_hash->hash[i];
}
*nitems=idx;
return tmp_array;
}
int ADIOI_allsame_access(ADIO_File fd,
int count, MPI_Datatype datatype, ADIO_Offset offset)
{
/* we determine equivalence of access this way:
* - file views are identical: same type signature, same type map. For
* efficency at set_view time we marshaled the type and hashed the result
* - same displacement when file view set
* - amount of data requested (a memory region defined by 'buf, count,
* datatype' tuple) needs to be the same. It can be laid out any which
* way in memory.
* - all processors need to access data at the same offset
*/
/* we hash the marshaled representation but maybe it's better to compare
* the marshaled version? */
ADIOI_hashed_dtype *etype_hash, *ftype_hash;
ADIO_Offset *my_result, *max_result, *min_result;
int eflag, fflag, nitems, i, ret;
int memtype_size;
MPI_Type_get_attr(fd->etype, fd->etype_hash_key, &etype_hash, &eflag);
if (!eflag) {
/* unlikely unless no file view was set ?*/
etype_hash = ADIOI_Calloc(1, sizeof(*etype_hash));
ADIOI_dtype_hash(fd->etype, etype_hash);
}
MPI_Type_get_attr(fd->filetype, fd->ftype_hash_key, &ftype_hash, &fflag);
if (!fflag) {
/* unlikely unless no file view was set ?*/
ftype_hash = ADIOI_Calloc(1, sizeof(*ftype_hash));
ADIOI_dtype_hash(fd->etype, etype_hash);
}
/* does not matter what the memory type looks like; can put data anywhere
* as long as identical amount of data read from file */
MPI_Type_size(datatype, &memtype_size);
/* we now have the four pieces of infomaiton we need: the disp, the hashed
* etype and ftype, and the size of the request */
my_result = build_answer_array(fd->disp, memtype_size*count, offset, ftype_hash,
etype_hash, &nitems);
min_result = ADIOI_Calloc(nitems, sizeof(ADIO_Offset));
max_result = ADIOI_Calloc(nitems, sizeof(ADIO_Offset));
/* reduction of integers can be pretty fast on some platforms */
MPI_Allreduce(my_result, min_result, nitems, ADIO_OFFSET, MPI_MIN, fd->comm);
MPI_Allreduce(my_result, max_result, nitems, ADIO_OFFSET, MPI_MAX, fd->comm);
ret = 1;
for (i=0; i<nitems; i++) {
if (min_result[i] != max_result[i]) {
ret = 0;
break;
}
}
fn_exit:
if (!eflag) ADIOI_Free(etype_hash);
if (!fflag) ADIOI_Free(ftype_hash);
ADIOI_Free(my_result);
ADIOI_Free(min_result);
ADIOI_Free(max_result);
return ret;
}
/*
* vim: ts=8 sts=4 sw=4 noexpandtab
*/
/*
SHA-1 in C
By Steve Reid <sreid@sea-to-sky.net>
100% Public Domain
-----------------
Modified 7/98
By James H. Brown <jbrown@burgoyne.com>
Still 100% Public Domain
Corrected a problem which generated improper hash values on 16 bit machines
Routine SHA1Update changed from
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
len)
to
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
long len)
The 'len' parameter was declared an int which works fine on 32 bit machines.
However, on 16 bit machines an int is too small for the shifts being done
against
it. This caused the hash function to generate incorrect values if len was
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
Since the file IO in main() reads 16K at a time, any file 8K or larger would
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
"a"s).
I also changed the declaration of variables i & j in SHA1Update to
unsigned long from unsigned int for the same reason.
These changes should make no difference to any 32 bit implementations since
an
int and a long are the same size in those environments.
--
I also corrected a few compiler warnings generated by Borland C.
1. Added #include <process.h> for exit() prototype
2. Removed unused variable 'j' in SHA1Final
3. Changed exit(0) to return(0) at end of main.
ALL changes I made can be located by searching for comments containing 'JHB'
-----------------
Modified 8/98
By Steve Reid <sreid@sea-to-sky.net>
Still 100% public domain
1- Removed #include <process.h> and used return() instead of exit()
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
-----------------
Modified 4/01
By Saul Kravitz <Saul.Kravitz@celera.com>
Still 100% PD
Modified to run on Compaq Alpha hardware.
-----------------
Modified 07/2002
By Ralph Giles <giles@ghostscript.com>
Still 100% public domain
modified for use with stdint types, autoconf
code cleanup, removed attribution comments
switched SHA1Final() argument order for consistency
use SHA1_ prefix for public api
move public api to sha1.h
*/
/*
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
/* #define SHA1HANDSOFF */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "sha1.h"
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64]);
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
/* FIXME: can we do this in an endian-proof way? */
#ifdef WORDS_BIGENDIAN
#define blk0(i) block->l[i]
#else
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
#ifdef VERBOSE /* SAK */
void SHAPrintContext(SHA1_CTX *context, char *msg){
printf("%s (%d,%d) %x %x %x %x %x\n",
msg,
context->count[0], context->count[1],
context->state[0],
context->state[1],
context->state[2],
context->state[3],
context->state[4]);
}
#endif /* VERBOSE */
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
{
uint32_t a, b, c, d, e;
typedef union {
uint8_t c[64];
uint32_t l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
static uint8_t workspace[64];
block = (CHAR64LONG16*)workspace;
memcpy(block, buffer, 64);
#else
block = (CHAR64LONG16*)buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context */
void SHA1_Init(SHA1_CTX* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1_Update(SHA1_CTX* context, const uint8_t* data, const size_t len)
{
size_t i, j;
#ifdef VERBOSE
SHAPrintContext(context, "before");
#endif
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1_Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1_Transform(context->state, data + i);
}
j = 0;
}