#ifndef __XRDOUCPGRWUTILS_HH__ #define __XRDOUCPGRWUTILS_HH__ /******************************************************************************/ /* */ /* X r d O u c P g r w U t i l s . h h */ /* */ /* (c) 2021 by the Board of Trustees of the Leland Stanford, Jr., University */ /* All Rights Reserved */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* XRootD is free software: you can redistribute it and/or modify it under */ /* the terms of the GNU Lesser General Public License as published by the */ /* Free Software Foundation, either version 3 of the License, or (at your */ /* option) any later version. */ /* */ /* XRootD 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 Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include class XrdOucPgrwUtils { public: //------------------------------------------------------------------------------ //! Compute a CRC32C checksums for a pgRead/pgWrite request. //! //! @param data Pointer to the data whose checksum it to be computed. //! @param offs The offset at which the read or write occurs. //! @param count The number of bytes pointed to by data. //! @param csval Pointer to a vector to hold individual page checksums. The //! raw vector must be sized as computed by csNum(). When //! passed an std::vector, it is done automatically. //! On return, each element of csval holds the checksum for //! the associated page. //------------------------------------------------------------------------------ static void csCalc(const char* data, off_t offs, size_t count, uint32_t* csval); static void csCalc(const char* data, off_t offs, size_t count, std::vector &csvec); //------------------------------------------------------------------------------ //! Compute the required size of a checksum vector based on offset & length //| applying the pgRead/pgWrite requirements. //! //! @param offs The offset at which the read or write occurs. //! @param count The number of bytes read or to write. //! //! @return The number of checksums that are needed. //------------------------------------------------------------------------------ static int csNum(off_t offs, int count); //------------------------------------------------------------------------------ //! Compute the required size of a checksum vector based on offset & length //| applying the pgRead/pgWrite requirements and return the length of the first //! and last segments required in the iov vector. //! //! @param offs The offset at which the read or write occurs. //! @param count The number of bytes read or to write excluding checksums. //! @param fLen The number of bytes needed in iov[0].iov_length //! @param lLen The number of bytes needed in iov[csnum-1].iov_length //! //! @return The number of checksums that are needed. //------------------------------------------------------------------------------ static int csNum(off_t offs, int count, int &fLen, int &lLen); //------------------------------------------------------------------------------ //! Verify CRC32C checksums for a pgWrite request. //! //! @param dInfo Reference to the data information used or state control. //! @param bado The offset in error when return false. //! @param badc The length of erroneous data at bado. //! //! @return true if all the checksums match. Otherwise, false is returned with //! bado and badc set and dInfo is updated so that the next call with //! the same dInfo will verify the remaing data. To avoid an unneeded //! call first check if dInfo.count is positive. //------------------------------------------------------------------------------ struct dataInfo {const char* data; //!< Pointer to data buffer const uint32_t* csval; //!< Pointer to vector of checksums off_t offs; //!< Offset associated with data int count; //!< Number of bytes to check dataInfo(const char* dP, const uint32_t* cP, off_t o, int n) : data(dP), csval(cP), offs(o), count(n) {} }; static bool csVer(dataInfo &dInfo, off_t &bado, int &badc); //------------------------------------------------------------------------------ //! Compute the layout for an iovec that receives network bytes applying //| pgRead/pgWrite requirements. //! //! @param layout Reference to the layout parameter (see below). //! @param offs recvLayout: Offset at which the subsequent write occurs. //! sendLayout: Offset at which the preceding read occurs. //! @param dlen recvLayout: Nmber of sock bytes to receive with checksums. //! @param dlen sendLayout: Nmber of file bytes to read without checksums. //! @param bsz The size of the buffer exclusive of any checksums and must //! be a multiple of 4096 (one page). If it's <= 0 then then the //! layout is computed as if bsz could fully accomodate the dlen. //! //! @return The number of checksums that are needed. If the result is zero then //! the supplied offset/dlen violates requirements amd eWhy holds reason. //! //! @note The iovec layout assumes iov[0] reads the checksum and iov[1] reads //! only the data where the last such pair is iov[csnum*-2],iov[csnum*-1]. //! @note dataLen can be used to adjust the next offset for filesystem I/O while //! sockLen is the total number of network bytes to receive or send. //------------------------------------------------------------------------------ struct Layout { off_t bOffset; //!< Buffer offset to apply iov[1].iov_base int dataLen; //!< Total number of filesys bytes the iovec will handle int sockLen; //!< Total number of network bytes the iovec will handle int fLen; //!< Length to use for iov[1].iov_len int lLen; //!< Length to use for iov[csnum*2-1].iov_len) const char *eWhy; //!< Reason for failure when zero is returned }; static int recvLayout(Layout &layout, off_t offs, int dlen, int bsz=0); static int sendLayout(Layout &layout, off_t offs, int dlen, int bsz=0); XrdOucPgrwUtils() {} ~XrdOucPgrwUtils() {} private: }; #endif