@Override public <K extends Comparable<? super K>, V extends Record, T extends KeyValuePage<K, V>> T combineRecordPages( final List<T> pages, final @Nonnegative int revToRestore, final PageReadTrx pageReadTrx) { assert pages.size() <= 2; final T firstPage = pages.get(0); final long recordPageKey = firstPage.getPageKey(); final T returnVal = firstPage.newInstance( recordPageKey, firstPage.getPageKind(), firstPage.getPreviousReference(), pageReadTrx); if (pages.size() == 2) { returnVal.setDirty(true); } final T latest = pages.get(0); T fullDump = pages.size() == 1 ? pages.get(0) : pages.get(1); assert latest.getPageKey() == recordPageKey; assert fullDump.getPageKey() == recordPageKey; for (final Map.Entry<K, V> entry : latest.entrySet()) { returnVal.setEntry(entry.getKey(), entry.getValue()); } for (final Map.Entry<K, PageReference> entry : latest.referenceEntrySet()) { returnVal.setPageReference(entry.getKey(), entry.getValue()); } // Skip full dump if not needed (fulldump equals latest page). if (pages.size() == 2) { for (final Entry<K, V> entry : fullDump.entrySet()) { if (returnVal.getValue(entry.getKey()) == null) { returnVal.setEntry(entry.getKey(), entry.getValue()); if (returnVal.size() == Constants.NDP_NODE_COUNT) { break; } } } for (final Entry<K, PageReference> entry : fullDump.referenceEntrySet()) { if (returnVal.getPageReference(entry.getKey()) == null) { returnVal.setPageReference(entry.getKey(), entry.getValue()); if (returnVal.size() == Constants.NDP_NODE_COUNT) { break; } } } } return returnVal; }
@Override public R apply(final T inputMap, final F function) { final R result = mapCreator.createMap(); for (final Entry<? extends K, ? extends E> entry : inputMap.entrySet()) { final Pair<NK, NE> mappedKeyValuepPair = function.apply(entry.getKey(), entry.getValue()); result.put(mappedKeyValuepPair.getValue1(), mappedKeyValuepPair.getValue2()); } return result; }
@Override public String marshall(final T o, final MarshallingSession ctx) { final StringBuilder buf = new StringBuilder(); buf.append("{"); int i = 0; for (final Map.Entry<Object, Object> entry : o.entrySet()) { if (i++ > 0) { buf.append(","); } final Marshaller<Object> keyMarshaller; final Marshaller<Object> valueMarshaller; if (entry.getKey() instanceof String) { buf.append("\"").append(entry.getKey()).append("\""); } else if (entry.getKey() != null) { if ((entry.getKey() instanceof Number && !(entry.getKey() instanceof BigInteger || entry.getKey() instanceof BigDecimal)) || entry.getKey() instanceof Boolean || entry.getKey() instanceof Character) { keyMarshaller = MarshallUtil.getQualifiedNumberMarshaller(entry.getKey()); } else { keyMarshaller = MarshallUtil.getMarshaller(entry.getKey(), ctx); } buf.append(("\"" + SerializationParts.EMBEDDED_JSON)) .append( MarshallUtil.jsonStringEscape( keyMarshaller.marshall(MarshallUtil.maybeUnwrap(entry.getKey()), ctx))) .append("\""); } else { buf.append("\"" + SerializationParts.NULL_VALUE + "\""); } buf.append(":"); if (entry.getValue() == null) { buf.append("null"); } else { if ((entry.getValue() instanceof Number && !(entry.getValue() instanceof BigInteger || entry.getValue() instanceof BigDecimal)) || entry.getValue() instanceof Boolean || entry.getValue() instanceof Character) { valueMarshaller = MarshallUtil.getQualifiedNumberMarshaller(entry.getValue()); } else { valueMarshaller = MarshallUtil.getMarshaller(entry.getValue(), ctx); } buf.append(valueMarshaller.marshall(MarshallUtil.maybeUnwrap(entry.getValue()), ctx)); } } return buf.append("}").toString(); }
@Override public <K extends Comparable<? super K>, V extends Record, T extends KeyValuePage<K, V>> T combineRecordPages( final List<T> pages, final @Nonnegative int revToRestore, final PageReadTrx pageReadTrx) { assert pages.size() <= revToRestore; final T firstPage = pages.get(0); final long recordPageKey = firstPage.getPageKey(); final T returnVal = firstPage.newInstance( firstPage.getPageKey(), firstPage.getPageKind(), firstPage.getPreviousReference(), firstPage.getPageReadTrx()); if (pages.size() > 1) { returnVal.setDirty(true); } boolean filledPage = false; for (int i = 0; i < pages.size(); i++) { final T page = pages.get(i); assert page.getPageKey() == recordPageKey; if (filledPage) { break; } for (final Entry<K, V> entry : page.entrySet()) { final K recordKey = entry.getKey(); if (returnVal.getValue(recordKey) == null) { returnVal.setEntry(recordKey, entry.getValue()); if (returnVal.size() == Constants.NDP_NODE_COUNT) { filledPage = true; break; } } } if (!filledPage) { for (final Entry<K, PageReference> entry : page.referenceEntrySet()) { final K recordKey = entry.getKey(); if (returnVal.getPageReference(recordKey) == null) { returnVal.setPageReference(recordKey, entry.getValue()); if (returnVal.size() == Constants.NDP_NODE_COUNT) { filledPage = true; break; } } } } } return returnVal; }
@Override public <K extends Comparable<? super K>, V extends Record, T extends KeyValuePage<K, V>> RecordPageContainer<T> combineRecordPagesForModification( final List<T> pages, final int revToRestore, final PageReadTrx pageReadTrx, final PageReference reference) { final T firstPage = pages.get(0); final long recordPageKey = firstPage.getPageKey(); final List<T> returnVal = new ArrayList<>(2); returnVal.add( firstPage.<T>newInstance( recordPageKey, firstPage.getPageKind(), Optional.of(reference), pageReadTrx)); returnVal.add( firstPage.<T>newInstance( recordPageKey, firstPage.getPageKind(), Optional.of(reference), pageReadTrx)); final T reconstructed = firstPage.<T>newInstance( recordPageKey, firstPage.getPageKind(), Optional.of(reference), pageReadTrx); boolean filledPage = false; for (int i = 0; i < pages.size() && !filledPage; i++) { final T page = pages.get(i); assert page.getPageKey() == recordPageKey; final boolean pageToSerialize = (i == pages.size() - 1 && revToRestore == pages.size()); for (final Entry<K, V> entry : page.entrySet()) { // Caching the complete page. final K key = entry.getKey(); assert key != null; if (!pageToSerialize) { reconstructed.setEntry(key, entry.getValue()); } if (returnVal.get(0).getValue(key) == null) { returnVal.get(0).setEntry(key, entry.getValue()); } if (pageToSerialize && reconstructed.getValue(key) == null) { returnVal.get(1).setEntry(key, entry.getValue()); } if (returnVal.get(0).size() == Constants.NDP_NODE_COUNT) { filledPage = true; break; } } if (!filledPage) { for (final Entry<K, PageReference> entry : page.referenceEntrySet()) { // Caching the complete page. final K key = entry.getKey(); assert key != null; if (!pageToSerialize) { reconstructed.setPageReference(key, entry.getValue()); } if (returnVal.get(0).getPageReference(key) == null) { returnVal.get(0).setPageReference(key, entry.getValue()); } if (pageToSerialize && reconstructed.getPageReference(key) == null) { returnVal.get(1).setPageReference(key, entry.getValue()); } if (returnVal.get(0).size() == Constants.NDP_NODE_COUNT) { filledPage = true; break; } } } } return new RecordPageContainer<>(returnVal.get(0), returnVal.get(1)); }
@Override public <K extends Comparable<? super K>, V extends Record, T extends KeyValuePage<K, V>> RecordPageContainer<T> combineRecordPagesForModification( final List<T> pages, final int revToRestore, final PageReadTrx pageReadTrx, final PageReference reference) { final T firstPage = pages.get(0); final long recordPageKey = firstPage.getPageKey(); // final int revision = pageReadTrx.getUberPage().getRevision(); final List<T> returnVal = new ArrayList<>(2); returnVal.add( firstPage.<T>newInstance( recordPageKey, firstPage.getPageKind(), Optional.of(reference), pageReadTrx)); returnVal.add( firstPage.<T>newInstance( recordPageKey, firstPage.getPageKind(), Optional.of(reference), pageReadTrx)); final boolean isFullDump = pages.size() == revToRestore; // (revision + 1) // % revToRestore // == 0; boolean filledPage = false; for (final T page : pages) { assert page.getPageKey() == recordPageKey; if (filledPage) { break; } for (final Entry<K, V> entry : page.entrySet()) { // Caching the complete page. final K key = entry.getKey(); assert key != null; if (entry != null && returnVal.get(0).getValue(key) == null) { returnVal.get(0).setEntry(key, entry.getValue()); if (returnVal.get(1).getValue(entry.getKey()) == null && isFullDump) { returnVal.get(1).setEntry(key, entry.getValue()); } if (returnVal.get(0).size() == Constants.NDP_NODE_COUNT) { filledPage = true; break; } } } if (!filledPage) { for (final Entry<K, PageReference> entry : page.referenceEntrySet()) { // Caching the complete page. final K key = entry.getKey(); assert key != null; if (entry != null && returnVal.get(0).getPageReference(key) == null) { returnVal.get(0).setPageReference(key, entry.getValue()); if (returnVal.get(1).getPageReference(entry.getKey()) == null && isFullDump) { returnVal.get(1).setPageReference(key, entry.getValue()); } if (returnVal.get(0).size() == Constants.NDP_NODE_COUNT) { filledPage = true; break; } } } } } return new RecordPageContainer<>(returnVal.get(0), returnVal.get(1)); }
@Override public <K extends Comparable<? super K>, V extends Record, T extends KeyValuePage<K, V>> RecordPageContainer<T> combineRecordPagesForModification( final List<T> pages, final @Nonnegative int revToRestore, final PageReadTrx pageReadTrx, final PageReference reference) { assert pages.size() <= 2; final T firstPage = pages.get(0); final long recordPageKey = firstPage.getPageKey(); final int revision = pageReadTrx.getUberPage().getRevision(); final List<T> returnVal = new ArrayList<>(2); returnVal.add( firstPage.<T>newInstance( recordPageKey, firstPage.getPageKind(), Optional.of(reference), pageReadTrx)); returnVal.add( firstPage.<T>newInstance( recordPageKey, firstPage.getPageKind(), Optional.of(reference), pageReadTrx)); final T latest = firstPage; T fullDump = pages.size() == 1 ? firstPage : pages.get(1); final boolean isFullDump = revision % revToRestore == 0; // Iterate through all nodes of the latest revision. for (final Map.Entry<K, V> entry : latest.entrySet()) { returnVal.get(0).setEntry(entry.getKey(), entry.getValue()); returnVal.get(1).setEntry(entry.getKey(), entry.getValue()); } // Iterate through all nodes of the latest revision. for (final Map.Entry<K, PageReference> entry : latest.referenceEntrySet()) { returnVal.get(0).setPageReference(entry.getKey(), entry.getValue()); returnVal.get(1).setPageReference(entry.getKey(), entry.getValue()); } // If not all entries are filled. if (latest.size() != Constants.NDP_NODE_COUNT) { // Iterate through the full dump. for (final Map.Entry<K, V> entry : fullDump.entrySet()) { if (returnVal.get(0).getValue(entry.getKey()) == null) { returnVal.get(0).setEntry(entry.getKey(), entry.getValue()); } if (isFullDump && returnVal.get(1).getValue(entry.getKey()) == null) { returnVal.get(1).setEntry(entry.getKey(), entry.getValue()); } if (returnVal.get(0).size() == Constants.NDP_NODE_COUNT) { // Page is filled, thus skip all other entries of the full dump. break; } } } // If not all entries are filled. if (latest.size() != Constants.NDP_NODE_COUNT) { // Iterate through the full dump. for (final Map.Entry<K, PageReference> entry : fullDump.referenceEntrySet()) { if (returnVal.get(0).getPageReference(entry.getKey()) == null) { returnVal.get(0).setPageReference(entry.getKey(), entry.getValue()); } if (isFullDump && returnVal.get(1).getPageReference(entry.getKey()) == null) { returnVal.get(1).setPageReference(entry.getKey(), entry.getValue()); } if (returnVal.get(0).size() == Constants.NDP_NODE_COUNT) { // Page is filled, thus skip all other entries of the full dump. break; } } } return new RecordPageContainer<>(returnVal.get(0), returnVal.get(1)); }