/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.server.service.text;
import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import com.foundationdb.ais.model.TableName;
import com.foundationdb.qp.util.SchemaCache;
import com.foundationdb.server.error.DuplicateIndexException;
import com.foundationdb.server.service.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Originally testing various sequences of background population but population
* is now done in the foreground.
*/
public class FullTextIndexServiceBug1172013IT extends FullTextIndexServiceITBase {
private static final Logger logger = LoggerFactory.getLogger(FullTextIndexServiceBug1172013IT.class);
private final Object lock = new Object();
@Before
public void createData() {
c = createTable(SCHEMA, "c",
"cid INT PRIMARY KEY NOT NULL",
"name VARCHAR(128) COLLATE en_us_ci");
o = createTable(SCHEMA, "o",
"oid INT PRIMARY KEY NOT NULL",
"cid INT NOT NULL",
"c1 VARCHAR(128) COLLATE en_us_ci",
"c2 VARCHAR(128) COLLATE en_us_ci",
"c3 VARCHAR(128) COLLATE en_us_ci",
"c4 VARCHAR(128) COLLATE en_us_ci",
"GROUPING FOREIGN KEY(cid) REFERENCES c(cid)",
"order_date DATE");
i = createTable(SCHEMA, "i",
"iid INT PRIMARY KEY NOT NULL",
"oid INT NOT NULL",
"GROUPING FOREIGN KEY(oid) REFERENCES o(oid)",
"sku VARCHAR(10) NOT NULL");
a = createTable(SCHEMA, "a",
"aid INT PRIMARY KEY NOT NULL",
"cid INT NOT NULL",
"GROUPING FOREIGN KEY(cid) REFERENCES c(cid)",
"state CHAR(2)");
writeRow(c, 1, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices justo in sapien ullamcorper eu mattis massa pretium.");
writeRow(o, 101, 1, "c1", "c2", "c3", "c4", "2012-12-12");
writeRow(i, 10101, 101, "ABCD");
writeRow(i, 10102, 101, "1234");
writeRow(o, 102, 1, "c1", "c2", "c3", "c4","2013-01-01");
writeRow(a, 101, 1, "MA");
writeRow(c, 2, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices justo in sapien ullamcorper eu mattis massa pretium.");
writeRow(a, 201, 2, "NY");
writeRow(c, 3, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices justo in sapien ullamcorper eu mattis massa pretium.");
writeRow(o, 301, 3, "c1", "c2", "c3", "c4", "2010-04-01");
writeRow(a, 301, 3, "MA");
writeRow(a, 302, 3, "ME");
schema = SchemaCache.globalSchema(ais());
adapter = newStoreAdapter();
queryContext = queryContext(adapter);
}
/** Race concurrent drop vs create. */
@Test
public void testDelete1 () throws InterruptedException {
logger.debug("Running test delete 1");
createFullTextIndex(
SCHEMA, "o", "idx3_o",
"oid", "c1", "c2", "c3", "c4");
Thread t = new Thread(new DropIndex());
t.start();
try {
createFullTextIndex(
SCHEMA, "o", "idx3_o",
"oid", "c1", "c2", "c3", "c4");
} catch(DuplicateIndexException e) {
// Possible outcome
}
t.join();
if(getTable(SCHEMA, "o").getFullTextIndex("idx3_o") != null) {
new DropIndex().run();
}
}
/** Race concurrent drop vs create, with lined up start. */
@Test
public void testDelete2() throws InterruptedException {
logger.debug("Running test delete 2");
createFullTextIndex(
SCHEMA, "o", "idx3_o",
"oid", "c1", "c2", "c3", "c4");
Thread t = new Thread(new DropIndex());
t.start();
synchronized (lock) {
lock.wait();
}
try {
createFullTextIndex(
SCHEMA, "o", "idx3_o",
"oid", "c1", "c2", "c3", "c4");
} catch (DuplicateIndexException ex) {
logger.debug("Got Duplicate Index");
// an expected possible outcome.
}
t.join();
if(getTable(SCHEMA, "o").getFullTextIndex("idx3_o") != null) {
new DropIndex().run();
}
}
/** Serial create and drop. */
@Test
public void testDelete3() throws InterruptedException {
logger.debug("Running test delete 3");
createFullTextIndex(
SCHEMA, "o", "idx3_o",
"oid", "c1", "c2", "c3", "c4");
new DropIndex().run();
}
@Test
public void testDropUpdate1 () throws InterruptedException {
logger.debug("Running test drop update 1");
// create the index, let it complete
createFullTextIndex(
SCHEMA, "o", "idx3_o",
"oid", "c1", "c2", "c3", "c4");
writeRow(o, 103, 1, "c1", "c2", "c3", "c4", "2012-12-12");
writeRow(o, 104, 1, "c1", "c2", "c3", "c4", "2012-12-12");
writeRow(o, 105, 1, "c1", "c2", "c3", "c4", "2012-12-12");
// Race update vs drop
Thread t = new Thread(new DropIndex());
t.start();
// But don't let it fall off the end
t.join();
}
private class DropIndex implements Runnable
{
@Override
public void run()
{
Session session = serviceManager().getSessionService().createSession();
TableName tableName = new TableName (SCHEMA, "o");
synchronized (lock) {
lock.notify();
}
ddl().dropTableIndexes(session, tableName, Collections.singletonList("idx3_o"));
}
}
}