blob: ccae14e1fdece96a5cc54b5cf88e8b759fafb9dd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.admin.remote;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import org.apache.geode.DataSerializer;
import org.apache.geode.GemFireCacheException;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.CacheStatistics;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.StatisticsDisabledException;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
/**
* Responds to {@link ObjectDetailsRequest}.
*/
public class ObjectDetailsResponse extends AdminResponse implements Cancellable {
// instance variables
private Object objectValue;
private Object userAttribute;
private RemoteCacheStatistics stats;
private transient boolean cancelled;
/**
* Returns a <code>ObjectValueResponse</code> that will be returned to the specified recipient.
* The message will contains a copy of the local manager's system config.
*/
public static ObjectDetailsResponse create(DistributionManager dm,
InternalDistributedMember recipient) {
ObjectDetailsResponse m = new ObjectDetailsResponse();
m.setRecipient(recipient);
return m;
}
void buildDetails(Region r, Object objName, int inspectionType) {
try {
objName = getObjectName(r, objName);
if (cancelled)
return;
if (r.containsKey(objName)) {
if (cancelled)
return;
// @todo darrel: race condition; could be unloaded between isPresent and get call.
Region.Entry e = r.getEntry(objName);
Object v = e.getValue();
if (cancelled)
return;
objectValue = CacheDisplay.getCachedObjectDisplay(v, inspectionType);
if (cancelled)
return;
userAttribute = CacheDisplay.getCachedObjectDisplay(e.getUserAttribute(), inspectionType);
if (cancelled)
return;
try {
stats = new RemoteCacheStatistics(e.getStatistics());
} catch (StatisticsDisabledException ignore) {
}
}
} catch (CacheException ex) {
throw new GemFireCacheException(ex);
}
}
@Override
public synchronized void cancel() {
cancelled = true;
}
// instance methods
public Object getObjectValue() {
return this.objectValue;
}
public Object getUserAttribute() {
return this.userAttribute;
}
public CacheStatistics getStatistics() {
return this.stats;
}
@Override
public int getDSFID() {
return OBJECT_DETAILS_RESPONSE;
}
@Override
public void toData(DataOutput out) throws IOException {
super.toData(out);
DataSerializer.writeObject(this.objectValue, out);
DataSerializer.writeObject(this.userAttribute, out);
DataSerializer.writeObject(this.stats, out);
}
@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
super.fromData(in);
this.objectValue = DataSerializer.readObject(in);
this.userAttribute = DataSerializer.readObject(in);
this.stats = (RemoteCacheStatistics) DataSerializer.readObject(in);
}
@Override
public String toString() {
return "ObjectDetailsResponse from " + this.getRecipient();
}
// Holds the last result of getObjectName to optimize the next call
@MakeNotStatic
private static Object lastObjectNameFound = null;
static Object getObjectName(Region r, Object objName) throws CacheException {
if (objName instanceof RemoteObjectName) {
synchronized (ObjectDetailsResponse.class) {
if (objName.equals(lastObjectNameFound)) {
return lastObjectNameFound;
}
}
Object obj = null;
Set keys = r.keySet();
synchronized (r) {
Iterator it = keys.iterator();
while (it.hasNext()) {
Object o = it.next();
if (objName.equals(o)) {
synchronized (ObjectDetailsResponse.class) {
lastObjectNameFound = o;
}
obj = o;
break;
}
}
}
if (obj != null) {
return obj;
}
// Didn't find it so just return the input RemoteObjectName instance.
// This should fail on the lookup and give a reasonable error.
synchronized (ObjectDetailsResponse.class) {
lastObjectNameFound = objName;
}
}
return objName;
}
}