private RecordId writeMap()

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);
        }