| /* |
| * 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.cache; |
| |
| import java.io.Serializable; |
| import java.util.Collection; |
| import java.util.Iterator; |
| |
| import org.apache.geode.CancelException; |
| import org.apache.geode.GemFireException; |
| import org.apache.geode.internal.cache.tier.sockets.VersionedObjectList; |
| |
| /** |
| * This exception is thrown if some sub-ops failed during a bulk operation. Current bulk ops are |
| * putAll and removeAll. Note: the name of this class is not changed to BulkOpPartialResultException |
| * to keep it compatible with old clients and old peers. |
| * |
| * |
| * |
| * @since GemFire 6.5 |
| */ |
| public class PutAllPartialResultException extends GemFireException { |
| |
| private static final long serialVersionUID = 2411654400733621071L; |
| |
| private PutAllPartialResult result; |
| |
| //////////////////// Constructors //////////////////// |
| |
| public PutAllPartialResultException(PutAllPartialResult result) { |
| super("Bulk operation had some failures"); |
| this.result = result; |
| } |
| |
| public PutAllPartialResultException() { |
| super("Bulk operation had some failures"); |
| result = new PutAllPartialResult(-1); |
| } |
| |
| /** |
| * consolidate exceptions |
| */ |
| public void consolidate(PutAllPartialResultException pre) { |
| this.result.consolidate(pre.getResult()); |
| } |
| |
| public void consolidate(PutAllPartialResult otherResult) { |
| this.result.consolidate(otherResult); |
| } |
| |
| public void setSucceededKeysAndVersions(VersionedObjectList keysAndVersions) { |
| this.result.setSucceededKeysAndVersions(keysAndVersions); |
| } |
| |
| public PutAllPartialResult getResult() { |
| return this.result; |
| } |
| |
| /** |
| * Returns the key set in exception |
| */ |
| public VersionedObjectList getSucceededKeysAndVersions() { |
| return this.result.getSucceededKeysAndVersions(); |
| } |
| |
| public Exception getFailure() { |
| return this.result.getFailure(); |
| } |
| |
| /** |
| * Returns there's failedKeys |
| */ |
| public boolean hasFailure() { |
| return this.result.hasFailure(); |
| } |
| |
| public Object getFirstFailedKey() { |
| return this.result.getFirstFailedKey(); |
| } |
| |
| @Override |
| public String getMessage() { |
| return this.result.toString(); |
| } |
| |
| public static class PutAllPartialResult implements Serializable { |
| private static final long serialVersionUID = -2168767259323206954L; |
| |
| private VersionedObjectList succeededKeys; |
| private Object firstFailedKey; |
| private Exception firstCauseOfFailure; |
| private int totalMapSize; |
| |
| //////////////////// Constructors //////////////////// |
| |
| public PutAllPartialResult(int totalMapSize) { |
| this.succeededKeys = new VersionedObjectList(); |
| this.totalMapSize = totalMapSize; |
| } |
| |
| public void setTotalMapSize(int totalMapSize) { |
| this.totalMapSize = totalMapSize; |
| } |
| |
| public void setSucceededKeysAndVersions(VersionedObjectList other) { |
| synchronized (this) { |
| this.succeededKeys = other; |
| } |
| } |
| |
| public void consolidate(PutAllPartialResult other) { |
| synchronized (this) { |
| this.succeededKeys.addAll(other.getSucceededKeysAndVersions()); |
| } |
| saveFailedKey(other.firstFailedKey, other.firstCauseOfFailure); |
| } |
| |
| public Exception getFailure() { |
| return this.firstCauseOfFailure; |
| } |
| |
| /** |
| * record all succeeded keys in a version list response |
| */ |
| public void addKeysAndVersions(VersionedObjectList keysAndVersions) { |
| synchronized (this) { |
| this.succeededKeys.addAll(keysAndVersions); |
| } |
| } |
| |
| /** |
| * record all succeeded keys when there are no version results |
| */ |
| public void addKeys(Collection<?> keys) { |
| synchronized (this) { |
| if (this.succeededKeys.getVersionTags().size() > 0) { |
| throw new IllegalStateException( |
| "attempt to store versionless keys when there are already versioned results"); |
| } |
| this.succeededKeys.addAllKeys(keys); |
| } |
| } |
| |
| |
| /** |
| * increment failed key number |
| */ |
| public void saveFailedKey(Object key, Exception cause) { |
| if (key == null) { |
| return; |
| } |
| // we give high priority for CancelException |
| if (firstFailedKey == null || cause instanceof CancelException) { |
| firstFailedKey = key; |
| firstCauseOfFailure = cause; |
| } |
| } |
| |
| /** |
| * Returns the key set in exception |
| */ |
| public VersionedObjectList getSucceededKeysAndVersions() { |
| return this.succeededKeys; |
| } |
| |
| /** |
| * Returns the first key that failed |
| */ |
| public Object getFirstFailedKey() { |
| return this.firstFailedKey; |
| } |
| |
| /** |
| * Returns there's failedKeys |
| */ |
| public boolean hasFailure() { |
| return this.firstFailedKey != null; |
| } |
| |
| /** |
| * Returns there's saved succeed keys |
| */ |
| public boolean hasSucceededKeys() { |
| return this.succeededKeys.size() > 0; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuffer sb = new StringBuffer("Key " + firstFailedKey |
| + " and possibly others failed the operation due to " + firstCauseOfFailure + "\n"); |
| if (totalMapSize > 0) { |
| int failedKeyNum = totalMapSize - this.succeededKeys.size(); |
| sb.append("The bulk operation failed on " + failedKeyNum + " out of " + totalMapSize |
| + " entries. "); |
| } |
| return sb.toString(); |
| } |
| |
| public String detailString() { |
| StringBuffer sb = new StringBuffer(toString()); |
| sb.append(getKeyListString()); |
| return sb.toString(); |
| } |
| |
| public String getKeyListString() { |
| StringBuffer sb = new StringBuffer(); |
| |
| sb.append("The keys for the successful entries are: "); |
| int cnt = 0; |
| final Iterator iterator = this.succeededKeys.iterator(); |
| while (iterator.hasNext()) { |
| Object key = iterator.next(); |
| sb.append(" ").append(key); |
| cnt++; |
| } |
| return sb.toString(); |
| } |
| } |
| } |