use of org.apache.jackrabbit.oak.plugins.document.NodeDocument in project jackrabbit-oak by apache.
the class MongoDocumentStore method update.
@Override
public <T extends Document> void update(Collection<T> collection, List<String> keys, UpdateOp updateOp) {
log("update", keys, updateOp);
UpdateUtils.assertUnconditional(updateOp);
DBCollection dbCollection = getDBCollection(collection);
QueryBuilder query = QueryBuilder.start(Document.ID).in(keys);
// make sure we don't modify the original updateOp
updateOp = updateOp.copy();
DBObject update = createUpdate(updateOp, false);
final Stopwatch watch = startWatch();
try {
Map<String, NodeDocument> cachedDocs = Collections.emptyMap();
if (collection == Collection.NODES) {
cachedDocs = Maps.newHashMap();
for (String key : keys) {
cachedDocs.put(key, nodesCache.getIfPresent(key));
}
}
try {
dbCollection.update(query.get(), update, false, true);
if (collection == Collection.NODES) {
Map<String, ModificationStamp> modCounts = getModStamps(filterValues(cachedDocs, notNull()).keySet());
// update cache
for (Entry<String, NodeDocument> entry : cachedDocs.entrySet()) {
// the cachedDocs is not empty, so the collection = NODES
Lock lock = nodeLocks.acquire(entry.getKey());
try {
ModificationStamp postUpdateModStamp = modCounts.get(entry.getKey());
if (postUpdateModStamp != null && entry.getValue() != null && entry.getValue() != NodeDocument.NULL && Long.valueOf(postUpdateModStamp.modCount - 1).equals(entry.getValue().getModCount())) {
// post update modCount is one higher than
// what we currently see in the cache. we can
// replace the cached document
NodeDocument newDoc = applyChanges(Collection.NODES, entry.getValue(), updateOp.shallowCopy(entry.getKey()));
nodesCache.replaceCachedDocument(entry.getValue(), newDoc);
} else {
// make sure concurrently loaded document is
// invalidated
nodesCache.invalidate(entry.getKey());
}
} finally {
lock.unlock();
}
}
}
} catch (MongoException e) {
throw handleException(e, collection, keys);
}
} finally {
stats.doneUpdate(watch.elapsed(TimeUnit.NANOSECONDS), collection, keys.size());
}
}
use of org.apache.jackrabbit.oak.plugins.document.NodeDocument in project jackrabbit-oak by apache.
the class MongoVersionGCSupport method getOldestDeletedOnceTimestamp.
@Override
public long getOldestDeletedOnceTimestamp(Clock clock, long precisionMs) {
LOG.debug("getOldestDeletedOnceTimestamp() <- start");
DBObject query = start(NodeDocument.DELETED_ONCE).is(Boolean.TRUE).get();
DBCursor cursor = getNodeCollection().find(query).sort(start(NodeDocument.MODIFIED_IN_SECS).is(1).get()).limit(1);
CloseableIterable<NodeDocument> results = CloseableIterable.wrap(transform(cursor, new Function<DBObject, NodeDocument>() {
@Override
public NodeDocument apply(DBObject input) {
return store.convertFromDBObject(NODES, input);
}
}), cursor);
try {
Iterator<NodeDocument> i = results.iterator();
if (i.hasNext()) {
NodeDocument doc = i.next();
long modifiedMs = doc.getModified() * TimeUnit.SECONDS.toMillis(1);
if (LOG.isDebugEnabled()) {
LOG.debug("getOldestDeletedOnceTimestamp() -> {}", Utils.timestampToString(modifiedMs));
}
return modifiedMs;
}
} finally {
Utils.closeIfCloseable(results);
}
LOG.debug("getOldestDeletedOnceTimestamp() -> none found, return current time");
return clock.getTime();
}
use of org.apache.jackrabbit.oak.plugins.document.NodeDocument in project jackrabbit-oak by apache.
the class MongoBlobReferenceIterator method getIteratorOverDocsWithBinaries.
@Override
public Iterator<NodeDocument> getIteratorOverDocsWithBinaries() {
DBObject query = QueryBuilder.start(NodeDocument.HAS_BINARY_FLAG).is(NodeDocument.HAS_BINARY_VAL).get();
// TODO It currently prefers secondary. Would that be Ok?
DBCursor cursor = documentStore.getDBCollection(Collection.NODES).find(query).setReadPreference(documentStore.getConfiguredReadPreference(Collection.NODES));
return CloseableIterable.wrap(transform(cursor, new Function<DBObject, NodeDocument>() {
@Override
public NodeDocument apply(DBObject input) {
return documentStore.convertFromDBObject(Collection.NODES, input);
}
}), cursor).iterator();
}
use of org.apache.jackrabbit.oak.plugins.document.NodeDocument in project jackrabbit-oak by apache.
the class MongoDocumentStore method queryInternal.
@SuppressWarnings("unchecked")
@Nonnull
<T extends Document> List<T> queryInternal(Collection<T> collection, String fromKey, String toKey, String indexedProperty, long startValue, int limit, long maxQueryTime) {
log("query", fromKey, toKey, indexedProperty, startValue, limit);
DBCollection dbCollection = getDBCollection(collection);
QueryBuilder queryBuilder = QueryBuilder.start(Document.ID);
queryBuilder.greaterThan(fromKey);
queryBuilder.lessThan(toKey);
DBObject hint = new BasicDBObject(NodeDocument.ID, 1);
if (indexedProperty != null) {
if (NodeDocument.DELETED_ONCE.equals(indexedProperty)) {
if (startValue != 1) {
throw new DocumentStoreException("unsupported value for property " + NodeDocument.DELETED_ONCE);
}
queryBuilder.and(indexedProperty);
queryBuilder.is(true);
} else {
queryBuilder.and(indexedProperty);
queryBuilder.greaterThanEquals(startValue);
if (NodeDocument.MODIFIED_IN_SECS.equals(indexedProperty) && canUseModifiedTimeIdx(startValue)) {
hint = new BasicDBObject(NodeDocument.MODIFIED_IN_SECS, -1);
}
}
}
DBObject query = queryBuilder.get();
String parentId = Utils.getParentIdFromLowerLimit(fromKey);
long lockTime = -1;
final Stopwatch watch = startWatch();
boolean isSlaveOk = false;
int resultSize = 0;
CacheChangesTracker cacheChangesTracker = null;
if (parentId != null && collection == Collection.NODES) {
cacheChangesTracker = nodesCache.registerTracker(fromKey, toKey);
}
try {
DBCursor cursor = dbCollection.find(query).sort(BY_ID_ASC);
if (!disableIndexHint && !hasModifiedIdCompoundIndex) {
cursor.hint(hint);
}
if (maxQueryTime > 0) {
// OAK-2614: set maxTime if maxQueryTimeMS > 0
cursor.maxTime(maxQueryTime, TimeUnit.MILLISECONDS);
}
ReadPreference readPreference = getMongoReadPreference(collection, parentId, null, getDefaultReadPreference(collection));
if (readPreference.isSlaveOk()) {
isSlaveOk = true;
LOG.trace("Routing call to secondary for fetching children from [{}] to [{}]", fromKey, toKey);
}
cursor.setReadPreference(readPreference);
List<T> list;
try {
list = new ArrayList<T>();
for (int i = 0; i < limit && cursor.hasNext(); i++) {
DBObject o = cursor.next();
T doc = convertFromDBObject(collection, o);
list.add(doc);
}
resultSize = list.size();
} finally {
cursor.close();
}
if (cacheChangesTracker != null) {
nodesCache.putNonConflictingDocs(cacheChangesTracker, (List<NodeDocument>) list);
}
return list;
} finally {
if (cacheChangesTracker != null) {
cacheChangesTracker.close();
}
stats.doneQuery(watch.elapsed(TimeUnit.NANOSECONDS), collection, fromKey, toKey, indexedProperty != null, resultSize, lockTime, isSlaveOk);
}
}
use of org.apache.jackrabbit.oak.plugins.document.NodeDocument in project jackrabbit-oak by apache.
the class NodeDocumentCache method putIfAbsent.
/**
* Puts document into cache iff no entry with the given key is cached
* already. This operation is atomic.
*
* @param doc the document to add to the cache.
* @return either the given <code>doc</code> or the document already present
* in the cache.
*/
@Nonnull
public NodeDocument putIfAbsent(@Nonnull final NodeDocument doc) {
if (doc == NodeDocument.NULL) {
throw new IllegalArgumentException("doc must not be NULL document");
}
doc.seal();
String id = doc.getId();
// make sure we only cache the document if it wasn't
// changed and cached by some other thread in the
// meantime. That is, use get() with a Callable,
// which is only used when the document isn't there
Lock lock = locks.acquire(id);
try {
for (; ; ) {
NodeDocument cached = get(id, new Callable<NodeDocument>() {
@Override
public NodeDocument call() {
return doc;
}
});
if (cached != NodeDocument.NULL) {
return cached;
} else {
invalidate(id);
}
}
} catch (ExecutionException e) {
// the already available doc
throw new IllegalStateException(e);
} finally {
lock.unlock();
}
}
Aggregations