Changeset a4fee13 for GenericIO.cxx


Ignore:
Timestamp:
10/09/15 19:14:02 (9 years ago)
Author:
Hal Finkel <hfinkel@…>
Branches:
master, pympi
Children:
8f0a211
Parents:
406b50a
git-author:
Hal Finkel <hfinkel@…> (10/09/15 19:14:02)
git-committer:
Hal Finkel <hfinkel@…> (10/09/15 19:14:02)
Message:

Implement reading of files of non-native Endianness

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GenericIO.cxx

    rda65757 ra4fee13  
    238238} 
    239239 
     240static void bswap(void *v, size_t s) { 
     241  char *p = (char *) v; 
     242  for (size_t i = 0; i < s/2; ++i) 
     243    std::swap(p[i], p[s - (i+1)]); 
     244} 
     245 
     246// Using #pragma pack here, instead of __attribute__((packed)) because xlc, at 
     247// least as of v12.1, won't take __attribute__((packed)) on non-POD and/or 
     248// templated types. 
     249#pragma pack(1) 
     250 
     251template <typename T, bool IsBigEndian> 
     252struct endian_specific_value { 
     253  operator T() const { 
     254    T rvalue = value; 
     255    if (IsBigEndian != isBigEndian()) 
     256      bswap(&rvalue, sizeof(T)); 
     257 
     258    return rvalue; 
     259  }; 
     260 
     261  endian_specific_value &operator = (T nvalue) { 
     262    if (IsBigEndian != isBigEndian()) 
     263      bswap(&nvalue, sizeof(T)); 
     264 
     265    value = nvalue; 
     266    return *this; 
     267  } 
     268 
     269  endian_specific_value &operator += (T nvalue) { 
     270    *this = *this + nvalue; 
     271    return *this; 
     272  } 
     273 
     274  endian_specific_value &operator -= (T nvalue) { 
     275    *this = *this - nvalue; 
     276    return *this; 
     277  } 
     278 
     279private: 
     280  T value; 
     281}; 
     282 
    240283static const size_t CRCSize = 8; 
    241284 
     
    244287static const char *MagicLE = "HACC01L"; 
    245288 
     289template <bool IsBigEndian> 
    246290struct GlobalHeader { 
    247291  char Magic[MagicSize]; 
    248   uint64_t HeaderSize; 
    249   uint64_t NElems; // The global total 
    250   uint64_t Dims[3]; 
    251   uint64_t NVars; 
    252   uint64_t VarsSize; 
    253   uint64_t VarsStart; 
    254   uint64_t NRanks; 
    255   uint64_t RanksSize; 
    256   uint64_t RanksStart; 
    257   uint64_t GlobalHeaderSize; 
    258   double  PhysOrigin[3]; 
    259   double  PhysScale[3]; 
    260   uint64_t BlocksSize; 
    261   uint64_t BlocksStart; 
    262 } __attribute__((packed)); 
     292  endian_specific_value<uint64_t, IsBigEndian> HeaderSize; 
     293  endian_specific_value<uint64_t, IsBigEndian> NElems; // The global total 
     294  endian_specific_value<uint64_t, IsBigEndian> Dims[3]; 
     295  endian_specific_value<uint64_t, IsBigEndian> NVars; 
     296  endian_specific_value<uint64_t, IsBigEndian> VarsSize; 
     297  endian_specific_value<uint64_t, IsBigEndian> VarsStart; 
     298  endian_specific_value<uint64_t, IsBigEndian> NRanks; 
     299  endian_specific_value<uint64_t, IsBigEndian> RanksSize; 
     300  endian_specific_value<uint64_t, IsBigEndian> RanksStart; 
     301  endian_specific_value<uint64_t, IsBigEndian> GlobalHeaderSize; 
     302  endian_specific_value<double,   IsBigEndian> PhysOrigin[3]; 
     303  endian_specific_value<double,   IsBigEndian> PhysScale[3]; 
     304  endian_specific_value<uint64_t, IsBigEndian> BlocksSize; 
     305  endian_specific_value<uint64_t, IsBigEndian> BlocksStart; 
     306}; 
    263307 
    264308enum { 
     
    272316 
    273317static const size_t NameSize = 256; 
     318template <bool IsBigEndian> 
    274319struct VariableHeader { 
    275320  char Name[NameSize]; 
    276   uint64_t Flags; 
    277   uint64_t Size; 
    278 } __attribute__((packed)); 
    279  
     321  endian_specific_value<uint64_t, IsBigEndian> Flags; 
     322  endian_specific_value<uint64_t, IsBigEndian> Size; 
     323}; 
     324 
     325template <bool IsBigEndian> 
    280326struct RankHeader { 
    281   uint64_t Coords[3]; 
    282   uint64_t NElems; 
    283   uint64_t Start; 
    284   uint64_t GlobalRank; 
    285 } __attribute__((packed)); 
     327  endian_specific_value<uint64_t, IsBigEndian> Coords[3]; 
     328  endian_specific_value<uint64_t, IsBigEndian> NElems; 
     329  endian_specific_value<uint64_t, IsBigEndian> Start; 
     330  endian_specific_value<uint64_t, IsBigEndian> GlobalRank; 
     331}; 
    286332 
    287333static const size_t FilterNameSize = 8; 
    288334static const size_t MaxFilters = 4; 
     335template <bool IsBigEndian> 
    289336struct BlockHeader { 
    290337  char Filters[MaxFilters][FilterNameSize]; 
    291   uint64_t Start; 
    292   uint64_t Size; 
    293 } __attribute__((packed)); 
    294  
     338  endian_specific_value<uint64_t, IsBigEndian> Start; 
     339  endian_specific_value<uint64_t, IsBigEndian> Size; 
     340}; 
     341 
     342template <bool IsBigEndian> 
    295343struct CompressHeader { 
    296   uint64_t OrigCRC; 
    297 } __attribute__((packed)); 
     344  endian_specific_value<uint64_t, IsBigEndian> OrigCRC; 
     345}; 
    298346const char *CompressName = "BLOSC"; 
     347 
     348#pragma pack() 
    299349 
    300350unsigned GenericIO::DefaultFileIOType = FileIOPOSIX; 
     
    309359 
    310360#ifndef GENERICIO_NO_MPI 
     361void GenericIO::write() { 
     362  if (isBigEndian()) 
     363    write<true>(); 
     364  else 
     365    write<false>(); 
     366} 
     367 
    311368// Note: writing errors are not currently recoverable (one rank may fail 
    312369// while the others don't). 
     370template <bool IsBigEndian> 
    313371void GenericIO::write() { 
    314   const char *Magic = isBigEndian() ? MagicBE : MagicLE; 
     372  const char *Magic = IsBigEndian ? MagicBE : MagicLE; 
    315373 
    316374  uint64_t FileSize = 0; 
     
    383441  } 
    384442 
    385   RankHeader RHLocal; 
     443  RankHeader<IsBigEndian> RHLocal; 
    386444  int Dims[3], Periods[3], Coords[3]; 
    387445 
     
    417475  } 
    418476 
    419   vector<BlockHeader> LocalBlockHeaders; 
     477  vector<BlockHeader<IsBigEndian> > LocalBlockHeaders; 
    420478  vector<void *> LocalData; 
    421479  vector<bool> LocalHasExtraSpace; 
     
    431489      // Filters null by default, leave null starting address (needs to be 
    432490      // calculated by the header-writing rank). 
    433       memset(&LocalBlockHeaders[i], 0, sizeof(BlockHeader)); 
     491      memset(&LocalBlockHeaders[i], 0, sizeof(BlockHeader<IsBigEndian>)); 
    434492      if (ShouldCompress) { 
    435         LocalCData[i].resize(sizeof(CompressHeader)); 
    436  
    437         CompressHeader *CH = (CompressHeader*) &LocalCData[i][0]; 
     493        LocalCData[i].resize(sizeof(CompressHeader<IsBigEndian>)); 
     494 
     495        CompressHeader<IsBigEndian> *CH = (CompressHeader<IsBigEndian>*) &LocalCData[i][0]; 
    438496        CH->OrigCRC = crc64_omp(Vars[i].Data, Vars[i].Size*NElems); 
    439497 
     
    455513        LocalCData[i].resize(LocalCData[i].size() + NElems*Vars[i].Size); 
    456514        if (blosc_compress(9, 1, Vars[i].Size, NElems*Vars[i].Size, Vars[i].Data, 
    457                            &LocalCData[i][0] + sizeof(CompressHeader), 
     515                           &LocalCData[i][0] + sizeof(CompressHeader<IsBigEndian>), 
    458516                           NElems*Vars[i].Size) <= 0) 
    459517          goto nocomp; 
     
    461519        strncpy(LocalBlockHeaders[i].Filters[0], CompressName, FilterNameSize); 
    462520        size_t CNBytes, CCBytes, CBlockSize; 
    463         blosc_cbuffer_sizes(&LocalCData[i][0] + sizeof(CompressHeader), 
     521        blosc_cbuffer_sizes(&LocalCData[i][0] + sizeof(CompressHeader<IsBigEndian>), 
    464522                            &CNBytes, &CCBytes, &CBlockSize); 
    465         LocalCData[i].resize(CCBytes + sizeof(CompressHeader)); 
     523        LocalCData[i].resize(CCBytes + sizeof(CompressHeader<IsBigEndian>)); 
    466524 
    467525        LocalBlockHeaders[i].Size = LocalCData[i].size(); 
     
    481539 
    482540  if (SplitRank == 0) { 
    483     uint64_t HeaderSize = sizeof(GlobalHeader) + Vars.size()*sizeof(VariableHeader) + 
    484                           SplitNRanks*sizeof(RankHeader) + CRCSize; 
     541    uint64_t HeaderSize = sizeof(GlobalHeader<IsBigEndian>) + Vars.size()*sizeof(VariableHeader<IsBigEndian>) + 
     542                          SplitNRanks*sizeof(RankHeader<IsBigEndian>) + CRCSize; 
    485543    if (NeedsBlockHeaders) 
    486       HeaderSize += SplitNRanks*Vars.size()*sizeof(BlockHeader); 
     544      HeaderSize += SplitNRanks*Vars.size()*sizeof(BlockHeader<IsBigEndian>); 
    487545 
    488546    vector<char> Header(HeaderSize, 0); 
    489     GlobalHeader *GH = (GlobalHeader *) &Header[0]; 
     547    GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &Header[0]; 
    490548    std::copy(Magic, Magic + MagicSize, GH->Magic); 
    491549    GH->HeaderSize = HeaderSize - CRCSize; 
     
    493551    std::copy(Dims, Dims + 3, GH->Dims); 
    494552    GH->NVars = Vars.size(); 
    495     GH->VarsSize = sizeof(VariableHeader); 
    496     GH->VarsStart = sizeof(GlobalHeader); 
     553    GH->VarsSize = sizeof(VariableHeader<IsBigEndian>); 
     554    GH->VarsStart = sizeof(GlobalHeader<IsBigEndian>); 
    497555    GH->NRanks = SplitNRanks; 
    498     GH->RanksSize = sizeof(RankHeader); 
    499     GH->RanksStart = GH->VarsStart + Vars.size()*sizeof(VariableHeader); 
    500     GH->GlobalHeaderSize = sizeof(GlobalHeader); 
     556    GH->RanksSize = sizeof(RankHeader<IsBigEndian>); 
     557    GH->RanksStart = GH->VarsStart + Vars.size()*sizeof(VariableHeader<IsBigEndian>); 
     558    GH->GlobalHeaderSize = sizeof(GlobalHeader<IsBigEndian>); 
    501559    std::copy(PhysOrigin, PhysOrigin + 3, GH->PhysOrigin); 
    502560    std::copy(PhysScale,  PhysScale  + 3, GH->PhysScale); 
     
    504562      GH->BlocksSize = GH->BlocksStart = 0; 
    505563    } else { 
    506       GH->BlocksSize = sizeof(BlockHeader); 
    507       GH->BlocksStart = GH->RanksStart + SplitNRanks*sizeof(RankHeader); 
     564      GH->BlocksSize = sizeof(BlockHeader<IsBigEndian>); 
     565      GH->BlocksStart = GH->RanksStart + SplitNRanks*sizeof(RankHeader<IsBigEndian>); 
    508566    } 
    509567 
    510568    uint64_t RecordSize = 0; 
    511     VariableHeader *VH = (VariableHeader *) &Header[GH->VarsStart]; 
     569    VariableHeader<IsBigEndian> *VH = (VariableHeader<IsBigEndian> *) &Header[GH->VarsStart]; 
    512570    for (size_t i = 0; i < Vars.size(); ++i, ++VH) { 
    513571      string VName(Vars[i].Name); 
     
    515573 
    516574      std::copy(VName.begin(), VName.end(), VH->Name); 
    517       if (Vars[i].IsFloat)  VH->Flags |= FloatValue; 
    518       if (Vars[i].IsSigned) VH->Flags |= SignedValue; 
    519       if (Vars[i].IsPhysCoordX) VH->Flags |= ValueIsPhysCoordX; 
    520       if (Vars[i].IsPhysCoordY) VH->Flags |= ValueIsPhysCoordY; 
    521       if (Vars[i].IsPhysCoordZ) VH->Flags |= ValueIsPhysCoordZ; 
    522       if (Vars[i].MaybePhysGhost) VH->Flags |= ValueMaybePhysGhost; 
     575      uint64_t VFlags = 0; 
     576      if (Vars[i].IsFloat)  VFlags |= FloatValue; 
     577      if (Vars[i].IsSigned) VFlags |= SignedValue; 
     578      if (Vars[i].IsPhysCoordX) VFlags |= ValueIsPhysCoordX; 
     579      if (Vars[i].IsPhysCoordY) VFlags |= ValueIsPhysCoordY; 
     580      if (Vars[i].IsPhysCoordZ) VFlags |= ValueIsPhysCoordZ; 
     581      if (Vars[i].MaybePhysGhost) VFlags |= ValueMaybePhysGhost; 
     582      VH->Flags = VFlags; 
    523583      RecordSize += VH->Size = Vars[i].Size; 
    524584    } 
     
    530590    if (NeedsBlockHeaders) { 
    531591      MPI_Gather(&LocalBlockHeaders[0], 
    532                  Vars.size()*sizeof(BlockHeader), MPI_BYTE, 
     592                 Vars.size()*sizeof(BlockHeader<IsBigEndian>), MPI_BYTE, 
    533593                 &Header[GH->BlocksStart], 
    534                  Vars.size()*sizeof(BlockHeader), MPI_BYTE, 
     594                 Vars.size()*sizeof(BlockHeader<IsBigEndian>), MPI_BYTE, 
    535595                 0, SplitComm); 
    536596 
    537       BlockHeader *BH = (BlockHeader *) &Header[GH->BlocksStart]; 
     597      BlockHeader<IsBigEndian> *BH = (BlockHeader<IsBigEndian> *) &Header[GH->BlocksStart]; 
    538598      for (int i = 0; i < SplitNRanks; ++i) 
    539599      for (size_t j = 0; j < Vars.size(); ++j, ++BH) { 
     
    544604      } 
    545605 
    546       RankHeader *RH = (RankHeader *) &Header[GH->RanksStart]; 
     606      RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &Header[GH->RanksStart]; 
    547607      RH->Start = HeaderSize; ++RH; 
    548608      for (int i = 1; i < SplitNRanks; ++i, ++RH) { 
    549609        RH->Start = 
    550           ((BlockHeader *) &Header[GH->BlocksStart])[i*Vars.size()].Start; 
     610          ((BlockHeader<IsBigEndian> *) &Header[GH->BlocksStart])[i*Vars.size()].Start; 
    551611        GH->NElems += RH->NElems; 
    552612      } 
     
    556616      FileSize = BH[-1].Start + LastData; 
    557617    } else { 
    558       RankHeader *RH = (RankHeader *) &Header[GH->RanksStart]; 
     618      RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &Header[GH->RanksStart]; 
    559619      RH->Start = HeaderSize; ++RH; 
    560620      for (int i = 1; i < SplitNRanks; ++i, ++RH) { 
     
    578638    if (NeedsBlockHeaders) 
    579639      MPI_Scatter(&Header[GH->BlocksStart], 
    580                   sizeof(BlockHeader)*Vars.size(), MPI_BYTE, 
     640                  sizeof(BlockHeader<IsBigEndian>)*Vars.size(), MPI_BYTE, 
    581641                  &LocalBlockHeaders[0], 
    582                   sizeof(BlockHeader)*Vars.size(), MPI_BYTE, 
     642                  sizeof(BlockHeader<IsBigEndian>)*Vars.size(), MPI_BYTE, 
    583643                  0, SplitComm); 
    584644 
     
    601661    MPI_Gather(&RHLocal, sizeof(RHLocal), MPI_BYTE, 0, 0, MPI_BYTE, 0, SplitComm); 
    602662    if (NeedsBlockHeaders) 
    603       MPI_Gather(&LocalBlockHeaders[0], Vars.size()*sizeof(BlockHeader), 
     663      MPI_Gather(&LocalBlockHeaders[0], Vars.size()*sizeof(BlockHeader<IsBigEndian>), 
    604664                 MPI_BYTE, 0, 0, MPI_BYTE, 0, SplitComm); 
    605665    MPI_Scatter(0, 0, MPI_BYTE, &RHLocal, sizeof(RHLocal), MPI_BYTE, 0, SplitComm); 
    606666    if (NeedsBlockHeaders) 
    607       MPI_Scatter(0, 0, MPI_BYTE, &LocalBlockHeaders[0], sizeof(BlockHeader)*Vars.size(), 
     667      MPI_Scatter(0, 0, MPI_BYTE, &LocalBlockHeaders[0], sizeof(BlockHeader<IsBigEndian>)*Vars.size(), 
    608668                  MPI_BYTE, 0, SplitComm); 
    609669  } 
     
    678738#endif // GENERICIO_NO_MPI 
    679739 
     740template <bool IsBigEndian> 
     741void GenericIO::readHeaderLeader(void *GHPtr, bool MustMatch, int SplitNRanks, 
     742                                 string &LocalFileName, uint64_t &HeaderSize, vector<char> &Header) { 
     743  GlobalHeader<IsBigEndian> &GH = *(GlobalHeader<IsBigEndian> *) GHPtr; 
     744 
     745  if (MustMatch) { 
     746    if (SplitNRanks != (int) GH.NRanks) { 
     747      stringstream ss; 
     748      ss << "Won't read " << LocalFileName << ": communicator-size mismatch: " << 
     749            "current: " << SplitNRanks << ", file: " << GH.NRanks; 
     750      throw runtime_error(ss.str()); 
     751    } 
     752 
     753#ifndef GENERICIO_NO_MPI 
     754    int TopoStatus; 
     755    MPI_Topo_test(Comm, &TopoStatus); 
     756    if (TopoStatus == MPI_CART) { 
     757      int Dims[3], Periods[3], Coords[3]; 
     758      MPI_Cart_get(Comm, 3, Dims, Periods, Coords); 
     759 
     760      bool DimsMatch = true; 
     761      for (int i = 0; i < 3; ++i) { 
     762        if ((uint64_t) Dims[i] != GH.Dims[i]) { 
     763          DimsMatch = false; 
     764          break; 
     765        } 
     766      } 
     767 
     768      if (!DimsMatch) { 
     769        stringstream ss; 
     770        ss << "Won't read " << LocalFileName << 
     771              ": communicator-decomposition mismatch: " << 
     772              "current: " << Dims[0] << "x" << Dims[1] << "x" << Dims[2] << 
     773              ", file: " << GH.Dims[0] << "x" << GH.Dims[1] << "x" << 
     774              GH.Dims[2]; 
     775        throw runtime_error(ss.str()); 
     776      } 
     777    } 
     778#endif 
     779  } 
     780 
     781  HeaderSize = GH.HeaderSize; 
     782  Header.resize(HeaderSize + CRCSize, 0xFE /* poison */); 
     783  FH.get()->read(&Header[0], HeaderSize + CRCSize, 0, "header"); 
     784 
     785  uint64_t CRC = crc64_omp(&Header[0], HeaderSize + CRCSize); 
     786  if (CRC != (uint64_t) -1) { 
     787    throw runtime_error("Header CRC check failed: " + LocalFileName); 
     788  } 
     789} 
     790 
    680791// Note: Errors from this function should be recoverable. This means that if 
    681792// one rank throws an exception, then all ranks should. 
    682793void GenericIO::openAndReadHeader(bool MustMatch, int EffRank, bool CheckPartMap) { 
    683   const char *Magic = isBigEndian() ? MagicBE : MagicLE; 
    684   const char *MagicInv = isBigEndian() ? MagicLE : MagicBE; 
    685  
    686794  int NRanks, Rank; 
    687795#ifndef GENERICIO_NO_MPI 
     
    785893      FH.get()->open(LocalFileName, true); 
    786894 
    787       GlobalHeader GH; 
    788       FH.get()->read(&GH, sizeof(GlobalHeader), 0, "global header"); 
    789  
    790       if (string(GH.Magic, GH.Magic + MagicSize - 1) != Magic) { 
    791         string Error; 
    792         if (string(GH.Magic, GH.Magic + MagicSize - 1) == MagicInv) { 
    793           Error = "wrong endianness"; 
    794         } else { 
    795           Error = "invalid file-type identifier"; 
    796         } 
     895      GlobalHeader<false> GH; // endianness does not matter yet... 
     896      FH.get()->read(&GH, sizeof(GlobalHeader<false>), 0, "global header"); 
     897 
     898      if (string(GH.Magic, GH.Magic + MagicSize - 1) == MagicLE) { 
     899        readHeaderLeader<false>(&GH, MustMatch, SplitNRanks, LocalFileName, 
     900                                HeaderSize, Header); 
     901      } else if (string(GH.Magic, GH.Magic + MagicSize - 1) == MagicBE) { 
     902        readHeaderLeader<true>(&GH, MustMatch, SplitNRanks, LocalFileName, 
     903                               HeaderSize, Header); 
     904      } else { 
     905        string Error = "invalid file-type identifier"; 
    797906        throw runtime_error("Won't read " + LocalFileName + ": " + Error); 
    798       } 
    799  
    800       if (MustMatch) { 
    801         if (SplitNRanks != (int) GH.NRanks) { 
    802           stringstream ss; 
    803           ss << "Won't read " << LocalFileName << ": communicator-size mismatch: " << 
    804                 "current: " << SplitNRanks << ", file: " << GH.NRanks; 
    805           throw runtime_error(ss.str()); 
    806         } 
    807  
    808 #ifndef GENERICIO_NO_MPI 
    809         int TopoStatus; 
    810         MPI_Topo_test(Comm, &TopoStatus); 
    811         if (TopoStatus == MPI_CART) { 
    812           int Dims[3], Periods[3], Coords[3]; 
    813           MPI_Cart_get(Comm, 3, Dims, Periods, Coords); 
    814  
    815           bool DimsMatch = true; 
    816           for (int i = 0; i < 3; ++i) { 
    817             if ((uint64_t) Dims[i] != GH.Dims[i]) { 
    818               DimsMatch = false; 
    819               break; 
    820             } 
    821           } 
    822  
    823           if (!DimsMatch) { 
    824             stringstream ss; 
    825             ss << "Won't read " << LocalFileName << 
    826                   ": communicator-decomposition mismatch: " << 
    827                   "current: " << Dims[0] << "x" << Dims[1] << "x" << Dims[2] << 
    828                   ", file: " << GH.Dims[0] << "x" << GH.Dims[1] << "x" << 
    829                   GH.Dims[2]; 
    830             throw runtime_error(ss.str()); 
    831           } 
    832         } 
    833 #endif 
    834       } 
    835  
    836       HeaderSize = GH.HeaderSize; 
    837       Header.resize(HeaderSize + CRCSize, 0xFE /* poison */); 
    838       FH.get()->read(&Header[0], HeaderSize + CRCSize, 0, "header"); 
    839  
    840       uint64_t CRC = crc64_omp(&Header[0], HeaderSize + CRCSize); 
    841       if (CRC != (uint64_t) -1) { 
    842         throw runtime_error("Header CRC check failed: " + LocalFileName); 
    843907      } 
    844908 
     
    872936#endif 
    873937 
     938 
    874939  FH.getHeaderCache().clear(); 
     940 
     941  GlobalHeader<false> *GH = (GlobalHeader<false> *) &Header[0]; 
     942  FH.setIsBigEndian(string(GH->Magic, GH->Magic + MagicSize - 1) == MagicBE); 
     943 
    875944  FH.getHeaderCache().swap(Header); 
    876945  OpenFileName = LocalFileName; 
     
    905974 
    906975int GenericIO::readNRanks() { 
     976  if (FH.isBigEndian()) 
     977    return readNRanks<true>(); 
     978  return readNRanks<false>(); 
     979} 
     980 
     981template <bool IsBigEndian> 
     982int GenericIO::readNRanks() { 
    907983  if (RankMap.size()) 
    908984    return RankMap.size(); 
    909985 
    910986  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    911   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
     987  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
    912988  return (int) GH->NRanks; 
    913989} 
    914990 
     991void GenericIO::readDims(int Dims[3]) { 
     992  if (FH.isBigEndian()) 
     993    readDims<true>(Dims); 
     994  else 
     995    readDims<false>(Dims); 
     996} 
     997 
     998template <bool IsBigEndian> 
    915999void GenericIO::readDims(int Dims[3]) { 
    9161000  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    917   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
     1001  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
    9181002  std::copy(GH->Dims, GH->Dims + 3, Dims); 
    9191003} 
    9201004 
     1005uint64_t GenericIO::readTotalNumElems() { 
     1006  if (FH.isBigEndian()) 
     1007    return readTotalNumElems<true>(); 
     1008  return readTotalNumElems<false>(); 
     1009} 
     1010 
     1011template <bool IsBigEndian> 
    9211012uint64_t GenericIO::readTotalNumElems() { 
    9221013  if (RankMap.size()) 
     
    9241015 
    9251016  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    926   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
     1017  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
    9271018  return GH->NElems; 
    9281019} 
    9291020 
     1021void GenericIO::readPhysOrigin(double Origin[3]) { 
     1022  if (FH.isBigEndian()) 
     1023    readPhysOrigin<true>(Origin); 
     1024  else 
     1025    readPhysOrigin<false>(Origin); 
     1026} 
     1027 
     1028// Define a "safe" version of offsetof (offsetof itself might not work for 
     1029// non-POD types, and at least xlC v12.1 will complain about this if you try). 
     1030#define offsetof_safe(S, F) (size_t(&(S)->F) - size_t(S)) 
     1031 
     1032template <bool IsBigEndian> 
    9301033void GenericIO::readPhysOrigin(double Origin[3]) { 
    9311034  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    932   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
    933   if (offsetof(GlobalHeader, PhysOrigin) >= GH->GlobalHeaderSize) { 
     1035  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
     1036  if (offsetof_safe(GH, PhysOrigin) >= GH->GlobalHeaderSize) { 
    9341037    std::fill(Origin, Origin + 3, 0.0); 
    9351038    return; 
     
    9401043 
    9411044void GenericIO::readPhysScale(double Scale[3]) { 
     1045  if (FH.isBigEndian()) 
     1046    readPhysScale<true>(Scale); 
     1047  else 
     1048    readPhysScale<false>(Scale); 
     1049} 
     1050 
     1051template <bool IsBigEndian> 
     1052void GenericIO::readPhysScale(double Scale[3]) { 
    9421053  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    943   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
    944   if (offsetof(GlobalHeader, PhysScale) >= GH->GlobalHeaderSize) { 
     1054  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
     1055  if (offsetof_safe(GH, PhysScale) >= GH->GlobalHeaderSize) { 
    9451056    std::fill(Scale, Scale + 3, 0.0); 
    9461057    return; 
     
    9501061} 
    9511062 
    952 static size_t getRankIndex(int EffRank, GlobalHeader *GH, 
     1063template <bool IsBigEndian> 
     1064static size_t getRankIndex(int EffRank, GlobalHeader<IsBigEndian> *GH, 
    9531065                           vector<int> &RankMap, vector<char> &HeaderCache) { 
    954   if (offsetof(RankHeader, GlobalRank) >= GH->RanksSize || RankMap.empty()) 
     1066  if (RankMap.empty()) 
    9551067    return EffRank; 
    9561068 
    9571069  for (size_t i = 0; i < GH->NRanks; ++i) { 
    958     RankHeader *RH = (RankHeader *) &HeaderCache[GH->RanksStart + 
     1070    RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &HeaderCache[GH->RanksStart + 
    9591071                                                 i*GH->RanksSize]; 
     1072    if (offsetof_safe(RH, GlobalRank) >= GH->RanksSize) 
     1073      return EffRank; 
     1074 
    9601075    if ((int) RH->GlobalRank == EffRank) 
    9611076      return i; 
     
    9661081} 
    9671082 
     1083int GenericIO::readGlobalRankNumber(int EffRank) { 
     1084  if (FH.isBigEndian()) 
     1085    return readGlobalRankNumber<true>(EffRank); 
     1086  return readGlobalRankNumber<false>(EffRank); 
     1087} 
     1088 
     1089template <bool IsBigEndian> 
    9681090int GenericIO::readGlobalRankNumber(int EffRank) { 
    9691091  if (EffRank == -1) { 
     
    9791101  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    9801102 
    981   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
    982   size_t RankIndex = getRankIndex(EffRank, GH, RankMap, FH.getHeaderCache()); 
     1103  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
     1104  size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 
    9831105 
    9841106  assert(RankIndex < GH->NRanks && "Invalid rank specified"); 
    9851107 
    986   if (offsetof(RankHeader, GlobalRank) >= GH->RanksSize) 
     1108  RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 
     1109                                               RankIndex*GH->RanksSize]; 
     1110 
     1111  if (offsetof_safe(RH, GlobalRank) >= GH->RanksSize) 
    9871112    return EffRank; 
    9881113 
    989   RankHeader *RH = (RankHeader *) &FH.getHeaderCache()[GH->RanksStart + 
    990                                                RankIndex*GH->RanksSize]; 
    991  
    9921114  return (int) RH->GlobalRank; 
    9931115} 
    9941116 
     1117size_t GenericIO::readNumElems(int EffRank) { 
     1118  if (FH.isBigEndian()) 
     1119    return readNumElems<true>(EffRank); 
     1120  return readNumElems<false>(EffRank); 
     1121} 
     1122 
     1123template <bool IsBigEndian> 
    9951124size_t GenericIO::readNumElems(int EffRank) { 
    9961125  if (EffRank == -1) { 
     
    10061135  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    10071136 
    1008   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
    1009   size_t RankIndex = getRankIndex(EffRank, GH, RankMap, FH.getHeaderCache()); 
     1137  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
     1138  size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 
    10101139 
    10111140  assert(RankIndex < GH->NRanks && "Invalid rank specified"); 
    10121141 
    1013   RankHeader *RH = (RankHeader *) &FH.getHeaderCache()[GH->RanksStart + 
     1142  RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 
    10141143                                               RankIndex*GH->RanksSize]; 
    10151144  return (size_t) RH->NElems; 
    10161145} 
    10171146 
     1147void GenericIO::readCoords(int Coords[3], int EffRank) { 
     1148  if (FH.isBigEndian()) 
     1149    readCoords<true>(Coords, EffRank); 
     1150  else 
     1151    readCoords<false>(Coords, EffRank); 
     1152} 
     1153 
     1154template <bool IsBigEndian> 
    10181155void GenericIO::readCoords(int Coords[3], int EffRank) { 
    10191156  if (EffRank == -1) { 
     
    10291166  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    10301167 
    1031   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
    1032   size_t RankIndex = getRankIndex(EffRank, GH, RankMap, FH.getHeaderCache()); 
     1168  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
     1169  size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 
    10331170 
    10341171  assert(RankIndex < GH->NRanks && "Invalid rank specified"); 
    10351172 
    1036   RankHeader *RH = (RankHeader *) &FH.getHeaderCache()[GH->RanksStart + 
     1173  RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 
    10371174                                               RankIndex*GH->RanksSize]; 
    10381175 
    10391176  std::copy(RH->Coords, RH->Coords + 3, Coords); 
     1177} 
     1178 
     1179void GenericIO::readData(int EffRank, bool PrintStats, bool CollStats) { 
     1180  if (FH.isBigEndian()) 
     1181    readData<true>(EffRank, PrintStats, CollStats); 
     1182  else 
     1183    readData<false>(EffRank, PrintStats, CollStats); 
    10401184} 
    10411185 
    10421186// Note: Errors from this function should be recoverable. This means that if 
    10431187// one rank throws an exception, then all ranks should. 
     1188template <bool IsBigEndian> 
    10441189void GenericIO::readData(int EffRank, bool PrintStats, bool CollStats) { 
    10451190  int Rank; 
     
    10571202    EffRank = Rank; 
    10581203 
    1059   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
    1060   size_t RankIndex = getRankIndex(EffRank, GH, RankMap, FH.getHeaderCache()); 
     1204  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
     1205  size_t RankIndex = getRankIndex<IsBigEndian>(EffRank, GH, RankMap, FH.getHeaderCache()); 
    10611206 
    10621207  assert(RankIndex < GH->NRanks && "Invalid rank specified"); 
    10631208 
    1064   RankHeader *RH = (RankHeader *) &FH.getHeaderCache()[GH->RanksStart + 
     1209  RankHeader<IsBigEndian> *RH = (RankHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->RanksStart + 
    10651210                                               RankIndex*GH->RanksSize]; 
    10661211 
     
    10771222    bool VarFound = false; 
    10781223    for (uint64_t j = 0; j < GH->NVars; ++j) { 
    1079       VariableHeader *VH = (VariableHeader *) &FH.getHeaderCache()[GH->VarsStart + 
     1224      VariableHeader<IsBigEndian> *VH = (VariableHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->VarsStart + 
    10801225                                                           j*GH->VarsSize]; 
    10811226 
     
    11211266      void *Data = Vars[i].Data; 
    11221267      bool HasExtraSpace = Vars[i].HasExtraSpace; 
    1123       if (offsetof(GlobalHeader, BlocksStart) < GH->GlobalHeaderSize && 
     1268      if (offsetof_safe(GH, BlocksStart) < GH->GlobalHeaderSize && 
    11241269          GH->BlocksSize > 0) { 
    1125         BlockHeader *BH = (BlockHeader *) 
     1270        BlockHeader<IsBigEndian> *BH = (BlockHeader<IsBigEndian> *) 
    11261271          &FH.getHeaderCache()[GH->BlocksStart + 
    11271272                               (RankIndex*GH->NVars + j)*GH->BlocksSize]; 
     
    12401385 
    12411386      if (LData.size()) { 
    1242         CompressHeader *CH = (CompressHeader*) &LData[0]; 
     1387        CompressHeader<IsBigEndian> *CH = (CompressHeader<IsBigEndian>*) &LData[0]; 
    12431388 
    12441389#ifdef _OPENMP 
     
    12571402#endif 
    12581403 
    1259         blosc_decompress(&LData[0] + sizeof(CompressHeader), 
     1404        blosc_decompress(&LData[0] + sizeof(CompressHeader<IsBigEndian>), 
    12601405                         Vars[i].Data, Vars[i].Size*RH->NElems); 
    12611406 
     
    12651410        } 
    12661411      } 
     1412 
     1413      // Byte swap the data if necessary. 
     1414      if (IsBigEndian != isBigEndian()) 
     1415        for (size_t j = 0; j < RH->NElems; ++j) { 
     1416          char *Offset = ((char *) Vars[i].Data) + j*Vars[i].Size; 
     1417          bswap(Offset, Vars[i].Size); 
     1418        } 
    12671419 
    12681420      break; 
     
    13521504 
    13531505void GenericIO::getVariableInfo(vector<VariableInfo> &VI) { 
     1506  if (FH.isBigEndian()) 
     1507    getVariableInfo<true>(VI); 
     1508  else 
     1509    getVariableInfo<false>(VI); 
     1510} 
     1511 
     1512template <bool IsBigEndian> 
     1513void GenericIO::getVariableInfo(vector<VariableInfo> &VI) { 
    13541514  assert(FH.getHeaderCache().size() && "HeaderCache must not be empty"); 
    13551515 
    1356   GlobalHeader *GH = (GlobalHeader *) &FH.getHeaderCache()[0]; 
     1516  GlobalHeader<IsBigEndian> *GH = (GlobalHeader<IsBigEndian> *) &FH.getHeaderCache()[0]; 
    13571517  for (uint64_t j = 0; j < GH->NVars; ++j) { 
    1358     VariableHeader *VH = (VariableHeader *) &FH.getHeaderCache()[GH->VarsStart + 
     1518    VariableHeader<IsBigEndian> *VH = (VariableHeader<IsBigEndian> *) &FH.getHeaderCache()[GH->VarsStart + 
    13591519                                                         j*GH->VarsSize]; 
    13601520 
Note: See TracChangeset for help on using the changeset viewer.