EnduranceEeprom::EnduranceEeprom(SafeEeprom &eeprom, uint16_t startAddr, uint16_t endurFactor, size_t dataSize) : m_eeprom(eeprom), m_statusAddr(startAddr), m_endurFactor(endurFactor), m_dataSize(dataSize) { if ( m_endurFactor > 1 ) { // Check if there is enough memory from the start address if ( (startAddr+storageSize()) > (1+E2END) ) { exit(-1); } #ifdef SERIAL_DEBUG if ( ( dataSize % E2PAGESIZE ) != 0 ) { Serial.println("EnduranceEeprom Warning: dataSize is not a multiple of the page size -> non optimal endurance!"); } #endif m_dataAddr = m_statusAddr+m_endurFactor*sizeof(Status); bool found = findCurrent(); if ( ! found ) { // This area of memory has never been used for this circular buffer m_status.index = 1; for ( uint16_t i=0; i<m_dataSize; i++) { m_eeprom.write_byte(m_dataAddr+i, 0xFF); } m_status.crc16 = memCrc16(m_dataAddr, m_dataSize); m_eeprom.write_block(m_statusAddr, (void *)&m_status, sizeof(Status)); } else { } } else { m_dataAddr = m_statusAddr; } }
Chunk::Chunk(VM* vm, u32 id) : vm_(vm), id_(id) { // We don't initialize the marking bitmap or the contents of the page, since the kernel will // zero-initialize pages before giving them to us. auto freePlace = reinterpret_cast<void*>(storageBase()); auto free = new(freePlace, storageSize()) Free(nullptr); setFreeListHead(free); }
void RecordStoreV1Base::appendCustomStats( OperationContext* txn, BSONObjBuilder* result, double scale ) const { result->append( "lastExtentSize", _details->lastExtentSize(txn) / scale ); result->append( "paddingFactor", _details->paddingFactor() ); result->append( "userFlags", _details->userFlags() ); if ( isCapped() ) { result->appendBool( "capped", true ); result->appendNumber( "max", _details->maxCappedDocs() ); result->appendNumber( "maxSize", static_cast<long long>( storageSize( txn, NULL, 0 ) ) ); } }
TimePermRingBuffer::TimePermRingBuffer(uint16_t startAddr, uint16_t bufferSize, size_t dataSize, int timePeriod, uint16_t endurFactor) : EepromRingBuffer(startAddr, bufferSize, dataSize, endurFactor), m_period(timePeriod), m_lastTimeStamp(startAddr+storageSize(), endurFactor, sizeof(long)) { // long time; // m_lastTimeStamp.readData((void *)&time); // if ( 0xFFFFFFFFl == time ) { // time = INT32_MIN; // m_lastTimeStamp.writeData((void *)&time); // } }
void RecordStoreV1Base::appendCustomStats(OperationContext* txn, BSONObjBuilder* result, double scale) const { result->append("lastExtentSize", _details->lastExtentSize(txn) / scale); result->append("paddingFactor", 1.0); // hard coded result->append("paddingFactorNote", "paddingFactor is unused and unmaintained in 3.0. It " "remains hard coded to 1.0 for compatibility only."); result->append("userFlags", _details->userFlags()); result->appendBool("capped", isCapped()); if (isCapped()) { result->appendNumber("max", _details->maxCappedDocs()); result->appendNumber("maxSize", static_cast<long long>(storageSize(txn, NULL, 0) / scale)); } }
void AppStorage::CheckSlot(size_t slot_index) { auto &slot = slot_storage_[slot_index]; auto &slot_info = slots_[slot_index]; slot_info.id = slot.header.id; if (!slot.header.id || !slot.header.valid_length) { SERIAL_PRINTLN("Slot %u: id=%04x, valid_length=%u -- Empty", slot_index, slot.header.id, slot.header.valid_length); slot_info.state = SLOT_STATE::EMPTY; return; } slot_info.state = SLOT_STATE::CORRUPT; if (!slot.CheckCRC()) { SERIAL_PRINTLN("Slot %u: id=%04x, valid_length=%u -- CRC check failed", slot_index, slot.header.id, slot.header.valid_length); return; } SERIAL_PRINTLN("Slot %u: id=%04x, valid_length=%u", slot_index, slot.header.id, slot.header.valid_length); auto app = app_switcher.find(slot_info.id); if (!app) { SERIAL_PRINTLN("Slot %u: id=%04x -- App not found!", slot_index, slot.header.id); return; } SERIAL_PRINTLN("Slot %u: id=%04x found app '%s'", slot_index, slot.header.id, app->name); if (slot.header.version != app->storage_version) { SERIAL_PRINTLN("Slot %u: id=%04x -- version mismatch, expected %04x, got %04x", slot_index, slot.header.id, app->storage_version, slot.header.version); } // Some apps might have variable length settings, so there might not be a // safe way to check this. size_t expected_length = app->storageSize(); if (slot.header.valid_length > expected_length) { SERIAL_PRINTLN("Slot %u: id=%04x -- storage length mismatch, expected %u, got %u", slot_index, slot.header.id, expected_length, slot.header.valid_length); return; } slot_info.state = SLOT_STATE::OK; }
DiskLoc NamespaceDetails::cappedAlloc(const char *ns, int len) { if ( len > theCapExtent()->length ) { // the extent check is a way to try and improve performance uassert( 16328 , str::stream() << "document is larger than capped size " << len << " > " << storageSize() , len <= storageSize() ); } // signal done allocating new extents. if ( !cappedLastDelRecLastExtent().isValid() ) getDur().writingDiskLoc( cappedLastDelRecLastExtent() ) = DiskLoc(); verify( len < 400000000 ); int passes = 0; int maxPasses = ( len / 30 ) + 2; // 30 is about the smallest entry that could go in the oplog if ( maxPasses < 5000 ) { // this is for bacwards safety since 5000 was the old value maxPasses = 5000; } DiskLoc loc; // delete records until we have room and the max # objects limit achieved. /* this fails on a rename -- that is ok but must keep commented out */ //verify( theCapExtent()->ns == ns ); theCapExtent()->assertOk(); DiskLoc firstEmptyExtent; while ( 1 ) { if ( _stats.nrecords < maxCappedDocs() ) { loc = __capAlloc( len ); if ( !loc.isNull() ) break; } // If on first iteration through extents, don't delete anything. if ( !_capFirstNewRecord.isValid() ) { advanceCapExtent( ns ); if ( _capExtent != _firstExtent ) _capFirstNewRecord.writing().setInvalid(); // else signal done with first iteration through extents. continue; } if ( !_capFirstNewRecord.isNull() && theCapExtent()->firstRecord == _capFirstNewRecord ) { // We've deleted all records that were allocated on the previous // iteration through this extent. advanceCapExtent( ns ); continue; } if ( theCapExtent()->firstRecord.isNull() ) { if ( firstEmptyExtent.isNull() ) firstEmptyExtent = _capExtent; advanceCapExtent( ns ); if ( firstEmptyExtent == _capExtent ) { maybeComplain( ns, len ); return DiskLoc(); } continue; } DiskLoc fr = theCapExtent()->firstRecord; theDataFileMgr.deleteRecord(this, ns, fr.rec(), fr, true); // ZZZZZZZZZZZZ compact(); if( ++passes > maxPasses ) { StringBuilder sb; sb << "passes >= maxPasses in NamespaceDetails::cappedAlloc: ns: " << ns << ", len: " << len << ", maxPasses: " << maxPasses << ", _maxDocsInCapped: " << _maxDocsInCapped << ", nrecords: " << _stats.nrecords << ", datasize: " << _stats.datasize; msgasserted(10345, sb.str()); } } // Remember first record allocated on this iteration through capExtent. if ( _capFirstNewRecord.isValid() && _capFirstNewRecord.isNull() ) getDur().writingDiskLoc(_capFirstNewRecord) = loc; return loc; }
size_t MemoryManager::objectCount() { return storageSize() - freeSlotsCount(); }