Пример #1
0
void AntiCacheEvictionManager::printLRUChain(PersistentTable* table, int max, bool forward)
{
    VOLT_INFO("num tuples in chain: %d", table->getNumTuplesInEvictionChain());
    VOLT_INFO("oldest tuple id: %u", table->getOldestTupleID());
    VOLT_INFO("newest tuple id: %u", table->getNewestTupleID());
    
    char chain[max * 4];
    int tuple_id;
    TableTuple tuple = table->tempTuple();
    
    if(forward)
        tuple_id = table->getOldestTupleID();
    else
        tuple_id = table->getNewestTupleID();
    
    chain[0] = '\0';
    
    int iterations = 0;
    while(iterations < table->getNumTuplesInEvictionChain() && iterations < max)
    {
        strcat(chain, itoa(tuple_id));
        strcat(chain, " ");
        
        tuple.move(table->dataPtrForTuple(tuple_id));
        
        if(forward)
            tuple_id = tuple.getNextTupleInChain();
        else
            tuple_id = tuple.getPreviousTupleInChain();
        
        iterations++;
    }
    
    VOLT_INFO("LRU CHAIN: %s", chain);
}
Пример #2
0
AntiCacheBlock AntiCacheDB::readBlockNVM(std::string tableName, int16_t blockId) {
    
   std::map<int16_t, std::pair<int, int32_t> >::iterator itr; 
   itr = m_blockMap.find(blockId); 
  
   if (itr == m_blockMap.end()) 
   {
     VOLT_INFO("Invalid anti-cache blockId '%d' for table '%s'", blockId, tableName.c_str());
     VOLT_ERROR("Invalid anti-cache blockId '%d' for table '%s'", blockId, tableName.c_str());
     throw UnknownBlockAccessException(tableName, blockId);
   }

   int blockIndex = itr->second.first; 
   // VOLT_INFO("Reading NVM block: ID = %d, index = %d, size = %ld.", blockId, blockIndex, itr->second.second);
   
   char* block_ptr = getNVMBlock(blockIndex);
   char* block = new char[itr->second.second];
   memcpy(block, block_ptr, itr->second.second); 

   AntiCacheBlock anticache_block(blockId, block, itr->second.second);
   
   freeNVMBlock(blockId); 

   m_blockMap.erase(itr); 
   return (anticache_block);
}
Пример #3
0
 TableIndex *getInstanceIfKeyFits()
 {
     if (m_keySize > KeySize) {
         return NULL;
     }
     if (m_intsOnly) {
         // The IntsKey size parameter ((KeySize-1)/8 + 1) is calculated to be
         // the number of 8-byte uint64's required to store KeySize packed bytes.
         return getInstanceForKeyType<IntsKey<(KeySize-1)/8 + 1> >();
     }
     // Generic Key
     if (m_type == HASH_TABLE_INDEX) {
         VOLT_INFO("Producing a tree index for %s: "
                   "hash index not currently supported for this index key.\n",
                   m_scheme.name.c_str());
         m_type = BALANCED_TREE_INDEX;
     }
     // If any indexed expression value can not either be stored "inline" within a (GenericKey) key tuple
     // or specifically in a non-inlined object shared with the base table (because it is a simple column value),
     // then the GenericKey will have to reference and maintain its own persistent non-inline storage.
     // That's exactly what the GenericPersistentKey subtype of GenericKey does. This incurs extra overhead
     // for object copying and freeing, so is only enabled as needed.
     if (m_inlinesOrColumnsOnly) {
         return getInstanceForKeyType<GenericKey<KeySize> >();
     }
     return getInstanceForKeyType<GenericPersistentKey<KeySize> >();
 }
Пример #4
0
NVMAntiCacheBlock::NVMAntiCacheBlock(uint32_t blockId, char* block, long size) :
    AntiCacheBlock(blockId) {

    /* m_block = block;
    m_size = size;
    m_blockType = ANTICACHEDB_NVM;
    */
    char* buffer = block;
    std::string tableName = buffer;
    
    block = buffer + tableName.size() + 1;
    size -= tableName.size() + 1;


    m_block = new char[size];
    memcpy(m_block, block, size);

    delete [] buffer;

    payload p;
    p.tableName = tableName;
    p.blockId = blockId;
    p.data = m_block;
    p.size = size;
     
    m_payload = p;
    m_size = static_cast<int32_t>(size);
    m_blockType = ANTICACHEDB_NVM;
    //std::string payload_str(m_payload.data, m_size);
    
    VOLT_INFO("NVMAntiCacheBlock #%u from table: %s [size=%d / payload=%ld]",
              blockId, m_payload.tableName.c_str(), m_size, m_payload.size);
    
}
Пример #5
0
AntiCacheBlock* NVMAntiCacheDB::readBlock(uint32_t blockId, bool isMigrate) {
    
    std::map<uint32_t, std::pair<uint32_t, int32_t> >::iterator itr; 
    itr = m_blockMap.find(blockId); 
  
    if (itr == m_blockMap.end()) {
        VOLT_INFO("Invalid anti-cache blockId '%u'", blockId);
        VOLT_ERROR("Invalid anti-cache blockId '%u'", blockId);
        //throw UnknownBlockAccessException(tableName, blockId);
        throw UnknownBlockAccessException(blockId);
   
    }

    uint32_t blockIndex = itr->second.first; 
    int blockSize = itr->second.second;
   
    char* block_ptr = getNVMBlock(blockIndex);
    char* block = new char[blockSize];
    memcpy(block, block_ptr, blockSize); 

    VOLT_DEBUG("Reading NVM block: ID = %u, index = %u, size = %d, isMigrate = %d, data = %s", blockId, blockIndex, blockSize, isMigrate, block);
    
    AntiCacheBlock* anticache_block = new NVMAntiCacheBlock(blockId, block, blockSize);

    if (this->isBlockMerge()) {
        freeNVMBlock(blockIndex); 

        m_blockMap.erase(itr); 

        //FIXME: I'm hacking!!!!!!!!!!!!!!!!!!!!!!!!!
        removeBlockLRU(blockId);

        m_bytesUnevicted += blockSize;
        m_blocksUnevicted++;
    } else {
        if (isMigrate) {
            freeNVMBlock(blockIndex); 

            m_blockMap.erase(itr); 

            removeBlockLRU(blockId);

            m_bytesUnevicted += static_cast<int32_t>( (int64_t)blockSize - blockSize / tupleInBlock[blockId] *
                    (tupleInBlock[blockId] - evictedTupleInBlock[blockId]));

            m_blocksUnevicted++;
        } else {
            m_bytesUnevicted += static_cast<int32_t>( blockSize / tupleInBlock[blockId]);
            evictedTupleInBlock[blockId]--;

            // FIXME: I'm hacking!!!!!!!!!!!!!!!!!!!!!!!!!
            if (rand() % 100 == 0) {
                removeBlockLRU(blockId);
                pushBlockLRU(blockId);
            }
        }
    }
    return (anticache_block);
}
Пример #6
0
Table* AntiCacheEvictionManager::readBlocks(PersistentTable *table, int numBlocks, int16_t blockIds[], int32_t tuple_offsets[]) {
    
    VOLT_INFO("Reading %d evicted blocks.", numBlocks);

    for(int i = 0; i < numBlocks; i++)
        table->readEvictedBlock(blockIds[i], tuple_offsets[i]);

    return (m_readResultTable);
}
Пример #7
0
void AntiCacheDB::writeBlockNVM(const std::string tableName,
                             int16_t blockId,
                             const int tupleCount,
			     const char* data,
                             const long size)  {
   
  //int index = getFreeNVMBlockIndex();
  //char* block = getNVMBlock(index);
    char* block = getNVMBlock(m_totalBlocks); 
    memcpy(block, data, size);                      
   //m_NVMBlocks[m_totalBlocks] = new char[size]; 
   //memcpy(m_NVMBlocks[m_totalBlocks], data, size); 

    VOLT_INFO("Writing NVM Block: ID = %d, index = %d, size = %ld", blockId, m_totalBlocks, size); 
    m_blockMap.insert(std::pair<int16_t, std::pair<int, int32_t> >(blockId, std::pair<int, int32_t>(m_totalBlocks, static_cast<int32_t>(size))));
    m_totalBlocks++; 
}
Пример #8
0
void AntiCacheDB::writeBlockBerkeleyDB(const std::string tableName,
                             int16_t blockId,
                             const int tupleCount,
                             const char* data,
                             const long size) {
                                 
    Dbt key; 
    key.set_data(&blockId);
    key.set_size(sizeof(int16_t));

    Dbt value;
    value.set_data(const_cast<char*>(data));
    value.set_size(static_cast<int32_t>(size)); 

    VOLT_INFO("Writing out a block #%d to anti-cache database [tuples=%d / size=%ld]",
               blockId, tupleCount, size);
    // TODO: Error checking
    m_db->put(NULL, &key, &value, 0);
}
Пример #9
0
 TableIndex *getInstanceIfKeyFits()
 {
     if (m_keySize > KeySize) {
         return NULL;
     }
     if (m_intsOnly) {
         // The IntsKey size parameter ((KeySize-1)/8 + 1) is calculated to be
         // the number of 8-byte uint64's required to store KeySize packed bytes.
         return getInstanceForKeyType<IntsKey<(KeySize-1)/8 + 1> >();
     }
     // Generic Key
     if (m_type == HASH_TABLE_INDEX) {
         VOLT_INFO("Producing a tree index for %s: "
                   "hash index not currently supported for this index key.\n",
                   m_scheme.name.c_str());
         m_type = BALANCED_TREE_INDEX;
     }
     return getInstanceForKeyType<GenericKey<KeySize> >();
 }
Пример #10
0
bool UpdateExecutor::p_execute(const NValueArray &params, ReadWriteTracker *tracker) {
    assert(m_inputTable);
    assert(m_targetTable);

    VOLT_TRACE("INPUT TABLE: %s\n", m_inputTable->debug().c_str());
    VOLT_TRACE("TARGET TABLE - BEFORE: %s\n", m_targetTable->debug().c_str());

    assert(m_inputTuple.sizeInValues() == m_inputTable->columnCount());
    assert(m_targetTuple.sizeInValues() == m_targetTable->columnCount());
    TableIterator input_iterator(m_inputTable);
    while (input_iterator.next(m_inputTuple)) {
        //
        // OPTIMIZATION: Single-Sited Query Plans
        // If our beloved UpdatePlanNode is apart of a single-site query plan,
        // then the first column in the input table will be the address of a
        // tuple on the target table that we will want to update. This saves us
        // the trouble of having to do an index lookup
        //
        void *target_address = m_inputTuple.getNValue(0).castAsAddress();
        m_targetTuple.move(target_address);
        
        // Read/Write Set Tracking
        if (tracker != NULL) {
            tracker->markTupleWritten(m_targetTable, &m_targetTuple);
        }

        // Loop through INPUT_COL_IDX->TARGET_COL_IDX mapping and only update
        // the values that we need to. The key thing to note here is that we
        // grab a temp tuple that is a copy of the target tuple (i.e., the tuple
        // we want to update). This insures that if the input tuple is somehow
        // bringing garbage with it, we're only going to copy what we really
        // need to into the target tuple.
        //
        TableTuple &tempTuple = m_targetTable->getTempTupleInlined(m_targetTuple);
        for (int map_ctr = 0; map_ctr < m_inputTargetMapSize; map_ctr++) {
            tempTuple.setNValue(m_inputTargetMap[map_ctr].second,
                                m_inputTuple.getNValue(m_inputTargetMap[map_ctr].first));
        }

        // if there is a partition column for the target table
        if (m_partitionColumn != -1) {
            // check for partition problems
            // get the value for the partition column
            NValue value = tempTuple.getNValue(m_partitionColumn);
            bool isLocal = m_engine->isLocalSite(value);

            // if it doesn't map to this site
            if (!isLocal) {
                VOLT_ERROR("Mispartitioned tuple in single-partition plan for"
                           " table '%s'", m_targetTable->name().c_str());
                return false;
            }
        }

        #ifdef ARIES
        if(m_engine->isARIESEnabled()){

            // add persistency check:
            PersistentTable* table = dynamic_cast<PersistentTable*>(m_targetTable);

            // only log if we are writing to a persistent table.
            if (table != NULL) {
                // before image -- target is old val with no updates
                // XXX: what about uninlined fields?
                // should we not be doing
                // m_targetTable->getTempTupleInlined(m_targetTuple); instead?
                TableTuple *beforeImage = &m_targetTuple;

                // after image -- temp is NEW, created using target and input
                TableTuple *afterImage = &tempTuple;

                TableTuple *keyTuple = NULL;
                char *keydata = NULL;
                std::vector<int32_t> modifiedCols;

                int32_t numCols = -1;

                // See if we can do better by using an index instead
                TableIndex *index = table->primaryKeyIndex();

                if (index != NULL) {
                    // First construct tuple for primary key
                    keydata = new char[index->getKeySchema()->tupleLength()];
                    keyTuple = new TableTuple(keydata, index->getKeySchema());

                    for (int i = 0; i < index->getKeySchema()->columnCount(); i++) {
                        keyTuple->setNValue(i, beforeImage->getNValue(index->getColumnIndices()[i]));
                    }

                    // no before image need be recorded, just the primary key
                    beforeImage = NULL;
                }

                // Set the modified column list
                numCols = m_inputTargetMapSize;

                modifiedCols.resize(m_inputTargetMapSize, -1);

                for (int map_ctr = 0; map_ctr < m_inputTargetMapSize; map_ctr++) {
                    // can't use column-id directly, otherwise we would go over vector bounds
                    int pos = m_inputTargetMap[map_ctr].first - 1;

                    modifiedCols.at(pos)
                    = m_inputTargetMap[map_ctr].second;
                }

                // Next, let the input tuple be the diff after image
                afterImage = &m_inputTuple;

                LogRecord *logrecord = new LogRecord(computeTimeStamp(),
                        LogRecord::T_UPDATE,// this is an update record
                        LogRecord::T_FORWARD,// the system is running normally
                        -1,// XXX: prevLSN must be fetched from table!
                        m_engine->getExecutorContext()->currentTxnId() ,// txn id
                        m_engine->getSiteId(),// which execution site
                        m_targetTable->name(),// the table affected
                        keyTuple,// primary key
                        numCols,
                        (numCols > 0) ? &modifiedCols : NULL,
                        beforeImage,
                        afterImage
                );

                size_t logrecordLength = logrecord->getEstimatedLength();
                char *logrecordBuffer = new char[logrecordLength];

                FallbackSerializeOutput output;
                output.initializeWithPosition(logrecordBuffer, logrecordLength, 0);

                logrecord->serializeTo(output);

                LogManager* m_logManager = this->m_engine->getLogManager();
                Logger m_ariesLogger = m_logManager->getAriesLogger();
                //VOLT_WARN("m_logManager : %p AriesLogger : %p",&m_logManager, &m_ariesLogger);
                const Logger *logger = m_logManager->getThreadLogger(LOGGERID_MM_ARIES);

                logger->log(LOGLEVEL_INFO, output.data(), output.position());

                delete[] logrecordBuffer;
                logrecordBuffer = NULL;

                delete logrecord;
                logrecord = NULL;

                if (keydata != NULL) {
                    delete[] keydata;
                    keydata = NULL;
                }

                if (keyTuple != NULL) {
                    delete keyTuple;
                    keyTuple = NULL;
                }
            }

        }
        #endif

        if (!m_targetTable->updateTuple(tempTuple, m_targetTuple,
                                        m_updatesIndexes)) {
            VOLT_INFO("Failed to update tuple from table '%s'",
                      m_targetTable->name().c_str());
            return false;
        }
    }

    VOLT_TRACE("TARGET TABLE - AFTER: %s\n", m_targetTable->debug().c_str());
    // TODO lets output result table here, not in result executor. same thing in
    // delete/insert

    // add to the planfragments count of modified tuples
    m_engine->m_tuplesModified += m_inputTable->activeTupleCount();

    return true;
}
Пример #11
0
  void AntiCacheDB::initializeNVM() {
    
    char nvm_file_name[150];
    char partition_str[50];

    m_totalBlocks = 0; 

    #ifdef ANTICACHE_DRAM
        VOLT_INFO("Allocating anti-cache in DRAM."); 
        m_NVMBlocks = new char[aligned_file_size];
	return; 
    #endif

    // use executor context to figure out which partition we are at
    int partition_id = (int)m_executorContext->getPartitionId(); 
    sprintf(partition_str, "%d", partition_id); 

    strcpy(nvm_file_name, m_dbDir.c_str()); 
    // there will be one NVM anti-cache file per partition, saved in /mnt/pmfs/anticache-XX
    strcat(nvm_file_name, "/anticache-");
    strcat(nvm_file_name, partition_str);
    VOLT_INFO("Creating nvm file: %s", nvm_file_name); 
    nvm_file = fopen(nvm_file_name, "w"); 

    if(nvm_file == NULL)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to open PMFS file %s: %s.", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    fclose(nvm_file); 
    nvm_file = fopen(nvm_file_name, "rw+"); 

    if(nvm_file == NULL)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to open PMFS file %s: %s.", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    nvm_fd = fileno(nvm_file); 
    if(nvm_fd < 0)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to allocate anti-cache PMFS file in directory %s.", m_dbDir.c_str());
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }
    
    if(ftruncate(nvm_fd, NVM_FILE_SIZE) < 0)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to ftruncate anti-cache PMFS file %s: %s", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    //off_t aligned_file_size = (((NVM_FILE_SIZE) + MMAP_PAGE_SIZE - 1) / MMAP_PAGE_SIZE * MMAP_PAGE_SIZE);  
    off_t aligned_file_size = NVM_FILE_SIZE; 

    m_NVMBlocks =  (char*)mmap(NULL, aligned_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, nvm_fd, 0);
 
    if(m_NVMBlocks == MAP_FAILED)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to mmap PMFS file %s: %s", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    close(nvm_fd); // can safely close file now, mmap creates new reference

    /*
    // write out NULL characters to ensure entire file has been fetchted from memory
    for(int i = 0; i < NVM_FILE_SIZE; i++)
    {
        m_NVMBlocks[i] = '\0'; 
    }
    */
}
Пример #12
0
/**
 * Reserve some tuples when an eviction requested.
 */
void EvictionIterator::reserve(int64_t amount) {
    VOLT_DEBUG("amount: %ld\n", amount);

    char* addr = NULL;
    PersistentTable* ptable = static_cast<PersistentTable*>(table);
    int tuple_size = ptable->m_schema->tupleLength() + TUPLE_HEADER_SIZE;
    int active_tuple = (int)ptable->activeTupleCount();
    int evict_num = 0;
    int64_t used_tuple = ptable->usedTupleCount();
#ifdef ANTICACHE_TIMESTAMPS_PRIME
    uint32_t tuples_per_block = ptable->m_tuplesPerBlock;
#endif

    if (active_tuple)   
        evict_num = (int)(amount / (tuple_size + ptable->nonInlinedMemorySize() / active_tuple));
    else 
        evict_num = (int)(amount / tuple_size);

    VOLT_DEBUG("Count: %lu %lu\n", ptable->usedTupleCount(), ptable->activeTupleCount());

    if (evict_num > active_tuple)
        evict_num = active_tuple;

    int pick_num = evict_num * RANDOM_SCALE;

    int block_num = (int)ptable->m_data.size();
    int block_size = ptable->m_tuplesPerBlock;
    int location_size;
#ifndef ANTICACHE_TIMESTAMPS_PRIME
    int block_location;
#endif

    srand((unsigned int)time(0));

    VOLT_INFO("evict pick num: %d %d\n", evict_num, pick_num);
    VOLT_INFO("active_tuple: %d\n", active_tuple);
    VOLT_INFO("block number: %d\n", block_num);

    m_size = 0;
    current_tuple_id = 0;

#ifdef ANTICACHE_TIMESTAMPS_PRIME
    int pick_num_block = (int)(((int64_t)pick_num * tuples_per_block) / used_tuple);
    int last_full_block = (int)(used_tuple / block_size);
    VOLT_INFO("LOG: %d %d %ld\n", last_full_block, tuples_per_block, used_tuple);
    int last_block_size = (int)(used_tuple % block_size);
    int pick_num_last_block = pick_num - pick_num_block * last_full_block;
#endif

    // If we'll evict the entire table, we should do a scan instead of sampling.
    // The main reason we should do that is to past the test...
    if (evict_num < active_tuple) {
        candidates = new EvictionTuple[pick_num];
#ifdef ANTICACHE_TIMESTAMPS_PRIME
        for (int i = 0; i < last_full_block; ++i) {
            
            /**
             * if this is a beginning of a loop of scan, find a proper step to let it sample tuples from almost the whole block
             * TODO: Here we use a method that every time try a different prime number from what we use last time. Is it better?
             *       That would need further analysis.
             */  
            if (ptable->m_stepPrime[i] < 0) {
                int ideal_step = (rand() % 5) * tuples_per_block / pick_num_block;
                int old_prime = - ptable->m_stepPrime[i];
                for (int j = prime_size - 1; j >= 0; --j) {
                    if (prime_list[j] != old_prime && (tuples_per_block % prime_list[j]) > 0) {
                        ptable->m_stepPrime[i] = prime_list[j];
                        VOLT_TRACE("DEBUG: %d %d\n", tuples_per_block, ptable->m_stepPrime[i]);
                    }
                    if (prime_list[j] <= ideal_step)
                        break;
                }
                VOLT_INFO("Prime of block %d: %d %d\n", i, tuples_per_block, ptable->m_stepPrime[i]);
            }

            // now scan the block with a step of we select.
            // if we go across the boundry, minus it back to the beginning (like a mod operation)
            int step_prime = ptable->m_stepPrime[i];
            int step_offset = step_prime * tuple_size;
            int block_size_bytes = block_size * tuple_size;
            addr = ptable->m_data[i] + ptable->m_evictPosition[i];
            uint64_t end_of_block = (uint64_t)ptable->m_data[i] + block_size_bytes;
            bool flag_new = false;
            for (int j = 0; j < pick_num_block; ++j) {
                VOLT_TRACE("Flip addr: %p %p %lu\n", addr, ptable->m_data[i], ((uint64_t)addr - (uint64_t)ptable->m_data[i]) / 1024);

                current_tuple->move(addr);

                if (current_tuple->isActive()) {
                    candidates[m_size].setTuple(current_tuple->getTimeStamp(), addr);
                    m_size++;
                }

                addr += step_offset;
                if ((uint64_t)addr >= end_of_block)
                    addr -= block_size_bytes;
                if (addr == ptable->m_data[i])
                    flag_new = true;
            }
            int new_position = (int)((uint64_t)addr - (uint64_t)ptable->m_data[i]);
            ptable->m_evictPosition[i] = new_position;
            if (flag_new)
                ptable->m_stepPrime[i] = - ptable->m_stepPrime[i];
        }
        if (last_full_block < block_num) {
            addr = ptable->m_data[last_full_block];
            char* current_addr;
            for (int j = 0; j < pick_num_last_block; ++j) {
                current_addr = addr + (rand() % last_block_size) * tuple_size;
                current_tuple->move(current_addr);
                if (!current_tuple->isActive() || current_tuple->isEvicted())
                    continue;

                candidates[m_size].setTuple(current_tuple->getTimeStamp(), current_addr);
                m_size++;
            }
        }

#else
        for (int i = 0; i < pick_num; i++) {
            // should we use a faster random generator?
            block_location = rand() % block_num;
            addr = ptable->m_data[block_location];
            if ((block_location + 1) * block_size > used_tuple)
                location_size = (int)(used_tuple - block_location * block_size);
            else
                location_size = block_size;
            addr += (rand() % location_size) * tuple_size;

            current_tuple->move(addr);

            VOLT_DEBUG("Flip addr: %p\n", addr);

            if (!current_tuple->isActive() || current_tuple->isEvicted())
                continue;

            candidates[m_size].setTuple(current_tuple->getTimeStamp(), addr);
            m_size++;
        }
#endif
    } else {
        candidates = new EvictionTuple[active_tuple];
        for (int i = 0; i < block_num; ++i) { 
            addr = ptable->m_data[i];
            if ((i + 1) * block_size > ptable->usedTupleCount())
                location_size = (int)(ptable->usedTupleCount() - i * block_size);
            else
                location_size = block_size;
            for (int j = 0; j < location_size; j++) {
                current_tuple->move(addr);

                if (!current_tuple->isActive() || current_tuple->isEvicted()) {
                    addr += tuple_size;
                    continue;
                }

                VOLT_TRACE("Flip addr: %p\n", addr);

                candidates[m_size].setTuple(current_tuple->getTimeStamp(), addr);
                m_size++;

                addr += tuple_size;
            }
        }
    }
    sort(candidates, candidates + m_size, less <EvictionTuple>());

    //VOLT_INFO("Size of eviction candidates: %lu %d %d\n", (long unsigned int)m_size, activeN, evictedN);
}
Пример #13
0
void NVMAntiCacheDB::initializeDB() {
    
    char nvm_file_name[150];
    char partition_str[50];

    m_blockIndex = 0; 
    m_nextFreeBlock = 0;
    m_monoBlockID = 0;
    // TODO: Make DRAM based store a separate type
    #ifdef ANTICACHE_DRAM
        VOLT_INFO("Allocating anti-cache in DRAM."); 
        m_NVMBlocks = new char[m_maxDBSize];
    return; 
    #endif

    int partition_id;
    // use executor context to figure out which partition we are at
    // if there is no executor context, assume this is a test and let it go
    if (!m_executorContext) {
        VOLT_WARN("NVMAntiCacheDB has no executor context. If this is an EE test, don't worry\n");
        partition_id = 0;
    } else {
        partition_id = (int)m_executorContext->getPartitionId(); 
    }
    
    sprintf(partition_str, "%d", partition_id); 

    strcpy(nvm_file_name, m_dbDir.c_str()); 
    // there will be one NVM anti-cache file per partition, saved in /mnt/pmfs/anticache-XX
    strcat(nvm_file_name, "/anticache-");
    strcat(nvm_file_name, partition_str);
    VOLT_INFO("Creating size %ld nvm file: %s", m_maxDBSize, nvm_file_name); 
    nvm_file = fopen(nvm_file_name, "w"); 

    if(nvm_file == NULL)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to open PMFS file %s: %s.", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    fclose(nvm_file); 
    nvm_file = fopen(nvm_file_name, "rw+"); 

    if(nvm_file == NULL)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to open PMFS file %s: %s.", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    nvm_fd = fileno(nvm_file); 
    if(nvm_fd < 0)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to allocate anti-cache PMFS file in directory %s.", m_dbDir.c_str());
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }
    
    if(ftruncate(nvm_fd, m_maxDBSize) < 0)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to ftruncate anti-cache PMFS file %s: %s", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    //off_t aligned_file_size = (((NVM_FILE_SIZE) + MMAP_PAGE_SIZE - 1) / MMAP_PAGE_SIZE * MMAP_PAGE_SIZE);  
    off_t aligned_file_size = (off_t)m_maxDBSize; 

    m_NVMBlocks =  (char*)mmap(NULL, aligned_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, nvm_fd, 0);
 
    if(m_NVMBlocks == MAP_FAILED)
    {
        VOLT_ERROR("Anti-Cache initialization error."); 
        VOLT_ERROR("Failed to mmap PMFS file %s: %s", nvm_file_name, strerror(errno));
        throwFatalException("Failed to initialize anti-cache PMFS file in directory %s.", m_dbDir.c_str());
    }

    close(nvm_fd); // can safely close file now, mmap creates new reference
    
    // write out NULL characters to ensure entire file has been fetchted from memory
    
    for(int i = 0; i < m_maxDBSize; i++)
    {
        m_NVMBlocks[i] = '\0'; 
    }
    
}