in oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java [248:332]
private RecordId writeMap(@Nullable MapRecord base, @NotNull Map<String, RecordId> changes) throws IOException {
if (base != null) {
if (base.size() >= MapRecord.WARN_SIZE) {
int maxMapRecordSize = Integer.getInteger(MAX_MAP_RECORD_SIZE_KEY, 0);
if (base.size() > maxMapRecordSize) {
System.setProperty(MAX_MAP_RECORD_SIZE_KEY, String.valueOf(base.size()));
}
if (base.size() >= MapRecord.ERROR_SIZE_HARD_STOP) {
throw new UnsupportedOperationException("Map record has more than " + MapRecord.ERROR_SIZE_HARD_STOP
+ " direct entries. Writing is not allowed. Please remove entries.");
} else if (base.size() >= MapRecord.ERROR_SIZE_DISCARD_WRITES) {
if (!Boolean.getBoolean("oak.segmentNodeStore.allowWritesOnHugeMapRecord")) {
if (shouldLog()) {
LOG.error(
"Map entry has more than {} entries. Writing more than {} entries (up to the hard limit of {}) is only allowed "
+ "if the system property \"oak.segmentNodeStore.allowWritesOnHugeMapRecord\" is set",
MapRecord.ERROR_SIZE, MapRecord.ERROR_SIZE_DISCARD_WRITES, MapRecord.ERROR_SIZE_HARD_STOP);
}
throw new UnsupportedOperationException("Map record has more than " + MapRecord.ERROR_SIZE_DISCARD_WRITES
+ " direct entries. Writing is not allowed. Please remove entries.");
}
} else if (base.size() >= MapRecord.ERROR_SIZE) {
if (shouldLog()) {
LOG.error("Map entry has more than {} entries. Please remove entries.", MapRecord.ERROR_SIZE);
}
} else {
if (shouldLog()) {
LOG.warn("Map entry has more than {} entries. Please remove entries.", MapRecord.WARN_SIZE);
}
}
}
}
if (base != null && base.isDiff()) {
Segment segment = base.getSegment();
RecordId key = segment.readRecordId(base.getRecordNumber(), 8);
String name = reader.readString(key);
if (!changes.containsKey(name)) {
changes.put(name, segment.readRecordId(base.getRecordNumber(), 8, 1));
}
base = new MapRecord(reader, segment.readRecordId(base.getRecordNumber(), 8, 2));
}
if (base != null && changes.size() == 1) {
Map.Entry<String, RecordId> change =
changes.entrySet().iterator().next();
RecordId value = change.getValue();
if (value != null) {
MapEntry entry = base.getEntry(change.getKey());
if (entry != null) {
if (value.equals(entry.getValue())) {
return base.getRecordId();
} else {
return writeOperationHandler.execute(gcGeneration, newWriteOperation(
RecordWriters.newMapBranchWriter(
entry.getHash(),
asList(entry.getKey(), value, base.getRecordId()))));
}
}
}
}
List<MapEntry> entries = newArrayList();
for (Map.Entry<String, RecordId> entry : changes.entrySet()) {
String key = entry.getKey();
RecordId keyId = null;
if (base != null) {
MapEntry e = base.getEntry(key);
if (e != null) {
keyId = e.getKey();
}
}
if (keyId == null && entry.getValue() != null) {
keyId = writeString(key);
}
if (keyId != null) {
entries.add(newModifiedMapEntry(reader, key, keyId, entry.getValue()));
}
}
return writeMapBucket(base, entries, 0);
}