fix: Fix overflow for vertex/edge insersion#8
Open
zhanglei1949 wants to merge 23 commits intomainfrom
Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR targets the 4096 insert failure (issue #7) by introducing proactive capacity growth for vertex/edge storage structures so that sequential CREATE statements can continue past the default reserved space.
Changes:
- Add
EnsureCapacityAPIs for vertex/edge storage and call them before inserts to avoid “reserved space exhausted” failures. - Introduce edge-table capacity tracking for unbundled edges and expose capacity/size helpers across storage layers.
- Add/extend Python binding tests for high-volume vertex/edge insertions; adjust some logging/error handling paths.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/python_bind/tests/test_tp_service.py | Adds TP service stress tests for inserting many vertices/edges; also updates execute() call style to pass access_mode. |
| tools/python_bind/tests/test_db_query.py | Adds embedded/local test for inserting many edges and validating count. |
| src/utils/property/column.cc | Fixes missing return in TypedEmptyColumn<T>::get_view. |
| src/transaction/update_transaction.cc | Calls graph_.EnsureCapacity(...) before vertex/edge inserts. |
| src/storages/graph/vertex_table.cc | Adds VertexTable::EnsureCapacity helper. |
| src/storages/graph/property_graph.cc | Adds PropertyGraph::EnsureCapacity for vertices/edges and improves vertex add error message. |
| src/storages/graph/graph_interface.cc | Calls EnsureCapacity in AP update interface before vertex/edge inserts. |
| src/storages/graph/edge_table.cc | Tracks/resizes unbundled edge property-table capacity and adds EdgeTable::EnsureCapacity. |
| src/storages/csr/mutable_csr.cc | Adds CSR capacity() API implementation. |
| src/storages/csr/immutable_csr.cc | Adds CSR capacity() API implementation. |
| src/server/neug_db_session.cc | Adds exception handling around transaction commit and returns structured internal errors. |
| src/compiler/planner/gopt_planner.cc | Downgrades compilePlan query logging from INFO to VLOG(1). |
| include/neug/storages/graph/vertex_table.h | Declares EnsureCapacity and adds Size() accessor. |
| include/neug/storages/graph/property_graph.h | Declares EnsureCapacity APIs (vertex and edge). |
| include/neug/storages/graph/edge_table.h | Declares EnsureCapacity, adds size/capacity helpers and capacity tracking member. |
| include/neug/storages/csr/csr_base.h | Adds pure virtual capacity() API for CSRs. |
| include/neug/storages/csr/mutable_csr.h | Declares capacity() overrides for mutable CSRs. |
| include/neug/storages/csr/immutable_csr.h | Declares capacity() overrides for immutable CSRs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
3fee21b to
12a19e3
Compare
Collaborator
Author
|
@greptile |
db68d39 to
ac3638f
Compare
Collaborator
Author
|
@greptile |
Committed-by: xiaolei.zl from Dev container Committed-by: xiaolei.zl from Dev container add capacity api Committed-by: xiaolei.zl from Dev container fix CI Committed-by: xiaolei.zl from Dev container remove tests for TP Committed-by: xiaolei.zl from Dev container Committed-by: xiaolei.zl from Dev container fixing Committed-by: xiaolei.zl from Dev container Committed-by: xiaolei.zl from Dev container Committed-by: xiaolei.zl from Dev container fix Update src/storages/graph/edge_table.cc Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> fixes fix use explicit capacity calculation for EnsureCapacity
3244938 to
a2f627c
Compare
Collaborator
Author
|
@greptile |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Collaborator
Author
|
@greptile |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Collaborator
Author
|
@greptile |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Louyk14
pushed a commit
that referenced
this pull request
Mar 12, 2026
- Add `.clang-format`. - Remove constraint of singleton `GraphDB`.
Committed-by: xiaolei.zl from Dev container
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix #7
Related Greptile view at https://github.com/GraphScope/neug/pull/1725
Greptile Summary
This PR fixes overflow issues during vertex and edge insertion by introducing explicit capacity tracking with a new
calculate_new_capacity()growth function (growth.h), persisted statistics files for edge tables, andEnsureCapacitymethods onVertexTable,EdgeTable, andPropertyGraph. It also fixes theTypedColumn<string_view>write-cursor persistence bug (.posfile) and removes the compaction-triggered buffer shrink that was destroying reserved capacity.Key changes:
growth.hprovides overflow-safe capacity growth (2× for vertices, ~20% for edges)EdgeTablegainscapacity_atomic,EnsureCapacity(), and a statistics file written onDump()/ read onOpen()to survive restartsVertexTable::Open()signature simplified (removed unusedbuild_empty_graphparam); eagerkeys_->resize()removed fromLFIndexer::open()TypedColumn<string_view>::pos_now persisted to a.posfile instead of being re-derived fromdata_size()after compactionmmap_array::compact()no longer shrinks the data buffer reservationIssues found:
AddEdge(update_transaction.cc), the WAL entry is serialized andop_num_incremented beforeEnsureCapacityis called. If the capacity check subsequently fails, the WAL contains a spurious uncommitted edge that was never applied, breaking WAL replay integrity.table_cap != capacity_integrity check inEdgeTable::Open/OpenInMemory/OpenWithHugepagesbreaks backward compatibility: upgrading an existing database (without statistics files) throws an exception for any non-empty edge table becausecapacity_is back-filled to0when no statistics file is found.growth.his missing#include <limits>forstd::numeric_limits.insert_edges_bundled_typed_implcallsedge_data.reserve(edge_data.size())(reserves 0) instead ofedge_data.reserve(property_vec.size()).read_fileopens files with"r"(text mode) instead of"rb"— a portability concern for binary data.Confidence Score: 2/5
Important Files Changed
Sequence Diagram
sequenceDiagram participant Client participant UpdateTransaction participant PropertyGraph participant VertexTable participant EdgeTable participant WAL Client->>UpdateTransaction: AddVertex(label, oid, props) UpdateTransaction->>PropertyGraph: EnsureCapacity(label) PropertyGraph->>VertexTable: EnsureCapacity(capacity) VertexTable-->>PropertyGraph: new_cap PropertyGraph-->>UpdateTransaction: Status::OK UpdateTransaction->>WAL: InsertVertexRedo::Serialize(...) UpdateTransaction->>PropertyGraph: AddVertex(...) PropertyGraph-->>UpdateTransaction: vid Client->>UpdateTransaction: AddEdge(src, dst, edge, props) Note over UpdateTransaction,WAL: ⚠️ BUG: Serialize happens BEFORE EnsureCapacity UpdateTransaction->>WAL: InsertEdgeRedo::Serialize(...) UpdateTransaction->>UpdateTransaction: op_num_ += 1 UpdateTransaction->>PropertyGraph: EnsureCapacity(src, dst, edge) alt EnsureCapacity fails PropertyGraph-->>UpdateTransaction: Status::ERR UpdateTransaction-->>Client: false (WAL already written!) else EnsureCapacity succeeds PropertyGraph->>EdgeTable: EnsureCapacity(capacity) EdgeTable-->>PropertyGraph: OK UpdateTransaction->>PropertyGraph: AddEdge(...) PropertyGraph-->>UpdateTransaction: oe_offset end Client->>PropertyGraph: Dump() PropertyGraph->>VertexTable: EnsureCapacity(calculate_new_capacity(size)) PropertyGraph->>EdgeTable: EnsureCapacity(calculate_new_capacity(Size())) EdgeTable->>EdgeTable: table_->resize(capacity) PropertyGraph->>VertexTable: Dump() PropertyGraph->>EdgeTable: Dump() EdgeTable->>EdgeTable: write_statistic_file(Capacity(), Size())Comments Outside Diff (4)
src/transaction/update_transaction.cc, line 738-746 (link)Redo log serialized before capacity check — inconsistent transaction state on failure
InsertEdgeRedo::Serializeandop_num_ += 1are executed on lines 738–741 beforeEnsureCapacityis checked on line 742. IfEnsureCapacityreturns an error (e.g., the edge label triplet doesn't exist), the function returnsfalsebut the redo log (arc_) already contains a serialized edge entry andop_num_has been incremented. This leaves the transaction's redo log in an inconsistent state and could cause incorrect replay during crash recovery.This is directly inconsistent with the pattern used in the
AddVertexfunction in this same file (lines 683–691), which correctly callsEnsureCapacitybefore callingInsertVertexRedo::Serializeand incrementingop_num_.The fix is to move the
EnsureCapacitycall (and early return on failure) before the serialize/increment:src/transaction/update_transaction.cc, line 738-746 (link)Redo log serialized before capacity check — transaction log corruption on failure
InsertEdgeRedo::Serialize(line 738) andop_num_ += 1(line 741) execute beforeEnsureCapacityis checked. IfEnsureCapacityreturns an error and the function returnsfalse, the redo log entry has already been appended andop_num_incremented, but the edge was never actually inserted. This leaves the transaction log in an inconsistent state and could cause incorrect replay during recovery.This is directly inconsistent with the fixed
AddVertexpath in the same file (lines 683–692), where serialization is correctly placed after the capacity check:The
AddEdgeblock should follow the same pattern:src/transaction/update_transaction.cc, line 738-746 (link)Redo log serialized before capacity check
InsertEdgeRedo::Serialize(line 738) andop_num_ += 1(line 741) are called beforeEnsureCapacity(line 742). IfEnsureCapacityfails and the function returnsfalse, the WAL already contains the edge-insert entry andop_num_has been incremented — but the edge was never actually written to the graph.On WAL replay after a crash at this point, the replayed edge insertion would fail again (or worse, succeed spuriously with uninitialised capacity), corrupting the graph state.
The
AddVertexpath (line 683) does this correctly: it callsEnsureCapacityfirst, and only then serializes the redo entry.AddEdgeshould follow the same ordering:src/storages/graph/edge_table.cc, line 263-264 (link)reservereserves 0 instead of the intended sizeedge_datais freshly default-constructed, soedge_data.size()is0. The calledge_data.reserve(edge_data.size())is a no-op and the intent was clearly to pre-allocateproperty_vec.size()slots to avoid repeated reallocations during the loop below.Last reviewed commit: f6501a8