mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 22:37:37 +03:00
implement getFilesChangedSince
Summary: This is pretty straightforward; we just walk back until we hit the boundary with the requested JournalPosition.sequenceNumber Reviewed By: simpkins Differential Revision: D3872970 fbshipit-source-id: 1405f05957346d7ac513070f0407a477548aff1d
This commit is contained in:
parent
82c57b2bf8
commit
8f4373571b
@ -7,10 +7,11 @@
|
||||
# LICENSE file in the root directory of this source tree. An additional grant
|
||||
# of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
import errno
|
||||
import os
|
||||
import stat
|
||||
from .lib import testcase
|
||||
|
||||
from facebook.eden import EdenService
|
||||
|
||||
@testcase.eden_repo_test
|
||||
class MaterializedQueryTest:
|
||||
@ -42,9 +43,26 @@ class MaterializedQueryTest:
|
||||
self.assertEqual(1, pos.sequenceNumber)
|
||||
self.assertNotEqual(0, pos.mountGeneration)
|
||||
|
||||
def test_addFile(self):
|
||||
changed = self.client.getFilesChangedSince(self.mount, pos)
|
||||
self.assertEqual(0, len(changed.paths))
|
||||
self.assertEqual(pos, changed.fromPosition)
|
||||
self.assertEqual(pos, changed.toPosition)
|
||||
|
||||
def test_invalidProcessGeneration(self):
|
||||
# Get a candidate position
|
||||
pos = self.client.getCurrentJournalPosition(self.mount)
|
||||
self.assertEqual(1, pos.sequenceNumber)
|
||||
|
||||
# poke the generation to a value that will never manifest in practice
|
||||
pos.mountGeneration = 0
|
||||
|
||||
with self.assertRaises(EdenService.EdenError) as context:
|
||||
self.client.getFilesChangedSince(self.mount, pos)
|
||||
self.assertEqual(errno.ERANGE, context.exception.errorCode,
|
||||
msg='Must return ERANGE')
|
||||
|
||||
def test_addFile(self):
|
||||
initial_pos = self.client.getCurrentJournalPosition(self.mount)
|
||||
self.assertEqual(1, initial_pos.sequenceNumber)
|
||||
|
||||
name = os.path.join(self.mount, 'overlaid')
|
||||
with open(name, 'w+') as f:
|
||||
@ -52,13 +70,25 @@ class MaterializedQueryTest:
|
||||
self.assertEqual(2, pos.sequenceNumber,
|
||||
msg='creating a file bumps the journal')
|
||||
|
||||
changed = self.client.getFilesChangedSince(self.mount, initial_pos)
|
||||
self.assertEqual(['overlaid'], changed.paths)
|
||||
self.assertEqual(initial_pos.sequenceNumber + 1,
|
||||
changed.fromPosition.sequenceNumber,
|
||||
msg='changes start AFTER initial_pos')
|
||||
|
||||
f.write('NAME!\n')
|
||||
|
||||
pos = self.client.getCurrentJournalPosition(self.mount)
|
||||
self.assertEqual(3, pos.sequenceNumber, msg='writing bumps the journal')
|
||||
pos_after_overlaid = self.client.getCurrentJournalPosition(self.mount)
|
||||
self.assertEqual(3, pos_after_overlaid.sequenceNumber,
|
||||
msg='writing bumps the journal')
|
||||
changed = self.client.getFilesChangedSince(self.mount, initial_pos)
|
||||
self.assertEqual(['overlaid'], changed.paths)
|
||||
self.assertEqual(initial_pos.sequenceNumber + 1,
|
||||
changed.fromPosition.sequenceNumber,
|
||||
msg='changes start AFTER initial_pos')
|
||||
|
||||
info = self.client.getMaterializedEntries(self.mount)
|
||||
self.assertEqual(pos, info.currentPosition,
|
||||
self.assertEqual(pos_after_overlaid, info.currentPosition,
|
||||
msg='consistent with getCurrentJournalPosition')
|
||||
|
||||
items = info.fileInfo
|
||||
@ -81,6 +111,13 @@ class MaterializedQueryTest:
|
||||
self.assertEqual(4, pos.sequenceNumber,
|
||||
msg='appending bumps the journal')
|
||||
|
||||
changed = self.client.getFilesChangedSince(
|
||||
self.mount, pos_after_overlaid)
|
||||
self.assertEqual(['adir/file'], changed.paths)
|
||||
self.assertEqual(pos_after_overlaid.sequenceNumber + 1,
|
||||
changed.fromPosition.sequenceNumber,
|
||||
msg='changes start AFTER pos_after_overlaid')
|
||||
|
||||
info = self.client.getMaterializedEntries(self.mount)
|
||||
self.assertEqual(pos, info.currentPosition,
|
||||
msg='consistent with getCurrentJournalPosition')
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <boost/polymorphic_cast.hpp>
|
||||
#include <folly/FileUtil.h>
|
||||
#include <folly/String.h>
|
||||
#include <unordered_set>
|
||||
#include "EdenServer.h"
|
||||
#include "eden/fs/config/ClientConfig.h"
|
||||
#include "eden/fs/inodes/EdenMount.h"
|
||||
@ -328,6 +329,55 @@ void EdenServiceHandler::getCurrentJournalPosition(
|
||||
out.snapshotHash = StringPiece(latest->toHash.getBytes()).str();
|
||||
}
|
||||
|
||||
void EdenServiceHandler::getFilesChangedSince(
|
||||
FileDelta& out,
|
||||
std::unique_ptr<std::string> mountPoint,
|
||||
std::unique_ptr<JournalPosition> fromPosition) {
|
||||
auto edenMount = server_->getMount(*mountPoint);
|
||||
auto inodeDispatcher = edenMount->getMountPoint()->getDispatcher();
|
||||
|
||||
auto delta = edenMount->getJournal().rlock()->getLatest();
|
||||
|
||||
if (fromPosition->mountGeneration != edenMount->getMountGeneration()) {
|
||||
throw EdenError(
|
||||
apache::thrift::FragileConstructor(),
|
||||
"fromPosition.mountGeneration does not match the current "
|
||||
"mountGeneration. "
|
||||
"You need to compute a new basis for delta queries.",
|
||||
ERANGE);
|
||||
}
|
||||
|
||||
std::unordered_set<RelativePath> changedFiles;
|
||||
|
||||
out.toPosition.sequenceNumber = delta->toSequence;
|
||||
out.toPosition.snapshotHash = StringPiece(delta->toHash.getBytes()).str();
|
||||
out.toPosition.mountGeneration = edenMount->getMountGeneration();
|
||||
|
||||
out.fromPosition = out.toPosition;
|
||||
|
||||
while (delta) {
|
||||
if (delta->toSequence <= fromPosition->sequenceNumber) {
|
||||
// We've reached the end of the interesting section
|
||||
break;
|
||||
}
|
||||
|
||||
changedFiles.insert(
|
||||
delta->changedFilesInOverlay.begin(),
|
||||
delta->changedFilesInOverlay.end());
|
||||
|
||||
out.fromPosition.sequenceNumber = delta->fromSequence;
|
||||
out.fromPosition.snapshotHash =
|
||||
StringPiece(delta->fromHash.getBytes()).str();
|
||||
out.fromPosition.mountGeneration = edenMount->getMountGeneration();
|
||||
|
||||
delta = delta->previous;
|
||||
}
|
||||
|
||||
for (auto& path : changedFiles) {
|
||||
out.paths.emplace_back(path.stringPiece().str());
|
||||
}
|
||||
}
|
||||
|
||||
void EdenServiceHandler::shutdown() {
|
||||
server_->stop();
|
||||
}
|
||||
|
@ -56,6 +56,11 @@ class EdenServiceHandler : virtual public EdenServiceSvIf,
|
||||
JournalPosition& out,
|
||||
std::unique_ptr<std::string> mountPoint) override;
|
||||
|
||||
void getFilesChangedSince(
|
||||
FileDelta& out,
|
||||
std::unique_ptr<std::string> mountPoint,
|
||||
std::unique_ptr<JournalPosition> fromPosition) override;
|
||||
|
||||
/**
|
||||
* When this Thrift handler is notified to shutdown, it notifies the
|
||||
* EdenServer to shut down, as well.
|
||||
|
@ -143,6 +143,7 @@ service EdenService extends fb303.FacebookService {
|
||||
FileDelta getFilesChangedSince(
|
||||
1: string mountPoint,
|
||||
2: JournalPosition fromPosition)
|
||||
throws (1: EdenError ex)
|
||||
|
||||
/** Returns a subset of the stat() information for a list of paths.
|
||||
* The returned list of information corresponds to the input list of
|
||||
|
Loading…
Reference in New Issue
Block a user