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
|
# 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.
|
# of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
|
||||||
|
import errno
|
||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
from .lib import testcase
|
from .lib import testcase
|
||||||
|
from facebook.eden import EdenService
|
||||||
|
|
||||||
@testcase.eden_repo_test
|
@testcase.eden_repo_test
|
||||||
class MaterializedQueryTest:
|
class MaterializedQueryTest:
|
||||||
@ -42,9 +43,26 @@ class MaterializedQueryTest:
|
|||||||
self.assertEqual(1, pos.sequenceNumber)
|
self.assertEqual(1, pos.sequenceNumber)
|
||||||
self.assertNotEqual(0, pos.mountGeneration)
|
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)
|
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')
|
name = os.path.join(self.mount, 'overlaid')
|
||||||
with open(name, 'w+') as f:
|
with open(name, 'w+') as f:
|
||||||
@ -52,13 +70,25 @@ class MaterializedQueryTest:
|
|||||||
self.assertEqual(2, pos.sequenceNumber,
|
self.assertEqual(2, pos.sequenceNumber,
|
||||||
msg='creating a file bumps the journal')
|
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')
|
f.write('NAME!\n')
|
||||||
|
|
||||||
pos = self.client.getCurrentJournalPosition(self.mount)
|
pos_after_overlaid = self.client.getCurrentJournalPosition(self.mount)
|
||||||
self.assertEqual(3, pos.sequenceNumber, msg='writing bumps the journal')
|
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)
|
info = self.client.getMaterializedEntries(self.mount)
|
||||||
self.assertEqual(pos, info.currentPosition,
|
self.assertEqual(pos_after_overlaid, info.currentPosition,
|
||||||
msg='consistent with getCurrentJournalPosition')
|
msg='consistent with getCurrentJournalPosition')
|
||||||
|
|
||||||
items = info.fileInfo
|
items = info.fileInfo
|
||||||
@ -81,6 +111,13 @@ class MaterializedQueryTest:
|
|||||||
self.assertEqual(4, pos.sequenceNumber,
|
self.assertEqual(4, pos.sequenceNumber,
|
||||||
msg='appending bumps the journal')
|
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)
|
info = self.client.getMaterializedEntries(self.mount)
|
||||||
self.assertEqual(pos, info.currentPosition,
|
self.assertEqual(pos, info.currentPosition,
|
||||||
msg='consistent with getCurrentJournalPosition')
|
msg='consistent with getCurrentJournalPosition')
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <boost/polymorphic_cast.hpp>
|
#include <boost/polymorphic_cast.hpp>
|
||||||
#include <folly/FileUtil.h>
|
#include <folly/FileUtil.h>
|
||||||
#include <folly/String.h>
|
#include <folly/String.h>
|
||||||
|
#include <unordered_set>
|
||||||
#include "EdenServer.h"
|
#include "EdenServer.h"
|
||||||
#include "eden/fs/config/ClientConfig.h"
|
#include "eden/fs/config/ClientConfig.h"
|
||||||
#include "eden/fs/inodes/EdenMount.h"
|
#include "eden/fs/inodes/EdenMount.h"
|
||||||
@ -328,6 +329,55 @@ void EdenServiceHandler::getCurrentJournalPosition(
|
|||||||
out.snapshotHash = StringPiece(latest->toHash.getBytes()).str();
|
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() {
|
void EdenServiceHandler::shutdown() {
|
||||||
server_->stop();
|
server_->stop();
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,11 @@ class EdenServiceHandler : virtual public EdenServiceSvIf,
|
|||||||
JournalPosition& out,
|
JournalPosition& out,
|
||||||
std::unique_ptr<std::string> mountPoint) override;
|
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
|
* When this Thrift handler is notified to shutdown, it notifies the
|
||||||
* EdenServer to shut down, as well.
|
* EdenServer to shut down, as well.
|
||||||
|
@ -143,6 +143,7 @@ service EdenService extends fb303.FacebookService {
|
|||||||
FileDelta getFilesChangedSince(
|
FileDelta getFilesChangedSince(
|
||||||
1: string mountPoint,
|
1: string mountPoint,
|
||||||
2: JournalPosition fromPosition)
|
2: JournalPosition fromPosition)
|
||||||
|
throws (1: EdenError ex)
|
||||||
|
|
||||||
/** Returns a subset of the stat() information for a list of paths.
|
/** Returns a subset of the stat() information for a list of paths.
|
||||||
* The returned list of information corresponds to the input list of
|
* The returned list of information corresponds to the input list of
|
||||||
|
Loading…
Reference in New Issue
Block a user