Exemple #1
0
void NVMAntiCacheDB::writeBlock(const std::string tableName,
                                uint32_t blockId,
                                const int tupleCount,
                                const char* data,
                                const long size,
                                const int evictedTupleCount)  {
   
    VOLT_TRACE("free blocks: %d", getFreeBlocks());
    if (getFreeBlocks() == 0) {
        VOLT_WARN("No free space in ACID %d for blockid %u with blocksize %ld",
                m_ACID, blockId, size);
        throw FullBackingStoreException(((int32_t)m_ACID << 16) & blockId, 0);
    }
    uint32_t index = getFreeNVMBlockIndex();
    VOLT_TRACE("block index: %u", index);
    char* block = getNVMBlock(index); 
    long bufsize; 
    char* buffer = new char [tableName.size() + 1 + size];
    memset(buffer, 0, tableName.size() + 1 + size);
    bufsize = tableName.size() + 1;
    memcpy(buffer, tableName.c_str(), bufsize);
    memcpy(buffer + bufsize, data, size);
    bufsize += size;
    memcpy(block, buffer, bufsize); 
    delete[] buffer;

    VOLT_DEBUG("Writing NVM Block: ID = %u, index = %u, tupleCount = %d, size = %ld, tableName = %s",
            blockId, index, tupleCount, bufsize, tableName.c_str()); 

    m_blocksEvicted++;
    if (!isBlockMerge()) {
        tupleInBlock[blockId] = tupleCount;
        evictedTupleInBlock[blockId] = evictedTupleCount;
        blockSize[blockId] = bufsize;
        m_bytesEvicted += static_cast<int32_t>((int64_t)bufsize * evictedTupleCount / tupleCount);
    }
    else {
        m_bytesEvicted += static_cast<int32_t>(bufsize);
    }

    m_blockMap.insert(std::pair<uint32_t, std::pair<int, int32_t> >(blockId, std::pair<uint32_t, int32_t>(index, static_cast<int32_t>(bufsize))));
    m_monoBlockID++;
    
    // FIXME: I'm hacking!!!!!!!!!!!!!!!!!!!!!!!!!
    pushBlockLRU(blockId);
}
Exemple #2
0
uint32_t NVMAntiCacheDB::getFreeNVMBlockIndex() {
  
    
    uint32_t free_index = 0; 

    if(m_NVMBlockFreeList.size() > 0) {
        free_index = m_NVMBlockFreeList.back(); 
        VOLT_DEBUG("popping %u from list of size: %d", free_index, (int)m_NVMBlockFreeList.size());
        m_NVMBlockFreeList.pop_back(); 
    } else {
        if (m_nextFreeBlock == getMaxBlocks()) {
            VOLT_WARN("Backing store full m_nextFreeBlock %d == max %d", m_nextFreeBlock, getMaxBlocks());
            throw FullBackingStoreException(0, m_nextFreeBlock);
        } else {
            free_index = m_nextFreeBlock;
            VOLT_DEBUG("no reusable blocks (size: %d), using index %u", (int)m_NVMBlockFreeList.size(), free_index);
            ++m_nextFreeBlock;
        }
    }
    

    //int free_index = m_blockIndex++; 
    return free_index; 
}
Table* TableCatalogDelegate::constructTableFromCatalog(catalog::Database const& catalogDatabase,
                                                       catalog::Table const& catalogTable,
                                                       bool isXDCR,
                                                       int tableAllocationTargetSize,
                                                       bool forceNoDR) {
    // Create a persistent table for this table in our catalog
    int32_t tableId = catalogTable.relativeIndex();

    // get an array of table column names
    const int numColumns = static_cast<int>(catalogTable.columns().size());
    std::map<std::string, catalog::Column*>::const_iterator colIterator;
    std::vector<std::string> columnNames(numColumns);
    for (colIterator = catalogTable.columns().begin();
         colIterator != catalogTable.columns().end();
         colIterator++) {
        auto catalogColumn = colIterator->second;
        columnNames[catalogColumn->index()] = catalogColumn->name();
    }

    // get the schema for the table
    TupleSchema* schema = createTupleSchema(catalogTable, isXDCR);

    // Indexes
    std::map<std::string, TableIndexScheme> index_map;
    std::map<std::string, catalog::Index*>::const_iterator idxIterator;
    for (idxIterator = catalogTable.indexes().begin();
         idxIterator != catalogTable.indexes().end(); idxIterator++) {
        auto catalogIndex = idxIterator->second;

        TableIndexScheme index_scheme;
        if (getIndexScheme(catalogTable, *catalogIndex, schema, &index_scheme)) {
            index_map[catalogIndex->name()] = index_scheme;
        }
    }

    // Constraints
    std::string pkeyIndexId;
    std::map<std::string, catalog::Constraint*>::const_iterator constraintIterator;
    for (constraintIterator = catalogTable.constraints().begin();
         constraintIterator != catalogTable.constraints().end();
         constraintIterator++) {
        auto catalogConstraint = constraintIterator->second;

        // Constraint Type
        ConstraintType type = (ConstraintType) catalogConstraint->type();
        switch (type) {
        case CONSTRAINT_TYPE_PRIMARY_KEY:
            // Make sure we have an index to use
            assert(catalogConstraint->index());
            // Make sure they didn't declare more than one primary key index
            assert(pkeyIndexId.empty());
            pkeyIndexId = catalogConstraint->index()->name();
            break;
        case CONSTRAINT_TYPE_UNIQUE:
            // Make sure we have an index to use
            // TODO: In the future I would like bring back my Constraint
            //       object so that we can keep track of everything that a
            //       table has...
            assert(catalogConstraint->index());
            break;
        // Unsupported
        case CONSTRAINT_TYPE_CHECK:
        case CONSTRAINT_TYPE_FOREIGN_KEY:
        case CONSTRAINT_TYPE_MAIN:
            VOLT_WARN("Unsupported type '%s' for constraint '%s'",
                      constraintutil::getTypeName(type).c_str(),
                      catalogConstraint->name().c_str());
            break;
        // Unknown
        default:
            VOLT_ERROR("Invalid constraint type '%s' for '%s'",
                       constraintutil::getTypeName(type).c_str(),
                       catalogConstraint->name().c_str());
            assert(false);
            return NULL;
        }
    }

    // Build the index array
    // Please note the index array should follow the order of primary key first,
    // all unique indices afterwards, and all the non-unique indices at the end.
    std::deque<TableIndexScheme> indexes;
    TableIndexScheme pkeyIndex_scheme;
    std::map<std::string, TableIndexScheme>::const_iterator indexIterator;
    for (indexIterator = index_map.begin(); indexIterator != index_map.end();
         indexIterator++) {
        // Exclude the primary key
        if (indexIterator->second.name.compare(pkeyIndexId) == 0) {
            pkeyIndex_scheme = indexIterator->second;
        // Just add it to the list
        }
        else {
            if (indexIterator->second.unique) {
                indexes.push_front(indexIterator->second);
            }
            else {
                indexes.push_back(indexIterator->second);
            }
        }
    }

    // partition column:
    catalog::Column const* partitionColumn = catalogTable.partitioncolumn();
    int partitionColumnIndex = -1;
    if (partitionColumn != NULL) {
        partitionColumnIndex = partitionColumn->index();
    }

    bool exportEnabled = isExportEnabledForTable(catalogDatabase, tableId);
    bool tableIsExportOnly = isTableExportOnly(catalogDatabase, tableId);
    bool drEnabled = !forceNoDR && catalogTable.isDRed();
    bool isReplicated = catalogTable.isreplicated();
    m_materialized = isTableMaterialized(catalogTable);
    std::string const& tableName = catalogTable.name();
    int32_t databaseId = catalogDatabase.relativeIndex();
    SHA1_CTX shaCTX;
    SHA1Init(&shaCTX);
    SHA1Update(&shaCTX, reinterpret_cast<const uint8_t*>(catalogTable.signature().c_str()), (uint32_t )::strlen(catalogTable.signature().c_str()));
    SHA1Final(reinterpret_cast<unsigned char*>(m_signatureHash), &shaCTX);
    // Persistent table will use default size (2MB) if tableAllocationTargetSize is zero.
    if (m_materialized) {
      catalog::MaterializedViewInfo* mvInfo = catalogTable.materializer()->views().get(catalogTable.name());
      if (mvInfo && mvInfo->groupbycols().size() == 0) {
        // ENG-8490: If the materialized view came with no group by, set table block size to 64KB
        // to achieve better space efficiency.
        // FYI: maximum column count = 1024, largest fixed length data type is short varchars (64 bytes)
        tableAllocationTargetSize = 1024 * 64;
      }
    }
    VOLT_DEBUG("Creating %s %s as %s", m_materialized?"VIEW":"TABLE", tableName.c_str(), isReplicated?"REPLICATED":"PARTITIONED");
    Table* table = TableFactory::getPersistentTable(databaseId, tableName,
                                                    schema, columnNames, m_signatureHash,
                                                    m_materialized,
                                                    partitionColumnIndex, exportEnabled,
                                                    tableIsExportOnly,
                                                    tableAllocationTargetSize,
                                                    catalogTable.tuplelimit(),
                                                    m_compactionThreshold,
                                                    drEnabled,
                                                    isReplicated);
    PersistentTable* persistentTable = dynamic_cast<PersistentTable*>(table);
    if ( ! persistentTable) {
        assert(pkeyIndexId.empty());
        assert(indexes.empty());
        return table;
    }

    // add a pkey index if one exists
    if ( ! pkeyIndexId.empty()) {
        TableIndex* pkeyIndex = TableIndexFactory::getInstance(pkeyIndex_scheme);
        assert(pkeyIndex);
        persistentTable->addIndex(pkeyIndex);
        persistentTable->setPrimaryKeyIndex(pkeyIndex);
    }

    // add other indexes
    BOOST_FOREACH(TableIndexScheme& scheme, indexes) {
        TableIndex* index = TableIndexFactory::getInstance(scheme);
        assert(index);
        persistentTable->addIndex(index);
    }
int
TableCatalogDelegate::init(ExecutorContext *executorContext,
                           catalog::Database &catalogDatabase,
                           catalog::Table &catalogTable)
{
    // Create a persistent table for this table in our catalog
    int32_t table_id = catalogTable.relativeIndex();

    // Columns:
    // Column is stored as map<String, Column*> in Catalog. We have to
    // sort it by Column index to preserve column order.
    const int numColumns = static_cast<int>(catalogTable.columns().size());
    vector<ValueType> columnTypes(numColumns);
    vector<int32_t> columnLengths(numColumns);
    vector<bool> columnAllowNull(numColumns);
    // GWW
    vector<bool> columnisEscrow(numColumns);

    map<string, catalog::Column*>::const_iterator col_iterator;
    string *columnNames = new string[numColumns];
    for (col_iterator = catalogTable.columns().begin();
         col_iterator != catalogTable.columns().end(); col_iterator++) {
        const catalog::Column *catalog_column = col_iterator->second;
        const int columnIndex = catalog_column->index();
        const ValueType type = static_cast<ValueType>(catalog_column->type());
        columnTypes[columnIndex] = type;
        const int32_t size = static_cast<int32_t>(catalog_column->size());
        //Strings length is provided, other lengths are derived from type
        bool varlength = (type == VALUE_TYPE_VARCHAR) || (type == VALUE_TYPE_VARBINARY);
        const int32_t length = varlength ? size : static_cast<int32_t>(NValue::getTupleStorageSize(type));
        columnLengths[columnIndex] = length;
        columnAllowNull[columnIndex] = catalog_column->nullable();
        //GWW
        columnisEscrow[columnIndex] = catalog_column->escrowColumn();
        columnNames[catalog_column->index()] = catalog_column->name();
    }

    /*
    TupleSchema *schema = TupleSchema::createTupleSchema(columnTypes,
                                                         columnLengths,
                                                         columnAllowNull, true);

    */

    TupleSchema *schema = TupleSchema::createTupleSchema(columnTypes,
                                                         columnLengths,
                                                         columnAllowNull,
                                                         columnisEscrow, true);


    // Indexes
    map<string, TableIndexScheme> index_map;
    map<string, catalog::Index*>::const_iterator idx_iterator;
    for (idx_iterator = catalogTable.indexes().begin();
         idx_iterator != catalogTable.indexes().end(); idx_iterator++) {
        catalog::Index *catalog_index = idx_iterator->second;
        vector<int> index_columns;
        vector<ValueType> column_types;

        // The catalog::Index object now has a list of columns that are to be
        // used
        if (catalog_index->columns().size() == (size_t)0) {
            VOLT_ERROR("Index '%s' in table '%s' does not declare any columns"
                       " to use",
                       catalog_index->name().c_str(),
                       catalogTable.name().c_str());
            delete [] columnNames;
            return false;
        }

        // Since the columns are not going to come back in the proper order from
        // the catalogs, we'll use the index attribute to make sure we put them
        // in the right order
        index_columns.resize(catalog_index->columns().size());
        column_types.resize(catalog_index->columns().size());
        bool isIntsOnly = true;
        map<string, catalog::ColumnRef*>::const_iterator colref_iterator;
        for (colref_iterator = catalog_index->columns().begin();
             colref_iterator != catalog_index->columns().end();
             colref_iterator++) {
            catalog::ColumnRef *catalog_colref = colref_iterator->second;
            if (catalog_colref->index() < 0) {
                VOLT_ERROR("Invalid column '%d' for index '%s' in table '%s'",
                           catalog_colref->index(),
                           catalog_index->name().c_str(),
                           catalogTable.name().c_str());
                delete [] columnNames;
                return false;
            }
            // check if the column does not have an int type
            if ((catalog_colref->column()->type() != VALUE_TYPE_TINYINT) &&
                (catalog_colref->column()->type() != VALUE_TYPE_SMALLINT) &&
                (catalog_colref->column()->type() != VALUE_TYPE_INTEGER) &&
                (catalog_colref->column()->type() != VALUE_TYPE_BIGINT)) {
                isIntsOnly = false;
            }
            index_columns[catalog_colref->index()] = catalog_colref->column()->index();
            column_types[catalog_colref->index()] = (ValueType) catalog_colref->column()->type();
        }

        TableIndexScheme index_scheme(catalog_index->name(),
                                      (TableIndexType)catalog_index->type(),
                                      index_columns,
                                      column_types,
                                      catalog_index->unique(),
                                      isIntsOnly,
                                      schema);
        index_map[catalog_index->name()] = index_scheme;
    }

    // Constraints
    string pkey_index_id;
    map<string, catalog::Constraint*>::const_iterator constraint_iterator;
    for (constraint_iterator = catalogTable.constraints().begin();
         constraint_iterator != catalogTable.constraints().end();
         constraint_iterator++) {
        catalog::Constraint *catalog_constraint = constraint_iterator->second;

        // Constraint Type
        ConstraintType type = (ConstraintType)catalog_constraint->type();
        switch (type) {
            case CONSTRAINT_TYPE_PRIMARY_KEY:
                // Make sure we have an index to use
                if (catalog_constraint->index() == NULL) {
                    VOLT_ERROR("The '%s' constraint '%s' on table '%s' does"
                               " not specify an index",
                               constraintutil::getTypeName(type).c_str(),
                               catalog_constraint->name().c_str(),
                               catalogTable.name().c_str());
                    delete [] columnNames;
                    return false;
                }
                // Make sure they didn't declare more than one primary key index
                else if (pkey_index_id.size() > 0) {
                    VOLT_ERROR("Trying to declare a primary key on table '%s'"
                               "using index '%s' but '%s' was already set as"
                               " the primary key",
                               catalogTable.name().c_str(),
                               catalog_constraint->index()->name().c_str(),
                               pkey_index_id.c_str());
                    delete [] columnNames;
                    return false;
                }
                pkey_index_id = catalog_constraint->index()->name();
                break;
            case CONSTRAINT_TYPE_UNIQUE:
                // Make sure we have an index to use
                // TODO: In the future I would like bring back my Constraint
                //       object so that we can keep track of everything that a
                //       table has...
                if (catalog_constraint->index() == NULL) {
                    VOLT_ERROR("The '%s' constraint '%s' on table '%s' does"
                               " not specify an index",
                               constraintutil::getTypeName(type).c_str(),
                               catalog_constraint->name().c_str(),
                               catalogTable.name().c_str());
                    delete [] columnNames;
                    return false;
                }
                break;
            // Unsupported
            case CONSTRAINT_TYPE_CHECK:
            case CONSTRAINT_TYPE_FOREIGN_KEY:
            case CONSTRAINT_TYPE_MAIN:
                VOLT_WARN("Unsupported type '%s' for constraint '%s'",
                          constraintutil::getTypeName(type).c_str(),
                          catalog_constraint->name().c_str());
                break;
            // Unknown
            default:
                VOLT_ERROR("Invalid constraint type '%s' for '%s'",
                           constraintutil::getTypeName(type).c_str(),
                           catalog_constraint->name().c_str());
                delete [] columnNames;
                return false;
        }
    }

    // Build the index array
    vector<TableIndexScheme> indexes;
    TableIndexScheme pkey_index;
    map<string, TableIndexScheme>::const_iterator index_iterator;
    for (index_iterator = index_map.begin(); index_iterator != index_map.end();
         index_iterator++) {
        // Exclude the primary key
        if (index_iterator->first.compare(pkey_index_id) == 0) {
            pkey_index = index_iterator->second;
        // Just add it to the list
        } else {
            indexes.push_back(index_iterator->second);
        }
    }

    // partition column:
    const catalog::Column* partitionColumn = catalogTable.partitioncolumn();
    int partitionColumnIndex = -1;
    if (partitionColumn != NULL) {
        partitionColumnIndex = partitionColumn->index();
    }

    if (pkey_index_id.size() == 0) {
        int32_t databaseId = catalogDatabase.relativeIndex();
        m_table = TableFactory::getPersistentTable(databaseId, executorContext,
                                                 catalogTable.name(), schema, columnNames,
                                                 indexes, partitionColumnIndex,
                                                 isExportEnabledForTable(catalogDatabase, table_id),
                                                 isTableExportOnly(catalogDatabase, table_id));
    } else {
        int32_t databaseId = catalogDatabase.relativeIndex();
        m_table = TableFactory::getPersistentTable(databaseId, executorContext,
                                                 catalogTable.name(), schema, columnNames,
                                                 pkey_index, indexes, partitionColumnIndex,
                                                 isExportEnabledForTable(catalogDatabase, table_id),
                                                 isTableExportOnly(catalogDatabase, table_id));
    }
    delete[] columnNames;

    m_exportEnabled = isExportEnabledForTable(catalogDatabase, table_id);
    m_table->incrementRefcount();
    return 0;
}
Exemple #5
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'; 
    }
    
}