001/* 002 * Copyright 2021 DuraSpace, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.fcrepo.migration.handlers.ocfl; 017 018import java.io.InputStream; 019import java.time.OffsetDateTime; 020import java.util.List; 021import java.util.stream.Stream; 022 023import io.micrometer.core.instrument.Metrics; 024import io.micrometer.core.instrument.Timer; 025import org.fcrepo.storage.ocfl.CommitType; 026import org.fcrepo.storage.ocfl.OcflObjectSession; 027import org.fcrepo.storage.ocfl.OcflVersionInfo; 028import org.fcrepo.storage.ocfl.ResourceContent; 029import org.fcrepo.storage.ocfl.ResourceHeaders; 030 031/** 032 * A wrapper similar to the FcrepoOcflObjectSessionWrapper to time operations 033 * 034 * @author mikejritter 035 */ 036public class OcflObjectSessionWrapper implements OcflObjectSession { 037 038 private final OcflObjectSession inner; 039 040 private static final String METRIC_NAME = "fcrepo.storage.ocfl.object"; 041 private static final String OPERATION = "operation"; 042 private static final Timer writeTimer = Metrics.timer(METRIC_NAME, OPERATION, "write"); 043 private static final Timer writeHeadersTimer = Metrics.timer(METRIC_NAME, OPERATION, "writeHeaders"); 044 private static final Timer deleteContentTimer = Metrics.timer(METRIC_NAME, OPERATION, "deleteContent"); 045 private static final Timer deleteResourceTimer = Metrics.timer(METRIC_NAME, OPERATION, "deleteResource"); 046 private static final Timer readHeadersTimer = Metrics.timer(METRIC_NAME, OPERATION, "readHeaders"); 047 private static final Timer readContentTimer = Metrics.timer(METRIC_NAME, OPERATION, "readContent"); 048 private static final Timer listVersionsTimer = Metrics.timer(METRIC_NAME, OPERATION, "listVersions"); 049 private static final Timer containsResourceTimer = Metrics.timer(METRIC_NAME, OPERATION, "containsResource"); 050 private static final Timer commitTimer = Metrics.timer(METRIC_NAME, OPERATION, "commit"); 051 052 053 public OcflObjectSessionWrapper(final OcflObjectSession inner) { 054 this.inner = inner; 055 } 056 057 @Override 058 public String sessionId() { 059 return inner.sessionId(); 060 } 061 062 @Override 063 public String ocflObjectId() { 064 return inner.ocflObjectId(); 065 } 066 067 @Override 068 public ResourceHeaders writeResource(final ResourceHeaders headers, final InputStream content) { 069 // The ocfl write further down expects content to be nullable, so if it is null just continue to pass it down 070 final var countingStream = content != null ? new CountingInputStream(content) : null; 071 return writeTimer.record(() -> inner.writeResource(headers, countingStream)); 072 } 073 074 @Override 075 public void writeHeaders(final ResourceHeaders headers) { 076 writeHeadersTimer.record(() -> inner.writeHeaders(headers)); 077 } 078 079 @Override 080 public void deleteContentFile(final ResourceHeaders headers) { 081 deleteContentTimer.record(() -> inner.deleteContentFile(headers)); 082 } 083 084 @Override 085 public void deleteResource(final String resourceId) { 086 deleteResourceTimer.record(() -> inner.deleteResource(resourceId)); 087 } 088 089 @Override 090 public boolean containsResource(final String resourceId) { 091 return containsResourceTimer.record(() -> inner.containsResource(resourceId)); 092 } 093 094 @Override 095 public ResourceHeaders readHeaders(final String resourceId) { 096 return readHeadersTimer.record(() -> inner.readHeaders(resourceId)); 097 } 098 099 @Override 100 public ResourceHeaders readHeaders(final String resourceId, final String versionNumber) { 101 return readHeadersTimer.record(() -> inner.readHeaders(resourceId, versionNumber)); 102 } 103 104 @Override 105 public ResourceContent readContent(final String resourceId) { 106 return readContentTimer.record(() -> inner.readContent(resourceId)); 107 } 108 109 @Override 110 public ResourceContent readContent(final String resourceId, final String versionNumber) { 111 return readContentTimer.record(() -> inner.readContent(resourceId, versionNumber)); 112 } 113 114 @Override 115 public ResourceContent readRange(final String resourceId, final String versionNumber, 116 final long startPosition, final long endPosition) { 117 return readContentTimer.record(() -> inner.readRange(resourceId, versionNumber, 118 startPosition, endPosition)); 119 } 120 121 @Override 122 public ResourceContent readRange(final String resourceId, final long startPosition, final long endPosition) { 123 return readContentTimer.record(() -> inner.readRange(resourceId, null, startPosition, endPosition)); 124 } 125 126 @Override 127 public List<OcflVersionInfo> listVersions(final String resourceId) { 128 return listVersionsTimer.record(() -> inner.listVersions(resourceId)); 129 } 130 131 @Override 132 public Stream<ResourceHeaders> streamResourceHeaders() { 133 return inner.streamResourceHeaders(); 134 } 135 136 @Override 137 public void versionCreationTimestamp(final OffsetDateTime timestamp) { 138 inner.versionCreationTimestamp(timestamp); 139 } 140 141 @Override 142 public void versionAuthor(final String name, final String address) { 143 inner.versionAuthor(name, address); 144 } 145 146 @Override 147 public void versionMessage(final String message) { 148 inner.versionMessage(message); 149 } 150 151 @Override 152 public void invalidateCache(final String objectId) { 153 inner.invalidateCache(objectId); 154 } 155 156 @Override 157 public void commitType(final CommitType commitType) { 158 inner.commitType(commitType); 159 } 160 161 @Override 162 public void commit() { 163 commitTimer.record(inner::commit); 164 } 165 166 @Override 167 public void abort() { 168 inner.abort(); 169 } 170 171 @Override 172 public void rollback() { 173 inner.rollback(); 174 } 175 176 @Override 177 public boolean isOpen() { 178 return inner.isOpen(); 179 } 180 181 @Override 182 public void close() { 183 inner.close(); 184 } 185}