From 814bb66ea6b401426cf55fd9fdefe0275166513c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Budiseli=C4=87?= <marko.budiselic@memgraph.com> Date: Wed, 21 Oct 2020 18:56:15 +0200 Subject: [PATCH] Clean Memgraph repository (#12) * Update documentation * Update structure, CODEOWNERS, license files * Update release/README * Stop Actions if only docs file were updated * Remove unused hidden files, move Doxygen logo --- .arcconfig | 7 - .arclint | 16 -- .github/workflows/diff.yaml | 6 +- .ycm_extra_conf.py | 172 ------------------ CODEOWNERS | 4 + Doxyfile | 2 +- README.md | 55 ++++-- docs/dev/communication/contents.md | 5 + docs/dev/durability/snapshots.md | 22 --- docs/dev/query/build-html | 16 -- docs/dev/query/interpreter-class.png | Bin 0 -> 56219 bytes docs/dev/quick-start.md | 15 +- docs/dev/storage/{ => v1}/accessors.md | 6 +- docs/dev/storage/v1/contents.md | 6 + .../wal.md => storage/v1/durability.md} | 27 ++- docs/dev/storage/{ => v1}/indexes.md | 8 +- docs/dev/storage/{ => v1}/property-storage.md | 22 +-- docs/dev/storage/v2/contents.md | 3 + docs/dev/toolchain-bootstrap.md | 152 ---------------- docs/dev/workflow.md | 69 +------ docs/doxygen/README.md | 7 +- .../doxygen/memgraph_logo.png | Bin docs/feature_spec/contents.md | 3 + release/README.md | 12 +- 24 files changed, 135 insertions(+), 500 deletions(-) delete mode 100644 .arcconfig delete mode 100644 .arclint delete mode 100644 .ycm_extra_conf.py create mode 100644 CODEOWNERS create mode 100644 docs/dev/communication/contents.md delete mode 100644 docs/dev/durability/snapshots.md delete mode 100755 docs/dev/query/build-html create mode 100644 docs/dev/query/interpreter-class.png rename docs/dev/storage/{ => v1}/accessors.md (98%) create mode 100644 docs/dev/storage/v1/contents.md rename docs/dev/{durability/wal.md => storage/v1/durability.md} (72%) rename docs/dev/storage/{ => v1}/indexes.md (98%) rename docs/dev/storage/{ => v1}/property-storage.md (95%) create mode 100644 docs/dev/storage/v2/contents.md delete mode 100644 docs/dev/toolchain-bootstrap.md rename Doxylogo.png => docs/doxygen/memgraph_logo.png (100%) create mode 100644 docs/feature_spec/contents.md diff --git a/.arcconfig b/.arcconfig deleted file mode 100644 index d65ecaefa..000000000 --- a/.arcconfig +++ /dev/null @@ -1,7 +0,0 @@ -{ - "project_id" : "memgraph", - "conduit_uri" : "https://phabricator.memgraph.io", - "phabricator_uri" : "https://phabricator.memgraph.io", - "git.default-relative-commit": "origin/master", - "arc.land.onto.default": "master" -} diff --git a/.arclint b/.arclint deleted file mode 100644 index e854dec99..000000000 --- a/.arclint +++ /dev/null @@ -1,16 +0,0 @@ -{ - "linters": { - "clang-tidy": { - "type": "script-and-regex", - "include": "(\\.(cpp|cc|cxx|c|h|hpp|lcp)$)", - "script-and-regex.script": "./tools/arc-clang-tidy", - "script-and-regex.regex": "/^(?P<file>.*):(?P<line>\\d+):(?P<char>\\d+): (?P<severity>warning|error): (?P<message>.*)$/m" - }, - "clang-format": { - "type": "script-and-regex", - "include": "(\\.(cpp|cc|cxx|c|h|hpp)$)", - "script-and-regex.script": "./tools/arc-clang-format", - "script-and-regex.regex": "/^(?P<severity>warning):(?P<offset>\\d+):(?P<message>.*)$/m" - } - } -} diff --git a/.github/workflows/diff.yaml b/.github/workflows/diff.yaml index cac272151..f87ab1296 100644 --- a/.github/workflows/diff.yaml +++ b/.github/workflows/diff.yaml @@ -1,6 +1,10 @@ name: Diff -on: [push] +on: + push: + paths-ignore: + - 'docs/**' + - '*.md' jobs: community_build: diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py deleted file mode 100644 index 0e172c1b6..000000000 --- a/.ycm_extra_conf.py +++ /dev/null @@ -1,172 +0,0 @@ -import os -import os.path -import fnmatch -import logging -import ycm_core - -BASE_FLAGS = [ - '-Wall', - '-Wextra', - '-Werror', - '-Wno-long-long', - '-Wno-variadic-macros', - '-fexceptions', - '-ferror-limit=10000', - '-std=c++1z', - '-xc++', - '-I/usr/lib/', - '-I/usr/include/', - '-I./src', - '-I./include', - '-I./libs/fmt', - '-I./libs/yaml-cpp', - '-I./libs/glog/include', - '-I./libs/googletest/googletest/include', - '-I./libs/googletest/googlemock/include', - '-I./libs/benchmark/include', - '-I./libs/cereal/include', - # We include cppitertools headers directly from libs directory. - '-I./libs', - '-I./libs/rapidcheck/include', - '-I./libs/antlr4/runtime/Cpp/runtime/src', - '-I./libs/gflags/include', - '-I./experimental/distributed/src', - '-I./libs/postgresql/include', - '-I./libs/bzip2', - '-I./libs/zlib', - '-I./libs/rocksdb/include', - '-I./libs/librdkafka/include/librdkafka', - '-I./build/include' -] - -SOURCE_EXTENSIONS = [ - '.cpp', - '.cxx', - '.cc', - '.c', - '.m', - '.mm' -] - -HEADER_EXTENSIONS = [ - '.h', - '.hxx', - '.hpp', - '.hh' -] - -# set the working directory of YCMD to be this file -os.chdir(os.path.dirname(os.path.realpath(__file__))) - -def IsHeaderFile(filename): - extension = os.path.splitext(filename)[1] - return extension in HEADER_EXTENSIONS - -def GetCompilationInfoForFile(database, filename): - if IsHeaderFile(filename): - basename = os.path.splitext(filename)[0] - for extension in SOURCE_EXTENSIONS: - replacement_file = basename + extension - if os.path.exists(replacement_file): - compilation_info = database.GetCompilationInfoForFile(replacement_file) - if compilation_info.compiler_flags_: - return compilation_info - return None - return database.GetCompilationInfoForFile(filename) - -def FindNearest(path, target): - candidate = os.path.join(path, target) - if(os.path.isfile(candidate) or os.path.isdir(candidate)): - logging.info("Found nearest " + target + " at " + candidate) - return candidate; - else: - parent = os.path.dirname(os.path.abspath(path)); - if(parent == path): - raise RuntimeError("Could not find " + target); - return FindNearest(parent, target) - -def MakeRelativePathsInFlagsAbsolute(flags, working_directory): - if not working_directory: - return list(flags) - new_flags = [] - make_next_absolute = False - path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] - for flag in flags: - new_flag = flag - - if make_next_absolute: - make_next_absolute = False - if not flag.startswith('/'): - new_flag = os.path.join(working_directory, flag) - - for path_flag in path_flags: - if flag == path_flag: - make_next_absolute = True - break - - if flag.startswith(path_flag): - path = flag[ len(path_flag): ] - new_flag = path_flag + os.path.join(working_directory, path) - break - - if new_flag: - new_flags.append(new_flag) - return new_flags - - -def FlagsForClangComplete(root): - try: - clang_complete_path = FindNearest(root, '.clang_complete') - clang_complete_flags = open(clang_complete_path, 'r').read().splitlines() - return clang_complete_flags - except: - return None - -def FlagsForInclude(root): - try: - include_path = FindNearest(root, 'include') - flags = [] - for dirroot, dirnames, filenames in os.walk(include_path): - for dir_path in dirnames: - real_path = os.path.join(dirroot, dir_path) - flags = flags + ["-I" + real_path] - return flags - except: - return None - -def FlagsForCompilationDatabase(root, filename): - try: - compilation_db_path = FindNearest(root, 'compile_commands.json') - compilation_db_dir = os.path.dirname(compilation_db_path) - logging.info("Set compilation database directory to " + compilation_db_dir) - compilation_db = ycm_core.CompilationDatabase(compilation_db_dir) - if not compilation_db: - logging.info("Compilation database file found but unable to load") - return None - compilation_info = GetCompilationInfoForFile(compilation_db, filename) - if not compilation_info: - logging.info("No compilation info for " + filename + " in compilation database") - return None - return MakeRelativePathsInFlagsAbsolute( - compilation_info.compiler_flags_, - compilation_info.compiler_working_dir_) - except: - return None - -def FlagsForFile(filename): - root = os.path.realpath(filename); - compilation_db_flags = FlagsForCompilationDatabase(root, filename) - if compilation_db_flags: - final_flags = compilation_db_flags - else: - final_flags = BASE_FLAGS - clang_flags = FlagsForClangComplete(root) - if clang_flags: - final_flags = final_flags + clang_flags - include_flags = FlagsForInclude(root) - if include_flags: - final_flags = final_flags + include_flags - return { - 'flags': final_flags, - 'do_cache': True - } diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000..f871ca5f9 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,4 @@ +/docs/ @gitbuda +/src/communication/ @antonio2368 +/src/query/ @the-joksim +/src/storage/ @antonio2368 diff --git a/Doxyfile b/Doxyfile index 3fb0b6763..9281d1cf8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -51,7 +51,7 @@ PROJECT_BRIEF = "The World's Most Powerful Graph Database" # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = Doxylogo.png +PROJECT_LOGO = docs/doxygen/memgraph_logo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is diff --git a/README.md b/README.md index 6d7fe1457..a141030e3 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,47 @@ -# memgraph +# Memgraph Memgraph is an ACID compliant high performance transactional distributed in-memory graph database featuring runtime native query compiling, lock free data structures, multi-version concurrency control and asynchronous IO. -## dependencies +## Development Documentation -Memgraph can be compiled using any modern c++ compiler. It mostly relies on -the standard template library, however, some things do require external -libraries. +* [Quick Start](docs/dev/quick-start.md) +* [Workflow](docs/dev/workflow.md) +* [Storage](docs/dev/storage/v2/contents.md) +* [Query Engine](docs/dev/query/contents.md) +* [Communication](docs/dev/communication/contents.md) +* [Lisp C++ Preprocessor (LCP)](docs/dev/lcp.md) -Some code contains linux-specific libraries and the build is only supported -on a 64 bit linux kernel. +## Feature Specifications -* linux -* clang 3.8 (good c++11 support, especially lock free atomics) -* antlr (compiler frontend) -* cppitertools -* fmt format -* google benchmark -* google test -* glog -* gflags +Each prominent Memgraph feature requires a feature specification. The purpose +of the feature specification is to have a base for discussing all aspects of +the feature. Elements of feature specifications should be: + +* High-level context. +* Interface. +* User stories. Usage from the end-user perspective. In the case of a library, + that should be cases on how to use the programming interface. In the case of +a shell script, that should be cases on how to use flags. +* Discussion about concurrency, memory management, error management. +* Any other essential functional or non-functional requirements. +* Test and benchmark strategy. +* Possible future changes/improvements/extensions. +* Security concerns. +* Additional and/or optional implementation details. + +It's crucial to keep feature spec up-to-date with the implementation. Take a +look at the list of [feature specifications](docs/feature_spec/contents.md) to +learn more about powerful Memgraph features. + +## User Documentation + +Memgraph user documentation is maintained within +[docs](https://github.com/memgraph/docs) repository. The documentation is also +available on [GitBook](https://docs.memgraph.com). + +## Licences + +* [Community](release/LICENSE_COMMUNITY.md) +* [Enterprise](release/LICENSE_ENTERPRISE.md) diff --git a/docs/dev/communication/contents.md b/docs/dev/communication/contents.md new file mode 100644 index 000000000..6b515b32a --- /dev/null +++ b/docs/dev/communication/contents.md @@ -0,0 +1,5 @@ +# Communication + +## Bolt + +Memgraph implements [Bolt communication protocol](https://7687.org/). diff --git a/docs/dev/durability/snapshots.md b/docs/dev/durability/snapshots.md deleted file mode 100644 index 32f1b3a5b..000000000 --- a/docs/dev/durability/snapshots.md +++ /dev/null @@ -1,22 +0,0 @@ -# Snapshots - -A "snapshot" is a record of the current database state stored in permanent -storage. Note that the term "snapshot" is used also in the context of -the transaction engine to denote a set of running transactions. - -A snapshot is written to the file by Memgraph periodically if so -configured. The snapshot creation process is done within a transaction created -specifically for that purpose. The transaction is needed to ensure that -the stored state is internally consistent. - -The database state can be recovered from the snapshot during startup, if -so configured. This recovery works in conjunction with write-ahead log -recovery. - -A single snapshot contains all the data needed to recover a database. In -that sense snapshots are independent of each other and old snapshots can -be deleted once the new ones are safely stored, if it is not necessary -to revert the database to some older state. - -The exact format of the snapshot file is defined inline in the snapshot -creation code. diff --git a/docs/dev/query/build-html b/docs/dev/query/build-html deleted file mode 100755 index d012f45c8..000000000 --- a/docs/dev/query/build-html +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -mkdir -p $script_dir/html - -for markdown_file in $(find $script_dir -name '*.md'); do - name=$(basename -s .md $markdown_file) - sed -e 's/.md/.html/' $markdown_file | \ - pandoc -s -f markdown -t html -o $script_dir/html/$name.html -done - -for dot_file in $(find $script_dir -name '*.dot'); do - name=$(basename -s .dot $dot_file) - dot -Tpng $dot_file -o $script_dir/html/$name.png -done diff --git a/docs/dev/query/interpreter-class.png b/docs/dev/query/interpreter-class.png new file mode 100644 index 0000000000000000000000000000000000000000..b36d223f30343d0d30d296186b88b3375a21a5e2 GIT binary patch literal 56219 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 U<a%g^KSRe>-5ol2wU3_t2VC+e$^ZZW literal 0 HcmV?d00001 diff --git a/docs/dev/quick-start.md b/docs/dev/quick-start.md index c7fc541ab..d62199917 100644 --- a/docs/dev/quick-start.md +++ b/docs/dev/quick-start.md @@ -17,7 +17,7 @@ On ArchLinux or Gentoo, you probably already know what to do. After installing `git`, you are now ready to fetch your own copy of Memgraph source code. Run the following command: - git clone https://phabricator.memgraph.io/diffusion/MG/memgraph.git + git clone https://github.com/memgraph/memgraph.git The above will create a `memgraph` directory and put all source code there. @@ -52,12 +52,13 @@ After installing the packages, issue the following commands: ### Compiling Memgraph is compiled using our own custom toolchain that can be obtained from -[Toolchain repository](https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/toolchain). You should read -the `README.txt` file in the repository and install the apropriate toolchain -for your distribution. After you have installed the toolchain you should read -the instructions for the toolchain in the toolchain install directory -(`/opt/toolchain-vXYZ/README.md`) and install dependencies that are necessary -to run the toolchain. +[Toolchain +repository](https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/toolchain). You +should read the `README.txt` file in the repository and install the apropriate +toolchain for your distribution. After you have installed the toolchain you +should read the instructions for the toolchain in the toolchain install +directory (`/opt/toolchain-vXYZ/README.md`) and install dependencies that are +necessary to run the toolchain. When you want to compile Memgraph you should activate the toolchain using the prepared toolchain activation script that is also described in the toolchain diff --git a/docs/dev/storage/accessors.md b/docs/dev/storage/v1/accessors.md similarity index 98% rename from docs/dev/storage/accessors.md rename to docs/dev/storage/v1/accessors.md index f6c37955b..2a8fac6ce 100644 --- a/docs/dev/storage/accessors.md +++ b/docs/dev/storage/v1/accessors.md @@ -38,7 +38,7 @@ interpretation code) should work with accessors. There is a `RecordAccessor` as a base class for `VertexAccessor` and `EdgeAccessor`. Following is an enumeration of their purpose. -### Data access +### Data Access The client interacts with Memgraph using the Cypher query language. That language has certain semantics which imply that multiple versions of the @@ -75,7 +75,7 @@ In distributed Memgraph accessors also contain a lot of the remote graph element handling logic. More info on that is available in the documentation for distributed. -### Deferred MVCC data lookup for Edges +### Deferred MVCC Data Lookup for Edges Vertices and edges are versioned using MVCC. This means that for each transaction an MVCC lookup needs to be done to determine which version @@ -100,7 +100,7 @@ working with that data directly whenever possible! Always consider the accessors to be the first go-to for interacting with data, especially when in the context of a transaction. -# Skiplist accessor +# Skiplist Accessor The term "accessor" is also used in the context of a skiplist. Every operation on a skiplist must be performed within on an diff --git a/docs/dev/storage/v1/contents.md b/docs/dev/storage/v1/contents.md new file mode 100644 index 000000000..e378d1379 --- /dev/null +++ b/docs/dev/storage/v1/contents.md @@ -0,0 +1,6 @@ +# Storage v1 + +* [Accessors](accessors.md) +* [Indexes](indexes.md) +* [Property Storage](property-storage.md) +* [Durability](durability.md) diff --git a/docs/dev/durability/wal.md b/docs/dev/storage/v1/durability.md similarity index 72% rename from docs/dev/durability/wal.md rename to docs/dev/storage/v1/durability.md index a64603f52..6648a3dc9 100644 --- a/docs/dev/durability/wal.md +++ b/docs/dev/storage/v1/durability.md @@ -1,4 +1,6 @@ -# Write-ahead logging +# Durability + +## Write-ahead Logging Typically WAL denotes the process of writing a "log" of database operations (state changes) to persistent storage before committing the @@ -53,3 +55,26 @@ inefficient) to recover the database from WAL only, provided all the WAL files created from DB start are available. It is not possible to recover partial database state (i.e. from some suffix of WAL files, without the preceding snapshot). + +## Snapshots + +A "snapshot" is a record of the current database state stored in permanent +storage. Note that the term "snapshot" is used also in the context of +the transaction engine to denote a set of running transactions. + +A snapshot is written to the file by Memgraph periodically if so +configured. The snapshot creation process is done within a transaction created +specifically for that purpose. The transaction is needed to ensure that +the stored state is internally consistent. + +The database state can be recovered from the snapshot during startup, if +so configured. This recovery works in conjunction with write-ahead log +recovery. + +A single snapshot contains all the data needed to recover a database. In +that sense snapshots are independent of each other and old snapshots can +be deleted once the new ones are safely stored, if it is not necessary +to revert the database to some older state. + +The exact format of the snapshot file is defined inline in the snapshot +creation code. diff --git a/docs/dev/storage/indexes.md b/docs/dev/storage/v1/indexes.md similarity index 98% rename from docs/dev/storage/indexes.md rename to docs/dev/storage/v1/indexes.md index 147f4448e..b623d13d3 100644 --- a/docs/dev/storage/indexes.md +++ b/docs/dev/storage/v1/indexes.md @@ -1,10 +1,10 @@ -# Label indexes +# Label Indexes These are unsorted indexes that contain all the vertices that have the label the indexes are for (one index per label). These kinds of indexes get automatically generated for each label used in the database. -### Updating the indexes +### Updating the Indexes Whenever something gets added to the record we update the index (add that record to index). We keep an index which might contain garbage (not relevant @@ -64,7 +64,7 @@ same order, with (record, vlist) pair already superseded by a newer record and as such won't be inserted while it's being deleted -### Querying the index +### Querying the Index We run through the index for the given label and do `vlist.find` operation for the current transaction, and check if the newest return record has that @@ -75,7 +75,7 @@ in the index are sorted by their `vlist*` and as such we can filter consecutive duplicate `vlist*` to only return one of those while still being able to create an iterator to index. -### Cleaning the index +### Cleaning the Index Cleaning the index is not as straightforward as it seems as a lot of garbage can accumulate, but it's hard to know when exactly can we delete some (record, diff --git a/docs/dev/storage/property-storage.md b/docs/dev/storage/v1/property-storage.md similarity index 95% rename from docs/dev/storage/property-storage.md rename to docs/dev/storage/v1/property-storage.md index 897c54ce7..947c4d8b3 100644 --- a/docs/dev/storage/property-storage.md +++ b/docs/dev/storage/v1/property-storage.md @@ -1,7 +1,7 @@ -# Property storage +# Property Storage Although the reader is probably familiar with properties in *Memgraph*, let's -briefly recap. +briefly recap. Both vertices and edges can store an arbitrary number of properties. Properties are, in essence, ordered pairs of property names and property values. Each @@ -21,9 +21,9 @@ must be one of the following types: Property values are modeled in a class conveniently called `PropertyValue`. -## Mapping between property names and property keys. +## Mapping Between Property Names and Property Keys. -Although users think of property names in terms of descriptive strings +Although users think of property names in terms of descriptive strings (e.g. "location" or "department"), *Memgraph* internally converts those names into property keys which are, essentially, unsigned 16-bit integers. @@ -49,7 +49,7 @@ An interface of `PropertyValueStore` is as follows: `clear` | Clears the storage. `iterator`| Provides an extension of `std::input_iterator` that iterates over storage. -## Storage location +## Storage Location By default, *Memgraph* is an in-memory database and all properties are therefore stored in working memory unless specified otherwise by the user. User has an @@ -63,12 +63,12 @@ property key has the following format: ``` |---location--|------id------| |-Memory|Disk-|-----2^15-----| -``` +``` In other words, the most significant bit determines the location where the -property will be stored. +property will be stored. -### In-memory storage +### In-memory Storage The underlying implementation of in-memory storage for the time being is `std::vector<std::pair<Property, PropertyValue>>`. Implementations of`at`, `set` @@ -76,7 +76,7 @@ and `erase` are linear in time. This implementation is arguably more efficient than `std::map` or `std::unordered_map` when the average number of properties of a record is relatively small (up to 10) which seems to be the case. -### On-disk storage +### On-disk Storage #### KVStore @@ -120,12 +120,12 @@ KVStore storage = ...; for (auto it = storage.begin("alpha"); it != storage.end("omega"); ++it) {} ``` -#### Data organization on disk +#### Data Organization on Disk Each `PropertyValueStore` instance can access a static `KVStore` object that can store `(key, value)` pairs on disk. The key of each property on disk consists of two parts — a unique identifier (unsigned 64-bit integer) of the current -record version (see mvcc docummentation for further clarification) and a +record version (see mvcc docummentation for further clarification) and a property key as described above. The actual value of the property is serialized into a bytestring using bolt `BaseEncoder`. Similarly, deserialization is performed by bolt `Decoder`. diff --git a/docs/dev/storage/v2/contents.md b/docs/dev/storage/v2/contents.md new file mode 100644 index 000000000..33496731e --- /dev/null +++ b/docs/dev/storage/v2/contents.md @@ -0,0 +1,3 @@ +# Storage v2 + +TODO(gitbuda): Write documentation. diff --git a/docs/dev/toolchain-bootstrap.md b/docs/dev/toolchain-bootstrap.md deleted file mode 100644 index a55177c26..000000000 --- a/docs/dev/toolchain-bootstrap.md +++ /dev/null @@ -1,152 +0,0 @@ -# Bootstrapping Compilation Toolchain for Memgraph - -Requirements: - - * libstdc++ shipped with gcc-6.3 or gcc-6.4 - * cmake >= 3.1, Debian Stretch uses cmake-3.7.2 - * clang-3.9 - -## Installing gcc-6.4 - -gcc-6.3 has a bug, so use the 6.4 version which is just a bugfix release. - -Requirements on CentOS 7: - - * wget - * make - * gcc (bootstrap) - * gcc-c++ (bootstrap) - * gmp-devel (bootstrap) - * mpfr-devel (bootstrap) - * libmpc-devel (bootstrap) - * zip - * perl - * dejagnu (testing) - * expect (testing) - * tcl (testing) - -``` -wget ftp://ftp.mpi-sb.mpg.de/pub/gnu/mirror/gcc.gnu.org/pub/gcc/releases/gcc-6.4.0/gcc-6.4.0.tar.gz -tar xf gcc-6.4.0.tar.gz -cd gcc-6.4.0 -mkdir build -cd build -../configure --disable-multilib --prefix=<install-dst> -make -# Testing -make -k check -make install -``` - -*Do not put gcc + libs on PATH* (unless you know what you are doing). - -## Installing cmake-3.7.2 - -Requirements on CentOS 7: - - * wget - * make - * gcc - * gcc-c++ - * ncurses-devel (optional, for ccmake) - -``` -wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz -tar xf cmake-3.7.2.tar.gz -cd cmake-3.7.2.tar.gz -./bootstrap --prefix<install-dst> -make -make install -``` - -Put cmake on PATH (if appropriate) - -**Fix the bug in CpackRPM** - -`"<path-to-cmake>/share/cmake-3.7/Modules/CPackRPM.cmake" line 2273 of 2442` - -The line - -``` -set(RPMBUILD_FLAGS "-bb") -``` -needs to be before - -``` -if(CPACK_RPM_GENERATE_USER_BINARY_SPECFILE_TEMPLATE OR NOT CPACK_RPM_USER_BINARY_SPECFILE) -``` - -It was probably accidentally placed after, and is fixed in later cmake -releases. - -## Installing clang-3.9 - -Requirements on CentOS 7: - - * wget - * make - * cmake - -``` -wget http://releases.llvm.org/3.9.1/llvm-3.9.1.src.tar.xz -tar xf llvm-3.9.1.src.tar.xz -mv llvm-3.9.1.src llvm - -wget http://releases.llvm.org/3.9.1/cfe-3.9.1.src.tar.xz -tar xf cfe-3.9.1.src.tar.xz -mv cfe-3.9.1.src llvm/tools/clang - -cd llvm -mkdir build -cd build -cmake -DCMAKE_BUILD_TYPE="Release" -DGCC_INSTALL_PREFIX=<gcc-dir> \ --DCMAKE_C_COMPILER=<gcc> -DCMAKE_CXX_COMPILER=<g++> \ --DCMAKE_CXX_LINK_FLAGS="-L<gcc-dir>/lib64 -Wl,-rpath,<gcc-dir>/lib64" \ --DCMAKE_INSTALL_PREFIX=<install-dst> .. -make -# Testing -make check-clang -make install -``` - -Put clang on PATH (if appropriate) - -## Memgraph - -Requirements on CentOS 7: - - * libuuid-devel (antlr4) - * java-1.8.0-openjdk (antlr4) - * boost-static (too low version --- compile manually) - * rpm-build (RPM) - * python3 (tests, ...) - * which (required for rocksdb) - * sbcl (lisp C++ preprocessing) - -### Boost 1.62 - -``` -wget https://netix.dl.sourceforge.net/project/boost/boost/1.62.0/boost_1_62_0.tar.gz -tar xf boost_1_62_0.tar.gz -cd boost_1_62_0 -./bootstrap.sh --with-toolset=clang --with-libraries=iostreams,serialization --prefix=<install-dst> -./b2 -# Default installs to /usr/local/ -./b2 install -``` - -### Building Memgraph - -clang is *required* to be findable by cmake, i.e. it should be on PATH. -cmake isn't required to be on the path, since you run it manually, so can use -the full path to executable in order to run it. Obviously, it is convenient to -put cmake also on PATH. - -Building is done as explained in [Quick Start](quick-start.md), but each -`make` invocation needs to be prepended with: - -`LD_RUN_PATH=<gcc-dir>/lib64 make ...` - -### RPM - -Name format: `memgraph-<version>-<pkg-version>.<arch>.rpm` diff --git a/docs/dev/workflow.md b/docs/dev/workflow.md index 62f2839c3..8ba36f0f0 100644 --- a/docs/dev/workflow.md +++ b/docs/dev/workflow.md @@ -20,18 +20,12 @@ Finally, make git aware of your favourite editor: git config --global core.editor "vim" -## Phabricator +## Github All of the code in Memgraph needs to go through code review before it can be -accepted in the codebase. This is done through -[Phabricator](https://phacility.com/phabricator/). The command line tool for -interfacing with Phabricator is -[arcanist](https://phacility.com/phabricator/arcanist/). You should already -have it installed if you followed the steps in [Quick Start](quick-start.md). - -The only required setup is to go in the root of Memgraph's project and run: - - arc install-certificate +accepted in the codebase. This is done through [Github](https://github.com/). +You should already have it installed if you followed the steps in [Quick +Start](quick-start.md). ## Working on Your Feature Branch @@ -46,6 +40,7 @@ out of the `master` branch. For example, let's say you are adding static type checking to the query language compiler. You would create a branch called `mg_query_static_typing` with the following command: + # TODO(gitbuda): Discuss the naming conventions. git branch mg_query_static_typing To switch to that branch, type: @@ -98,34 +93,9 @@ possible. ### Sending Changes on a Review After finishing your work on your feature branch, you will want to send it on -code review. This is done through Arcanist. To do that, run the following -command: - - arc diff - -You will, once again, be presented with an editor where you need to describe -your whole work. `arc` will by default fill that description with your commit -messages. The title and summary of your work should also follow the -conventions of git messages as described above. If you followed the -guidelines, the message filled by `arc` should be fine. - -In addition to the message, you need to fill the `Reviewers:` line with -usernames of people who should do the code review. - -You changes will be visible on Phabricator as a so called "diff". You can find -the default view of active diffs -[here](https://phabricator.memgraph.io/differential/) - -### Updating Changes Based on Review - -When you get comments in the code review, you will want to make additional -modifications to your work. The same workflow as before applies: [Making and -Committing Changes](#making-and-committing-changes) - -After making those changes, send them back on code review: - - arc diff - +code review. This is done by pushing the branch to Github and creating a pull +request. You can find all PRs +[here](https://github.com/memgraph/memgraph/pulls). ### Updating From New Master @@ -152,26 +122,3 @@ your feature branch as if you just created and started working on that branch. You may continue with the usual workflow of [Making and Committing Changes](#making-and-committing-changes) and [Sending Changes on a Review](#sending-changes-on-a-review). - -### Sending Your Changes on Master Branch - -When your changes pass the code review, you are ready to integrate them in the -`master` branch. To do that, run the following command: - - arc land - -Arcanist will take care of obtaining the latest changes from `master` and -merging your changes on top. If the `land` was successful, Arcanist will -delete your local branch and you will be back on `master`. Continuing from the -examples above, the deleted branch would be `mg_query_static_typing`. - -This marks the completion of your changes, and you are ready to work on -something else. - -### Note For People Familiar With Git - -Since Arcanist takes care of merging your git commits and pushing them on -`master`, you should *never* have to call `git merge` and `git push`. If you -find yourself typing those commands, check that you are doing the right thing. -The most common mistake is to use `git merge` instead of `git rebase` for the -case described in [Updating From New Master](#updating-from-new-master). diff --git a/docs/doxygen/README.md b/docs/doxygen/README.md index 082368097..a571b02b3 100644 --- a/docs/doxygen/README.md +++ b/docs/doxygen/README.md @@ -1,7 +1,6 @@ # Memgraph Code Documentation -IMPORTANT: auto-generated (run doxygen Doxyfile in the project root) +IMPORTANT: Auto-generated (run doxygen Doxyfile in the project root). -* HTML - just open docs/doxygen/html/index.html - -* Latex - run make inside docs/doxygen/latex +* HTML - Open docs/doxygen/html/index.html. +* Latex - Run make inside docs/doxygen/latex. diff --git a/Doxylogo.png b/docs/doxygen/memgraph_logo.png similarity index 100% rename from Doxylogo.png rename to docs/doxygen/memgraph_logo.png diff --git a/docs/feature_spec/contents.md b/docs/feature_spec/contents.md new file mode 100644 index 000000000..c700a401c --- /dev/null +++ b/docs/feature_spec/contents.md @@ -0,0 +1,3 @@ +# Feature Specifications + +* [Python Query Modules](python-query-modules.md) diff --git a/release/README.md b/release/README.md index 63fe8aa99..920e7042a 100644 --- a/release/README.md +++ b/release/README.md @@ -23,12 +23,12 @@ scenarios: To release a new major.minor release of Memgraph you should execute the following steps: - 1. Land all diffs that must be in the new release - 2. Document all changes in `CHANGELOG.md` and land them + 1. Merge all PRs that must be in the new release + 2. Document all changes in `CHANGELOG.md` and merge them 3. From the `master` branch, create a branch named `release/X.Y` and push it to `origin` - 4. Create the release packages triggering a `mg-master-release-branch-test` - using branch `release/X.Y` on Apollo + 4. Create the release packages triggering a `Release {{Operating System}}` + workflow using branch `release/X.Y` on Github Actions 5. Enjoy To release a new patch release in an existing major.minor series you should @@ -38,6 +38,6 @@ execute the following steps: 3. Document all changes in `CHANGELOG.md` and commit them 4. Edit the root `CMakeLists.txt` and set `MEMGRAPH_OVERRIDE_VERSION` to `X.Y.patch` and commit the change - 5. Create the release packages triggering a `mg-master-release-branch-test` - using branch `release/X.Y` on Apollo + 5. Create the release packages triggering a `Release {{Operating System}}` + workflow using branch `release/X.Y` on Github Actions 6. Enjoy