Merge lp:~oontvoo/akiban-server/bug_drop_fulltext_index into lp:~akiban-technologies/akiban-server/trunk

Proposed by Vy Nguyen
Status: Merged
Approved by: Nathan Williams
Approved revision: 2647
Merged at revision: 2652
Proposed branch: lp:~oontvoo/akiban-server/bug_drop_fulltext_index
Merge into: lp:~akiban-technologies/akiban-server/trunk
Prerequisite: lp:~oontvoo/akiban-server/new-trunk_do-maintenance
Diff against target: 542 lines (+122/-84)
14 files modified
src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java (+4/-2)
src/main/java/com/akiban/server/service/text/FullTextIndexInfo.java (+3/-2)
src/main/java/com/akiban/server/service/text/FullTextIndexInfosImpl.java (+5/-6)
src/main/java/com/akiban/server/service/text/FullTextIndexService.java (+2/-1)
src/main/java/com/akiban/server/service/text/FullTextIndexServiceImpl.java (+20/-17)
src/main/java/com/akiban/server/service/text/FullTextIndexShared.java (+0/-1)
src/main/java/com/akiban/server/store/PersistitStore.java (+24/-0)
src/main/java/com/akiban/sql/aisddl/IndexDDL.java (+1/-1)
src/test/java/com/akiban/server/service/config/TestConfigService.java (+3/-0)
src/test/java/com/akiban/server/service/text/FullTextIndexServiceIT.java (+3/-42)
src/test/java/com/akiban/server/test/ApiTestBase.java (+6/-0)
src/test/java/com/akiban/sql/optimizer/OptimizerTestBase.java (+2/-11)
src/test/java/com/akiban/sql/pg/PostgresServerMiscYamlIT.java (+4/-1)
src/test/resources/com/akiban/sql/pg/yaml/functional/test-drop-fulltext.yaml (+45/-0)
To merge this branch: bzr merge lp:~oontvoo/akiban-server/bug_drop_fulltext_index
Reviewer Review Type Date Requested Status
Nathan Williams Approve
Vy Nguyen (community) Needs Resubmitting
Review via email: mp+159495@code.launchpad.net

This proposal supersedes a proposal from 2013-04-15.

Description of the change

fix drop fulltext index bug (bug 1163026) and bug1154336

[Resubmit with pre-requisite: lp:~oontvoo/akiban-server/new-trunk_do-maintenance]

[ Resubmit #2: Remove pre-req because it is in trunk]

To post a comment you must log in.
Revision history for this message
Nathan Williams (nwilliams) wrote : Posted in a previous version of this proposal

What is the IndexDef needed for?

I'm guessing bug1154336 is quite similar too. Perhaps dropTableInternal() needs to be in on the game.

review: Needs Information
Revision history for this message
Vy Nguyen (oontvoo) wrote : Posted in a previous version of this proposal

PersisitStore.java - line 1554 (+/- a few lines)

It looks like the index needs to be 'attached' to an IndexDef.

Revision history for this message
Nathan Williams (nwilliams) wrote : Posted in a previous version of this proposal

Only to delete the tree, which full texts don't have.

DDLFunctions has separate methods for dropping table and group indexes. Something different needs to happen for full texts (i.e. FullTextIndexService#dropIndex), so another entry point would be consistent and make sense.

Revision history for this message
Nathan Williams (nwilliams) wrote : Posted in a previous version of this proposal

Actually, handling the distinction in PS#deleteIndexes() would let dropTableInternal() use it as well, so I'm fine with that too.

Revision history for this message
Vy Nguyen (oontvoo) wrote : Posted in a previous version of this proposal

skip fulltext index in persistitStore.deleteIndexes()

review: Needs Resubmitting
Revision history for this message
Nathan Williams (nwilliams) wrote : Posted in a previous version of this proposal

Since we're here, can you please fix the other bug I mentioned. We just need to call FTIS#dropIndex() for them.

review: Needs Fixing
Revision history for this message
Vy Nguyen (oontvoo) wrote : Posted in a previous version of this proposal

I am having a compilation-error in

src/test/java/com/akiban/server/test/FailureOnStartupIT.java:[85,12] error: constructor OperatorStore in class OperatorStore cannot be applied to given types;

(I declared FTS as an argument in PersistStore's ctor, and other places where it's called.)

What did I miss?

review: Needs Information
Revision history for this message
Vy Nguyen (oontvoo) wrote : Posted in a previous version of this proposal

Hm, never mind, found it!

Revision history for this message
Nathan Williams (nwilliams) wrote : Posted in a previous version of this proposal

Look at FailureOnStartupIT.java, line 85. It extends OperatorStore so its constructor needs adjusted too.

Revision history for this message
Vy Nguyen (oontvoo) wrote : Posted in a previous version of this proposal

Actually, it's more complicated than just calling FTS.dropIndex()

+ By the time deleteIndexes() is called, the index is no longer in AIS for FullTextIndexShared.forAIS() to look up. But that's not the 'complicated' part.

+ In order for dropIndex() to work, the index needs to be in 'indexes' map, which none of the current fulltext index is because no one puts it in there. The createIndex() method, which would do this, needs to be called manually.
This problem is solved in the do-maintenance branch. And I can certainly have it fix the bug you mentioned. (In fact, I tried merging this branch into it and the delete works correctly, which it wouldn't in this branch).

review: Needs Resubmitting
Revision history for this message
Nathan Williams (nwilliams) wrote : Posted in a previous version of this proposal

> By the time deleteIndexes() is called, the index is no
> longer in AIS for FullTextIndexShared.forAIS() to look up

It does not need to be in the current AIS and probably shouldn't be, given that it's being removed. Look at the flow of the other drop methods (e.g. table, index). The AIS changes are performed through the SchemaManager before tree deletion is done. You can either hang onto the 'old' AIS or get it through the Index reference.

> In order for dropIndex() to work, the index needs to be in 'indexes' map,

It should be, and sounds like will be once your other branch is in, but doesn't need to be. The getIndex() method will populate the indexes map on demand. It creates a value cached on the AIS, which is going away in this case, but will work just fine.

review: Needs Fixing
Revision history for this message
Vy Nguyen (oontvoo) wrote : Posted in a previous version of this proposal

clean up and more tests

review: Needs Resubmitting
2637. By Vy Nguyen

use wait() in test instead of blindly sleep for a long time

Revision history for this message
Nathan Williams (nwilliams) wrote :

akserver.text.indexpath is already in both configuration-defaults and TestConfigService, so it shouldn't be needed in PSMYIT. Moving the interval setting into TestConfigService might be good, as it is now in 3 places.

The new getIndexToDrop() helper is misleading. It will throw NoSuchIndex if the cache hasn't been created (e.g. create a FT and then immediately drop). Using the existing method is fine. Attempting to optimize away the Info creation is just noise.

Otherwise looks good.

review: Needs Fixing
2638. By Vy Nguyen

merge trunk, move configs to TestConfigService

2639. By Vy Nguyen

edge cases in removeTrees()

Revision history for this message
Vy Nguyen (oontvoo) wrote :

A few *subtle* changes:

- in removeTrees():
  The change is to ensure dropIndex is called on a particular index only once (for the same reason described in the comment in the code)

- in FullTextIndexServiceIT
  Because fullText index deletions were not done properly (which is what the branch is trying to fix), these test methods could call FTS.dropIndex() whenever they want.
  Now that the bug is fixed, these should not eagerly drop the index (simply to remove it from the tree( because tearDown() would then not be able to find the indices to really drop them.

- About your comment on getIndexToDrop()
  The error message could change, but using the existing method would require some mechanism to ensure the downstream methods lookup the index in the old AIS, not the new one, because the index is no longer in there. And all that is just not necessary because all we really want to do here is to remove the index from the cache and delete relating document(s).

  Deleting the index right after creating it is similar to using it right after creation. Unexpected things could happen, given that the index is populated asynchronously .

Revision history for this message
Vy Nguyen (oontvoo) :
review: Needs Resubmitting
2640. By Vy Nguyen

remove unused imports in FullTextIndexServiceIT

Revision history for this message
Nathan Williams (nwilliams) wrote :

There is a helper to return the 'owned' full text indexes: UserTable#getOwnFullTextIndexes().

Multiple tests still set the indexpath and working intervals.

The re-insertion in FullTextIndexServiceIT is highly suspect. Either the test needs rewritten or tearDown's assumptions need changed, though I didn't see what tearDown was actually refering too.

We can't rely on the contents of the cache to determine whether or not there is work to do. It is a cache and can be empty at any time. The decision *must* be made on the basis of the presence in the AIS. Getting it from the old AIS is simple, just pass it the old AIS.

We also can't say that "unexpected things could happen" if you drop an index. Not a very good user experience. Instead, we should ensure that the correct thing always happens. I see that the existing dropIndex() attempts to remove a 'promise' for population. That isn't enough, given that they could be concurrent. Instead, a shared claim should be made during the population or maintenance steps (see LockService). An exclusive claim is already taken during DROP processing.

review: Needs Fixing
2641. By Vy Nguyen

use getownFullTextIndex

2642. By Vy Nguyen

clean up

Revision history for this message
Vy Nguyen (oontvoo) wrote :

> The re-insertion in FullTextIndexServiceIT is highly suspect. Either the test
> needs rewritten or tearDown's assumptions need changed, though I didn't see
> what tearDown was actually refering too.
>

tearDown() is called automatically at the end of the test class to drop all tables/indices/schemas, etc. It does not make any assumption, so I don't think we should change anything about that, though I agree testDelete() isn't exactly straightforward.

The test is intended to test the the populate-worker, NOT the deletion of the index per se.
In other words, we wanted to make sure that when a fulltext index is created, an entry about it is inserted into a tree for later processing, but if the index is dropped before the time scheduled for population, we wants to make sure the entry is removed from that tree. Otherwise, when the worker wakes up, it will populate a non-existing index.

> We can't rely on the contents of the cache to determine whether or not there
> is work to do. It is a cache and can be empty at any time. The decision *must*
> be made on the basis of the presence in the AIS. Getting it from the old AIS
> is simple, just pass it the old AIS.

I believe I misused the word 'cache' in the resubmit comment. What I really meant was FTS.dropIndex() only needed to remove the entry about the index from the hashmap (ie., `indexes`), and to delete relating document(s).

It wasn't checking some cache to see if the given index exists in there. The index must exist in `indexes` if it was properly populated.

Now that I thought about it, throwing an error on line 44 is 'over-reacting'. That wouldn't really be an error. Probably just a warning in the debug log would be sufficient. The only time this would happen is, as you said, when the index is deleted before it was populated, and because all that FTS.dropIndex() is responsible for doing is to clean up the stuff that only exists *after* the population, there is nothing to do here (other than removing the 'promise' for population, of course).

Revision history for this message
Nathan Williams (nwilliams) wrote :

> The test is intended to test the the populate-worker, NOT
> the deletion of the index per se. In other words, we wanted
> to make sure that when a fulltext index is created, an entry
> about it is inserted into a tree for later processing, but if
> the index is dropped before the time scheduled for population,
> we wants to make sure the entry is removed from that tree

Since, I believe, we should claim a lock on the table when performing the populate or update, this would be a good time to check that the index still exists. If it doesn't, the entry from the background tree can be removed and all work skipped. As I mentioned in the previous comment, removing the entry from the dropIndex() processing isn't enough.

> I believe I misused the word 'cache' in the resubmit comment.

Cache is the correct word. The IndexInfo is stored in a cache that is attached to the AIS. We can make no assumptions about its contents or lifetime.

> The only time this would happen is, as you said, when the index is
> deleted before it was populated,

No. The best way to think of it is really as a cache that can be cleared at any time. In the current implementation, the cache will be empty any time there is *any* DDL, not just one related to the table. This is because a brand new AIS each time.time.

2643. By Vy Nguyen

clean up

2644. By Vy Nguyen

pass Index as an argument to dropIndex to correctly determine the treename

Revision history for this message
Vy Nguyen (oontvoo) wrote :

- construct a simple* FulLTextIndexShared/Info for deleting the docs, if none already exists.
This should get rid of the NoSuchIndexException in getIndexToDrop()

*simple* because we don't want to
(1) cache the object in AIS (No one is ever going to use the cached value)
(2) compute operator plan for lookup the rows of the index (same reason as above)
(3) All that we wants here is the path to the document file(s)

review: Needs Resubmitting
2645. By Vy Nguyen

delete fulltext index

Revision history for this message
Nathan Williams (nwilliams) wrote :

As I mentioned a number of comments ago, optimizing away the cache generation is noise. The unlikely case is it doesn't exist. Less code is generally better.

Please address the issues in my previous comments most importantly locking but also duplicate settings tests.

review: Needs Fixing
Revision history for this message
Vy Nguyen (oontvoo) wrote :

> As I mentioned a number of comments ago, optimizing away the cache generation
> is noise.
> The unlikely case is it doesn't exist.

That is not a *little* optimisation. The current getIndex() would cause a bunch of stuff to be done including building a list of rowTypes and computing plans to lookup related rows. Why would we want to do all that just to delete the index?

> Please address the issues in my previous comments most importantly locking but
> also duplicate settings tests.

I did. All the settings are gone, only TestConfigService still sets the interval now.

What about locking that you were getting at? If that's about an entry being the tree possibly being modified elsewhere, too, it's addressed in the ww_bug branch that I just put in.

Revision history for this message
Nathan Williams (nwilliams) wrote :

> That is not a *little* optimisation. The current getIndex()
> would cause a bunch of stuff to be done including building
> a list of rowTypes and computing plans to lookup related
> rows. Why would we want to do all that just to delete the
> index?

The amount of time that the getIndex() would take compared to the rest of the DROP processing is miniscule. Yes, it creates a little garbage but that's about it.

Why? As I said earlier, less code is generally better. Less to understand, maintain, document, and test. In a scenario where we can have a single code path vs two, and the cost is a little garbage in uncommon scenarios, I'll always choose the former.

> I did. All the settings are gone, only TestConfigService still
> sets the interval now.

OptimizerTestBase.java:136
OptimizerTestBase.java:137
OptimizerTestBase.java:138

TestConfigService also declares TEXT_INDEX_PATH_KEY, which duplicates FTISI#INDEX_PATH_PROPERTY.

> What about locking that you were getting at?

As I mentioned previously, removing the key in FTSISI#deleteFromTree() is not enough. What happens if population is occurring the same time as deletion? Slightly before? Slightly after?

review: Needs Fixing
2646. By Vy Nguyen

use default settings in OptimizerTestBase

Revision history for this message
Vy Nguyen (oontvoo) wrote :

- configs: removed

- locking: this is addressed the ww_bug. I am not going to touch it here.

- I still don't see your arguments about more vs less code. To use the current code (ie., getIndex), we'd need to pass the old AIS to it, which'd lead to a series of change in its callers to take the AIS all the way from [Index|Table| *]DDL.java.
That doesn't look any less code.

At least, the current change is local.

Revision history for this message
Nathan Williams (nwilliams) wrote :

Thanks for the tweaks.

> - locking: this is addressed the ww_bug. I am not going to
> touch it here.

The other branch addresses part, but not all unfortunately. Note the specific cases I said in the previous comment (i.e. writes before populate is done). Doing this in another branch is fine.

> - I still don't see your arguments about more vs less code.
> To use the current code (ie., getIndex), we'd need to pass the
> old AIS to it,

In this instance, it's already immediately available: idx.getIndexedTable().getAIS(). If that isn't palatable, there are only two callers of dropIndex() so passing it in isn't onerous.

2647. By Vy Nguyen

use the old AIS when neccessary

Revision history for this message
Vy Nguyen (oontvoo) wrote :

use the old AIS when neccessary

review: Needs Resubmitting
2648. By Vy Nguyen

remove unused import accidentally added

Revision history for this message
Nathan Williams (nwilliams) wrote :

Thanks.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java'
2--- src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-14 04:32:58 +0000
3+++ src/main/java/com/akiban/server/service/dxl/BasicDDLFunctions.java 2013-04-29 16:13:27 +0000
4@@ -1032,8 +1032,10 @@
5 Collection<Index> indexes = new HashSet<>();
6 for(String indexName : indexNamesToDrop) {
7 Index index = table.getIndex(indexName);
8- if(index == null) {
9- throw new NoSuchIndexException (indexName);
10+ if(index == null
11+ && !(table.isUserTable()
12+ && ((index = ((UserTable)table).getFullTextIndex(indexName)) != null))) {
13+ throw new NoSuchIndexException (indexName);
14 }
15 if(index.isPrimaryKey()) {
16 throw new ProtectedIndexException(indexName, table.getName());
17
18=== modified file 'src/main/java/com/akiban/server/service/text/FullTextIndexInfo.java'
19--- src/main/java/com/akiban/server/service/text/FullTextIndexInfo.java 2013-04-01 19:04:26 +0000
20+++ src/main/java/com/akiban/server/service/text/FullTextIndexInfo.java 2013-04-29 16:13:27 +0000
21@@ -264,10 +264,11 @@
22 return indexer;
23 }
24
25- // TODO: _Lookup plan to get rows just from a row being updated.
26-
27 public void deletePath() {
28 File path = shared.getPath();
29+ // no doc to delete
30+ if (!path.exists() || path.listFiles() == null)
31+ return;
32 for (File f : path.listFiles()) {
33 f.delete();
34 }
35
36=== modified file 'src/main/java/com/akiban/server/service/text/FullTextIndexInfosImpl.java'
37--- src/main/java/com/akiban/server/service/text/FullTextIndexInfosImpl.java 2013-03-22 20:05:57 +0000
38+++ src/main/java/com/akiban/server/service/text/FullTextIndexInfosImpl.java 2013-04-29 16:13:27 +0000
39@@ -21,7 +21,6 @@
40 import com.akiban.ais.model.IndexName;
41 import com.akiban.qp.operator.QueryContext;
42 import com.akiban.qp.rowtype.RowType;
43-import com.akiban.qp.rowtype.Schema;
44 import com.akiban.server.error.FullTextQueryParseException;
45 import com.akiban.server.service.session.Session;
46
47@@ -30,7 +29,6 @@
48 import org.apache.lucene.search.Query;
49
50 import java.io.File;
51-import java.io.IOException;
52 import java.util.HashMap;
53 import java.util.Map;
54
55@@ -41,7 +39,7 @@
56 @Override
57 public Query parseQuery(QueryContext context, IndexName name,
58 String defaultField, String query) {
59- FullTextIndexInfo index = getIndex(context.getSession(), name);
60+ FullTextIndexInfo index = getIndex(context.getSession(), name, null);
61 if (defaultField == null) {
62 defaultField = index.getDefaultFieldName();
63 }
64@@ -58,15 +56,16 @@
65
66 @Override
67 public RowType searchRowType(Session session, IndexName name) {
68- FullTextIndexInfo index = getIndex(session, name);
69+ FullTextIndexInfo index = getIndex(session, name, null);
70 return index.getHKeyRowType();
71 }
72
73 protected abstract AkibanInformationSchema getAIS(Session session);
74 protected abstract File getIndexPath();
75
76- protected FullTextIndexInfo getIndex(Session session, IndexName name) {
77- AkibanInformationSchema ais = getAIS(session);
78+ protected FullTextIndexInfo getIndex(Session session, IndexName name, AkibanInformationSchema ais) {
79+ if (ais == null)
80+ ais = getAIS(session);
81 FullTextIndexInfo info;
82 synchronized (indexes) {
83 FullTextIndexShared shared = indexes.get(name);
84
85=== modified file 'src/main/java/com/akiban/server/service/text/FullTextIndexService.java'
86--- src/main/java/com/akiban/server/service/text/FullTextIndexService.java 2013-04-08 19:43:08 +0000
87+++ src/main/java/com/akiban/server/service/text/FullTextIndexService.java 2013-04-29 16:13:27 +0000
88@@ -17,6 +17,7 @@
89
90 package com.akiban.server.service.text;
91
92+import com.akiban.ais.model.FullTextIndex;
93 import com.akiban.ais.model.IndexName;
94 import com.akiban.qp.operator.Cursor;
95 import com.akiban.qp.operator.QueryContext;
96@@ -50,7 +51,7 @@
97 * @return An array of available background works
98 */
99 public List<? extends BackgroundWork> getBackgroundWorks();
100- public void dropIndex(Session session, IndexName name);
101+ public void dropIndex(Session session, FullTextIndex name);
102 public Cursor searchIndex(QueryContext context, IndexName name,
103 Query query, int limit);
104 }
105
106=== modified file 'src/main/java/com/akiban/server/service/text/FullTextIndexServiceImpl.java'
107--- src/main/java/com/akiban/server/service/text/FullTextIndexServiceImpl.java 2013-04-17 17:51:15 +0000
108+++ src/main/java/com/akiban/server/service/text/FullTextIndexServiceImpl.java 2013-04-29 16:13:27 +0000
109@@ -18,7 +18,7 @@
110 package com.akiban.server.service.text;
111
112 import com.akiban.ais.model.AkibanInformationSchema;
113-import com.akiban.ais.model.Index;
114+import com.akiban.ais.model.FullTextIndex;
115 import com.akiban.ais.model.IndexName;
116 import com.akiban.ais.model.TableName;
117 import com.akiban.ais.model.UserTable;
118@@ -34,7 +34,6 @@
119 import com.akiban.qp.rowtype.HKeyRowType;
120 import com.akiban.qp.util.HKeyCache;
121 import com.akiban.server.error.AkibanInternalException;
122-import com.akiban.server.service.BackgroundObserver;
123 import com.akiban.server.service.BackgroundWork;
124 import com.akiban.server.service.BackgroundWorkBase;
125 import com.akiban.server.service.Service;
126@@ -63,8 +62,6 @@
127 import java.util.Arrays;
128 import java.util.Collections;
129 import java.util.List;
130-import java.util.Observable;
131-import java.util.Observer;
132 import java.util.Timer;
133 import java.util.TimerTask;
134
135@@ -114,7 +111,7 @@
136 /* FullTextIndexService */
137
138 private long createIndex(Session session, IndexName name) {
139- FullTextIndexInfo index = getIndex(session, name);
140+ FullTextIndexInfo index = getIndex(session, name, null);
141 try {
142 return populateIndex(session, index);
143 }
144@@ -123,12 +120,10 @@
145 }
146 }
147
148- @Override
149- public void dropIndex(Session session, IndexName name) {
150-
151+ void deleteFromTree(Session session, IndexName name)
152+ {
153 try
154 {
155- // see if there exists a promise for populating this index
156 Exchange ex = getPopulateExchange(session);
157 ex.clear().append(name.getSchemaName())
158 .append(name.getTableName())
159@@ -136,22 +131,29 @@
160
161 if (ex.traverse(Key.Direction.EQ, true, 0))
162 ex.fetchAndRemove();
163-
164- FullTextIndexInfo index = getIndex(session, name);
165- index.deletePath();
166- synchronized (indexes) {
167- indexes.remove(name);
168- }
169 }
170 catch (PersistitException e)
171 {
172 throw new AkibanInternalException("Error while removing index", e);
173 }
174 }
175+
176+ @Override
177+ public void dropIndex(Session session, FullTextIndex idx) {
178+ // delete 'promise' for population, if any
179+ deleteFromTree(session, idx.getIndexName());
180+
181+ // delete documents
182+ FullTextIndexInfo idxInfo = getIndex(session, idx.getIndexName(), idx.getIndexedTable().getAIS());
183+ idxInfo.deletePath();
184+ synchronized (indexes) {
185+ indexes.remove(idx.getIndexName());
186+ }
187+ }
188
189 @Override
190 public Cursor searchIndex(QueryContext context, IndexName name, Query query, int limit) {
191- FullTextIndexInfo index = getIndex(context.getSession(), name);
192+ FullTextIndexInfo index = getIndex(context.getSession(), name, null);
193 try {
194 return index.getSearcher().search(context, index.getHKeyRowType(),
195 query, limit);
196@@ -172,6 +174,7 @@
197 @Override
198 public void start() {
199 persistitStore = store.getPersistitStore();
200+ persistitStore.setFullTextService(this);
201 enableUpdateWorker();
202 enablePopulateWorker();
203 }
204@@ -255,7 +258,7 @@
205 {
206 try
207 {
208- FullTextIndexInfo indexInfo = getIndex(session, name);
209+ FullTextIndexInfo indexInfo = getIndex(session, name, null);
210 StoreAdapter adapter = session.get(StoreAdapter.STORE_ADAPTER_KEY);
211 if (adapter == null)
212 adapter = new PersistitAdapter(indexInfo.getSchema(),
213
214=== modified file 'src/main/java/com/akiban/server/service/text/FullTextIndexShared.java'
215--- src/main/java/com/akiban/server/service/text/FullTextIndexShared.java 2013-03-22 20:05:57 +0000
216+++ src/main/java/com/akiban/server/service/text/FullTextIndexShared.java 2013-04-29 16:13:27 +0000
217@@ -27,7 +27,6 @@
218 import org.apache.lucene.store.FSDirectory;
219
220 import java.io.*;
221-import java.util.List;
222 import java.util.Set;
223
224 public class FullTextIndexShared implements CacheValueGenerator<FullTextIndexInfo>, Closeable
225
226=== modified file 'src/main/java/com/akiban/server/store/PersistitStore.java'
227--- src/main/java/com/akiban/server/store/PersistitStore.java 2013-04-15 16:20:25 +0000
228+++ src/main/java/com/akiban/server/store/PersistitStore.java 2013-04-29 16:13:27 +0000
229@@ -18,6 +18,7 @@
230 package com.akiban.server.store;
231
232 import com.akiban.ais.model.*;
233+import com.akiban.ais.model.Index.IndexType;
234 import com.akiban.qp.operator.StoreAdapter;
235 import com.akiban.qp.persistitadapter.OperatorBasedRowCollector;
236 import com.akiban.qp.persistitadapter.PersistitAdapter;
237@@ -41,6 +42,7 @@
238 import com.akiban.server.service.config.ConfigurationService;
239 import com.akiban.server.service.lock.LockService;
240 import com.akiban.server.service.session.Session;
241+import com.akiban.server.service.text.FullTextIndexService;
242 import com.akiban.server.service.transaction.TransactionService;
243 import com.akiban.server.service.tree.TreeLink;
244 import com.akiban.server.service.tree.TreeService;
245@@ -130,6 +132,8 @@
246
247 private int deferredIndexKeyLimit = MAX_INDEX_TRANCHE_SIZE;
248
249+ private FullTextIndexService fullTextService;
250+
251 private RowDataValueCoder valueCoder;
252
253 // Each row change has a 'uniqueChangeId', stored in the 'maintenance.full_text' table
254@@ -157,6 +161,11 @@
255 this.transactionService = transactionService;
256 }
257
258+ public void setFullTextService(FullTextIndexService service)
259+ {
260+ fullTextService = service;
261+ }
262+
263 // --- for tracking changes
264 private Exchange getChangeExchange(Session session) throws PersistitException
265 {
266@@ -1890,6 +1899,14 @@
267 @Override
268 public void removeTrees(Session session, Table table) {
269 Collection<TreeLink> treeLinks = new ArrayList<>();
270+
271+ // delete all fulltext indexes
272+ if (table.isUserTable())
273+ {
274+ for (FullTextIndex idx : ((UserTable)table).getOwnFullTextIndexes())
275+ fullTextService.dropIndex(session, idx);
276+ }
277+
278 // Add all index trees
279 final Collection<TableIndex> tableIndexes = table.isUserTable() ? ((UserTable)table).getIndexesIncludingInternal() : table.getIndexes();
280 final Collection<GroupIndex> groupIndexes = table.getGroupIndexes();
281@@ -1931,6 +1948,13 @@
282 public void deleteIndexes(final Session session, final Collection<? extends Index> indexes) {
283 List<TreeLink> links = new ArrayList<>(indexes.size());
284 for(Index index : indexes) {
285+ // no trees to drop
286+ if (index.getIndexType() == IndexType.FULL_TEXT)
287+ {
288+ fullTextService.dropIndex(session, (FullTextIndex)index);
289+ indexes.remove(index);
290+ continue;
291+ }
292 final IndexDef indexDef = index.indexDef();
293 if(indexDef == null) {
294 throw new IllegalStateException("indexDef is null for index: " + index);
295
296=== modified file 'src/main/java/com/akiban/sql/aisddl/IndexDDL.java'
297--- src/main/java/com/akiban/sql/aisddl/IndexDDL.java 2013-03-27 04:42:10 +0000
298+++ src/main/java/com/akiban/sql/aisddl/IndexDDL.java 2013-04-29 16:13:27 +0000
299@@ -89,7 +89,7 @@
300 }
301 // if we can't find the index, set tableName to null
302 // to flag not a user table index.
303- if (table.getIndex(indexName) == null) {
304+ if (table.getIndex(indexName) == null && table.getFullTextIndex(indexName) == null) {
305 tableName = null;
306 }
307 // Check the group associated to the table for the
308
309=== modified file 'src/test/java/com/akiban/server/service/config/TestConfigService.java'
310--- src/test/java/com/akiban/server/service/config/TestConfigService.java 2013-03-22 20:05:57 +0000
311+++ src/test/java/com/akiban/server/service/config/TestConfigService.java 2013-04-29 16:13:27 +0000
312@@ -22,6 +22,7 @@
313 import com.akiban.server.service.plugins.Plugin;
314 import com.akiban.server.service.plugins.PluginsFinder;
315
316+import com.akiban.server.service.text.FullTextIndexServiceImpl;
317 import java.io.File;
318 import java.util.Collection;
319 import java.util.Collections;
320@@ -60,6 +61,8 @@
321 protected Map<String, String> loadProperties() {
322 Map<String, String> ret = new HashMap<>(super.loadProperties());
323 makeDataDirectory();
324+ ret.put(FullTextIndexServiceImpl.UPDATE_INTERVAL, Long.toString(1000));
325+ ret.put(FullTextIndexServiceImpl.POPULATE_DELAY_INTERVAL, Long.toString(1000));
326 ret.put(DATA_PATH_KEY, dataDirectory.getAbsolutePath());
327 ret.put(TEXT_INDEX_PATH_KEY, dataDirectory.getAbsolutePath());
328 final int bufferSize = Integer.parseInt(ret.get(BUFFER_SIZE_KEY));
329
330=== modified file 'src/test/java/com/akiban/server/service/text/FullTextIndexServiceIT.java'
331--- src/test/java/com/akiban/server/service/text/FullTextIndexServiceIT.java 2013-04-15 19:21:09 +0000
332+++ src/test/java/com/akiban/server/service/text/FullTextIndexServiceIT.java 2013-04-29 16:13:27 +0000
333@@ -45,8 +45,6 @@
334 public class FullTextIndexServiceIT extends ITBase
335 {
336 public static final String SCHEMA = "test";
337- private static final long updateInterval = 1000L; // for testing
338- private static final long populateDelayInterval = 1000L;
339 protected FullTextIndexService fullText;
340 protected Schema schema;
341 protected PersistitAdapter adapter;
342@@ -63,15 +61,6 @@
343 .bindAndRequire(FullTextIndexService.class, FullTextIndexServiceImpl.class);
344 }
345
346- @Override
347- protected Map<String, String> startupConfigProperties() {
348- Map<String, String> properties = new HashMap<>();
349- properties.put("akserver.text.indexpath", "/tmp/aktext");
350- properties.put(FullTextIndexServiceImpl.UPDATE_INTERVAL, Long.toString(updateInterval));
351- properties.put(FullTextIndexServiceImpl.POPULATE_DELAY_INTERVAL, Long.toString(populateDelayInterval));
352- return properties;
353- }
354-
355 @Before
356 public void createData() {
357 c = createTable(SCHEMA, "c",
358@@ -179,12 +168,6 @@
359 assertEquals (0, n);
360 }
361 });
362-
363- // drop all the indices
364- Session session = new SessionServiceImpl().createSession();
365- for (FullTextIndex idx : expecteds)
366- fullTextImpl.dropIndex(session, idx.getIndexName());
367- session.close();
368 }
369
370
371@@ -217,29 +200,9 @@
372
373 // <3> delete 2 of them
374 Session session = new SessionServiceImpl().createSession();
375- boolean sawNPE = false;
376- try
377- {
378- fullTextImpl.dropIndex(session, expecteds[0].getIndexName());
379- }
380- catch (NullPointerException e) // NPE is expected because, the index hasn't been
381- { // populated yet. But we're not testing that!
382- sawNPE = true;
383- }
384- assertTrue("NPE should have happened", sawNPE);
385-
386+ deleteFullTextIndex(serviceManager(), expecteds[0].getIndexName());
387+ deleteFullTextIndex(serviceManager(), expecteds[1].getIndexName());
388
389- sawNPE = false;
390- try
391- {
392- fullTextImpl.dropIndex(session, expecteds[1].getIndexName());
393- }
394- catch (NullPointerException e) // NPE is expected because, the index hasn't been
395- { // populated yet. But we're not testing that!
396- sawNPE = true;
397- }
398- assertTrue("NPE should have happened", sawNPE);
399-
400 // <4> check that the tree only has one entry now (ie., epxecteds2[2]
401 traverse(fullTextImpl,
402 new Visitor()
403@@ -259,13 +222,11 @@
404 assertEquals (1, n);
405 }
406 });
407-
408+
409 // wake the worker up to do its job
410 fullTextImpl.enablePopulateWorker();
411 WaitFunctionHelpers.waitOn(fullText.getBackgroundWorks());
412
413- // drop the remaining index
414- fullTextImpl.dropIndex(session, expecteds[2].getIndexName());
415 session.close();
416 }
417
418
419=== modified file 'src/test/java/com/akiban/server/test/ApiTestBase.java'
420--- src/test/java/com/akiban/server/test/ApiTestBase.java 2013-04-10 18:32:00 +0000
421+++ src/test/java/com/akiban/server/test/ApiTestBase.java 2013-04-29 16:13:27 +0000
422@@ -767,6 +767,12 @@
423 return ddl().getAIS(session()).getGroup(groupName).getIndex(indexName);
424 }
425
426+ protected final void deleteFullTextIndex(ServiceManager sm, IndexName name)
427+ {
428+ ddl().dropTableIndexes(session(), name.getFullTableName(), Arrays.asList(name.getName()));
429+ updateAISGeneration();
430+ }
431+
432 protected final FullTextIndex createFullTextIndex(ServiceManager sm, String schema, String table, String indexName, String... indexCols) {
433 AkibanInformationSchema tempAIS = createIndexInternal(schema, table, indexName, "FULL_TEXT(" + Strings.join(Arrays.asList(indexCols), ",") + ")");
434 Index tempIndex = tempAIS.getUserTable(schema, table).getFullTextIndex(indexName);
435
436=== modified file 'src/test/java/com/akiban/sql/optimizer/OptimizerTestBase.java'
437--- src/test/java/com/akiban/sql/optimizer/OptimizerTestBase.java 2013-04-01 19:04:26 +0000
438+++ src/test/java/com/akiban/sql/optimizer/OptimizerTestBase.java 2013-04-29 16:13:27 +0000
439@@ -117,7 +117,7 @@
440 }
441
442
443- protected static ServiceManager createServiceManager(Map<String, String> startupConfigProperties)
444+ protected static ServiceManager createServiceManager()
445 {
446 return new GuicedServiceManager(serviceBindingsProvider());
447 }
448@@ -130,19 +130,10 @@
449 FullTextIndexServiceImpl.class);
450 }
451
452-
453- protected static Map<String, String> startupConfigProperties() {
454- Map<String, String> properties = new HashMap<>();
455- properties.put("akserver.text.indexpath", "/tmp/aktext");
456- properties.put(FullTextIndexServiceImpl.UPDATE_INTERVAL, Long.toString(updateInterval));
457- properties.put(FullTextIndexServiceImpl.POPULATE_DELAY_INTERVAL, Long.toString(populateDelayInterval));
458- return properties;
459- }
460-
461 private static ServiceManager prepareServices()
462 {
463 System.setProperty("akiban.home", System.getProperty("user.home"));
464- ServiceManager ret = createServiceManager(startupConfigProperties());
465+ ServiceManager ret = createServiceManager();
466 ret.startServices();
467
468 return ret;
469
470=== modified file 'src/test/java/com/akiban/sql/pg/PostgresServerMiscYamlIT.java'
471--- src/test/java/com/akiban/sql/pg/PostgresServerMiscYamlIT.java 2013-04-11 05:18:38 +0000
472+++ src/test/java/com/akiban/sql/pg/PostgresServerMiscYamlIT.java 2013-04-29 16:13:27 +0000
473@@ -23,6 +23,8 @@
474 import com.akiban.server.service.is.BasicInfoSchemaTablesService;
475 import com.akiban.server.service.is.BasicInfoSchemaTablesServiceImpl;
476 import com.akiban.server.service.servicemanager.GuicedServiceManager;
477+import com.akiban.server.service.text.FullTextIndexService;
478+import com.akiban.server.service.text.FullTextIndexServiceImpl;
479 import com.akiban.sql.NamedParamsTestBase;
480 import com.akiban.sql.embedded.EmbeddedJDBCService;
481 import com.akiban.sql.embedded.EmbeddedJDBCServiceImpl;
482@@ -79,7 +81,8 @@
483 protected GuicedServiceManager.BindingsConfigurationProvider serviceBindingsProvider() {
484 return super.serviceBindingsProvider()
485 .bindAndRequire(BasicInfoSchemaTablesService.class, BasicInfoSchemaTablesServiceImpl.class)
486- .bindAndRequire(EmbeddedJDBCService.class, EmbeddedJDBCServiceImpl.class);
487+ .bindAndRequire(EmbeddedJDBCService.class, EmbeddedJDBCServiceImpl.class)
488+ .bindAndRequire(FullTextIndexService.class, FullTextIndexServiceImpl.class);
489 }
490
491 @Override
492
493=== added file 'src/test/resources/com/akiban/sql/pg/yaml/functional/test-drop-fulltext.yaml'
494--- src/test/resources/com/akiban/sql/pg/yaml/functional/test-drop-fulltext.yaml 1970-01-01 00:00:00 +0000
495+++ src/test/resources/com/akiban/sql/pg/yaml/functional/test-drop-fulltext.yaml 2013-04-29 16:13:27 +0000
496@@ -0,0 +1,45 @@
497+# test drop full_text index
498+---
499+- CreateTable: t(id int, name varchar(224));
500+---
501+- Statement: CREATE INDEX idx on t(full_text(name));
502+---
503+- Statement: SELECT fulltext_maintenance_wait();
504+---
505+- Statement: INSERT INTO t values (1, 'bar1'), (2, 'bar2'), (3, 'bar3'), (4, 'bar1');
506+---
507+- Statement: SELECT fulltext_maintenance_wait();
508+---
509+- Statement: SELECT id from t where full_text_search(name='bar1');
510+- output: [[1], [4]]
511+---
512+- Statement: DROP INDEX t.idx;
513+---
514+- DropTable: t;
515+---
516+- CreateTable: t2(id int, name varchar(32));
517+---
518+- Statement: INSERT INTO t2 VALUES (1, 'John'), (2, 'Sally');
519+---
520+- Statement: CREATE INDEX t2_idx on t2(full_text(name));
521+---
522+- Statement: SELECT fulltext_maintenance_wait();
523+---
524+- Statement: SELECT * FROM t2 WHERE FULL_TEXT_SEARCH(name, 'Jo*');
525+- row_count: 0
526+---
527+- DropTable: t2;
528+---
529+- CreateTable: t2(id INT NOT NULL PRIMARY KEY, name VARCHAR(32) COLLATE en_ci);
530+---
531+- Statement: INSERT INTO t2 VALUES (1, 'John'), (2, 'Sally');
532+---
533+- Statement: CREATE INDEX t2_idx on t2(full_text(name));
534+---
535+- Statement: SELECT fulltext_maintenance_wait()
536+---
537+- Statement: SELECT * FROM t2 WHERE FULL_TEXT_SEARCH(name, 'Jo*');
538+- output: [[1, 'John']]
539+---
540+- DropTable: t2;
541+...
542\ No newline at end of file

Subscribers

People subscribed via source and target branches

to all changes: