This PR adds a writing API and implements the md_apply_delta using the API. There's also a few other changes to enable this work:
query_cxt_t and its members were renamed to acccess_cxt_t and moved to the internal header (for declarations) and access.c (for definitions).
Basic cursor manipulation functions were moved into internal.h so they can be used from multiple implementation files.
write_* variants were added to bytes.c that mirror the read_* methods.
mdmem_t and family were changed to make the mdmem_t structure an implementation detail that isn't exposed outside of the linked-list that tracks allocated memory.
Users can get a token from a cursor that points just past the end of a table.
Users can get a token from a cursor that points to the 0th entry of a table that has no entries (aka does not exist).
The new public APIs are split into three categories:
Write columns
These methods are all in the shape of md_set_column_value_as_* and mirror the shape of the corresponding md_get_column_value_as_* methods.
Add rows
There are methods for inserting rows in a particular spot in a table and a method for inserting rows into tables that represent lists of items (like Field, MethodDef, Param, Property, Event).
I try to preserve the "is sorted" bit on tables when possible for better performance. There's a method to mark a row as "this row has been initialized" that validates sorting. After adding a row and before this method is called, the table is treated as unsorted.
Add a user string to the heap
User strings can be added to the heap separate from metadata column entries, so there's a separate API to directly add them.
The code is split into different files per this logic:
access.c: Raw reading/writing of column data and traversal of column data between rows.
bytes.c: Raw reading/writing of data at the byte/primitive level
streams.c: Introspection into stream/heap data and logic around heap ids
tables.c: Introspection into table data and logic around table ids and structure
query.c: Reading data from cursors
write.c: Writing data to cursors. Adding rows to tables.
editor.c: High level memory management of tables/heaps
Allocates writable memory and maintains pointers on DNMD's internal API surface to point to valid data.
Allocates new tables as necessary and ensures that tables are allocated with expected layouts.
Resizes table columns as needed to ensure that table schemas are up to date with the current sizes of tables.
Adding new data to heaps/streams.
deltas.c: Implements delta application by traversing the ENCLog and ENCMap tables.
There are two TODOs left for this PR, but I think enough is in place to do a review:
[X] As an optimization, some writers (ILASM) will write a 0 table index for columns that have no entries (like a type with no fields). CoreCLR's metadata library will change this value when an indirection table is added. I need to investigate if we need to do the same.
I think we're good here with how we implemented our querying API. Our implementation should be okay.
[x] The EnC Log operation to add a parameter has some slightly different logic in CoreCLR than the rest of the "add to list" operations. I need to take a closer look and determine what if anything needs to be done in DNMD to match behavior.
This PR adds a writing API and implements the
md_apply_delta
using the API. There's also a few other changes to enable this work:query_cxt_t
and its members were renamed toacccess_cxt_t
and moved to the internal header (for declarations) and access.c (for definitions).internal.h
so they can be used from multiple implementation files.write_*
variants were added tobytes.c
that mirror theread_*
methods.The new public APIs are split into three categories:
md_set_column_value_as_*
and mirror the shape of the correspondingmd_get_column_value_as_*
methods.The code is split into different files per this logic:
There are two TODOs left for this PR, but I think enough is in place to do a review:
0
table index for columns that have no entries (like a type with no fields). CoreCLR's metadata library will change this value when an indirection table is added. I need to investigate if we need to do the same.