Skip to content

Commit db47120

Browse files
committed
libutil: Get rid of restartableSourceFromFactory
Instead we can just seek back in the file - duh. Also this makes use of the anonymous temp file facility, since that is much safer (no need window where the we don't have an open file descriptor for it).
1 parent 1d1b425 commit db47120

File tree

4 files changed

+43
-73
lines changed

4 files changed

+43
-73
lines changed

src/libstore/binary-cache-store.cc

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ std::optional<std::string> BinaryCacheStore::getNixCacheInfo()
7979
void BinaryCacheStore::upsertFile(
8080
const std::string & path, std::string && data, const std::string & mimeType, uint64_t sizeHint)
8181
{
82-
auto source = restartableSourceFromFactory([data = std::move(data)]() { return make_unique<StringSource>(data); });
83-
upsertFile(path, *source, mimeType, sizeHint);
82+
StringSource source{data};
83+
upsertFile(path, source, mimeType, sizeHint);
8484
}
8585

8686
void BinaryCacheStore::getFile(const std::string & path, Callback<std::optional<std::string>> callback) noexcept
@@ -140,9 +140,7 @@ void BinaryCacheStore::writeNarInfo(ref<NarInfo> narInfo)
140140
ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
141141
Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs, std::function<ValidPathInfo(HashResult)> mkInfo)
142142
{
143-
auto [fdTemp, fnTemp] = createTempFile();
144-
145-
AutoDelete autoDelete(fnTemp);
143+
auto fdTemp = createAnonymousTempFile();
146144

147145
auto now1 = std::chrono::steady_clock::now();
148146

@@ -272,19 +270,10 @@ ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
272270

273271
/* Atomically write the NAR file. */
274272
if (repair || !fileExists(narInfo->url)) {
275-
auto source = restartableSourceFromFactory([fnTemp]() {
276-
struct AutoCloseFDSource : AutoCloseFD, FdSource
277-
{
278-
AutoCloseFDSource(AutoCloseFD fd)
279-
: AutoCloseFD(std::move(fd))
280-
, FdSource(get())
281-
{
282-
}
283-
};
284-
return std::make_unique<AutoCloseFDSource>(toDescriptor(open(fnTemp.c_str(), O_RDONLY)));
285-
});
273+
FdSource source{fdTemp.get()};
274+
source.restart(); /* Seek back to the start of the file. */
286275
stats.narWrite++;
287-
upsertFile(narInfo->url, *source, "application/x-nix-nar", narInfo->fileSize);
276+
upsertFile(narInfo->url, source, "application/x-nix-nar", narInfo->fileSize);
288277
} else
289278
stats.narWriteAverted++;
290279

src/libutil-tests/file-system.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,4 +398,20 @@ TEST(createAnonymousTempFile, works)
398398
EXPECT_EQ(source.drain(), "testtest");
399399
}
400400

401+
/* ----------------------------------------------------------------------------
402+
* FdSource
403+
* --------------------------------------------------------------------------*/
404+
405+
TEST(FdSource, restartWorks)
406+
{
407+
auto fd = createAnonymousTempFile();
408+
writeFull(fd.get(), "hello world");
409+
lseek(fd.get(), 0, SEEK_SET);
410+
FdSource source{fd.get()};
411+
EXPECT_EQ(source.drain(), "hello world");
412+
source.restart();
413+
EXPECT_EQ(source.drain(), "hello world");
414+
EXPECT_EQ(source.drain(), "");
415+
}
416+
401417
} // namespace nix

src/libutil/include/nix/util/serialise.hh

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ struct Source
105105
* A buffered abstract source. Warning: a BufferedSource should not be
106106
* used from multiple threads concurrently.
107107
*/
108-
struct BufferedSource : Source
108+
struct BufferedSource : virtual Source
109109
{
110110
size_t bufSize, bufPosIn, bufPosOut;
111111
std::unique_ptr<char[]> buffer;
@@ -132,6 +132,14 @@ protected:
132132
virtual size_t readUnbuffered(char * data, size_t len) = 0;
133133
};
134134

135+
/**
136+
* Source type that can be restarted.
137+
*/
138+
struct RestartableSource : virtual Source
139+
{
140+
virtual void restart() = 0;
141+
};
142+
135143
/**
136144
* A sink that writes data to a file descriptor.
137145
*/
@@ -174,7 +182,7 @@ private:
174182
/**
175183
* A source that reads data from a file descriptor.
176184
*/
177-
struct FdSource : BufferedSource
185+
struct FdSource : BufferedSource, RestartableSource
178186
{
179187
Descriptor fd;
180188
size_t read = 0;
@@ -196,6 +204,7 @@ struct FdSource : BufferedSource
196204
FdSource & operator=(FdSource && s) = default;
197205

198206
bool good() override;
207+
void restart() override;
199208

200209
/**
201210
* Return true if the buffer is not empty after a non-blocking
@@ -230,14 +239,6 @@ struct StringSink : Sink
230239
void operator()(std::string_view data) override;
231240
};
232241

233-
/**
234-
* Source type that can be restarted.
235-
*/
236-
struct RestartableSource : Source
237-
{
238-
virtual void restart() = 0;
239-
};
240-
241242
/**
242243
* A source that reads data from a string.
243244
*/
@@ -316,15 +317,6 @@ public:
316317
}
317318
};
318319

319-
/**
320-
* Create a restartable Source from a factory function.
321-
*
322-
* @param factory Factory function that returns a fresh instance of the Source. Gets
323-
* called for each source restart.
324-
* @pre factory must return an equivalent source for each invocation.
325-
*/
326-
std::unique_ptr<RestartableSource> restartableSourceFromFactory(std::function<std::unique_ptr<Source>()> factory);
327-
328320
/**
329321
* A sink that writes all incoming data to two other sinks.
330322
*/

src/libutil/serialise.cc

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,16 @@ bool FdSource::hasData()
201201
}
202202
}
203203

204+
void FdSource::restart()
205+
{
206+
if (!isSeekable)
207+
throw Error("can't seek to the start of a file");
208+
buffer.reset();
209+
read = bufPosOut = bufPosOut = 0;
210+
if (lseek(fd, 0, SEEK_SET) == -1)
211+
throw SysError("seeking to the start of a file");
212+
}
213+
204214
void FdSource::skip(size_t len)
205215
{
206216
/* Discard data in the buffer. */
@@ -527,41 +537,4 @@ size_t ChainSource::read(char * data, size_t len)
527537
}
528538
}
529539

530-
std::unique_ptr<RestartableSource> restartableSourceFromFactory(std::function<std::unique_ptr<Source>()> factory)
531-
{
532-
struct RestartableSourceImpl : RestartableSource
533-
{
534-
RestartableSourceImpl(decltype(factory) factory_)
535-
: factory_(std::move(factory_))
536-
, impl(this->factory_())
537-
{
538-
}
539-
540-
decltype(factory) factory_;
541-
std::unique_ptr<Source> impl = factory_();
542-
543-
size_t read(char * data, size_t len) override
544-
{
545-
return impl->read(data, len);
546-
}
547-
548-
bool good() override
549-
{
550-
return impl->good();
551-
}
552-
553-
void skip(size_t len) override
554-
{
555-
return impl->skip(len);
556-
}
557-
558-
void restart() override
559-
{
560-
impl = factory_();
561-
}
562-
};
563-
564-
return std::make_unique<RestartableSourceImpl>(std::move(factory));
565-
}
566-
567540
} // namespace nix

0 commit comments

Comments
 (0)