⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 class.cpp

📁 最新版本!fastdb是高效的内存数据库系统
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//-< CLASS.CPP >-----------------------------------------------------*--------*
// FastDB                    Version 1.0         (c) 1999  GARRET    *     ?  *
// (Main Memory Database Management System)                          *   /\|  *
//                                                                   *  /  \  *
//                          Created:     20-Nov-98    K.A. Knizhnik  * / [] \ *
//                          Last update:  1-Jan-99    K.A. Knizhnik  * GARRET *
//-------------------------------------------------------------------*--------*
// Metaclass information
//-------------------------------------------------------------------*--------*

#define INSIDE_FASTDB

#include "fastdb.h"
#include "compiler.h"
#include "symtab.h"

BEGIN_FASTDB_NAMESPACE

#ifndef CHECK_RECORD_SIZE
#define CHECK_RECORD_SIZE 1
#endif

const size_t MAX_MSG_SIZE = 1024;

dbTableDescriptor* dbTableDescriptor::chain;
dbMutex* dbTableDescriptor::chainMutex;

dbMutex& dbTableDescriptor::getChainMutex() 
{
    if (chainMutex == NULL) { 
        chainMutex = new dbMutex();
    }
    return *chainMutex;
}

void dbTableDescriptor::link()
{
    dbCriticalSection cs(getChainMutex());
    next = chain;
    chain = this;
}
    
void dbTableDescriptor::unlink()
{
    dbCriticalSection cs(getChainMutex());
    dbTableDescriptor **tpp;
    for (tpp = &chain; *tpp != this; tpp = &(*tpp)->next);
    *tpp = next;
}

void* dbFieldDescriptor::operator new(size_t size EXTRA_DEBUG_NEW_PARAMS)
{
    return dbMalloc(size);
}

void  dbFieldDescriptor::operator delete(void* p EXTRA_DEBUG_NEW_PARAMS)
{
    dbFree(p);
}

dbFieldDescriptor::dbFieldDescriptor(char const* name) 
{ 
    next = prev = this;
    this->name = (char*)name;
    longName = NULL;
    dbSymbolTable::add(this->name, tkn_ident, FASTDB_CLONE_ANY_IDENTIFIER);
    appOffs = dbsOffs = 0;
    defTable = refTable = NULL;
    refTableName = NULL;
    components = NULL;
    inverseRefName = NULL;
    inverseRef = NULL;
    indexType = 0;
    method = NULL;
    attr = OneToOneMapping;
    tTree = 0;
    hashTable = 0;
    comparator = (dbUDTComparator)&memcmp;
}


dbFieldDescriptor::dbFieldDescriptor(char const*        fieldName,
                                     size_t             offs, 
                                     size_t             size,
                                     int                index,
                                     char const*        inverse,
                                     dbFieldDescriptor* fieldComponents)
{
    next = prev = this;
    name = (char*)fieldName;
    longName = NULL;
    dbSymbolTable::add(name, tkn_ident, FASTDB_CLONE_ANY_IDENTIFIER);
    appOffs = (int)offs;
    dbsOffs = 0;
    alignment = appSize = dbsSize = (int)size;
    defTable = refTable = NULL;
    refTableName = NULL;
    indexType = index;
    type = appType = dbField::tpStructure;
    inverseRefName = (char*)inverse;
    if (inverseRefName != NULL) { 
        dbSymbolTable::add(inverseRefName, tkn_ident, FASTDB_CLONE_ANY_IDENTIFIER);
    }
    inverseRef = NULL;
    components = fieldComponents;
    method = NULL;
    attr = 0;
    tTree = 0;
    hashTable = 0;
    comparator = (dbUDTComparator)&memcmp;
}

dbFieldDescriptor::~dbFieldDescriptor() 
{
    if (type == dbField::tpString) { 
        delete components;
    } else if (type == dbField::tpStructure) {
        dbFieldDescriptor* last = components->prev;
        while (last->method != NULL) { 
            dbFieldDescriptor* prev = last->prev;
            delete last->method;
            delete last;
            if (last == components) { 
                break;
            }
            last = prev;
        }
    }
    delete[] longName; 
}


dbFieldDescriptor* dbFieldDescriptor::find(const char* name)
{
    dbFieldDescriptor* field = components;
    do { 
        if (field->name == name) { 
            return field;
        }
    } while ((field = field->next) != components);
    return NULL;
}


void dbFieldDescriptor::adjustReferences(byte* record,
                                         size_t base, size_t size, long shift)
{
    dbFieldDescriptor* fd = this;
    do { 
        
        if (fd->type == dbField::tpArray) { 
            byte** ptr = (byte**)((dbAnyArray*)(record + fd->appOffs) + 1);
            if ((unsigned long)*ptr - base <= size) {
                *ptr += shift;
            } else { 
                if (fd->attr & HasArrayComponents) { 
                    int nElems = ((dbAnyArray*)(record+fd->appOffs))->length();
                    byte* arrBase = *ptr;
                    while (--nElems >= 0) { 
                        fd->components->adjustReferences(arrBase, 
                                                         base, size, shift);
                        arrBase += fd->components->appSize;
                    }
                }
            } 
        } else if (fd->type == dbField::tpString) { 
            char** str = (char**)(record + fd->appOffs);
            if ((unsigned long)*str - base <= size) {
                *str += shift;
            }
        } else if (fd->attr & HasArrayComponents) { 
            fd->components->adjustReferences(record + fd->appOffs, 
                                             base, size, shift);
        }
    } while ((fd = fd->next) != this);
}


size_t dbFieldDescriptor::calculateRecordSize(byte* base, size_t offs)
{
    dbFieldDescriptor* fd = this;
    do { 
        switch (fd->appType) { 
          case dbField::tpArray:
            {
                int nElems = ((dbAnyArray*)(base + fd->appOffs))->length();
                offs = DOALIGN(offs, fd->components->alignment)
                    + nElems*fd->components->dbsSize;
                if (fd->attr & HasArrayComponents) { 
                    byte* elem = (byte*)((dbAnyArray*)(base+fd->appOffs))->base();
                    dbFieldDescriptor* component = fd->components;
                    size_t elemSize = component->appSize;
                    while (--nElems >= 0) { 
                        offs = component->calculateRecordSize(elem, offs);
                        elem += elemSize;
                    }
                } 
                continue;
            } 
          case dbField::tpString:
            {
                char* str = *(char**)(base + fd->appOffs);
                if (str != NULL) { 
                    offs += strlen(str) + 1;
                } else { 
                    offs += 1;
                }
                continue;
            }
#ifdef USE_STD_STRING
          case dbField::tpStdString:
            offs += ((std::string*)(base + fd->appOffs))->length() + 1;
            continue;
#endif
          default:
            if (fd->attr & HasArrayComponents) { 
                offs = fd->components->calculateRecordSize(base+fd->appOffs, offs);
            }
        }
    } while ((fd = fd->next) != this);
    return offs;
}



size_t dbFieldDescriptor::calculateNewRecordSize(byte* base, size_t offs) 
{
    dbFieldDescriptor* fd = this;
    do { 
        if (fd->type == dbField::tpArray) { 
            if (fd->oldDbsType == dbField::tpUnknown) { 
                continue;
            }
            int nElems = ((dbVarying*)(base + fd->oldDbsOffs))->size;
            offs = DOALIGN(offs, fd->components->alignment)
                 + nElems*fd->components->dbsSize;
            if (fd->attr & HasArrayComponents) { 
                byte* elem = base + ((dbVarying*)(base+fd->oldDbsOffs))->offs;
                while (--nElems >= 0) { 
                    offs = fd->components->calculateNewRecordSize(elem, offs);
                    elem += fd->components->oldDbsSize;
                }
            } 
        } else if (fd->type == dbField::tpString) { 
            if (fd->oldDbsType == dbField::tpUnknown) { 
                offs += 1;
            } else { 
                offs += ((dbVarying*)(base + fd->oldDbsOffs))->size;
            }
        } else if (fd->attr & HasArrayComponents) {
            offs = fd->components->calculateNewRecordSize(base, offs);
        }
    } while ((fd = fd->next) != this);
    return offs;
}

void dbFieldDescriptor::fetchRecordFields(byte* dst, byte* src)
{
    dbFieldDescriptor* fd = this;
    do { 
        switch (fd->appType) { 
          case dbField::tpBool:
            *(bool*)(dst+fd->appOffs) = *(bool*)(src+fd->dbsOffs);
            break;
          case dbField::tpInt1:
            *(int1*)(dst+fd->appOffs) = *(int1*)(src+fd->dbsOffs);
            break;
          case dbField::tpInt2:
            *(int2*)(dst+fd->appOffs) = *(int2*)(src+fd->dbsOffs);
            break;
          case dbField::tpInt4:
            *(int4*)(dst+fd->appOffs) = *(int4*)(src+fd->dbsOffs);
            break;
          case dbField::tpInt8:
            *(db_int8*)(dst+fd->appOffs) = *(db_int8*)(src+fd->dbsOffs);
            break;
          case dbField::tpReal4:
            *(real4*)(dst+fd->appOffs) = *(real4*)(src+fd->dbsOffs);
            break;
          case dbField::tpReal8:
            *(real8*)(dst+fd->appOffs) = *(real8*)(src+fd->dbsOffs);
            break;
          case dbField::tpRawBinary:
            memcpy(dst+fd->appOffs, src+fd->dbsOffs, fd->dbsSize);
            break;          
          case dbField::tpString:
            *(char**)(dst+fd->appOffs) = 
                (char*)(src + ((dbVarying*)(src+fd->dbsOffs))->offs);
            break;
#ifdef USE_STD_STRING
          case dbField::tpStdString:
            ((std::string*)(dst + fd->appOffs))->assign((char*)(src + ((dbVarying*)(src+fd->dbsOffs))->offs), 
                                                   ((dbVarying*)(src+fd->dbsOffs))->size - 1);
            break;
#endif
          case dbField::tpArray:
            {
                int nElems = ((dbVarying*)(src+fd->dbsOffs))->size;
                byte* srcElem = src + ((dbVarying*)(src+fd->dbsOffs))->offs;
                dbAnyArray* array = (dbAnyArray*)(dst+fd->appOffs);
                if (fd->attr & dbFieldDescriptor::OneToOneMapping) { 
                    fd->arrayAllocator(array, srcElem, nElems);
                } else { 
                    fd->arrayAllocator(array, NULL, nElems);
                    byte* dstElem = (byte*)array->base();
                    dbFieldDescriptor* component = fd->components;
                    while (--nElems >= 0) { 
                        component->fetchRecordFields(dstElem, srcElem);
                        dstElem += component->appSize;
                        srcElem += component->dbsSize;
                    }
                }
            }  
            break;
          case dbField::tpReference:
            ((dbAnyReference*)(dst+fd->appOffs))->oid = 
                *(oid_t*)(src+fd->dbsOffs);
            break;
          case dbField::tpRectangle:
            *(rectangle*)(dst+fd->appOffs) = *(rectangle*)(src+fd->dbsOffs);
            break;
          case dbField::tpStructure:
            fd->components->fetchRecordFields(dst + fd->appOffs, src);
            break;
          default:
            return;
        }
    } while ((fd = fd->next) != this);
}


size_t dbFieldDescriptor::storeRecordFields(byte* dst, byte* src, size_t offs, StoreMode mode)
{
    dbFieldDescriptor* fd = this;
    do { 
#ifdef AUTOINCREMENT_SUPPORT
        if ((fd->indexType & AUTOINCREMENT) != 0) { 
            if (mode == Insert || (mode == Import && *(int4*)(src+fd->appOffs) == 0)) { 
                assert (fd->appType == dbField::tpInt4);
                *(int4*)(dst+fd->dbsOffs) = *(int4*)(src+fd->appOffs) = fd->defTable->autoincrementCount;
                continue;
            } else if (mode == Import) { 
                if (*(int4*)(src+fd->appOffs) > fd->defTable->autoincrementCount) {
                    fd->defTable->autoincrementCount = *(int4*)(src+fd->appOffs);
                } 
            }
        }
#endif
        switch (fd->appType) { 
          case dbField::tpBool:
            *(bool*)(dst+fd->dbsOffs) = *(bool*)(src+fd->appOffs);
            break;
          case dbField::tpInt1:
            *(int1*)(dst+fd->dbsOffs) = *(int1*)(src+fd->appOffs);
            break;
          case dbField::tpInt2:
            *(int2*)(dst+fd->dbsOffs) = *(int2*)(src+fd->appOffs);
            break;
          case dbField::tpInt4:
            *(int4*)(dst+fd->dbsOffs) = *(int4*)(src+fd->appOffs);
            break;
          case dbField::tpInt8:
            *(db_int8*)(dst+fd->dbsOffs) = *(db_int8*)(src+fd->appOffs);
            break;
          case dbField::tpReal4:
            *(real4*)(dst+fd->dbsOffs) = *(real4*)(src+fd->appOffs);
            break;
          case dbField::tpReal8:
            *(real8*)(dst+fd->dbsOffs) = *(real8*)(src+fd->appOffs);
            break;      
          case dbField::tpRawBinary:
            memcpy(dst+fd->dbsOffs, src+fd->appOffs, fd->dbsSize);
            break;          
#ifdef USE_STD_STRING
          case dbField::tpStdString:
            { 
                ((dbVarying*)(dst+fd->dbsOffs))->offs = offs;
                std::string* str = (std::string*)(src + fd->appOffs);
                int len = str->length();
                str->copy((char*)dst + offs, len);
                dst[offs + len] = '\0';
                ((dbVarying*)(dst+fd->dbsOffs))->size = len+1;
                offs += (len+1);
            }
            break;
#endif
          case dbField::tpString:
            {
                ((dbVarying*)(dst+fd->dbsOffs))->offs = offs;
                char* str = *(char**)(src + fd->appOffs);
                if (str != NULL) { 
                    strcpy((char*)dst + offs, str);
                    offs += ((dbVarying*)(dst+fd->dbsOffs))->size = strlen(str) + 1;
                } else { 
                    *((char*)dst + offs) = '\0';
                    ((dbVarying*)(dst+fd->dbsOffs))->size = 1;
                    offs += 1;
                }
            }
            break;
          case dbField::tpArray:
            {
                int nElems = ((dbAnyArray*)(src + fd->appOffs))->length();
                byte* srcElem=(byte*)((dbAnyArray*)(src+fd->appOffs))->base();
                offs = DOALIGN(offs, fd->components->alignment);
                byte* dstElem = dst+offs;
                ((dbVarying*)(dst+fd->dbsOffs))->size = nElems;
                ((dbVarying*)(dst+fd->dbsOffs))->offs = offs;
                size_t sizeElem = fd->components->dbsSize;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -