This is an automated email from the ASF dual-hosted git repository. rnewson pushed a commit to branch lucene-10-again in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit a0bdef22a8410dc4285814f3c8491187d912de4a Author: Robert Newson <[email protected]> AuthorDate: Mon Aug 18 17:04:11 2025 +0100 Allow ?upgrade=true on search to trigger upgrade --- .../org/apache/couchdb/nouveau/core/Index.java | 8 ++ .../apache/couchdb/nouveau/core/IndexManager.java | 107 +++++++++++++++------ .../couchdb/nouveau/health/IndexHealthCheck.java | 4 +- .../couchdb/nouveau/resources/IndexResource.java | 27 ++++-- .../couchdb/nouveau/lucene/LuceneIndexTest.java | 2 +- src/nouveau/include/nouveau.hrl | 3 +- src/nouveau/src/nouveau_api.erl | 17 +++- src/nouveau/src/nouveau_fabric_info.erl | 16 +-- src/nouveau/src/nouveau_fabric_search.erl | 4 +- src/nouveau/src/nouveau_httpd.erl | 15 ++- src/nouveau/src/nouveau_index_manager.erl | 6 +- src/nouveau/src/nouveau_index_updater.erl | 7 +- 12 files changed, 151 insertions(+), 65 deletions(-) diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java index b8a03e1d1..2e88241e6 100644 --- a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java +++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/Index.java @@ -52,6 +52,14 @@ public abstract class Index implements Closeable { return new IndexInfo(updateSeq, purgeSeq, numDocs, diskSize, upgradeRequired); } + public synchronized long getUpdateSeq() { + return updateSeq; + } + + public synchronized long getPurgeSeq() { + return purgeSeq; + } + protected abstract int doNumDocs() throws IOException; protected abstract long doDiskSize() throws IOException; diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java index da185aa2a..8570bcd0b 100644 --- a/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java +++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/core/IndexManager.java @@ -38,6 +38,7 @@ import org.apache.couchdb.nouveau.api.IndexDefinition; import org.apache.couchdb.nouveau.lucene.LuceneAnalyzerFactory; import org.apache.couchdb.nouveau.lucene.LuceneIndex; import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.index.IndexFileNames; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.IndexWriterConfig.OpenMode; @@ -78,7 +79,8 @@ public final class IndexManager implements Managed { private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); private ScheduledFuture<?> commitFuture; private HolderState state = HolderState.NOT_LOADED; - private Index index; + private Index latestIndex; + private Index legacyIndex; } private static final Logger LOGGER = LoggerFactory.getLogger(IndexManager.class); @@ -104,7 +106,7 @@ public final class IndexManager implements Managed { private StripedLock<String> createLock; - public <R> R with(final String name, final IndexFunction<Index, R> indexFun) + public <R> R with(final String name, final boolean upgrade, final IndexFunction<Index, R> indexFun) throws IOException, InterruptedException { evictIfOverCapacity(); @@ -123,21 +125,29 @@ public final class IndexManager implements Managed { // Load if not already loaded or remove if Lucene closed the index elsewhere. if (holder.state == HolderState.NOT_LOADED - || (holder.state == HolderState.LOADED && !holder.index.isOpen())) { + || (holder.state == HolderState.LOADED + && (!holder.latestIndex.isOpen() + || (holder.legacyIndex != null && !holder.legacyIndex.isOpen()) + || upgradeComplete(holder)))) { holder.lock.readLock().unlock(); holder.lock.writeLock().lock(); try { - if (holder.state == HolderState.LOADED && !holder.index.isOpen()) { + if (holder.state == HolderState.LOADED && !holder.latestIndex.isOpen() + || (holder.legacyIndex != null && !holder.legacyIndex.isOpen())) { LOGGER.info("removing closed index {}", name); holder.state = HolderState.UNLOADED; - holder.index = null; + if (holder.latestIndex.isOpen() || holder.legacyIndex.isOpen()) { + close(name, holder); + } + holder.latestIndex = null; + holder.legacyIndex = null; synchronized (cache) { cache.remove(name, holder); } continue retry; } if (holder.state == HolderState.NOT_LOADED) { - holder.index = load(name); + load(name, holder); holder.commitFuture = this.schedulerExecutorService.scheduleWithFixedDelay( commitFun(name, holder), commitIntervalSeconds, @@ -145,6 +155,12 @@ public final class IndexManager implements Managed { TimeUnit.SECONDS); holder.state = HolderState.LOADED; } + if (holder.state == HolderState.LOADED && upgradeComplete(holder)) { + LOGGER.info("Upgrade of {} complete, removing legacy index", name); + holder.legacyIndex.setDeleteOnClose(true); + holder.legacyIndex.close(); + holder.legacyIndex = null; + } holder.lock.readLock().lock(); } finally { holder.lock.writeLock().unlock(); @@ -159,7 +175,11 @@ public final class IndexManager implements Managed { Thread.sleep(1000); continue retry; case LOADED: - return indexFun.apply(holder.index); + // Use latest index if upgrading or legacy index if it exists if not. + var index = upgrade + ? holder.latestIndex + : holder.legacyIndex != null ? holder.legacyIndex : holder.latestIndex; + return indexFun.apply(index); } } finally { holder.lock.readLock().unlock(); @@ -167,6 +187,14 @@ public final class IndexManager implements Managed { } } + private boolean upgradeComplete(final IndexHolder holder) throws IOException { + if (holder.legacyIndex == null) { + return false; + } + return holder.latestIndex.getUpdateSeq() >= holder.legacyIndex.getUpdateSeq() + && holder.latestIndex.getPurgeSeq() >= holder.legacyIndex.getPurgeSeq(); + } + private void evictIfOverCapacity() throws IOException, InterruptedException { while (true) { final String candidate; @@ -190,7 +218,10 @@ public final class IndexManager implements Managed { switch (holder.state) { case LOADED: if (forceDelete) { - holder.index.setDeleteOnClose(true); + holder.latestIndex.setDeleteOnClose(true); + if (holder.legacyIndex != null) { + holder.legacyIndex.setDeleteOnClose(true); + } } LOGGER.info("closing {}", name); try { @@ -199,7 +230,8 @@ public final class IndexManager implements Managed { LOGGER.error("I/O exception when evicting {}", name, e); } holder.state = HolderState.UNLOADED; - holder.index = null; + holder.latestIndex = null; + holder.legacyIndex = null; break; case NOT_LOADED: case UNLOADED: @@ -331,8 +363,11 @@ public final class IndexManager implements Managed { return () -> { holder.lock.readLock().lock(); try { - if (holder.index.commit()) { - LOGGER.info("committed {}", name); + if (holder.latestIndex.commit()) { + LOGGER.info("committed {} (latest)", name); + } + if (holder.legacyIndex != null && holder.legacyIndex.commit()) { + LOGGER.info("committed {} (legacy)", name); } } catch (final IOException e) { LOGGER.warn("I/O exception while committing " + name, e); @@ -377,14 +412,31 @@ public final class IndexManager implements Managed { throw new WebApplicationException(name + " attempts to escape from index root directory", Status.BAD_REQUEST); } - private Index load(final String name) throws IOException { + private void load(final String name, final IndexHolder holder) throws IOException { LOGGER.info("opening {}", name); final Path path = indexPath(name); final IndexDefinition indexDefinition = loadIndexDefinition(name); final Analyzer analyzer = LuceneAnalyzerFactory.fromDefinition(indexDefinition); - final int version = getIndexVersion(path); + holder.latestIndex = load(name, Version.LATEST.major, analyzer); + if (indexExists(path.resolve(Integer.toString(Version.LATEST.major - 1)))) { + LOGGER.warn("{} has a legacy index", name); + holder.legacyIndex = load(name, Version.LATEST.major - 1, analyzer); + } + } + + // Same logic as DirectoryReader.indexExists() but without needing a Directory. + private boolean indexExists(final Path path) throws IOException { + if (!Files.exists(path)) { + return false; + } + try (var stream = Files.walk(path, 1)) { + return stream.anyMatch(f -> f.getFileName().toString().startsWith(IndexFileNames.SEGMENTS + "_")); + } + } + + private LuceneIndex load(final String name, final int version, final Analyzer analyzer) throws IOException { + final Path indexPath = indexPath(name).resolve(Integer.toString(version)); final boolean upgradeRequired = version < Version.LATEST.major; - final Path indexPath = path.resolve(Integer.toString(version)); final Directory dir = new DirectIODirectory(FSDirectory.open(indexPath)); final IndexWriterConfig config = new IndexWriterConfig(analyzer); config.setOpenMode(upgradeRequired ? OpenMode.APPEND : OpenMode.CREATE_OR_APPEND); @@ -396,19 +448,6 @@ public final class IndexManager implements Managed { return new LuceneIndex(analyzer, writer, updateSeq, purgeSeq, upgradeRequired, searcherManager); } - /** - * Find highest version index on disk, or latest version if none. - */ - private int getIndexVersion(final Path path) throws IOException { - if (Files.exists(path.resolve(Integer.toString(Version.LATEST.major)))) { - return Version.LATEST.major; - } - if (Files.exists(path.resolve(Integer.toString(Version.LATEST.major - 1)))) { - return Version.LATEST.major - 1; - } - return Version.LATEST.major; - } - private long getSeq(final IndexWriter writer, final String key) throws IOException { final Iterable<Map.Entry<String, String>> commitData = writer.getLiveCommitData(); if (commitData == null) { @@ -429,15 +468,21 @@ public final class IndexManager implements Managed { holder.commitFuture.cancel(true); IOUtils.runAll( () -> { - if (holder.index.commit()) { - LOGGER.debug("committed {} before close", name); + if (holder.latestIndex.commit()) { + LOGGER.debug("committed {} (latest) before close", name); + } + if (holder.legacyIndex != null && holder.legacyIndex.commit()) { + LOGGER.debug("committed {} (legacy) before close", name); } }, () -> { - holder.index.close(); + holder.latestIndex.close(); + if (holder.legacyIndex != null) { + holder.legacyIndex.close(); + } }, () -> { - if (holder.index.isDeleteOnClose()) { + if (holder.latestIndex.isDeleteOnClose()) { IOUtils.rm(indexRootPath(name)); } }); diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java index f20efe0c9..64733eb20 100644 --- a/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java +++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/health/IndexHealthCheck.java @@ -43,13 +43,13 @@ public final class IndexHealthCheck extends HealthCheck { try { final DocumentUpdateRequest documentUpdateRequest = new DocumentUpdateRequest(0, 1, null, Collections.emptyList()); - indexResource.updateDoc(name, "foo", documentUpdateRequest); + indexResource.updateDoc(name, true, "foo", documentUpdateRequest); final SearchRequest searchRequest = new SearchRequest(); searchRequest.setQuery("_id:foo"); searchRequest.setMinUpdateSeq(1); - final SearchResults searchResults = indexResource.searchIndex(name, searchRequest); + final SearchResults searchResults = indexResource.searchIndex(name, true, searchRequest); if (searchResults.getTotalHits() == 1) { return Result.healthy(); } else { diff --git a/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java b/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java index a52e00da9..d66220496 100644 --- a/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java +++ b/nouveau/src/main/java/org/apache/couchdb/nouveau/resources/IndexResource.java @@ -26,6 +26,7 @@ import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import java.io.IOException; import java.util.List; @@ -65,10 +66,11 @@ public final class IndexResource { @Path("/doc/{docId}") public Ok deleteDoc( @PathParam("name") String name, + @QueryParam("upgrade") boolean upgrade, @PathParam("docId") String docId, @NotNull @Valid DocumentDeleteRequest request) throws Exception { - return indexManager.with(name, (index) -> { + return indexManager.with(name, upgrade, (index) -> { index.delete(docId, request); return Ok.INSTANCE; }); @@ -81,15 +83,20 @@ public final class IndexResource { } @GET - public IndexInfo getIndexInfo(@PathParam("name") String name) throws Exception { - return indexManager.with(name, (index) -> { + public IndexInfo getIndexInfo(@PathParam("name") String name, @QueryParam("upgrade") boolean upgrade) + throws Exception { + return indexManager.with(name, upgrade, (index) -> { return index.info(); }); } @POST - public Ok setIndexInfo(@PathParam("name") String name, @NotNull @Valid IndexInfoRequest request) throws Exception { - return indexManager.with(name, (index) -> { + public Ok setIndexInfo( + @PathParam("name") String name, + @QueryParam("upgrade") boolean upgrade, + @NotNull @Valid IndexInfoRequest request) + throws Exception { + return indexManager.with(name, upgrade, (index) -> { if (request.getMatchUpdateSeq().isPresent() && request.getUpdateSeq().isPresent()) { index.setUpdateSeq( @@ -107,9 +114,12 @@ public final class IndexResource { @POST @Path("/search") - public SearchResults searchIndex(@PathParam("name") String name, @NotNull @Valid SearchRequest request) + public SearchResults searchIndex( + @PathParam("name") String name, + @QueryParam("upgrade") boolean upgrade, + @NotNull @Valid SearchRequest request) throws Exception { - return indexManager.with(name, (index) -> { + return indexManager.with(name, upgrade, (index) -> { return index.search(request); }); } @@ -118,10 +128,11 @@ public final class IndexResource { @Path("/doc/{docId}") public Ok updateDoc( @PathParam("name") String name, + @QueryParam("upgrade") boolean upgrade, @PathParam("docId") String docId, @NotNull @Valid DocumentUpdateRequest request) throws Exception { - return indexManager.with(name, (index) -> { + return indexManager.with(name, upgrade, (index) -> { index.update(docId, request); return Ok.INSTANCE; }); diff --git a/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java b/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java index 9206b83d9..10dd599e8 100644 --- a/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java +++ b/nouveau/src/test/java/org/apache/couchdb/nouveau/lucene/LuceneIndexTest.java @@ -56,7 +56,7 @@ public class LuceneIndexTest { config.setUseCompoundFile(false); final IndexWriter writer = new IndexWriter(dir, config); final SearcherManager searcherManager = new SearcherManager(writer, null); - return new LuceneIndex(analyzer, writer, 0L, 0L, searcherManager); + return new LuceneIndex(analyzer, writer, 0L, 0L, false, searcherManager); } protected final void cleanup(final Index index) throws IOException { diff --git a/src/nouveau/include/nouveau.hrl b/src/nouveau/include/nouveau.hrl index e50cd45d3..b8d986161 100644 --- a/src/nouveau/include/nouveau.hrl +++ b/src/nouveau/include/nouveau.hrl @@ -19,5 +19,6 @@ def, def_lang, name, - sig=nil + sig=nil, + upgrade=false }). diff --git a/src/nouveau/src/nouveau_api.erl b/src/nouveau/src/nouveau_api.erl index 319170a4c..f59efe599 100644 --- a/src/nouveau/src/nouveau_api.erl +++ b/src/nouveau/src/nouveau_api.erl @@ -171,7 +171,7 @@ update_doc(#index{} = Index, DocId, MatchSeq, UpdateSeq, Partition, Fields) when send_error(Reason) end. -search(#index{} = Index, QueryArgs) -> +search(#index{} = Index, #{} = QueryArgs) -> Resp = send_if_enabled( search_path(Index), [?JSON_CONTENT_TYPE], <<"POST">>, jiffy:encode(QueryArgs) ), @@ -219,18 +219,25 @@ set_seq(#index{} = Index, ReqBody) -> index_path(Path) when is_binary(Path) -> [<<"/index/">>, couch_util:url_encode(Path)]; index_path(#index{} = Index) -> - [<<"/index/">>, couch_util:url_encode(nouveau_util:index_name(Index))]. + upgrade(Index, [<<"/index/">>, couch_util:url_encode(nouveau_util:index_name(Index))]). doc_path(#index{} = Index, DocId) -> - [ + upgrade(Index, [ <<"/index/">>, couch_util:url_encode(nouveau_util:index_name(Index)), <<"/doc/">>, couch_util:url_encode(DocId) - ]. + ]). search_path(#index{} = Index) -> - [<<"/index/">>, couch_util:url_encode(nouveau_util:index_name(Index)), <<"/search">>]. + upgrade(Index, [ + <<"/index/">>, couch_util:url_encode(nouveau_util:index_name(Index)), <<"/search">> + ]). + +upgrade(#index{upgrade = false}, Path) -> + Path; +upgrade(#index{upgrade = true}, Path) -> + [Path, <<"?upgrade=true">>]. jaxrs_error(400, Body) -> {bad_request, message(Body)}; diff --git a/src/nouveau/src/nouveau_fabric_info.erl b/src/nouveau/src/nouveau_fabric_info.erl index 45bdf177e..0f62d5dca 100644 --- a/src/nouveau/src/nouveau_fabric_info.erl +++ b/src/nouveau/src/nouveau_fabric_info.erl @@ -15,22 +15,22 @@ -module(nouveau_fabric_info). --export([go/3]). +-export([go/4]). -include_lib("mem3/include/mem3.hrl"). +-include_lib("nouveau/include/nouveau.hrl"). -go(DbName, DDocId, IndexName) when is_binary(DDocId) -> +go(DbName, DDocId, IndexName, Upgrade) when is_binary(DDocId), is_boolean(Upgrade) -> {ok, DDoc} = fabric:open_doc(DbName, <<"_design/", DDocId/binary>>, [ejson_body]), - go(DbName, DDoc, IndexName); -go(DbName, DDoc, IndexName) -> + go(DbName, DDoc, IndexName, Upgrade); +go(DbName, DDoc, IndexName, Upgrade) when is_boolean(Upgrade) -> case nouveau_util:design_doc_to_index(DbName, DDoc, IndexName) of {ok, Index} -> - go(DbName, DDoc, IndexName, Index); + go(DbName, DDoc, IndexName, Index#index{upgrade = Upgrade}); {error, Reason} -> {error, Reason} - end. - -go(DbName, _DDoc, _IndexName, Index) -> + end; +go(DbName, _DDoc, _IndexName, #index{} = Index) -> Shards = mem3:shards(DbName), Counters0 = lists:map( fun(#shard{} = Shard) -> diff --git a/src/nouveau/src/nouveau_fabric_search.erl b/src/nouveau/src/nouveau_fabric_search.erl index 3ec9d96fd..fa6e0db2e 100644 --- a/src/nouveau/src/nouveau_fabric_search.erl +++ b/src/nouveau/src/nouveau_fabric_search.erl @@ -20,6 +20,7 @@ -include_lib("mem3/include/mem3.hrl"). -include_lib("couch/include/couch_db.hrl"). -include("nouveau_int.hrl"). +-include_lib("nouveau/include/nouveau.hrl"). -record(state, { limit, @@ -36,9 +37,10 @@ go(DbName, GroupId, IndexName, QueryArgs0) when is_binary(GroupId) -> ), go(DbName, DDoc, IndexName, QueryArgs0); go(DbName, #doc{} = DDoc, IndexName, QueryArgs0) -> + #{upgrade := Upgrade} = QueryArgs0, case nouveau_util:design_doc_to_index(DbName, DDoc, IndexName) of {ok, Index} -> - go(DbName, DDoc, IndexName, QueryArgs0, Index); + go(DbName, DDoc, IndexName, QueryArgs0, Index#index{upgrade = Upgrade}); {error, Reason} -> {error, Reason} end. diff --git a/src/nouveau/src/nouveau_httpd.erl b/src/nouveau/src/nouveau_httpd.erl index 878e001b7..6ae470ade 100644 --- a/src/nouveau/src/nouveau_httpd.erl +++ b/src/nouveau/src/nouveau_httpd.erl @@ -75,7 +75,8 @@ handle_search_req_int(#httpd{method = 'GET', path_parts = [_, _, _, _, IndexName counts => chttpd:qs_value(Req, "counts"), update => chttpd:qs_value(Req, "update"), bookmark => chttpd:qs_value(Req, "bookmark"), - include_docs => chttpd:qs_value(Req, "include_docs") + include_docs => chttpd:qs_value(Req, "include_docs"), + upgrade => chttpd:qs_value(Req, "upgrade") }), handle_search_req(Req, DbName, DDoc, IndexName, QueryArgs, ?RETRY_LIMIT); handle_search_req_int( @@ -95,7 +96,8 @@ handle_search_req_int( counts => json_or_undefined(<<"counts">>, ReqBody), update => maps:get(<<"update">>, ReqBody, undefined), bookmark => maps:get(<<"bookmark">>, ReqBody, undefined), - include_docs => maps:get(<<"include_docs">>, ReqBody, undefined) + include_docs => maps:get(<<"include_docs">>, ReqBody, undefined), + upgrade => maps:get(<<"upgrade">>, ReqBody, undefined) }), handle_search_req(Req, DbName, DDoc, IndexName, QueryArgs, ?RETRY_LIMIT); handle_search_req_int(Req, _Db, _DDoc) -> @@ -136,7 +138,8 @@ handle_info_req( ) -> check_if_enabled(), DbName = couch_db:name(Db), - case nouveau_fabric_info:go(DbName, DDoc, IndexName) of + Upgrade = chttpd:qs_value(Req, "upgrade") == "true", + case nouveau_fabric_info:go(DbName, DDoc, IndexName, Upgrade) of {ok, IndexInfo} -> send_json( Req, @@ -260,6 +263,12 @@ validate_query_arg(include_docs, "false") -> false; validate_query_arg(include_docs, "true") -> true; +validate_query_arg(upgrade, undefined) -> + false; +validate_query_arg(upgrade, "false") -> + false; +validate_query_arg(upgrade, "true") -> + true; validate_query_arg(Key, Val) -> Msg = io_lib:format("Invalid value for ~p: ~p", [Key, Val]), throw({query_parse_error, ?l2b(Msg)}). diff --git a/src/nouveau/src/nouveau_index_manager.erl b/src/nouveau/src/nouveau_index_manager.erl index 45f7a1e8d..04f14ccf8 100644 --- a/src/nouveau/src/nouveau_index_manager.erl +++ b/src/nouveau/src/nouveau_index_manager.erl @@ -60,10 +60,12 @@ init(_) -> {ok, nil}. handle_call({update, #index{} = Index0}, From, State) -> - DbSig = {Index0#index.dbname, Index0#index.sig}, + DbSig = {Index0#index.dbname, Index0#index.sig, Index0#index.upgrade}, case ets:lookup(?BY_DBSIG, DbSig) of [] -> - {_IndexerPid, IndexerRef} = spawn_monitor(nouveau_index_updater, update, [Index0]), + {_IndexerPid, IndexerRef} = spawn_monitor(nouveau_index_updater, update, [ + Index0 + ]), Queue = queue:in(From, queue:new()), true = ets:insert(?BY_DBSIG, {DbSig, Index0, Queue}), true = ets:insert(?BY_REF, {IndexerRef, DbSig}); diff --git a/src/nouveau/src/nouveau_index_updater.erl b/src/nouveau/src/nouveau_index_updater.erl index 3952a893f..ff2cf07cd 100644 --- a/src/nouveau/src/nouveau_index_updater.erl +++ b/src/nouveau/src/nouveau_index_updater.erl @@ -18,10 +18,10 @@ -include("nouveau.hrl"). %% public api --export([outdated/1, get_db_info/1]). +-export([get_db_info/1]). %% callbacks --export([update/1]). +-export([outdated/1, update/1]). -import(couch_query_servers, [get_os_process/1, ret_os_process/1, proc_prompt/2]). -import(nouveau_util, [index_path/1]). @@ -70,7 +70,8 @@ update(#index{} = Index) -> {index, Index#index.name}, {progress, 0}, {changes_done, 0}, - {total_changes, TotalChanges} + {total_changes, TotalChanges}, + {upgrading, Index#index.upgrade} ]), %% update status every half second
