unsigned LFS::countDeadBlocksForSegmentAtIndex(unsigned index) { Segment* segment = segments[index]; unsigned deadCount = 0; for (unsigned i = 0; i < 1024 - 8; i++) { unsigned currentBlockAddress = (index << 10) + i; unsigned blockIndexInINode = segment->getBlockStatusForBlockAtIndex(i); unsigned iNodeIndexInInIMap = segment->getINodeStatusForBlockAtIndex(i); if (blockIndexInINode == std::numeric_limits<unsigned>::max() && iNodeIndexInInIMap == std::numeric_limits<unsigned>::max()) { // block is empty deadCount++; continue; } else if (iNodeIndexInInIMap == 10 * 1024) { // block is imap unsigned iMapAddress = iMapAddresses[blockIndexInINode]; if (currentBlockAddress != iMapAddress) { deadCount++; } } else if (blockIndexInINode == 128) { // block is inode unsigned iMapIndex = iNodeIndexInInIMap % iMapAddresses.size(); unsigned iMapAddress = iMapAddresses[iMapIndex]; unsigned iMapSegmentIdx = getSegmentIndexFromAddress(iMapAddress); unsigned iMapBlockIdx = getBlockIndexFromAddress(iMapAddress); IMap iMap(segments[iMapSegmentIdx]->blocks[iMapBlockIdx]); unsigned iNodeAddress = iMap.iNodeAddresses[iNodeIndexInInIMap]; if (currentBlockAddress != iNodeAddress) { deadCount++; } } else { // block is data unsigned iMapIndex = iNodeIndexInInIMap % iMapAddresses.size(); unsigned iMapAddress = iMapAddresses[iMapIndex]; unsigned iMapSegmentIdx = getSegmentIndexFromAddress(iMapAddress); unsigned iMapBlockIdx = getBlockIndexFromAddress(iMapAddress); IMap iMap(segments[iMapSegmentIdx]->blocks[iMapBlockIdx]); unsigned iNodeAddress = iMap.iNodeAddresses[iNodeIndexInInIMap]; unsigned iNodeSegmentIdx = getSegmentIndexFromAddress(iNodeAddress); unsigned iNodeBlockIdx = getBlockIndexFromAddress(iNodeAddress); INode iNode(segments[iNodeSegmentIdx]->blocks[iNodeBlockIdx]); unsigned blockAddress = iNode.blockAddresses[blockIndexInINode]; if (currentBlockAddress != blockAddress) { deadCount++; } } } return deadCount; }
LFS::LFS() : checkpointFile("DRIVE/CHECKPOINT_REGION", std::ios::binary | std::ios::in | std::ios::out), isClean(32, true), iMapAddresses(40, 0), currentIMapIdx{0}, currentSegmentIdx{0}, currentBlockIdx{0}, numCleanSegments{32} { // read or create segments for (int i = 0; i < 32; i++) { segments.push_back(new Segment("DRIVE/SEGMENT" + std::to_string(i + 1))); } // read or create checkpoint region if (!checkpointFile) { checkpointFile.close(); checkpointFile.open("DRIVE/CHECKPOINT_REGION", std::ios::binary | std::ios::in | std::ios::out | std::ios::trunc); } else { for (unsigned i = 0; i < isClean.size() && checkpointFile; i++) { bool clean = isClean[i]; checkpointFile.read((char*)&clean, sizeof(clean)); isClean[i] = clean; if (!isClean[i]) { numCleanSegments--; } } for (unsigned i = 0; i < iMapAddresses.size() && checkpointFile; i++) { unsigned address = 0; checkpointFile.read((char*)&address, sizeof(address)); iMapAddresses[i] = address; if (iMapAddresses[i] != 0) { currentIMapIdx = i; } } checkpointFile.clear(); checkpointFile.seekg(0, std::ios::beg); // read filenames for (unsigned i = 0; i <= currentIMapIdx; i++) { unsigned iMapAddress = iMapAddresses[currentIMapIdx]; unsigned iMapSegmentIdx = getSegmentIndexFromAddress(iMapAddress); unsigned iMapBlockIdx = getBlockIndexFromAddress(iMapAddress); IMap iMap(segments[iMapSegmentIdx]->blocks[iMapBlockIdx]); for (unsigned i = 0; i < iMap.iNodeAddresses.size(); i++) { unsigned iNodeAddress = iMap.iNodeAddresses[i]; if (iNodeAddress != 0) { unsigned iNodeSegmentIdx = getSegmentIndexFromAddress(iNodeAddress); unsigned iNodeBlockIdx = getBlockIndexFromAddress(iNodeAddress); INode iNode(segments[iNodeSegmentIdx]->blocks[iNodeBlockIdx]); files[iNode.fileName] = iNodeAddress; } } } // find a clean segment } }
void LFS::import(std::string& lfsFileName, std::istream& data) { unsigned iMapAddress = iMapAddresses[currentIMapIdx]; unsigned iMapSegmentIdx = getSegmentIndexFromAddress(iMapAddress); unsigned iMapBlockIdx = getBlockIndexFromAddress(iMapAddress); IMap iMap(segments[iMapSegmentIdx]->blocks[iMapBlockIdx]); if (iMapAddress == 0) { iMap = IMap(); } if (!iMap.hasFree()) { iMap = IMap(); currentIMapIdx++; // may go out of bounds. } INode iNode(lfsFileName); while (data) { Block dataBlock; data >> dataBlock; unsigned blockOffset = segments[currentSegmentIdx]->addBlock( dataBlock, iNode.fileSize, iMap.getNextINodeIndex()); if (blockOffset == 0) { selectNewCleanSegment(); blockOffset = segments[currentSegmentIdx]->addBlock( dataBlock, iNode.fileSize, iMap.getNextINodeIndex()); } unsigned blockAddress = (currentSegmentIdx << 10) + blockOffset; iNode.addBlockAddress(blockAddress); if (iNode.fileSize == 128) { data.setstate(std::ios::badbit); break; } } unsigned iNodeOffset =segments[currentSegmentIdx]->addBlock( iNode, iMap.getNextINodeIndex()); if (iNodeOffset == 0) { selectNewCleanSegment(); iNodeOffset = segments[currentSegmentIdx]->addBlock( iNode, iMap.getNextINodeIndex()); } unsigned iNodeAddress = (currentSegmentIdx << 10) + iNodeOffset; iMap.addINodeWithAddress(iNodeAddress); unsigned iMapOffset = segments[currentSegmentIdx]->addBlock(iMap, currentIMapIdx); if (iMapOffset == 0) { selectNewCleanSegment(); iMapOffset = segments[currentSegmentIdx]->addBlock(iMap, currentIMapIdx); } iMapAddress = (currentSegmentIdx << 10) + iMapOffset; iMapAddresses[currentIMapIdx] = iMapAddress; files[lfsFileName] = iNodeAddress; }
std::string LFS::list() { std::stringstream fNames; for (auto file: files) { unsigned iNodeAddress = file.second; unsigned int segmentIdx = getSegmentIndexFromAddress(iNodeAddress); unsigned int blockIdx = getBlockIndexFromAddress(iNodeAddress); INode iNode(segments[segmentIdx]->blocks[blockIdx]); fNames << file.first << " "; fNames << iNode.fileSize; fNames << std::endl; } return fNames.str(); }
std::string LFS::cat(std::string lfsFileName) { std::stringstream data; unsigned iNodeAddress = findFile(lfsFileName); unsigned segmentIdx = getSegmentIndexFromAddress(iNodeAddress); unsigned blockIdx = getBlockIndexFromAddress(iNodeAddress); INode iNode(segments[segmentIdx]->blocks[blockIdx]); unsigned i = 0; while(iNode.data[i++] != '\0') ; unsigned numBlocks = iNode.data[i++]; for(unsigned j = 0; j < numBlocks; j++) { unsigned dataBlockAdd = 0; for(int k = 6; k >= 0; k -= 2) { dataBlockAdd += (iNode.data[i++] << k); } unsigned dataSegIdx = getSegmentIndexFromAddress(dataBlockAdd); unsigned dataBlockIdx = getBlockIndexFromAddress(dataBlockAdd); data << segments[dataSegIdx]->blocks[dataBlockIdx]; } return data.str(); }
std::string LFS::display(std::string lfsFileName, int howMany, int start) { std::stringstream result; if (files.find(lfsFileName) != files.end()) { unsigned iNodeAddress = findFile(lfsFileName); unsigned iNodeSegmentIdx = getSegmentIndexFromAddress(iNodeAddress); unsigned iNodeBlockIdx = getBlockIndexFromAddress(iNodeAddress); INode iNode(segments[iNodeSegmentIdx]->blocks[iNodeBlockIdx]); for (auto blockAddress: iNode.blockAddresses) { if (blockAddress == 0 || howMany < 1) { break; } unsigned blockSegmentIdx = getSegmentIndexFromAddress(blockAddress); unsigned blockIdx = getBlockIndexFromAddress(blockAddress); unsigned numToPrint = 1024; if(howMany < 1024) numToPrint = howMany; howMany -= numToPrint; result << segments[blockSegmentIdx]->blocks[blockIdx].getFormattedBytesOfLength(numToPrint); } } else { result << "File " << lfsFileName << " does not exitst."; } return result.str(); }
MayaMeshWriter::MayaMeshWriter(MDagPath & iDag, Alembic::Abc::OObject & iParent, Alembic::Util::uint32_t iTimeIndex, const JobArgs & iArgs, GetMembersMap& gmMap) : mNoNormals(iArgs.noNormals), mWriteUVs(iArgs.writeUVs), mWriteColorSets(iArgs.writeColorSets), mWriteUVSets(iArgs.writeUVSets), mIsGeometryAnimated(false), mDagPath(iDag) { MStatus status = MS::kSuccess; MFnMesh lMesh( mDagPath, &status ); if ( !status ) { MGlobal::displayError( "MFnMesh() failed for MayaMeshWriter" ); } // intermediate objects aren't translated MObject surface = iDag.node(); if (iTimeIndex != 0 && util::isAnimated(surface)) { mIsGeometryAnimated = true; } else { iTimeIndex = 0; } std::vector<float> uvs; std::vector<Alembic::Util::uint32_t> indices; std::string uvSetName; MString name = lMesh.name(); name = util::stripNamespaces(name, iArgs.stripNamespace); // check to see if this poly has been tagged as a SubD MPlug plug = lMesh.findPlug("SubDivisionMesh"); if ( !plug.isNull() && plug.asBool() ) { Alembic::AbcGeom::OSubD obj(iParent, name.asChar(), iTimeIndex); mSubDSchema = obj.getSchema(); Alembic::AbcGeom::OV2fGeomParam::Sample uvSamp; if (mWriteUVs || mWriteUVSets) { getUVs(uvs, indices, uvSetName); if (!uvs.empty()) { if (!uvSetName.empty()) { mSubDSchema.setUVSourceName(uvSetName); } uvSamp.setScope( Alembic::AbcGeom::kFacevaryingScope ); uvSamp.setVals(Alembic::AbcGeom::V2fArraySample( (const Imath::V2f *) &uvs.front(), uvs.size() / 2)); if (!indices.empty()) { uvSamp.setIndices(Alembic::Abc::UInt32ArraySample( &indices.front(), indices.size())); } } } Alembic::Abc::OCompoundProperty cp; Alembic::Abc::OCompoundProperty up; if (AttributesWriter::hasAnyAttr(lMesh, iArgs)) { cp = mSubDSchema.getArbGeomParams(); up = mSubDSchema.getUserProperties(); } mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, lMesh, iTimeIndex, iArgs)); writeSubD(uvSamp); } else { Alembic::AbcGeom::OPolyMesh obj(iParent, name.asChar(), iTimeIndex); mPolySchema = obj.getSchema(); Alembic::AbcGeom::OV2fGeomParam::Sample uvSamp; if (mWriteUVs || mWriteUVSets) { getUVs(uvs, indices, uvSetName); if (!uvs.empty()) { if (!uvSetName.empty()) { mPolySchema.setUVSourceName(uvSetName); } uvSamp.setScope( Alembic::AbcGeom::kFacevaryingScope ); uvSamp.setVals(Alembic::AbcGeom::V2fArraySample( (const Imath::V2f *) &uvs.front(), uvs.size() / 2)); if (!indices.empty()) { uvSamp.setIndices(Alembic::Abc::UInt32ArraySample( &indices.front(), indices.size())); } } } Alembic::Abc::OCompoundProperty cp; Alembic::Abc::OCompoundProperty up; if (AttributesWriter::hasAnyAttr(lMesh, iArgs)) { cp = mPolySchema.getArbGeomParams(); up = mPolySchema.getUserProperties(); } // set the rest of the props and write to the writer node mAttrs = AttributesWriterPtr(new AttributesWriter(cp, up, obj, lMesh, iTimeIndex, iArgs)); writePoly(uvSamp); } if (mWriteColorSets) { MStringArray colorSetNames; lMesh.getColorSetNames(colorSetNames); if (colorSetNames.length() > 0) { // Create the color sets compound prop Alembic::Abc::OCompoundProperty arbParams; if (mPolySchema.valid()) { arbParams = mPolySchema.getArbGeomParams(); } else { arbParams = mSubDSchema.getArbGeomParams(); } std::string currentColorSet = lMesh.currentColorSetName().asChar(); for (unsigned int i=0; i < colorSetNames.length(); ++i) { // Create an array property for each color set std::string colorSetPropName = colorSetNames[i].asChar(); Alembic::AbcCoreAbstract::MetaData md; if (currentColorSet == colorSetPropName) { md.set("mayaColorSet", "1"); } else { md.set("mayaColorSet", "0"); } if (lMesh.getColorRepresentation(colorSetNames[i]) == MFnMesh::kRGB) { Alembic::AbcGeom::OC3fGeomParam colorProp(arbParams, colorSetPropName, true, Alembic::AbcGeom::kFacevaryingScope, 1, iTimeIndex, md); mRGBParams.push_back(colorProp); } else { Alembic::AbcGeom::OC4fGeomParam colorProp(arbParams, colorSetPropName, true, Alembic::AbcGeom::kFacevaryingScope, 1, iTimeIndex, md); mRGBAParams.push_back(colorProp); } } writeColor(); } } if (mWriteUVSets) { MStringArray uvSetNames; lMesh.getUVSetNames(uvSetNames); unsigned int uvSetNamesLen = uvSetNames.length(); if (uvSetNamesLen > 1) { // Create the uv sets compound prop Alembic::Abc::OCompoundProperty arbParams; if (mPolySchema.valid()) { arbParams = mPolySchema.getArbGeomParams(); } else { arbParams = mSubDSchema.getArbGeomParams(); } MString currentUV = lMesh.currentUVSetName(); for (unsigned int i = 0; i < uvSetNamesLen; ++i) { // Create an array property for each uv set MString uvSetPropName = uvSetNames[i]; // the current UV set gets mapped to the primary UVs if (currentUV == uvSetPropName) { continue; } if (uvSetPropName.length() > 0 && lMesh.numUVs(uvSetPropName) > 0) { mUVparams.push_back(Alembic::AbcGeom::OV2fGeomParam( arbParams, uvSetPropName.asChar(), true, Alembic::AbcGeom::kFacevaryingScope, 1, iTimeIndex)); } } writeUVSets(); } } // write out facesets if(!iArgs.writeFaceSets) return; // get the connected shading engines MObjectArray connSGObjs (getOutConnectedSG(mDagPath)); const unsigned int sgCount = connSGObjs.length(); for (unsigned int i = 0; i < sgCount; ++i) { MObject connSGObj, compObj; connSGObj = connSGObjs[i]; MFnDependencyNode fnDepNode(connSGObj); MString connSgObjName = fnDepNode.name(); // retrive the component MObject status = getSetComponents(mDagPath, connSGObj, gmMap, compObj); if (status != MS::kSuccess) { // for some reason the shading group doesn't represent a face set continue; } // retrieve the face indices MIntArray indices; MFnSingleIndexedComponent compFn; compFn.setObject(compObj); compFn.getElements(indices); const unsigned int numData = indices.length(); // encountered the whole object mapping. skip it. if (numData == 0) continue; std::vector<Alembic::Util::int32_t> faceIndices(numData); for (unsigned int j = 0; j < numData; ++j) { faceIndices[j] = indices[j]; } connSgObjName = util::stripNamespaces(connSgObjName, iArgs.stripNamespace); Alembic::AbcGeom::OFaceSet faceSet; std::string faceSetName(connSgObjName.asChar()); MPlug abcFacesetNamePlug = fnDepNode.findPlug("AbcFacesetName", true); if (!abcFacesetNamePlug.isNull()) { faceSetName = abcFacesetNamePlug.asString().asChar(); } if (mPolySchema.valid()) { if (mPolySchema.hasFaceSet(faceSetName)) { faceSet = mPolySchema.getFaceSet(faceSetName); } else { faceSet = mPolySchema.createFaceSet(faceSetName); } } else { if (mSubDSchema.hasFaceSet(faceSetName)) { faceSet = mSubDSchema.getFaceSet(faceSetName); } else { faceSet = mSubDSchema.createFaceSet(faceSetName); } } Alembic::AbcGeom::OFaceSetSchema::Sample samp; samp.setFaces(Alembic::Abc::Int32ArraySample(faceIndices)); Alembic::AbcGeom::OFaceSetSchema faceSetSchema = faceSet.getSchema(); faceSetSchema.set(samp); faceSetSchema.setFaceExclusivity(Alembic::AbcGeom::kFaceSetExclusive); MFnDependencyNode iNode(connSGObj); Alembic::Abc::OCompoundProperty cp; Alembic::Abc::OCompoundProperty up; if (AttributesWriter::hasAnyAttr(iNode, iArgs)) { cp = faceSetSchema.getArbGeomParams(); up = faceSetSchema.getUserProperties(); } AttributesWriter attrWriter(cp, up, faceSet, iNode, iTimeIndex, iArgs); attrWriter.write(); } }
void LFS::overwrite(std::string lfsFileName, int howMany, int start, char c) { unsigned iNodeAddress = findFile(lfsFileName); unsigned iNodeSegmentIdx = getSegmentIndexFromAddress(iNodeAddress); unsigned iNodeBlockIdx = getBlockIndexFromAddress(iNodeAddress); INode iNode(segments[iNodeSegmentIdx]->blocks[iNodeBlockIdx]); unsigned iMapIndex = getImapIndexFromINodeAddress(iNodeAddress); unsigned iMapAddress = iMapAddresses[iMapIndex]; unsigned iMapSegmentIndex = getSegmentIndexFromAddress(iMapAddress); unsigned iMapBlockIndex = getBlockIndexFromAddress(iMapAddress); IMap iMap(segments[iMapSegmentIndex]->blocks[iMapBlockIndex]); unsigned iNodeIndex = 0; for(unsigned i = 0; i < iMap.iNodeAddresses.size(); i++) { if(iMap.iNodeAddresses[i] == iNodeAddress) iNodeIndex = i; } unsigned i = 0; while(iNode.data[i++] != '\0') ; //Scanning past filename unsigned numBlocks = iNode.data[i++]; int numBlocksRem = numBlocks; int howManyRem = howMany; int remStart = start; int workingBlockIndex = 0; //Don't need to create new data block or update INode while(remStart > 1023 && numBlocksRem > 0) { remStart -= 1024; numBlocksRem--; workingBlockIndex++; } //Create new data blocks until start point is within next block while(remStart > 1023) { Block dataBlock; unsigned blockOffset = segments[currentSegmentIdx]->addBlock( dataBlock, iNode.fileSize, iMap.getNextINodeIndex()); if (blockOffset == 0) { selectNewCleanSegment(); blockOffset = segments[currentSegmentIdx]->addBlock( dataBlock, iNode.fileSize, iMap.getNextINodeIndex()); } unsigned blockAddress = (currentSegmentIdx << 10) + blockOffset; if((unsigned)workingBlockIndex <= numBlocks) iNode.addBlockAddress(blockAddress); else iNode.updateBlockAddressAtIndex(blockAddress, workingBlockIndex); remStart -= 1024; workingBlockIndex++; } while(howManyRem > 0) { unsigned workingBitIndex = 0; Block newDataBlock; unsigned oldDataBlockAdd = 0; for(int j = 6; j >= 0; j -= 2) { oldDataBlockAdd += (iNode.data[i++] << j); } unsigned oldDataSegIdx = getSegmentIndexFromAddress(oldDataBlockAdd); unsigned oldDataBlockIdx = getBlockIndexFromAddress(oldDataBlockAdd); while(remStart > 0) { if((unsigned)workingBlockIndex <= numBlocks) newDataBlock.data[workingBitIndex] = segments[oldDataSegIdx]->blocks[oldDataBlockIdx]. data[workingBitIndex]; else newDataBlock.data[workingBitIndex] = '\0'; workingBitIndex++; remStart--; } while(workingBitIndex <= 1024 && howManyRem >= 0) { newDataBlock.data[workingBitIndex++] = c; howManyRem--; } while(workingBitIndex <= 1024) { if((unsigned)workingBlockIndex <= numBlocks) newDataBlock.data[workingBitIndex] = segments[oldDataSegIdx]->blocks[oldDataBlockIdx]. data[workingBitIndex]; else newDataBlock.data[workingBitIndex] = '\0'; workingBitIndex++; remStart--; } unsigned blockOffset = segments[currentSegmentIdx]->addBlock( newDataBlock, iNode.fileSize, iMap.getNextINodeIndex()); if (blockOffset == 0) { selectNewCleanSegment(); blockOffset = segments[currentSegmentIdx]->addBlock( newDataBlock, iNode.fileSize, iMap.getNextINodeIndex()); } unsigned blockAddress = (currentSegmentIdx << 10) + blockOffset; if((unsigned)workingBlockIndex < numBlocks) { iNode.updateBlockAddressAtIndex(blockAddress, workingBlockIndex); } else iNode.addBlockAddress(blockAddress); numBlocksRem--; workingBlockIndex++; } unsigned iNodeOffset = segments[currentSegmentIdx]->addBlock( iNode, iMap.getNextINodeIndex()); if (iNodeOffset == 0) { selectNewCleanSegment(); iNodeOffset = segments[currentSegmentIdx]->addBlock( iNode, iMap.getNextINodeIndex()); } iNodeAddress = (currentSegmentIdx << 10) + iNodeOffset; iMap.updateINodeAddressAtIndex(iNodeAddress, iNodeIndex); unsigned iMapOffset = segments[currentSegmentIdx]->addBlock(iMap, currentIMapIdx); if (iMapOffset == 0) { selectNewCleanSegment(); iMapOffset = segments[currentSegmentIdx]->addBlock(iMap, currentIMapIdx); } iMapAddress = (currentSegmentIdx << 10) + iMapOffset; iMapAddresses[currentIMapIdx] = iMapAddress; files[lfsFileName] = iNodeAddress; }