-
Notifications
You must be signed in to change notification settings - Fork 683
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Geode 2469 #404
Geode 2469 #404
Changes from 11 commits
44b90c4
27d7600
a4ee164
d5191fb
0b3bf68
1958b1e
628f509
3316d25
f2b7ee7
886289e
0327403
c29b3ca
6412412
454e09a
3f8c590
d3b2642
31c4c4a
cf8f0cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -135,8 +135,14 @@ private void writeToChannel(ByteBuf message) { | |
*/ | ||
@Override | ||
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { | ||
Command command = (Command) msg; | ||
executeCommand(ctx, command); | ||
try { | ||
Command command = (Command) msg; | ||
executeCommand(ctx, command); | ||
} catch (Exception e) { | ||
logger.error(e); | ||
throw e; | ||
} | ||
|
||
} | ||
|
||
/** | ||
|
@@ -198,6 +204,7 @@ private void executeCommand(ChannelHandlerContext ctx, Command command) throws E | |
else | ||
executeWithoutTransaction(exec, command); | ||
|
||
|
||
if (hasTransaction() && command.getCommandType() != RedisCommandType.MULTI) { | ||
writeToChannel( | ||
Coder.getSimpleStringResponse(this.byteBufAllocator, RedisConstants.COMMAND_QUEUED)); | ||
|
@@ -235,6 +242,8 @@ private void executeWithoutTransaction(final Executor exec, Command command) thr | |
exec.executeCommand(command, this); | ||
return; | ||
} catch (Exception e) { | ||
logger.error(e); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see error logging comment above |
||
|
||
cause = e; | ||
if (e instanceof RegionDestroyedException || e instanceof RegionNotFoundException | ||
|| e.getCause() instanceof QueryInvocationTargetException) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,8 @@ | |
import org.apache.geode.redis.internal.executor.ExpirationExecutor; | ||
import org.apache.geode.redis.internal.executor.ListQuery; | ||
import org.apache.geode.redis.internal.executor.SortedSetQuery; | ||
import org.apache.geode.redis.internal.executor.hash.HashExecutor; | ||
import org.apache.geode.redis.internal.executor.set.SetExecutor; | ||
import org.apache.geode.internal.hll.HyperLogLogPlus; | ||
import org.apache.geode.management.cli.Result; | ||
import org.apache.geode.management.cli.Result.Status; | ||
|
@@ -80,6 +82,9 @@ public class RegionProvider implements Closeable { | |
*/ | ||
private final Region<ByteArrayWrapper, HyperLogLogPlus> hLLRegion; | ||
|
||
private final Region<ByteArrayWrapper, Map<ByteArrayWrapper, ByteArrayWrapper>> hashRegion; | ||
private final Region<ByteArrayWrapper, Set<ByteArrayWrapper>> setRegion; | ||
|
||
private final Cache cache; | ||
private final QueryService queryService; | ||
private final ConcurrentMap<ByteArrayWrapper, Map<Enum<?>, Query>> preparedQueries = | ||
|
@@ -95,18 +100,38 @@ public RegionProvider(Region<ByteArrayWrapper, ByteArrayWrapper> stringsRegion, | |
Region<ByteArrayWrapper, HyperLogLogPlus> hLLRegion, | ||
Region<String, RedisDataType> redisMetaRegion, | ||
ConcurrentMap<ByteArrayWrapper, ScheduledFuture<?>> expirationsMap, | ||
ScheduledExecutorService expirationExecutor, RegionShortcut defaultShortcut) { | ||
ScheduledExecutorService expirationExecutor, RegionShortcut defaultShortcut, | ||
Region<ByteArrayWrapper, Map<ByteArrayWrapper, ByteArrayWrapper>> hashRegion, | ||
Region<ByteArrayWrapper, Set<ByteArrayWrapper>> setRegion) { | ||
|
||
this(stringsRegion, hLLRegion, redisMetaRegion, expirationsMap, expirationExecutor, | ||
defaultShortcut, hashRegion, setRegion, GemFireCacheImpl.getInstance()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 for making the cache an argument to the constructor (even if it's optional). Anything that makes things a little more decoupled. |
||
} | ||
|
||
public RegionProvider(Region<ByteArrayWrapper, ByteArrayWrapper> stringsRegion, | ||
Region<ByteArrayWrapper, HyperLogLogPlus> hLLRegion, | ||
Region<String, RedisDataType> redisMetaRegion, | ||
ConcurrentMap<ByteArrayWrapper, ScheduledFuture<?>> expirationsMap, | ||
ScheduledExecutorService expirationExecutor, RegionShortcut defaultShortcut, | ||
Region<ByteArrayWrapper, Map<ByteArrayWrapper, ByteArrayWrapper>> hashRegion, | ||
Region<ByteArrayWrapper, Set<ByteArrayWrapper>> setRegion, Cache cache) { | ||
if (stringsRegion == null || hLLRegion == null || redisMetaRegion == null) | ||
throw new NullPointerException(); | ||
|
||
this.hashRegion = hashRegion; | ||
this.setRegion = setRegion; | ||
|
||
this.regions = new ConcurrentHashMap<ByteArrayWrapper, Region<?, ?>>(); | ||
this.stringsRegion = stringsRegion; | ||
this.hLLRegion = hLLRegion; | ||
this.redisMetaRegion = redisMetaRegion; | ||
this.cache = GemFireCacheImpl.getInstance(); | ||
this.cache = cache; | ||
|
||
this.queryService = cache.getQueryService(); | ||
this.expirationsMap = expirationsMap; | ||
this.expirationExecutor = expirationExecutor; | ||
this.defaultRegionType = defaultShortcut; | ||
|
||
this.locks = new ConcurrentHashMap<String, Lock>(); | ||
} | ||
|
||
|
@@ -143,14 +168,19 @@ public RedisDataType metaGet(ByteArrayWrapper key) { | |
} | ||
|
||
public Region<?, ?> getRegion(ByteArrayWrapper key) { | ||
if (key == null) | ||
return null; | ||
|
||
return this.regions.get(key); | ||
|
||
} | ||
|
||
public void removeRegionReferenceLocally(ByteArrayWrapper key, RedisDataType type) { | ||
Lock lock = this.locks.get(key.toString()); | ||
boolean locked = false; | ||
try { | ||
locked = lock.tryLock(); | ||
if (lock != null) | ||
locked = lock.tryLock(); | ||
// If we cannot get the lock we ignore this remote event, this key has local event | ||
// that started independently, ignore this event to prevent deadlock | ||
if (locked) { | ||
|
@@ -174,7 +204,7 @@ public boolean removeKey(ByteArrayWrapper key, RedisDataType type) { | |
} | ||
|
||
public boolean removeKey(ByteArrayWrapper key, RedisDataType type, boolean cancelExpiration) { | ||
if (type == null || type == RedisDataType.REDIS_PROTECTED) | ||
if (type == RedisDataType.REDIS_PROTECTED) | ||
return false; | ||
Lock lock = this.locks.get(key.toString()); | ||
try { | ||
|
@@ -187,8 +217,26 @@ public boolean removeKey(ByteArrayWrapper key, RedisDataType type, boolean cance | |
return this.stringsRegion.remove(key) != null; | ||
} else if (type == RedisDataType.REDIS_HLL) { | ||
return this.hLLRegion.remove(key) != null; | ||
} else if (type == RedisDataType.REDIS_LIST) { | ||
return this.destroyRegion(key, type); | ||
} else { | ||
return destroyRegion(key, type); | ||
|
||
|
||
// Check hash | ||
ByteArrayWrapper regionName = HashExecutor.toRegionNameByteArray(key); | ||
Region<?, ?> region = this.getRegion(regionName); | ||
if (region != null) { | ||
region.remove(HashExecutor.toEntryKey(key)); | ||
} | ||
|
||
// remove the set | ||
region = this.getRegion(SetExecutor.SET_REGION_KEY); | ||
if (region != null) { | ||
region.remove(key); | ||
} | ||
|
||
|
||
return true; | ||
} | ||
} catch (Exception exc) { | ||
return false; | ||
|
@@ -259,6 +307,10 @@ public void createRemoteRegionReferenceLocally(ByteArrayWrapper key, RedisDataTy | |
|
||
private Region<?, ?> getOrCreateRegion0(ByteArrayWrapper key, RedisDataType type, | ||
ExecutionHandlerContext context, boolean addToMeta) { | ||
|
||
String regionName = key.toString(); | ||
|
||
|
||
checkDataType(key, type); | ||
Region<?, ?> r = this.regions.get(key); | ||
if (r != null && r.isDestroyed()) { | ||
|
@@ -289,7 +341,9 @@ public void createRemoteRegionReferenceLocally(ByteArrayWrapper key, RedisDataTy | |
Exception concurrentCreateDestroyException = null; | ||
do { | ||
concurrentCreateDestroyException = null; | ||
r = createRegionGlobally(stringKey); | ||
|
||
r = createRegionGlobally(regionName); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why change |
||
|
||
try { | ||
if (type == RedisDataType.REDIS_LIST) { | ||
doInitializeList(key, r); | ||
|
@@ -455,6 +509,20 @@ public Region<ByteArrayWrapper, ByteArrayWrapper> getStringsRegion() { | |
return this.stringsRegion; | ||
} | ||
|
||
/** | ||
* @return the hashRegion | ||
*/ | ||
public Region<ByteArrayWrapper, Map<ByteArrayWrapper, ByteArrayWrapper>> getHashRegion() { | ||
return hashRegion; | ||
} | ||
|
||
/** | ||
* @return the setRegion | ||
*/ | ||
public Region<ByteArrayWrapper, Set<ByteArrayWrapper>> getSetRegion() { | ||
return setRegion; | ||
} | ||
|
||
public Region<ByteArrayWrapper, HyperLogLogPlus> gethLLRegion() { | ||
return this.hLLRegion; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're going to be logging exceptions as they propagate, I'd like to think about the best place to catch all of them and also it would be nice to add a little error message so we know where we caught the exception.