@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() == 1; 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)); for (final Map.Entry<K, V> entry : pages.get(0).entrySet()) { returnVal.get(0).setEntry(entry.getKey(), entry.getValue()); returnVal.get(1).setEntry(entry.getKey(), entry.getValue()); } return new RecordPageContainer<>(returnVal.get(0), returnVal.get(1)); }
/** Returns a clone with exactly the requested fields shallowly copied */ @SuppressWarnings("unchecked") private static <T extends Persistent> T getPersistent(T obj, String[] fields) { if (Arrays.equals(fields, obj.getFields())) { return obj; } T newObj = (T) obj.newInstance(new StateManagerImpl()); for (String field : fields) { int index = newObj.getFieldIndex(field); ((PersistentBase) newObj).put(index, ((PersistentBase) obj).get(index)); } return newObj; }
@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 <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)); }