package org.apache.lucene.store;

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util._TestUtil;

public class TestLockFactory extends LuceneTestCase {

    // Verify: we can provide our own LockFactory implementation, the right
    // methods are called at the right time, locks are created, etc.

    public void testCustomLockFactory() throws IOException {
        Directory dir = new RAMDirectory();
        MockLockFactory lf = new MockLockFactory();
        dir.setLockFactory(lf);

        // Lock prefix should have been set:
        assertTrue("lock prefix was not set by the RAMDirectory", lf.lockPrefixSet);

        IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true,
                                             IndexWriter.MaxFieldLength.LIMITED);

        // add 100 documents (so that commit lock is used)
        for (int i = 0; i < 100; i++) {
            addDoc(writer);
        }

        // Both write lock and commit lock should have been created:
        assertEquals("# of unique locks created (after instantiating IndexWriter)",
                     1, lf.locksCreated.size());
        assertTrue("# calls to makeLock is 0 (after instantiating IndexWriter)",
                   lf.makeLockCount >= 1);
        
        for(Iterator e = lf.locksCreated.keySet().iterator(); e.hasNext();) {
            String lockName = (String) e.next();
            MockLockFactory.MockLock lock = (MockLockFactory.MockLock) lf.locksCreated.get(lockName);
            assertTrue("# calls to Lock.obtain is 0 (after instantiating IndexWriter)",
                       lock.lockAttempts > 0);
        }
        
        writer.close();
    }

    // Verify: we can use the NoLockFactory with RAMDirectory w/ no
    // exceptions raised:
    // Verify: NoLockFactory allows two IndexWriters
    public void testRAMDirectoryNoLocking() throws IOException {
        Directory dir = new RAMDirectory();
        dir.setLockFactory(NoLockFactory.getNoLockFactory());

        assertTrue("RAMDirectory.setLockFactory did not take",
                   NoLockFactory.class.isInstance(dir.getLockFactory()));

        IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true,
                                             IndexWriter.MaxFieldLength.LIMITED);

        // Create a 2nd IndexWriter.  This is normally not allowed but it should run through since we're not
        // using any locks:
        IndexWriter writer2 = null;
        try {
            writer2 = new IndexWriter(dir, new WhitespaceAnalyzer(), false,
                                      IndexWriter.MaxFieldLength.LIMITED);
        } catch (Exception e) {
            e.printStackTrace(System.out);
            fail("Should not have hit an IOException with no locking");
        }

        writer.close();
        if (writer2 != null) {
            writer2.close();
        }
    }

    // Verify: SingleInstanceLockFactory is the default lock for RAMDirectory
    // Verify: RAMDirectory does basic locking correctly (can't create two IndexWriters)
    public void testDefaultRAMDirectory() throws IOException {
        Directory dir = new RAMDirectory();

        assertTrue("RAMDirectory did not use correct LockFactory: got " + dir.getLockFactory(),
                   SingleInstanceLockFactory.class.isInstance(dir.getLockFactory()));

        IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true,
                                             IndexWriter.MaxFieldLength.LIMITED);

        // Create a 2nd IndexWriter.  This should fail:
        IndexWriter writer2 = null;
        try {
            writer2 = new IndexWriter(dir, new WhitespaceAnalyzer(), false,
                                      IndexWriter.MaxFieldLength.LIMITED);
            fail("Should have hit an IOException with two IndexWriters on default SingleInstanceLockFactory");
        } catch (IOException e) {
        }

        writer.close();
        if (writer2 != null) {
            writer2.close();
        }
    }
    
    public void testSimpleFSLockFactory() throws IOException {
      // test string file instantiation
      new SimpleFSLockFactory("test");
    }

    // Verify: do stress test, by opening IndexReaders and
    // IndexWriters over & over in 2 threads and making sure
    // no unexpected exceptions are raised:
    public void testStressLocks() throws Exception {
      _testStressLocks(null, _TestUtil.getTempDir("index.TestLockFactory6"));
    }

    // Verify: do stress test, by opening IndexReaders and
    // IndexWriters over & over in 2 threads and making sure
    // no unexpected exceptions are raised, but use
    // NativeFSLockFactory:
    public void testStressLocksNativeFSLockFactory() throws Exception {
      File dir = _TestUtil.getTempDir("index.TestLockFactory7");
      _testStressLocks(new NativeFSLockFactory(dir), dir);
    }

    public void _testStressLocks(LockFactory lockFactory, File indexDir) throws Exception {
        FSDirectory fs1 = FSDirectory.open(indexDir, lockFactory);

        // First create a 1 doc index:
        IndexWriter w = new IndexWriter(fs1, new WhitespaceAnalyzer(), true,
                                        IndexWriter.MaxFieldLength.LIMITED);
        addDoc(w);
        w.close();

        WriterThread writer = new WriterThread(100, fs1);
        SearcherThread searcher = new SearcherThread(100, fs1);
        writer.start();
        searcher.start();

        while(writer.isAlive() || searcher.isAlive()) {
          Thread.sleep(1000);
        }

        assertTrue("IndexWriter hit unexpected exceptions", !writer.hitException);
        assertTrue("IndexSearcher hit unexpected exceptions", !searcher.hitException);

        // Cleanup
        _TestUtil.rmDir(indexDir);
    }

    // Verify: NativeFSLockFactory works correctly
    public void testNativeFSLockFactory() throws IOException {

      NativeFSLockFactory f = new NativeFSLockFactory(System.getProperty("tempDir"));

      f.setLockPrefix("test");
      Lock l = f.makeLock("commit");
      Lock l2 = f.makeLock("commit");

      assertTrue("failed to obtain lock", l.obtain());
      assertTrue("succeeded in obtaining lock twice", !l2.obtain());
      l.release();

      assertTrue("failed to obtain 2nd lock after first one was freed", l2.obtain());
      l2.release();

      // Make sure we can obtain first one again, test isLocked():
      assertTrue("failed to obtain lock", l.obtain());
      assertTrue(l.isLocked());
      assertTrue(l2.isLocked());
      l.release();
      assertFalse(l.isLocked());
      assertFalse(l2.isLocked());
    }

    // Verify: NativeFSLockFactory assigns null as lockPrefix if the lockDir is inside directory
    public void testNativeFSLockFactoryPrefix() throws IOException {

      File fdir1 = _TestUtil.getTempDir("TestLockFactory.8");
      File fdir2 = _TestUtil.getTempDir("TestLockFactory.8.Lockdir");
      Directory dir1 = FSDirectory.open(fdir1, new NativeFSLockFactory(fdir1));
      // same directory, but locks are stored somewhere else. The prefix of the lock factory should != null
      Directory dir2 = FSDirectory.open(fdir1, new NativeFSLockFactory(fdir2));

      String prefix1 = dir1.getLockFactory().getLockPrefix();
      assertNull("Lock prefix for lockDir same as directory should be null", prefix1);
      
      String prefix2 = dir2.getLockFactory().getLockPrefix();
      assertNotNull("Lock prefix for lockDir outside of directory should be not null", prefix2);

      _TestUtil.rmDir(fdir1);
      _TestUtil.rmDir(fdir2);
    }

    // Verify: default LockFactory has no prefix (ie
    // write.lock is stored in index):
    public void testDefaultFSLockFactoryPrefix() throws IOException {

      // Make sure we get null prefix:
      File dirName = _TestUtil.getTempDir("TestLockFactory.10");
      Directory dir = FSDirectory.open(dirName);

      String prefix = dir.getLockFactory().getLockPrefix();

      assertTrue("Default lock prefix should be null", null == prefix);

      _TestUtil.rmDir(dirName);
    }

    private class WriterThread extends Thread { 
        private Directory dir;
        private int numIteration;
        public boolean hitException = false;
        public WriterThread(int numIteration, Directory dir) {
            this.numIteration = numIteration;
            this.dir = dir;
        }
        @Override
        public void run() {
            WhitespaceAnalyzer analyzer = new WhitespaceAnalyzer();
            IndexWriter writer = null;
            for(int i=0;i<this.numIteration;i++) {
                try {
                    writer = new IndexWriter(dir, analyzer, false,
                                             IndexWriter.MaxFieldLength.LIMITED);
                } catch (IOException e) {
                    if (e.toString().indexOf(" timed out:") == -1) {
                        hitException = true;
                        System.out.println("Stress Test Index Writer: creation hit unexpected IOException: " + e.toString());
                        e.printStackTrace(System.out);
                    } else {
                        // lock obtain timed out
                        // NOTE: we should at some point
                        // consider this a failure?  The lock
                        // obtains, across IndexReader &
                        // IndexWriters should be "fair" (ie
                        // FIFO).
                    }
                } catch (Exception e) {
                    hitException = true;
                    System.out.println("Stress Test Index Writer: creation hit unexpected exception: " + e.toString());
                    e.printStackTrace(System.out);
                    break;
                }
                if (writer != null) {
                    try {
                        addDoc(writer);
                    } catch (IOException e) {
                        hitException = true;
                        System.out.println("Stress Test Index Writer: addDoc hit unexpected exception: " + e.toString());
                        e.printStackTrace(System.out);
                        break;
                    }
                    try {
                        writer.close();
                    } catch (IOException e) {
                        hitException = true;
                        System.out.println("Stress Test Index Writer: close hit unexpected exception: " + e.toString());
                        e.printStackTrace(System.out);
                        break;
                    }
                    writer = null;
                }
            }
        }
    }

    private class SearcherThread extends Thread { 
        private Directory dir;
        private int numIteration;
        public boolean hitException = false;
        public SearcherThread(int numIteration, Directory dir) {
            this.numIteration = numIteration;
            this.dir = dir;
        }
        @Override
        public void run() {
            IndexSearcher searcher = null;
            Query query = new TermQuery(new Term("content", "aaa"));
            for(int i=0;i<this.numIteration;i++) {
                try{
                    searcher = new IndexSearcher(dir, false);
                } catch (Exception e) {
                    hitException = true;
                    System.out.println("Stress Test Index Searcher: create hit unexpected exception: " + e.toString());
                    e.printStackTrace(System.out);
                    break;
                }
                if (searcher != null) {
                    ScoreDoc[] hits = null;
                    try {
                        hits = searcher.search(query, null, 1000).scoreDocs;
                    } catch (IOException e) {
                        hitException = true;
                        System.out.println("Stress Test Index Searcher: search hit unexpected exception: " + e.toString());
                        e.printStackTrace(System.out);
                        break;
                    }
                    // System.out.println(hits.length() + " total results");
                    try {
                        searcher.close();
                    } catch (IOException e) {
                        hitException = true;
                        System.out.println("Stress Test Index Searcher: close hit unexpected exception: " + e.toString());
                        e.printStackTrace(System.out);
                        break;
                    }
                    searcher = null;
                }
            }
        }
    }

    public class MockLockFactory extends LockFactory {

        public boolean lockPrefixSet;
        public Map locksCreated = Collections.synchronizedMap(new HashMap());
        public int makeLockCount = 0;

        @Override
        public void setLockPrefix(String lockPrefix) {    
            super.setLockPrefix(lockPrefix);
            lockPrefixSet = true;
        }

        @Override
        synchronized public Lock makeLock(String lockName) {
            Lock lock = new MockLock();
            locksCreated.put(lockName, lock);
            makeLockCount++;
            return lock;
        }

        @Override
        public void clearLock(String specificLockName) {}

        public class MockLock extends Lock {
            public int lockAttempts;

            @Override
            public boolean obtain() {
                lockAttempts++;
                return true;
            }
            @Override
            public void release() {
                // do nothing
            }
            @Override
            public boolean isLocked() {
                return false;
            }
        }
    }

    private void addDoc(IndexWriter writer) throws IOException {
        Document doc = new Document();
        doc.add(new Field("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
        writer.addDocument(doc);
    }
}
