Skip to content

Commit 75ec723

Browse files
dougqhclaude
andcommitted
Make TagMap a facade over an id store and a name store
TagMap keeps known tags in an IdStore (by id) and custom tags in a HashStore (by name), instead of one bucket array. A name is classified once, at the boundary, and routed to its store; known and custom tags never share a key, so read-through and precedence work per store and never cross between them. The name store is created on the first custom write; until then a map borrows its read-through parent's store read-only. Behavior is unchanged: the TagMap suites pass as they are, and Entry objects are still shared across copies. The span still holds a single TagMap; it starts owning the stores directly in the next change. TagMap.Internals stays for now, writing straight to the id store, and goes away with that change. Reads by id go straight to the id store. stream() and spliterator() yield stable Entries, and getEntryReader gives a momentary reader for typed reads. TagStoresTest covers the stores through TagMap, and IdStoreContractTest gains the view cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent ec6ec40 commit 75ec723

8 files changed

Lines changed: 1012 additions & 834 deletions

File tree

‎gradle/forbiddenApiFilters/instrumentation.txt‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,14 @@ datadog.trace.bootstrap.instrumentation.api.AgentSpan#setServiceName(java.lang.S
77
# (see datadog.apicontract.Restricted). Instrumentation uses TagMap's checked methods.
88
@defaultMessage TagMap.internals() is restricted to the tracer core; use TagMap's checked methods instead.
99
datadog.trace.api.TagMap#internals()
10+
11+
# A span's tag stores, how it gets them from a parent, and the span's view of them skip checks the tracer
12+
# core has already made; they are @Restricted to the core (see datadog.apicontract.Restricted).
13+
# Instrumentation uses TagMap's checked methods.
14+
@defaultMessage Tag stores are restricted to the tracer core; use TagMap's checked methods instead.
15+
datadog.trace.api.HashStore
16+
datadog.trace.api.IdStore
17+
datadog.trace.api.TagMap#readThroughParent(datadog.trace.api.TagMap)
18+
datadog.trace.api.TagMap#viewOf(datadog.trace.api.IdStore,datadog.trace.api.HashStore,boolean)
19+
datadog.trace.api.TagMap#customStore()
20+
datadog.trace.api.TagMap#isCustomStoreBorrowed()

‎internal-api/src/main/java/datadog/trace/api/HashStore.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ public final class HashStore {
3838
*/
3939
private Set<String> removedFromParent;
4040

41+
/**
42+
* {@code parent}'s custom store, for an owner to borrow read-only until its first custom write,
43+
* or null.
44+
*/
45+
public static HashStore inheritedFrom(TagMap parent) {
46+
return parent == null ? null : parent.nameStore;
47+
}
48+
4149
/**
4250
* A fresh custom store for an owner's first custom write, reading through to {@code borrowed},
4351
* the store it borrowed until now (may be null).

‎internal-api/src/main/java/datadog/trace/api/HashSupport.java‎

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -414,24 +414,6 @@ static String toInternalString(Object[] buckets) {
414414
return ledger.toString();
415415
}
416416

417-
/** Whether {@code buckets} holds no entry, checked bucket by bucket. */
418-
static boolean isEmpty(Object[] buckets) {
419-
Object[] thisBuckets = buckets;
420-
421-
for (int i = 0; i < thisBuckets.length; ++i) {
422-
Object curBucket = thisBuckets[i];
423-
424-
if (curBucket instanceof Entry) {
425-
return false;
426-
} else if (curBucket instanceof BucketGroup) {
427-
BucketGroup curGroup = (BucketGroup) curBucket;
428-
if (!curGroup.isEmptyChain()) return false;
429-
}
430-
}
431-
432-
return true;
433-
}
434-
435417
/** Walks a bucket array's raw entries, tombstones included, for an iterator. */
436418
static final class BucketWalker {
437419
private Object[] buckets;

‎internal-api/src/main/java/datadog/trace/api/IdStore.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ interface Cursor {
2727
EntryReader next();
2828
}
2929

30+
/** A fresh id store reading through to {@code parent}'s known tags (parent may be null). */
31+
public static IdStore create(TagMap parent) {
32+
return IdStoreFactory.Default.INSTANCE.create(parent == null ? null : parent.knownStore);
33+
}
34+
3035
/** Throws for an id that names no known tag. */
3136
static IllegalArgumentException notKnown(long tagId) {
3237
return new IllegalArgumentException("not a known tag id: " + Long.toHexString(tagId));

0 commit comments

Comments
 (0)