norian: (Default)
во второй ледниковый период морозов уже нет, но снега сыпет как не в себя, уже метра полтора местами

когда всё это растает, деревню котюкино смоет
может быть

вообще к следующей зиме надо будет перестраивать внутреннюю нору, утепляя во всех возможных местах, переделать окна, прикрутить на крышу пару скоб снегозадержания чтобы трубы не сносило и во внутренние стены тоже добавить утеплителя

коты тут подумали что правильное приспособление чтобы спать должно представлять собой поверхность второго порядка как минимум
с каким-нть хитрым отверстием через которое можно высовывать дыхательный хобот во все стороны
потому что плоское одеяло невозможно преобразовать так, чтобы не было складок, через которые начинает хреначить холодный воздух
а та поверхность которая снизу не должна приминацца, но это уже опцыональные мелочи

ещё немножко и коты перестанут прокрастинировать и продолжать фигачить отвёртку с моторчегом, как тот снег как не в себя
может быть
norian: (Default)
ещё одна годовщина сказочного каминг-аута отмечена, и запас днищ на пробитие походу не ограничен ничем

бакшевскую масэлэницу (большой некоммерческий зимний арт-фестиваль под нерезиновском) разогнали методом оцепления полицаями понастроенных из снега артобъектов

коты туда не ездили с тех пор, когда там начала громко радовацца каминг-ауту зомбанутая вата, составляющая не абсолютное большинство, но громкую и поэтому заметную часть (большинство обычные мордорские двуногие бараны)
norian: (Default)
настала оттепель, астрологи объявили неделю жестянщега-травматолога

наросший за первый ледниковый период слой льда на крыше рухнул и по пути снёс нах трубу кухонной вытяжки нах

теперь надо будет делать какую-нть хрень для залезания на крышу и как-нть чинить, четыре метра по тонкому воздуху прямо вверх тот ещё челлендж, и ещё какую-нть хрень на следующую зиму на крыше сделать чтобы предотвратить и не пущать всё это безобразие

завтра обещают вторую серию ледникового периода, для тех кому с первого раза не дошло почемуто

в йапонии меж тем день дарения шоколадок самцам которые в модельной реальности кажуцца подходящими для, у котариума конечно про это естьчо, как правильно упаковывать красными ленточгами под микс симфонического оркестра с гитарными запилами

norian: (Default)
день котурка N+1

внешнюю нору засыпало хде-то метровым слоем снега и минус 20 цельсиуса

котёл раскочегарен до 75, поэтому во внутренней норе хде-то 15 цельсиуса, если обмотацца вокруг батареи, то ничо

летом внутреннюю нору надо будет как-то покрыть толстым слоем стекловаты

в качестве физических упражнений коты копают траншеи в снегу чтобы можно было пойти за едой иногда

через несколько дней обещают оттепель, через месяц наверно все эти ужосы кончацца и вместо дикого количества снегу будет море воды - интересно, смоет ли деревню котюкино совсем или только местами
norian: (Default)
"Neocities founder Kyle Drake has spent weeks trapped in Microsoft's automated support loop after discovering that Bing quietly blocked all 1.5 million websites hosted on his platform, a free web-hosting service since 2013. Drake first noticed the issue last summer and thought it was resolved, but a second complete block went into effect in January, cratering Bing traffic from roughly half a million daily visitors to zero. He submitted nearly a dozen tickets through Bing's webmaster tools but could not get past the AI chatbot to reach a human. After Ars Technica contacted Microsoft, the company restored the Neocities front page within 24 hours but most subdomains remain blocked. Microsoft cited policy violations related to low-quality content yet declined to identify the offending sites or work directly with Drake to fix the problem"

походу самая выгодная профессия будущего - решалы, которые добывают телефоны и адреса случайно оставшихся в техподдержках двуногих
norian: (Default)
Гибридная Графовая База Данных (отвертка с моторчиком для моделирования моделей)

День 9. Доработка тестов и планы на будущее.

Это конечно не полноценные юниттесты с 146% кавереджем, но лучше чтобы основная функциональность постоянно тестировалась, чем не тестировалась и разводила в своих внутренностях регрессии. Помимо вышеупомянутых тестов для некоторых вспомогательных модулей, добавлены тесты для операций с узлами данных (добавление, редактирование, удаление), а также тесты для линков и индексов.

Весь код из локального репозитория закачан на гитхаб (https://github.com/norian-n/nekodb).

Дальнейшие шаги: демо приложение для обкатки двигла на как бы практических задачах, добавление требуемой для этого приложения функциональности и рефакторинг понаписанного. Рефакторинг является необходимым методом для повышения качества софта. Он направлен на уменьшение количества кода и перенос дополнительной функциональности в отдельные плагины, чтобы в основных модулях оставалась только самая необходимая функциональность в самом рациональном виде. Это постоянный итеративный процесс небольших изменений, который заканчивается только с гибелью системы под собственной тяжестью.

Процесс сборки всего и запуска тестов выглядит так:

> ./all_tests.sh 
============ build lib and test apps ============
g++ -fPIC -std=c++20  -c service/egByteArray.cpp -o service/egByteArray.o
g++ -fPIC -std=c++20  -c nodes/egDataNodesType.cpp -o nodes/egDataNodesType.o
g++ -fPIC -std=c++20  -c nodes/egDataNodesLocalFile.cpp -o nodes/egDataNodesLocalFile.o
g++ -fPIC -std=c++20  -c nodes/egDataNodesContainer.cpp -o nodes/egDataNodesContainer.o
g++ -fPIC -std=c++20  -c nodes/egDataNodeBlueprint.cpp -o nodes/egDataNodeBlueprint.o
g++ -fPIC -std=c++20  -c nodes/egDataNode.cpp -o nodes/egDataNode.o
g++ -fPIC -std=c++20  -c indexes/egIndexes.cpp -o indexes/egIndexes.o
g++ -fPIC -std=c++20  -c indexes/egIndexConditions.cpp -o indexes/egIndexConditions.o
g++ -fPIC -std=c++20  -c indexes/egFingers.cpp -o indexes/egFingers.o
g++ -fPIC -std=c++20  -c links/egLinksType.cpp -o links/egLinksType.o
g++ -fPIC -std=c++20  -c links/egFlexLinksType.cpp -o links/egFlexLinksType.o
g++ -fPIC -std=c++20  -c metainfo/egLayersType.cpp -o metainfo/egLayersType.o
g++ -fPIC -std=c++20  -c metainfo/egDatabaseType.cpp -o metainfo/egDatabaseType.o
g++ -shared -o libegdb.so service/egByteArray.o nodes/egDataNodesType.o nodes/egDataNodesLocalFile.o nodes/egDataNodesContainer.o nodes/egDataNodeBlueprint.o nodes/egDataNode.o indexes/egIndexes.o indexes/egIndexConditions.o indexes/egFingers.o links/egLinksType.o links/egFlexLinksType.o metainfo/egLayersType.o metainfo/egDatabaseType.o
=============== Finished compilation of libegdb.so ===============
-rwxrwxr-x  1068760 libegdb.so
=============== clean ===============
rm -f service/egByteArray.o nodes/egDataNodesType.o nodes/egDataNodesLocalFile.o nodes/egDataNodesContainer.o nodes/egDataNodeBlueprint.o nodes/egDataNode.o indexes/egIndexes.o indexes/egIndexConditions.o indexes/egFingers.o links/egLinksType.o links/egFlexLinksType.o metainfo/egLayersType.o metainfo/egDatabaseType.o
g++   -std=c++20  -c tests/testDataNodesLocalFile.cpp -o tests/testDataNodesLocalFile.o
g++  tests/testDataNodesLocalFile.o -L. -legdb -o tests/testDataNodesLocalFile.exe
g++   -std=c++20  -c tests/testFlexLinks.cpp -o tests/testFlexLinks.o
g++  tests/testFlexLinks.o -L. -legdb -o tests/testFlexLinks.exe
g++   -std=c++20  -c tests/testGeneralOps.cpp -o tests/testGeneralOps.o
g++  tests/testGeneralOps.o -L. -legdb -o tests/testGeneralOps.exe
g++   -std=c++20  -c tests/testDataNodesContainer.cpp -o tests/testDataNodesContainer.o
g++  tests/testDataNodesContainer.o -L. -legdb -o tests/testDataNodesContainer.exe
g++   -std=c++20  -c tests/testIndexesUsage.cpp -o tests/testIndexesUsage.o
g++  tests/testIndexesUsage.o -L. -legdb -o tests/testIndexesUsage.exe
g++   -std=c++20  -c tests/testDataNodeBlueprint.cpp -o tests/testDataNodeBlueprint.o
g++  tests/testDataNodeBlueprint.o -L. -legdb -o tests/testDataNodeBlueprint.exe
g++   -std=c++20  -c tests/testFingers.cpp -o tests/testFingers.o
g++  tests/testFingers.o -L. -legdb -o tests/testFingers.exe
g++   -std=c++20  -c tests/testBasicOps.cpp -o tests/testBasicOps.o
g++  tests/testBasicOps.o -L. -legdb -o tests/testBasicOps.exe
g++   -std=c++20  -c tests/testLinks.cpp -o tests/testLinks.o
g++  tests/testLinks.o -L. -legdb -o tests/testLinks.exe
g++   -std=c++20  -c tests/testIndexes.cpp -o tests/testIndexes.o
g++  tests/testIndexes.o -L. -legdb -o tests/testIndexes.exe
g++   -std=c++20  -c tests/testDataFields.cpp -o tests/testDataFields.o
g++  tests/testDataFields.o -L. -legdb -o tests/testDataFields.exe
g++   -std=c++20  -c tests/testLayers.cpp -o tests/testLayers.o
g++  tests/testLayers.o -L. -legdb -o tests/testLayers.exe
tests/testDataNodesLocalFile.exe tests/testFlexLinks.exe tests/testGeneralOps.exe tests/testDataNodesContainer.exe tests/testIndexesUsage.exe tests/testDataNodeBlueprint.exe tests/testFingers.exe tests/testBasicOps.exe tests/testLinks.exe tests/testIndexes.exe tests/testDataFields.exe tests/testLayers.exe
=============== Finished compilation of tests ===============
rm -f tests/testDataNodesLocalFile.o tests/testFlexLinks.o tests/testGeneralOps.o tests/testDataNodesContainer.o tests/testIndexesUsage.o tests/testDataNodeBlueprint.o tests/testFingers.o tests/testBasicOps.o tests/testLinks.o tests/testIndexes.o tests/testDataFields.o tests/testLayers.o
rm -f tests/*.o
rm -f *.o
============ run test apps ============
initDatabase() not found metadata storage, create new: egNodesTypesMetainfo
initDatabase() not found metadata storage, create new: egLinksTypesMetainfo
initDatabase() not found metadata storage, create new: egLayersTypesMetainfo
===== Test basic database ops  =====
PASS
===== Test length convertor ( 123456789 ) =====
byteCountIn: 4 byteCountOut: 4 testLength: 123456789
===== Test hamSlicer =====
PASS
===== Test DataNodeBlueprint (2 errors must appear in negative tests)  =====
ERROR: AddIndex() for DataNodeBlueprint: "testNodes" field name "bad index name" not found
ERROR: Can't add field "try to add field after commit" to DataNodeBlueprint: "testNodes". Call BlueprintInitStart() first
PASS
===== Test NodesContainerType  =====
PASS
===== Test egDataNodeLocalFile =====
PASS
===== Test EgFingers Stage 1 =====
PASS
===== Test EgFingers Stage 2 =====
PASS
===== Test EgFreeLinksType =====
PASS
===== Test general database ops  =====
PASS
===== Test EgIndexes  =====
PASS
===== Test indexes ops  =====
PASS
===== Test EgLayersType =====
PASS
===== Test EgLinksType =====
PASS

PASS total: 13
FAIL total: 0

norian: (Default)
в большую войну город грибоград был прифронтовым, со всеми ужосами бычи прифронтовым городом для обитателей

но блокады там не было - речным транспортом можно было привезти любое количество еды и прочих ништяков при приложении достаточных усилий

только жрецам грибофараона было насрать на их рабов, и достаточное количество еды и ништяков они привозили только верхушке своей грибофараоновой иерархии и военным, которые удерживали позиции на болотах, а прочие жытели дохли от голода и холода и промышляли каннибализьмом

с точки зрения обычного помоешного кота это йобаный стыд, который лучше замести под коврег и не вспоминать никогда, а не повод для пафосного надрачивания из всех инфоутюгов
norian: (Default)
Гибридная Графовая База Данных (отвертка с моторчиком для моделирования моделей)

День 8. Индексы : дерево поиска, фингеры.

Можно было бы сделать унылое красно-черное бинарное дерево, но лучше попробовать дерево с чанками, которые для улучшения производительности помещаются в кэшлайн подобно чанком цепи индексов. Это называется "n-ary tree" или "m-ary tree" или "N-M tree" в зависимости от фазы луны.

Каждый элемент узлового чанка (ака фингер) содержит минимальный ключ, максимальный ключ и указатель на чанк цепи индексов или чанк дерева поиска. Для унификации операций используются функции-предикаты, которые передаются в качестве параметра.

source egFingers.h

#pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include "egCoreIndexTypes.h"
#include "../service/egByteArray.h"
#include "../service/egFileType.h"
template <typename KeyType> class EgIndexes;
// Finger in the file: KeyMin KeyMax nextChunkOffset isLeaf(root only)
// Chunk in the file:  FingersArray parentFingerOffset chunkIsLeaf fingersCount 
template <typename KeyType> class EgFingers { public: // fingers tree (N-M type) part of indexes-fingers complex
    const egMaxStreamSizeType nextChunkOffsetPosition  = sizeof(KeyType) * 2; //  + sizeof(keysCountType); 
    const egMaxStreamSizeType oneFingerSize        = nextChunkOffsetPosition + sizeof(uint64_t);  // last is next chunk offset
    const egMaxStreamSizeType rootHeaderSize       = oneFingerSize + sizeof(uint8_t); // bool isLeaf as uint8_t
    const egMaxStreamSizeType parentChunkOffsetPosition = egIndexesSpace::egChunkCapacity * oneFingerSize;
    const egMaxStreamSizeType chunkIsLeafPosition  = parentChunkOffsetPosition + sizeof(uint64_t);
    const egMaxStreamSizeType chunkCountPosition   = chunkIsLeafPosition  + sizeof(uint8_t);
    const egMaxStreamSizeType fingersChunkSize     = chunkCountPosition  + + sizeof(keysCountType); // bool isLeaf as uint8_t
    const bool  isRootFinger  = true;  // mnemonic
    const bool  notRootFinger = false; // mnemonic
    bool        rootFingerIsLoaded {false};
    bool        anyMinMaxChanged;
    std::string fingersFileName;
    egFinger<KeyType> rootFinger;
    egFinger<KeyType> parentFinger;
    egFinger<KeyType> currentFinger;
    egFinger<KeyType> newFinger;
    egFinger<KeyType> lastFinger;
    EgIndexes<KeyType>*               indexChunks {nullptr}; // ptr to related indexes object, set by upper IndexesFiles interface class
    std::vector < egFinger<KeyType> > fingersChain;          // store fingers path for update
    EgFileType        fingersFileStream;     // file operations
    EgDataStream*     localStream {nullptr}; // chunk buffer operations
    EgFingers(std::string a_fingersName, EgIndexes<KeyType>* indexChunksPtr);
    ~EgFingers() { delete localStream; }
    inline void InitFinger(egFinger<KeyType>& theFinger);
        // top API
    bool AddNewRootFinger(KeyType& Key, uint64_t indexesChunkOffset);
    bool FindIndexesChunkToInsert(KeyType& Key); // sets currentFinger and fingersChain
    bool UpdateFingersChainUp();        // uses currentFinger and fingersChain
    bool AddNewUpdateCurrentFinger();   // uses current and new fingers and fingersChain
    bool DeleteCurrentFingerByChain();  // uses currentFinger and fingersChain
    bool UpdateFingersByBackptrs();     // uses currentFinger (another index chunk, can't use chain)
    bool DeleteFingerByBackptrs();      // uses currentFinger (another index chunk, can't use chain)
        // files
    bool CheckIfFingerFileExists(){ return fingersFileStream.checkIfExists(); }
    bool DeleteFingersFile();
        // file ops
    inline bool LoadRootFingerFromFile (egFinger<KeyType>& theFinger, bool loadRootIsLeaf);
    inline bool StoreFingerToFile  (egFinger<KeyType>& theFinger);
    inline bool LoadFingersChunk  (uint64_t& chunkOffset); // to localStream-> bufData
    inline bool StoreFingersChunk (uint64_t fingersChunkOffset); // from localStream-> bufData
    inline bool StoreParentChunkOffsetDirect(uint64_t fingersChunkOffset, uint64_t parentChunkOffset);
    void SwapFingers(); // swaps current and new fingers for finger tests (if new key < current key)
        // chunk operations
    inline void ClearFingersChunk ();
    inline void ReadFingerFromChunk (egFinger<KeyType>& theFinger, const int fingerPositionNum);
    inline void WriteFingerToChunk (egFinger<KeyType>& theFinger); // QDataStream &localFingersStream,
    inline void ReadChunkMinMaxToParentFinger (egFinger<KeyType>& theParentFinger);
    inline bool GetParentFingerByOffset(uint64_t fingersChunkOffset, uint64_t nextOffset); // uses current finger
        // finger ops
    inline bool FingerIsRoot(egFinger<KeyType>& theFinger);
    inline void GetCountFromChunk(keysCountType& refCount);
    inline void WriteCountToChunk(keysCountType theCount);
    inline void GetCountDirect(keysCountType& refCount, uint64_t& chunkOffset);
    inline void GetChunkIsLeaf(uint8_t& isLeaf);
    inline void UpdateChunkIsLeaf(const uint8_t chunkIsLeaf);
    inline void GetChunkParentOffset(uint64_t& parentChunkOffset);
    inline void UpdateChunkParentOffset(uint64_t parentChunkOffset);
        // insert ops
    inline bool AppendNewFingersChunk(egFinger<KeyType>& theFinger);
    inline bool AddNewTopLevelChunk(); // ex AddNewSubRootChunk(); FIXME level number used
    inline void MoveTailToInsert(egMaxStreamSizeType fingerPositionBytes, egMaxStreamSizeType bytesToMove);
    inline void SaveLastFingerOfChunk();
    inline bool InsertNewFingerToChunk(); // bool replaceLast InsertSplittedFinger();
    // int SplitFingersChunk(); // TODO
        // update ops
    inline bool UpdateMinMaxByFlags(egFinger<KeyType>& theFinger);
        // delete ops
    inline bool DeleteFingerFromChunk(); // uses current and chunk
    inline bool DeleteFingersChunk(uint64_t fingersChunkOffset);
    inline bool DeleteTopChunk();
        // lookups
    typedef bool (*CompareFunctionType) (KeyType&, KeyType&);
    // static bool CompareEQ (KeyType& currentValue, KeyType& key) {return (currentValue == key);}
    static bool CompareGT (KeyType& currentValue, KeyType& key) {return (currentValue > key);}
    static bool CompareGE (KeyType& currentValue, KeyType& key) {return (currentValue >= key);}
    static bool CompareLT (KeyType& currentValue, KeyType& key) {return (currentValue < key);}
    static bool CompareLE (KeyType& currentValue, KeyType& key) {return (currentValue <= key);}
    inline bool OpenFileStream();
    bool FindIndexChunkEQ(KeyType& Key);    // first finger for key greater or equal then finger's min value
    inline void FindFirstFinger(KeyType& Key, CompareFunctionType predicate);
    inline void FindLastFinger(KeyType& Key, CompareFunctionType predicate);
    bool  FindIndexChunkLess(KeyType& Key, CompareFunctionType predicate);
    bool FindIndexChunkLT(KeyType& Key) { return FindIndexChunkLess(Key, CompareGE); }
    bool FindIndexChunkLE(KeyType& Key) { return FindIndexChunkLess(Key, CompareGT); }
    bool  FindIndexChunkGreater(KeyType& Key, CompareFunctionType predicate);
    bool FindIndexChunkGE(KeyType& Key) { return FindIndexChunkGreater(Key, CompareLT); }
    bool FindIndexChunkGT(KeyType& Key) { return FindIndexChunkGreater(Key, CompareLE); }
        // debug
    void PrintFingerInfo(egFinger<KeyType>& fingerInfo, const std::string theMessage);
};

norian: (Default)
Гибридная Графовая База Данных (отвертка с моторчиком для моделирования моделей)

День 7. Индексы : ускорение поиска данных.

Индекс представляет собой отсортированное по возрастанию поле данных плюс оффсеты соответствующих узлов данных в локальных файлах. Чтобы немного повысить скорость выполнения операций, индекс разбит на чанки, которые в лучшем случае помещаются в кэшлайн. Чанки связываются в двунаправленную цепь.

Чтобы искать индекс по значению, надо создать дерево поиска - это следующий этап, поскольку там много функциональности.

На первом этапе индексы поддерживают выбор по логическому условию, но не сортировку (она может быть сделана приложением или потом добавлена как плагин). Также для упрощения поддерживаются индесы только фиксированного размера - для данных переменного размера впоследствии можно будет делать соответствующие хэш функции.

API индексов выглядят как LoadAllDataGE(set& index_offsets, EgByteArrayAbstractType& keyBA) - получить множество файловых оффсетов по ключу и логической операции.


source egIndexes.h

#pragma once
#include <iostream> // debug
#include <fstream>
#include <set>
#include <vector>
// #include <experimental/filesystem> 
#include "egCoreIndexTypes.h"
#include "../service/egByteArray.h"
#include "../service/egFileType.h"
#include "egFingers.h"
// template <typename KeyType> class EgFingers;

class EgIndexesAbstractType { public:
    virtual bool AddNewIndex(EgByteArrayAbstractType& keyBA, uint64_t dataOffset) = 0;
    virtual bool DeleteIndex(EgByteArrayAbstractType& keyBA, uint64_t dataOffset) = 0;
    virtual bool UpdateDataOffset(EgByteArrayAbstractType& keyBA, uint64_t oldDataOffset, uint64_t newDataOffset) = 0;

    virtual bool LoadAllDataEQ(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA) = 0;
    virtual bool LoadAllDataGE(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA) = 0;
    virtual bool LoadAllDataGT(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA) = 0;
    virtual bool LoadAllDataLE(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA) = 0;
    virtual bool LoadAllDataLT(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA) = 0;

    virtual ~EgIndexesAbstractType() {}
};

template <typename KeyType> class EgIndexes : public EgIndexesAbstractType { public: // indexes chain part of indexes-fingers complex
    const uint64_t            indexHeaderSize       = sizeof(uint64_t);
    const egMaxStreamSizeType oneIndexSize          = sizeof(KeyType) + sizeof(uint64_t); // key and data offset
    const egMaxStreamSizeType fwdPtrPosition        = egIndexesSpace::egChunkCapacity * oneIndexSize;
    const egMaxStreamSizeType backPtrPosition       = fwdPtrPosition   + sizeof(uint64_t);
    const egMaxStreamSizeType chunkCountPosition    = backPtrPosition  + sizeof(uint64_t);
    const egMaxStreamSizeType fingersChunkOffsetPosition  = chunkCountPosition + sizeof(keysCountType);
    const egMaxStreamSizeType indexChunkSize        =  fingersChunkOffsetPosition + sizeof(uint64_t);

    bool fingersChainFlag {true};
    KeyType  theKey;                // index key to process
    uint64_t theDataOffset;         // offsets in data nodes file
    uint64_t theNewDataOffset;
    uint64_t theOldDataOffset;
    keysCountType theChunkCount;    // indexes count in the chunk for chain opers
    uint64_t theIndexesChunkOffset; // file position for chain connect
    int      theIndexPosition;      // position in the chunk
    uint64_t prevOffsetPtr;         // chunks chain operations
    uint64_t nextOffsetPtr;
    uint64_t currentIndexQuantity;  // position savepoint for Load*DataNext functions
    uint64_t currentChunkOffset;    // chunk savepoint for Load*DataNext functions
    keysCountType  transactionPosInChunk; // chunk position savepoint for Load*DataNext functions
    uint64_t reallyLoaded  {0};     // first/next opers support
    uint64_t transactionID {0};     // FIXME TODO first/next opers support

    EgFingers<KeyType>*     fingersTree {nullptr};  // fingers tree object ptr
    EgDataStream*           localStream {nullptr};  // chunk buffer operations
    EgIndexStruct<KeyType>  indexData;              // index data wrapper for flexibility
    EgFileType              indexFileStream;        // file operations
    std::string             indexFileName;
    
    EgIndexes(const std::string a_indexName);
    virtual ~EgIndexes() { delete localStream; }
        // top API
    bool AddNewIndex(EgByteArrayAbstractType& keyBA, uint64_t dataOffset) override;
    bool DeleteIndex(EgByteArrayAbstractType& keyBA, uint64_t dataOffset) override ;
    bool UpdateDataOffset(EgByteArrayAbstractType& keyBA, uint64_t oldDataOffset, uint64_t newDataOffset) override;
        // load data top API
    bool LoadAllDataFirst(std::set<uint64_t>& index_offsets, uint64_t& maxQuantity);
    bool LoadDataNextUp (std::set<uint64_t>& index_offsets, uint64_t& maxQuantity);

    bool LoadAllDataEQ(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA);
    bool LoadAllDataGE(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA);
    bool LoadAllDataGT(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA);
    bool LoadAllDataLE(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA);
    bool LoadAllDataLT(std::set<uint64_t>& index_offsets, EgByteArrayAbstractType& keyBA);
};

norian: (Default)
настала аццкая холодрыга, как всегда внезапно

обмотанные вокруг раскалённой батареи коты втыкают на занимательное природное явление - в иране и пендостане вооружённые двуногие пиздят, сажают в кледги и убивают своих сородичей, имеющих достаточно бейцев чтобы выйти протестовать на улицу

а потом объявляют их террористами, "кого убили, тот и террорист, а хто против нас вякнет, тот пособнег"

масштаб отличаецца раз в тысячу, но смысл и принципы те же - если среднестатистической сраной двуногой обезьяне дать оружие и право безнаказанно пиздить и убивать сородичей, она будет это делать, а если ещё и деньги давать, то ваще заебись, карта попёрла

все эти 100500 томов законов и полчища лоеров-дармоедов оказываюцца просто кучей бесполезного мусора, чисто модельной хренью, не влияющей на реальную реальность

вот в сказочном хуйлостане такого явления вообще нет - за неимением морали у лаптеногих свинособак они не против того, что вконец охуевшие сородичи творят и внутри, и на сопредельных территориях, те хто мог бы выйти на улицу или уехали или сидят

имко пирамиды двуногих хде пиздят и убивают за моральные принципы всё равно лучше пирамид хде всё стадо поддерживают всякие гадости, там хотя бы есть какая-то надежда на лучшее когда-то потом может быть, если не всех более лучших перебьют

уже несколько тысяч лет как лучше
norian: (Default)
Гибридная Графовая База Данных (отвертка с моторчиком для моделирования моделей)

День 6. Метаданные : регистрация типов узлов данных и линков.

Центральное хранилище данных о типах/блюпринтах узлов данных и линков. Здесь же находится API для создания блюпринтов.

Создание блюпринта (узла данных или линка) приложением выглядит как

graphDB.CreateNodeBlueprint("myDataNodes");
graphDB.AddNodeDataField("name");
graphDB.AddNodeDataField("cornerX");
graphDB.AddNodeDataField("cornerY");
graphDB.CommitNodeBlueprint();


API для всех операций создания блюпринтов для узлов данных и линков имплементировано в классе EgDatabaseType. Одно кольцо чтобы рулить всем.
Read more... )
norian: (Default)
Гибридная Графовая База Данных (отвертка с моторчиком для моделирования моделей)

День 5. Линки: как связать узлы данных и сохранять спокойствие

Для связи узлов данных фиксированных типов достаточно двух ID. В общем случае могут связываться узлы разных типов, то есть нужно дополнительно два ID типов/блюпринтов ("free link").

Также в линке могут быть дополнительные данные, таким образом в плане реализации тип линков является надстройкой над типом узлов данных.

Функциональность линка включает заполнение контейнеров динамических ссылок в узлах данных для ускорения операций с данными графа.

source egLinksType.h

#pragma once
#include "../metainfo/egDatabaseType.h"

class EgLinksType {
public:
    EgDataNodesType linksDataStorage;
    EgDataNodesMapType& dataMap; // shortcut to container nodes map,  for (auto iter : dataMap)
    // bool                        isConnected         { false };      // ? TODO nodes data status ( connected, no file, no server)
    EgBlueprintIDType   linkBlueprintID         { 0 };
    std::string         linkTypeName;

    EgDataNodeBlueprintType*  dataNodeBlueprint { nullptr }; // storage shortcut
    EgDatabaseType*           metaInfoDatabase  { nullptr };
    EgDataNodesContainerType* fromDataNodes     { nullptr };
    EgDataNodesContainerType* toDataNodes       { nullptr };

    EgLinksType(): dataMap(linksDataStorage.dataMap) {}
    ~EgLinksType() { linksDataStorage.clear(); }
    
    void clear();

    int  ConnectLinks(const std::string& linkNameStr, EgDatabaseType& myDB); // check links in database metainfo

    void AddRawLink(EgDataNodeIDType fromID, EgDataNodeIDType toID);
    int  AddNodeContainersLink(EgDataNodeIDType fromID, EgDataNodeIDType toID);

    EgLinksType& operator << (EgDataNode* newNode) { linksDataStorage.AddDataNode(newNode); return *this; }
    EgLinksType& operator << (EgDataNode& newNode) { linksDataStorage.AddDataNode(newNode); return *this; }

    EgDataNodeIDType getAddedNodeID() {return linksDataStorage.getAddedNodeID();}

    int LoadLinks();
    int StoreLinks();

    int AddLinkPtrsToNodes(EgDataNode& link, EgDataNode& from, EgDataNode& to);
    int ResolveNodesIDsToPtrs(EgDataNodesType& from, EgDataNodesType& to);

    int  MarkUpdatedLink(EgDataNodeIDType linkNodeID) {return linksDataStorage.MarkUpdatedDataNode(linkNodeID);}
    
    void DeleteArrowLink(EgDataLinkIDType linkID);
    void DeleteInLink(EgDataLinkIDType linkID);    
    void DeleteOutLink(EgDataLinkIDType linkID);
};

void PrintResolvedLinks(const EgDataNode& node);

norian: (Default)
Гибридная Графовая База Данных (отвертка с моторчиком для моделирования моделей)

День 4. API для работы с узлами, контейнеры, локальные файлы.

Основные операции с данными - добавление новых, изменение и удаление. Также данные сохраняются в локальном или удалённом хранилище и загружаются для использования в приложении. Практически всё то же самое, что и в табличных базах данных. Плюс поддержка сериализации объектов (на примере с++).

Для операций со всеми узлами данных/графа используется c++ класс EgDataNodesType.

Чтобы добавить гибкости использования, имя типа-класса-блюпринта устанавливается не при создании объекта, а функцией Connect(). Поскольку все типы-классы-блюпринты узлов должны регистрироваться в метаданных, сюда вставлена заглушка класса функциональности центральной базы.

source egDataNodesType.h

#pragma once
#include "egDataNodesContainer.h"

typedef void (*serialLoadFunctionType)  (EgDataNode& dataNode);
typedef void (*serialStoreFunctionType) (EgDataNode& dataNode);

class EgLinksType;      // arrow links
class EgDatabaseType;   // peer database 

class EgDataNodesType { // "type" means c++ type, data metatype called "blueprint"
public:
    bool                        isConnected         {  false  };    // checked blueprint file and central egDb metadata
    bool                        isDataLoaded        {  false  };
    bool                        isDataUpdated       {  false  };

    std::string                 dataNodesName;
    EgDatabaseType*             metaInfoDatabase    { nullptr };    // nodes and links layout == blueprint == class == type info
    EgDataNodeBlueprintType*    dataNodeBlueprint   { nullptr };    // layout == blueprint == class == type of these data nodes
    EgDataNodesContainerType*   nodesContainer      { nullptr };    // data storage of all these nodes
    EgDataNodesMapType&         dataMap;                            // shortcut to container nodes map,  for (auto iter : dataMap)

    serialLoadFunctionType      serialLoadFunction  { nullptr };    // function for automated data load from node to void* localDataPtr
    serialStoreFunctionType     serialStoreFunction { nullptr };    // function for automated data store to node form void* localDataPtr

    EgDataNodesType();
    ~EgDataNodesType() { clear(); delete dataNodeBlueprint; delete nodesContainer; }

    void clear();
    int  ConnectSystemNodeType(std::string a_dataNodesName); // for local testing or internal database storages
    int  OpenLocalBlueprint();    

    int  Connect(const std::string& nodesNameStr, EgDatabaseType& myDB);

    int  AddDataNode(EgDataNode* newNode);
    int  AddDataNode(EgDataNode& newNode) { return AddDataNode(&newNode); }

    EgDataNodesType& operator << (EgDataNode* newNode) { AddDataNode(newNode); return *this; }
    EgDataNodesType& operator << (EgDataNode& newNode) { AddDataNode(newNode); return *this; }
    EgDataNodeIDType getAddedNodeID() { return nodesContainer->lastNodeID; }

    int  MarkUpdatedDataNode(EgDataNodeIDType nodeID);
    int  MarkUpdatedDataNode(EgDataNode& updNode) { return MarkUpdatedDataNode(updNode.dataNodeID); }
    void DeleteDataNode(EgDataNodeIDType delID);
    void DeleteDataNode(EgDataNode& delNode) { return DeleteDataNode(delNode.dataNodeID); }

    int  Store();
    int  LoadAllNodes();
    bool LoadNodesEQ(const std::string& indexName, EgByteArrayAbstractType& fieldValue);

    // Projects.LoadIndexedNodes(IC<int>("owner", EQ, 2) &&  IC<int>("status", EQ, 3));
    // int  LoadNodesByOffsets() { return nodesContainer-> LoadLocalNodesByOffsets(indexOffsets); }
    
    EgDataNode& operator[](EgDataNodeIDType nodeID);
};



Каждый отдельный узел представляет класс EgDataNode, в котором для хранения данных узла служит EgPtrArrayType<EgByteArrayAbstractType*>*, объединяющий вышеупомянутые вспомогательные классы c++.
Read more... )
norian: (Default)
Гибридная Графовая База Данных (ака отвертка с моторчиком для моделирования моделей)

День 3. Узлы данных: типы, шаблоны, блюпринты.

Типы данных полей не сохраняются в базе данных, поэтому блюпринт содержит только имена полей узла или линка. Также в блюпринте содержится информация об индексах полей.

При редактировании типа требуются значительные изменения всей структуры базы данных, поэтому предполагается дата пампинг для подобных операций, то есть создание нового блюпринта, автоматизированная перекачка данных существующих узлов и апдейт индексов если они есть. Поэтому имена полей узла добавляются в виде транзакции, то есть старт - добавление всех полей - коммит и после коммита не могут быть изменены.

source egDataNodeBlueprint.h:

#pragma once

#include "../indexes/egCoreIndexTypes.h"
#include "../service/egByteArray.h"
#include "../service/egFileType.h"

const int egBlueprintInit   {1}; // int blueprintMode
const int egBlueprintActive {2};

class EgDataNodeBlueprintType
{
public:
    int blueprintMode {egBlueprintActive};   // blueprint can't be edited freely, data pumping on changes is required
    EgBlueprintIDType   blueprintID;                    // Data Nodes Blueprint (DNL) ID for graph DB
    std::string         blueprintName;                  // == dataNodesTypeName

    EgHamSlicerType     theHamSlicer;                   // memory allocator for data nodes (node has only blueprint out connect)
    EgFileType          blueprintFile;                  // local files load & store support (if local files used)    

    // EgNodeBlueprintSettingsType    blueprintSettings;   // add-ons for blueprint type
    EgFieldsCountType              fieldsCount {0};

    std::unordered_map < std::string, EgFieldsCountType >   dataFieldsNames;    // map  data node field names to fields indexes for dataFieldsPtrs
    std::unordered_map < std::string, EgIndexSettingsType > indexedFields;

    EgByteArrayAbstractType egNotFound;
    const char* egNotFoundStr {"<Data Not Found>"};

    EgDataNodeBlueprintType(std::string a_blueprintName): blueprintName(a_blueprintName), blueprintFile(a_blueprintName) 
        { egNotFound.dataSize = strlen(egNotFoundStr)+1; egNotFound.dataChunk = (unsigned char *) egNotFoundStr; }
    ~EgDataNodeBlueprintType() { /* std::cout << "EgDataNodeBlueprintType destructor " << std::endl; */ clear(); }

    void clear() { dataFieldsNames.clear(); indexedFields.clear(); }

    int  BlueprintInitStart();
    void AddDataFieldName(std::string fieldName);
    void AddIndex(std::string indexName, uint8_t indexSizeBytes = 4, uint8_t indexSubType = egIndexesSpace::egIntFT); // default int32
    void BlueprintInitCommit();

    bool isIndexedField(std::string& name);
    
    inline void writeDataFieldsNames();
    inline void readDataFieldsNames();
    inline void writeIndexedFields();
    inline void readIndexesFields();
    
    int  LocalStoreBlueprint();
    int  LocalLoadBlueprint();
};

// ======================== Debug ========================

void PrintDataNodeBlueprint(EgDataNodeBlueprintType& blueprint);



Для проверки функциональности блюпринта написана тестовая утилита (кое как левой задней, имко нет смысла серьёзно вкладываться в тесты на ранних этапах, но чем раньше они появятся, тем проще контролировать процесс).

Read more... )
norian: (Default)
Гибридная Графовая База Данных (отвертка с моторчиком для моделирования моделей)

День 2. Вспомогательная функциональность, системы сборки и тестирования.

Хедер алиасов основных типов (с++). Чтобы не было разных типов в разных местах кода.

source egCoreTypes.h:

#pragma once
#include <iostream>
#include <cstdint>
#include <map>
#include <unordered_map>

typedef unsigned char ByteType;
    // ID types
typedef uint32_t            EgDataNodeIDType;
typedef EgDataNodeIDType    EgDataLinkIDType;
typedef uint16_t            EgBlueprintIDType;     // data nodes and links blueprint/layout/type/class ID type
typedef uint16_t            EgLayerNumType;
    // count/size/length types
typedef uint16_t            EgFieldNameLengthType;
typedef uint8_t             EgFieldsCountType;
typedef uint16_t            EgStrSizeType;
typedef uint64_t            StaticLengthType;
    // map types
class EgDataNode;
class EgDataLinkType;
typedef std::unordered_map <EgDataNodeIDType, EgDataNode*>  EgDataNodesMapType;
typedef std::map <EgDataNodeIDType, EgDataNode*>            EgDataNodesOrdMapType;
typedef std::unordered_map <EgDataLinkIDType, EgDataNode*>  EgLinkIDsNodePtrsMapType;
typedef std::unordered_map <EgDataNode*, EgDataNode*>   EgLinkDataPtrsNodePtrsMapType;

const uint64_t egDefaultHamBrickSize = 1024;


Система аллокации памяти для небольших кусочков данных "Ham Slicer". При использовании системной аллокации для таких данных получается значительный оверхед и повышенные риски утечек. Ham Slicer аллоцирует относительно большие блоки памяти и выделяет кусочки из них под поля данных.
Read more... )
norian: (Default)
Гибридная Графовая База Данных (ака отверточка с моторчегом для моделирования моделей)

День 1. Общие размышления и архитектура.

Нужен инструмент чтобы строить и зумить графовую модель от верхних архитектурных уровней до самых мелких деталей в 2D, послойном 2D и 3D пространствах. Также необходима интеграция с языками и средами программирования для написания логики приложений. Существующие приложения, которые это делают, не были найдены.

Для этого надо написать движок гибридной графовой базы данных и интегрировать его с объектным языком (с++, но в принципе с любым другим, в котором есть мост к с++ функциям), чтобы можно было легко передавать данные и код из объектов языка в узлы графа и обратно.

Зачем ещё это может быть нужно:

Read more... )
norian: (Default)
среди прочих деревенских инструментов вроде топоров вил и отвёртог есть некоторая особая группа, перпендикулярная к уровням автоматизации

- инструменты моделирования реальной реальности

- инструменты разглядывания внутренностей моделей и внесения (как бэ) улучшений

- инструменты переноса изменённых моделей в реальную реальность

надо бы совершить героическое усилие, скоши скоши отмотацца от батареи и сделать мотыжку с моторчегом в смысле инструмента для окучивания моделей
norian: (Default)
совок был очень странным рабовладельческим строем

с одной стороны, рабы юридически не имели собственности - всякая собственность была ситуативной, хто что спиздил или жоповылизал, тот то и имеет. В зиккурате лежала мумия фараона, всё как полагаецца, жрецы возносили восхваления и засирали ганглий сородичей коммунизьмом на горизонте

с другой стороны, не было класса рабовладельцев - у сдохших жрецов отбирали все ништяки чтобы передать новым, согласно должностным уложениям

феодальный строй в хуйлостане тоже очень странный - феодалы обычно имеют какую-то автономию и действуют в своих интересах, а новое дворянство полностью легло под верхушку пирамиды и вместо своих приятных дворянских хотелок обслуживает кровавые фантазии ебанутых нв всю голову старцев

то ли потому что это почти полностью первое поколение, то ли осталось совковая ментальность собственной ничтожности по сравнению с модельным фараоном коллективного бессознательного - ну да и хуй с ними, пардон май котеговски дайлект, это их выбор и расплачивацца тоже им
norian: (Default)
центральный хуйлостан припорошыло снежгом немного

коты кое-как откопали днём выход из норы, но его засыпало взад уже

в новостях фм радио (обычного музыкального, на ватных такой угар 24/7 в любой момент скана частот) с гордостью рассказали как зашкварили гражданских в киеве и устроили блэкаут в днепре, потом продолжили радостные рождественские песенки и рекламные пожелания

ну то есть если вдруг жызнь как-то наладицца, то можно будет шкварить всех лаптеногих не слушая "ааа, мы не знали ничего", все всё знают даже в глубинах танка

но жызнь вряд ли наладицца, много лет по поводу любых новостей снаружи норы подходят два кото-диалектических выражения

"нанда каря?" в смысле чо за аццкая хрень происходит опять
"суки дакара" в смысле потому что суки
norian: (Default)
мнэ .. чтобы такого понаписать чтобы не напрягать маленький котеговский межушный ганглий

ну например - какие задачи есть у агента гэбни, которому удалось занять какой-то высокий пост в буржуйской стране ?

слив украины ? само собой, но в глобальных масштабах это всего лишь один из комков сноуболлинга, зогхват территорий с мобилизаией ейных ресурсов для зогхвата ещё больших территорий, и это тоже произойдёт, но как следствие более глобальных событий, а не основная сюжетная линия, при всём уважении к

собсно основных задач у него и его команды поддержки две - развалить нато и устроить гражданскую войну в пендостане, чтобы не до других стран было совсем

после чего зогхват всех гейропейских куколдов будет тривиальным - за почти 4 года они показали полную неготовность к решительным действиям, и против двухмиллионной армии с реальным боевым опытом шансы отбицца нулевые

как развалить нато ? ну например внаглую оккупировать часть одной из стран, желательно поубивав некоторое количество граждан в процессе, после чего вся эта халабуда рассыпецца как доминошная башня

просто встать с дивана и оккупироать как-то стрёмно, нужно создать пренцендент, накачать общественное мнение эйфорией и вот тогда уже пипл схавает

и вот тут на сцене происходит спектакль с кокаиновым презиком, который в практическом смысле ни на что не влияет и проходит согласно сценарию, без всяких потерь и с победными фанфарами выкрученными на максимум

а лучший повод для гражданской войны - объявление себя великой и могучей царственной особой, которой все эти выборы не нужные и только вредные, и это будет не в этом году, да и куда спешить когда впереди вечность

Profile

norian: (Default)
Murramoto Manulneko

February 2026

S M T W T F S
123456 7
8910 111213 14
15161718192021
2223 24 25262728

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Feb. 25th, 2026 11:18 am
Powered by Dreamwidth Studios