// ----------------------------------------------------------------------
// File: Adler.cc
// Author: Andreas-Joachim Peters/Elvin Sindrilaru - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2011 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
/*----------------------------------------------------------------------------*/
#include "fst/checksum/Adler.hh"
#ifdef ISAL_FOUND
#include
#endif
EOSFSTNAMESPACE_BEGIN
/*----------------------------------------------------------------------------*/
bool
Adler::Add (const char* buffer, size_t length, off_t offset)
{
if (offset != adleroffset)
needsRecalculation = true;
if (finalized) /* handle read/append case, no problem in this case */
finalized = false;
adler = adler32(0L, Z_NULL, 0);
Chunk currChunk;
#ifdef ISAL_FOUND
adler = isal_adler32(adler, (const unsigned char*) buffer, length);
#else
adler = adler32(adler, (const Bytef*) buffer, length);
#endif
adleroffset = offset + length;
if (adleroffset > maxoffset)
{
maxoffset = adleroffset;
}
currChunk.offset = offset;
currChunk.length = length;
currChunk.adler = adler;
map = AddElementToMap(map, currChunk);
return true;
}
/*----------------------------------------------------------------------------*/
MapChunks&
Adler::AddElementToMap (MapChunks& map, Chunk& chunk)
{
off_t offEndChunk = chunk.offset + chunk.length;
IterMap iter = map.find(offEndChunk);
if (iter != map.end())
{
map.erase(iter);
map.insert(std::pair (offEndChunk, chunk));
}
else
{
map.insert(std::pair (offEndChunk, chunk));
}
return map;
}
/*----------------------------------------------------------------------------*/
const char*
Adler::GetHexChecksum ()
{
char sadler[1024];
sprintf(sadler, "%08x", adler);
Checksum = sadler;
return Checksum.c_str();
}
/*----------------------------------------------------------------------------*/
const char*
Adler::GetBinChecksum (int &len)
{
len = sizeof (unsigned int);
return (char*) &adler;
}
/*----------------------------------------------------------------------------*/
/* compute the adler value of the map if we have the full map
* (starts from 0 and there are no holes)
*/
void
Adler::ValidateAdlerMap ()
{
unsigned int value;
adler = adler32(0L, Z_NULL, 0);
if (map.begin() == map.end())
{
adler = adler32(0L, Z_NULL, 0);
return;
}
IterMap iter1 = map.begin();
IterMap iter2 = iter1;
value = iter1->second.adler;
IterMap iter3;
// for (iter3= map.begin(); iter3!= map.end(); iter3++) {
// fprintf(stderr,"ADLER VALIDATE %llu %llu %llu %x\n", iter3->first,iter3->second.offset, iter3->second.length, iter3->second.adler);
// }
if (iter1->second.offset != 0)
{
// the first chunk is not at the beginning
needsRecalculation = true;
adler = adler32(0L, Z_NULL, 0);
return;
}
if (map.begin() == map.end())
{
//we have no chunk
adler = adler32(0L, Z_NULL, 0);
return;
}
needsRecalculation = false;
iter2++;
if (iter2 == map.end())
{
if ((iter1->first) != maxoffset)
{
// there was probably some overwrite
needsRecalculation = true;
}
else
{
if (iter1->second.offset != 0)
{
needsRecalculation = true;
}
}
//we have one chunk
adler = value;
return;
}
off_t appliedoffset = 0;
for (; iter2 != map.end(); iter1++, iter2++)
{
appliedoffset = iter2->first;
value = adler32_combine(value, iter2->second.adler, iter2->second.length);
if (iter1->first != iter2->second.offset)
{
needsRecalculation = true;
break;
}
}
if (appliedoffset != maxoffset)
{
// there was probably some overwrite
needsRecalculation = true;
}
if (!needsRecalculation)
{
adler = value;
}
else
{
adler = adler32(0L, Z_NULL, 0);
}
fflush(stdout);
return;
}
/*----------------------------------------------------------------------------*/
void
Adler::Finalize ()
{
if (!finalized) {
ValidateAdlerMap();
finalized = true;
}
}
/*----------------------------------------------------------------------------*/
EOSFSTNAMESPACE_END