Details
Description
The logic in FSNDNCacheOp#modifyCacheDirective is not correct. when modify cacheDirective,the expiration in directive may be a relative expiryTime, and EditLog will serial a relative expiry time.
// Some comments here static void modifyCacheDirective( FSNamesystem fsn, CacheManager cacheManager, CacheDirectiveInfo directive, EnumSet<CacheFlag> flags, boolean logRetryCache) throws IOException { final FSPermissionChecker pc = getFsPermissionChecker(fsn); cacheManager.modifyDirective(directive, pc, flags); fsn.getEditLog().logModifyCacheDirectiveInfo(directive, logRetryCache); }
But when SBN replay the log ,it will invoke FSImageSerialization#readCacheDirectiveInfo as a absolute expiryTime.It will result in the inconsistency .
public static CacheDirectiveInfo readCacheDirectiveInfo(DataInput in) throws IOException { CacheDirectiveInfo.Builder builder = new CacheDirectiveInfo.Builder(); builder.setId(readLong(in)); int flags = in.readInt(); if ((flags & 0x1) != 0) { builder.setPath(new Path(readString(in))); } if ((flags & 0x2) != 0) { builder.setReplication(readShort(in)); } if ((flags & 0x4) != 0) { builder.setPool(readString(in)); } if ((flags & 0x8) != 0) { builder.setExpiration( CacheDirectiveInfo.Expiration.newAbsolute(readLong(in))); } if ((flags & ~0xF) != 0) { throw new IOException("unknown flags set in " + "ModifyCacheDirectiveInfoOp: " + flags); } return builder.build(); }
In other words, fsn.getEditLog().logModifyCacheDirectiveInfo(directive, logRetryCache) may serial a relative expiry time,But builder.setExpiration(CacheDirectiveInfo.Expiration.newAbsolute(readLong(in))) read it as a absolute expiryTime.