Beispiel #1
0
EbUint8 *
EbRecord::LocateEncodedField(EbUint32 fid)
{
    // check fid
    EB_ASSERT(fid < NumberOfFields());
    EB_ASSERT(_pRecordData != NULL);

    EbUint8 * field = _pRecordData +
	PADDED_SIZE(NumberOfFields()*sizeof(EncodedFieldSize), 4);
    for (EbUint32 i=0; i< fid; i++) {
	field += PADDED_SIZE(((EncodedFieldSize*)_pRecordData)[i], 4);
    }
    return field;
}
Beispiel #2
0
/***********************************************************************
 * void Ebase::DeleteRecord()
 ***********************************************************************
 */
void
Ebase::DeleteRecord(EbRecord *pRecord)
{
    EbUint32 i;

    // check record validity
    if (pRecord == NULL || pRecord->_pEbase != this) {
		EB_ASSERT (0 == "EBE_INVALID_RECORD");
    }

    // check if it is a new record status
    if (pRecord->_pRecordData == NULL) {
		EB_ASSERT(pRecord->_handle == EB_INVALID_HANDLE);
		EB_ASSERT(*((EbInt32*)pRecord->_lField[RECORD_ID_INDEX]._decodedData) ==
			   NEW_RECORD_ID);

		// free memory space occupied by the record
		delete pRecord;
		return;
    }

    // this is an existing record

    EB_ASSERT(pRecord->_handle != EB_INVALID_HANDLE);
    EB_ASSERT(pRecord->_lField[RECORD_ID_INDEX]._decodedData == NULL ||
		   *((EbInt32*)pRecord->_lField[RECORD_ID_INDEX]._decodedData) !=
		   NEW_RECORD_ID);

    // we need to free the file space it occupies

    // free file space occupied by field data
    EbUint8* pField = pRecord->_pRecordData +
		PADDED_SIZE(_dbDef->NumberOfFields()*sizeof(EncodedFieldSize), 4);
//    EncodedFieldSize *& fieldSize = pRecord->_pRecordData;
    EncodedFieldSize * pFieldSize = (EncodedFieldSize*)pRecord->_pRecordData;
    for(i=0; i< _dbDef->NumberOfFields(); i++) {
//		_lpDataDriver[i]->FreeEncodedData(pField, fieldSize[i],_file);
//		pField += PADDED_SIZE(fieldSize[i], 4);
        _lpDataDriver[i]->FreeEncodedData(pField, pFieldSize[i],_file);
        pField += PADDED_SIZE(pFieldSize[i], 4);
    }

    // remove from the index entry array
//    for(i=0; i< _indexDefWrapper->Size(); i++) {
    _Int32IndexEntry->GetHandleArray()->Delete(
        _Int32IndexEntry->GetHandleArray()->Find(pRecord->_handle));
//    }

    // free the file space occupied by the record
    _file->DeleteData(pRecord->_handle);

    // adjust ebase state
    _hdr._numRecords --;

    // save index entries
    SaveHeader();
    SaveIndexEntries();

    // free the memory
    delete pRecord;
}
Beispiel #3
0
void
Ebase::AddNewRecord(EbRecord *pRecord)
{
    EB_ASSERT(_Int32IndexEntry->IsValid() == EB_TRUE);

    EbUint32 i;

    EbUint32 numFinishedFields, numFinishedIndices;

    EbErrorEnum error;

    // contain the encoded record data for the new record
    EbUint8 * pNewRecordData;

    // handle used to store the new record
    EbDataHandle newRecordHandle;

    EbUint32 numFields = pRecord->_pEbase->_dbDef->NumberOfFields();

    EbUint32 newRecordSize;

    // check if pRecord is created by this ebase
    if (pRecord->_pEbase != this)
    {
        EB_ASSERT (0 == "EBE_INVALID_RECORD");
    }

    // check if it is a new record
    EbInt32 *pRecordID = (EbInt32*)pRecord->_lField[RECORD_ID_INDEX]._decodedData;
    EB_ASSERT(*pRecordID == NEW_RECORD_ID);

    // set the record id
    *pRecordID = _hdr._nextRecordID;

    // calculate the new record size
    newRecordSize = PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
    for (i=0; i< numFields; i++) {
        EbUint32 size;
        DataDriver * pDriver = pRecord->_pEbase->_lpDataDriver[i];
        size = pDriver->EncodedDataSize(pRecord->_lField[i]._decodedData);
        EB_ASSERT(size <= EB_MAX_ENCODED_FIELD_SIZE);
        newRecordSize += PADDED_SIZE(size, 4);
    }

    // (res alloc #1) allocate memory to hold the new record
    pNewRecordData = new EbUint8[newRecordSize];
    if (pNewRecordData == NULL) {
        error = EBE_OUT_OF_MEMORY;
        goto bailout;
    }

    // (res alloc #2) allocate file space for the record
    // For existing record, we will re-use the same space if the new
    // record size is no greater than the old record size.
    newRecordHandle = _file->NewData(newRecordSize);
    if (newRecordHandle == EB_INVALID_HANDLE) {
        error = EBE_OUT_OF_FILE_SPACE;
        goto bailout_1;
    }

    //
    // (res alloc #3) encode data.  Some file space may be allocated in this
    //	step.
    //
    {
        // get the start of the field data area in the record data
        EbUint8 *pNewField =
            pNewRecordData +
            PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
//        EncodedFieldSize *& newEncodedFieldSize = pNewRecordData;
        EncodedFieldSize * pNewEncodedFieldSize = (EncodedFieldSize*)pNewRecordData;
        for (i=0; i< numFields; i++) {
            DataDriver * pDriver = pRecord->_pEbase->_lpDataDriver[i];
            EbUint32 size;
            pDriver->Encode(pRecord->_lField[i]._decodedData,
                            pNewField,
                            size,
                            EB_FALSE,
                            _file);
            EB_ASSERT(size <= EB_MAX_ENCODED_FIELD_SIZE);
//            newEncodedFieldSize[i] = (EncodedFieldSize)size;
            pNewEncodedFieldSize[i] = (EncodedFieldSize)size;

            // advance pField
            pNewField += PADDED_SIZE(size, 4);

        }
    }
    // for later error recovery
    numFinishedFields = numFields;

    //
    // (res alloc #4)
    // We sort the records.  For the new record case, we need to expand
    // index entry arrays.
    //

    // (res alloc #4_1) sort record id index - an optimization
    // A new record is always the last in the record ID index.
    numFinishedIndices = 0;
    if (_Int32IndexEntry->GetHandleArray()->Append(newRecordHandle) == EB_FAILURE) {
        error = EBE_OUT_OF_MEMORY;
        goto bailout_3;
    }

//    // (res alloc #4_2) for other indices

    numFinishedIndices = 1; //_Int32IndexEntry->IsValid() == EB_TRUE ? 1 : 0;

    //
    // (res alloc #5) reserve file space for the expanded index entry arrays
    //
    if (_Int32IndexEntry->ReserveSpace(*_file, _hdr._indexEntryHandle) == EB_FAILURE) {
        error = EBE_OUT_OF_FILE_SPACE;
        goto bailout_4;
    }

    // commit the record
    _file->WriteData(newRecordHandle, pNewRecordData);


    // adjust record state
    pRecord->_handle = newRecordHandle;
    pRecord->_pRecordData = pNewRecordData;
    for (i=0; i< numFields; i++) {
        EB_ASSERT(pRecord->_lField[i]._changed == EB_TRUE);
        pRecord->_lField[i]._changed = EB_FALSE;
        pRecord->_lField[i]._decoded = EB_TRUE;
    }

    // adjust ebase state
    _hdr._nextRecordID++;
    _hdr._numRecords++;

    // save & return
    // NOTE : we don't have to save index entries here since they can
    // be recovered.  But right now, we don't provide recovery and
    // we want to be a little convservative.
    SaveHeader();
    SaveIndexEntries();
    return;

bailout_4:
    //for (i=0; i< numFinishedIndices; i++) {
    if (numFinishedIndices == 1)
    {
        EbInt32 pos = _Int32IndexEntry->GetHandleArray()->Find(pRecord->_handle);
        EB_ASSERT(pos >= 0);
        _Int32IndexEntry->GetHandleArray()->Delete((EbUint32)pos);
    }

    // we just shrunk the array.  space reservation should be OK
    EB_VERIFY(_Int32IndexEntry->ReserveSpace(*_file, _hdr._indexEntryHandle),
           == EB_SUCCESS);

bailout_3:
    // free resources allocated during data encoding
    {
        EbUint8 *pNewField =
            pNewRecordData +
            PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
//        EncodedFieldSize *& newEncodedFieldSize = pNewRecordData;
        EncodedFieldSize * pNewEncodedFieldSize = (EncodedFieldSize*)pNewRecordData;
        for (EbUint32 j=0; j< numFinishedFields; j++) {
            if (pRecord->_lField[i]._changed == EB_TRUE) {
                DataDriver * pDriver = pRecord->_pEbase->_lpDataDriver[i];
                pDriver->FreeEncodedData(pNewField,
//                                         newEncodedFieldSize[i],
                                         pNewEncodedFieldSize[i],
                                         _file);
            }
//            pNewField += PADDED_SIZE(newEncodedFieldSize[i], 4);
            pNewField += PADDED_SIZE(pNewEncodedFieldSize[i], 4);
        }
    }

    /*bailout_2:*/
    _file->DeleteData(newRecordHandle);

bailout_1:
    delete[] pNewRecordData;

bailout:
    {
        EbError e(error);
        printf ("error: %s\n\n", e.GetStringName ());
        EB_ASSERT (0 == 1);
    }
}
Beispiel #4
0
//
// Modify an existing record :
//	1. calculate the new record size
//	2. allocate memory to hold the record
//	3. if the new size is bigger, we need to allocate a new data handle
//	4. encode all modified field data
//	5. re-sort indcies (no allocation is needed)
//	6. adjust record states, free old resources
//
void
Ebase::ModifyRecord(EbRecord *pRecord)
{
    // check the record is valid and is an existing record
    EB_ASSERT(pRecord != NULL);
    EB_ASSERT(pRecord->_lField[RECORD_ID_INDEX]._changed == EB_FALSE);
    EB_ASSERT(pRecord->_lField[RECORD_ID_INDEX]._decoded == EB_FALSE ||
           *(EbInt32*)pRecord->_lField[RECORD_ID_INDEX]._decodedData !=
           NEW_RECORD_ID);
    EB_ASSERT(pRecord->_handle != EB_INVALID_HANDLE);

    // check if pRecord is created by this ebase
    if (pRecord->_pEbase != this)
    {
        EB_ASSERT (0 == "EBE_INVALID_RECORD");
    }

    // local variables
    EbErrorEnum error;
    EbUint32 newRecordSize, oldRecordSize;
    EbUint8 * pNewRecordData;
    EbDataHandle newRecordHandle;
    EbUint32 numFinishedFields;
    EbUint32 i;
    EbUint32 numFields = _dbDef->NumberOfFields();
//    EncodedFieldSize *& oldFieldSize = pRecord->_pRecordData;
    EncodedFieldSize ** ppOldFieldSize = (EncodedFieldSize **)&(pRecord->_pRecordData);

    // get the old record size
    oldRecordSize = _file->DataSize(pRecord->_handle);

    // calculate the new record size
    newRecordSize = PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
    for (i=0; i< numFields; i++) {
        DataDriver * pDriver = pRecord->_pEbase->_lpDataDriver[i];
        if (pRecord->_lField[i]._changed == EB_TRUE) {
            // this is new data
            EbUint32 size =
                pDriver->EncodedDataSize(pRecord->_lField[i]._decodedData);
            EB_ASSERT(size <= EB_MAX_ENCODED_FIELD_SIZE);
            newRecordSize += PADDED_SIZE(size, 4);
        } else {
            // this the old data
//            newRecordSize += PADDED_SIZE(oldFieldSize[i], 4);
            newRecordSize += PADDED_SIZE((*ppOldFieldSize)[i], 4);
        }
    }

    // (res alloc #1) allocate memory to hold the new record
    pNewRecordData = new EbUint8[newRecordSize];
    if (pNewRecordData == NULL) {
        error = EBE_OUT_OF_MEMORY;
        goto bailout;
    }

    // (res alloc #2) allocate file space for the record
    // For existing record, we will re-use the same space if the new
    // record size is no greater than the old record size.
    if (newRecordSize > oldRecordSize) {
        newRecordHandle = _file->NewData(newRecordSize);
        if (newRecordHandle == EB_INVALID_HANDLE) {
            error = EBE_OUT_OF_FILE_SPACE;
            goto bailout_1;
        }
    } else {
        newRecordHandle = pRecord->_handle;
    }

    // (res alloc #3) Build the new record and encode any modified field
    // File space may be allocated when encoding field data
    {
        EbUint8 *pOldField =
            pRecord->_pRecordData +
            PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
        EbUint8 *pNewField =
            pNewRecordData +
            PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
//        EncodedFieldSize *& newFieldSize = pNewRecordData;
        EncodedFieldSize *pNewFieldSize = (EncodedFieldSize*)pNewRecordData;
        for (i=0; i< numFields; i++) {
            numFinishedFields = i;
            if (pRecord->_lField[i]._changed == EB_TRUE) {
                // this is new data
                DataDriver * pDriver = pRecord->_pEbase->_lpDataDriver[i];
                EbUint32 size;
                pDriver->Encode(pRecord->_lField[i]._decodedData,
                                pNewField,
                                size,
                                EB_FALSE,
                                _file);
                EB_ASSERT(size <= EB_MAX_ENCODED_FIELD_SIZE);
                pNewFieldSize[i] = (EncodedFieldSize)size;

                // advance pField
                pNewField += PADDED_SIZE(size, 4);
//                pOldField += PADDED_SIZE(oldFieldSize[i], 4);
                pOldField += PADDED_SIZE((*ppOldFieldSize)[i], 4);

            } else {
                // this is the old data.  We just copy it.
//                memcpy(pNewField, pOldField, oldFieldSize[i]);
//                newFieldSize[i] = oldFieldSize[i];
                memcpy(pNewField, pOldField, (*ppOldFieldSize)[i]);
                pNewFieldSize[i] = (*ppOldFieldSize)[i];

                // advance pField
//                pNewField += PADDED_SIZE(oldFieldSize[i], 4);
//                pOldField += PADDED_SIZE(oldFieldSize[i], 4);
                pNewField += PADDED_SIZE((*ppOldFieldSize)[i], 4);
                pOldField += PADDED_SIZE((*ppOldFieldSize)[i], 4);
            }
        }
    }

    numFinishedFields = numFields;

    // we still need to replace the old handle with
    // possibly a new handle
    {
        EbUint32 oldPos_0 = _Int32IndexEntry->GetHandleArray()->Find(pRecord->_handle);

        _Int32IndexEntry->Get(oldPos_0) = newRecordHandle;
    }

    // sort indices
    //  1. find the current position of the record
    //  2. find the new position of the record with modified fields
    //  3. move from old position to the new position.
    //
    // this step does not have any bailout handling.  so no step after
    // this can fail (for now).


    // commit writing the record.  This may make the original
    // record non-retrievable.  So nothing after this step
    // should cause failure.
    _file->WriteData(newRecordHandle, pNewRecordData);

    // free old resources
    {
        EbUint8 *pField =
            pRecord->_pRecordData +
            PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
        for (i=0; i< numFields; i++) {
            if (pRecord->_lField[i]._changed == EB_TRUE) {
                DataDriver * pDriver = pRecord->_pEbase->_lpDataDriver[i];
                pDriver->FreeEncodedData(pField,
//                                         oldFieldSize[i],
                                         (*ppOldFieldSize)[i],
                                         _file);
            }
//            pField += PADDED_SIZE(oldFieldSize[i], 4);
            pField += PADDED_SIZE((*ppOldFieldSize)[i], 4);
        }
    }
    if (pRecord->_handle != newRecordHandle) {
        _file->DeleteData(pRecord->_handle);
    }
    delete[] pRecord->_pRecordData;

    // adjust record state
    pRecord->_handle = newRecordHandle;
    pRecord->_pRecordData = pNewRecordData;
    for (i=0; i< numFields; i++) {
        if(pRecord->_lField[i]._changed == EB_TRUE) {
            pRecord->_lField[i]._changed = EB_FALSE;
            pRecord->_lField[i]._decoded = EB_TRUE;
        }
    }

    // save index entries and return
    SaveHeader();
    SaveIndexEntries();
    return;

//bailout_3:
    // free resources allocated during data encoding
    {
        EbUint8 *pNewField =
            pNewRecordData +
            PADDED_SIZE(numFields*sizeof(EncodedFieldSize), 4);
//        EncodedFieldSize *& newEncodedFieldSize = pNewRecordData;
        EncodedFieldSize *pNewEncodedFieldSize = (EncodedFieldSize*)pNewRecordData;
        for (EbUint32 j=0; j< numFinishedFields; j++) {
            if (pRecord->_lField[i]._changed == EB_TRUE) {
                DataDriver * pDriver = pRecord->_pEbase->_lpDataDriver[i];
                pDriver->FreeEncodedData(pNewField,
//                                         newEncodedFieldSize[i],
                                         pNewEncodedFieldSize[i],
                                         _file);
            }
//            pNewField += PADDED_SIZE(newEncodedFieldSize[i], 4);
            pNewField += PADDED_SIZE(pNewEncodedFieldSize[i], 4);
        }
    }

    /*bailout_2: */
    if (newRecordSize > oldRecordSize) {
        EB_ASSERT(newRecordHandle != pRecord->_handle);
        _file->DeleteData(newRecordHandle);
    }

bailout_1:
    delete[] pNewRecordData;

bailout:
    EB_ASSERT (0 == "EBE_OUT_OF_MEMORY");
}
Beispiel #5
0
/*
 * MPALMOSTSAFE
 */
int
sys_ogetdirentries(struct ogetdirentries_args *uap)
{
    int error, bytes_transfered;
    char *buf, *outbuf;
    size_t len;
    struct dirent *ndp;
    struct odirent *destdp;
    long base;

    if (uap->count > 16384)
        len = 16384;
    else
        len = uap->count;

    buf = kmalloc(len, M_TEMP, M_WAITOK);

    get_mplock();
    error = kern_getdirentries(uap->fd, buf, len,
                               &base, &bytes_transfered, UIO_SYSSPACE);
    rel_mplock();

    if (error) {
        kfree(buf, M_TEMP);
        return(error);
    }

    ndp = (struct dirent *)buf;
    outbuf = uap->buf;
    destdp = kmalloc(PADDED_SIZE(MAX_NAMELEN), M_TEMP, M_WAITOK);

    for (; (char *)ndp < buf + bytes_transfered; ndp = _DIRENT_NEXT(ndp)) {
        if ((char *)_DIRENT_NEXT(ndp) > buf + bytes_transfered)
            break;
        if (ndp->d_namlen > MAX_NAMELEN)
            continue;
        destdp->od_fileno = ndp->d_ino;
#if BYTE_ORDER == LITTLE_ENDIAN
        destdp->od_type = ndp->d_namlen;
        destdp->od_namlen = ndp->d_type;
#else
        destdp->od_type = ndp->d_type;
        destdp->od_namlen = ndp->d_namlen;
#endif
        destdp->od_reclen = PADDED_SIZE(destdp->od_namlen);
        if (destdp->od_reclen > len)
            break; /* XXX can not happen */
        bcopy(ndp->d_name, destdp->od_name, destdp->od_namlen);
        bzero(destdp->od_name + destdp->od_namlen,
              PADDED_SIZE(destdp->od_namlen) - sizeof(*destdp) -
              destdp->od_namlen);
        error = copyout(destdp, outbuf,
                        PADDED_SIZE(destdp->od_namlen));
        if (error)
            break;
        outbuf += PADDED_SIZE(destdp->od_namlen);
        len -= PADDED_SIZE(destdp->od_namlen);
    }

    kfree(destdp, M_TEMP);
    kfree(buf, M_TEMP);
    uap->sysmsg_iresult = (int)(outbuf - uap->buf);
    return (0);
}