Core: remove per-ID locking when ID was auto-generated

When we know the ID for the document we are about to index was
auto-generated, we don't need to acquire/release the per-ID lock,
which might provide small speedups during highly concurrent indexing.

Closes #6584
This commit is contained in:
mikemccand 2014-07-07 11:34:46 -04:00
parent ec92646289
commit 15b81c91f7
1 changed files with 43 additions and 39 deletions

View File

@ -402,13 +402,13 @@ public class InternalEngine extends AbstractIndexShardComponent implements Engin
} }
private void innerCreate(Create create, IndexWriter writer) throws IOException { private void innerCreate(Create create, IndexWriter writer) throws IOException {
synchronized (dirtyLock(create.uid())) { if (optimizeAutoGenerateId && create.autoGeneratedId() && !create.canHaveDuplicates()) {
final long currentVersion; // We don't need to lock because this ID cannot be concurrently updated:
final VersionValue versionValue; innerCreateNoLock(create, writer, Versions.NOT_FOUND, null);
if (optimizeAutoGenerateId && create.autoGeneratedId() && !create.canHaveDuplicates()) { } else {
currentVersion = Versions.NOT_FOUND; synchronized (dirtyLock(create.uid())) {
versionValue = null; final long currentVersion;
} else { final VersionValue versionValue;
versionValue = versionMap.getUnderLock(create.uid().bytes()); versionValue = versionMap.getUnderLock(create.uid().bytes());
if (versionValue == null) { if (versionValue == null) {
currentVersion = loadCurrentVersionFromIndex(create.uid()); currentVersion = loadCurrentVersionFromIndex(create.uid());
@ -419,51 +419,55 @@ public class InternalEngine extends AbstractIndexShardComponent implements Engin
currentVersion = versionValue.version(); currentVersion = versionValue.version();
} }
} }
innerCreateNoLock(create, writer, currentVersion, versionValue);
} }
}
}
// same logic as index private void innerCreateNoLock(Create create, IndexWriter writer, long currentVersion, VersionValue versionValue) throws IOException {
long updatedVersion;
long expectedVersion = create.version(); // same logic as index
if (create.versionType().isVersionConflictForWrites(currentVersion, expectedVersion)) { long updatedVersion;
if (create.origin() == Operation.Origin.RECOVERY) { long expectedVersion = create.version();
return; if (create.versionType().isVersionConflictForWrites(currentVersion, expectedVersion)) {
} else { if (create.origin() == Operation.Origin.RECOVERY) {
throw new VersionConflictEngineException(shardId, create.type(), create.id(), currentVersion, expectedVersion); return;
} } else {
throw new VersionConflictEngineException(shardId, create.type(), create.id(), currentVersion, expectedVersion);
} }
updatedVersion = create.versionType().updateVersion(currentVersion, expectedVersion); }
updatedVersion = create.versionType().updateVersion(currentVersion, expectedVersion);
// if the doc does not exist or it exists but is not deleted // if the doc does not exist or it exists but is not deleted
if (versionValue != null) { if (versionValue != null) {
if (!versionValue.delete()) { if (!versionValue.delete()) {
if (create.origin() == Operation.Origin.RECOVERY) {
return;
} else {
throw new DocumentAlreadyExistsException(shardId, create.type(), create.id());
}
}
} else if (currentVersion != Versions.NOT_FOUND) {
// its not deleted, its already there
if (create.origin() == Operation.Origin.RECOVERY) { if (create.origin() == Operation.Origin.RECOVERY) {
return; return;
} else { } else {
throw new DocumentAlreadyExistsException(shardId, create.type(), create.id()); throw new DocumentAlreadyExistsException(shardId, create.type(), create.id());
} }
} }
} else if (currentVersion != Versions.NOT_FOUND) {
create.updateVersion(updatedVersion); // its not deleted, its already there
if (create.origin() == Operation.Origin.RECOVERY) {
if (create.docs().size() > 1) { return;
writer.addDocuments(create.docs(), create.analyzer());
} else { } else {
writer.addDocument(create.docs().get(0), create.analyzer()); throw new DocumentAlreadyExistsException(shardId, create.type(), create.id());
} }
Translog.Location translogLocation = translog.add(new Translog.Create(create));
versionMap.putUnderLock(create.uid().bytes(), new VersionValue(updatedVersion, translogLocation));
indexingService.postCreateUnderLock(create);
} }
create.updateVersion(updatedVersion);
if (create.docs().size() > 1) {
writer.addDocuments(create.docs(), create.analyzer());
} else {
writer.addDocument(create.docs().get(0), create.analyzer());
}
Translog.Location translogLocation = translog.add(new Translog.Create(create));
versionMap.putUnderLock(create.uid().bytes(), new VersionValue(updatedVersion, translogLocation));
indexingService.postCreateUnderLock(create);
} }
@Override @Override