/*
 * Copyright 2009-2010 by The Regents of the University of California
 * Licensed 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 from
 * 
 *     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.
 */

package edu.uci.ics.hyracks.storage.am.btree;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;

import org.junit.Test;

import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.storage.am.btree.util.AbstractBTreeTest;
import edu.uci.ics.hyracks.storage.common.buffercache.IBufferCache;
import edu.uci.ics.hyracks.storage.common.buffercache.ICachedPage;
import edu.uci.ics.hyracks.storage.common.file.BufferedFileHandle;
import edu.uci.ics.hyracks.storage.common.sync.LatchType;

public class StorageManagerTest extends AbstractBTreeTest {
    public class PinnedLatchedPage {
        public final ICachedPage page;
        public final LatchType latch;
        public final int pageId;

        public PinnedLatchedPage(ICachedPage page, int pageId, LatchType latch) {
            this.page = page;
            this.pageId = pageId;
            this.latch = latch;
        }
    }

    public enum FileAccessType {
        FTA_READONLY,
        FTA_WRITEONLY,
        FTA_MIXED,
        FTA_UNLATCHED
    }

    public class FileAccessWorker implements Runnable {
        private int workerId;
        private final IBufferCache bufferCache;
        private final int maxPages;
        private final int fileId;
        private final long thinkTime;
        private final int maxLoopCount;
        private final int maxPinnedPages;
        private final int closeFileChance;
        private final FileAccessType fta;
        private int loopCount = 0;
        private boolean fileIsOpen = false;
        private Random rnd = new Random(50);
        private List<PinnedLatchedPage> pinnedPages = new LinkedList<PinnedLatchedPage>();

        public FileAccessWorker(int workerId, IBufferCache bufferCache, FileAccessType fta, int fileId, int maxPages,
                int maxPinnedPages, int maxLoopCount, int closeFileChance, long thinkTime) {
            this.bufferCache = bufferCache;
            this.fileId = fileId;
            this.maxPages = maxPages;
            this.maxLoopCount = maxLoopCount;
            this.maxPinnedPages = maxPinnedPages;
            this.thinkTime = thinkTime;
            this.closeFileChance = closeFileChance;
            this.workerId = workerId;
            this.fta = fta;
        }

        private void pinRandomPage() {
            int pageId = Math.abs(rnd.nextInt() % maxPages);

            if (LOGGER.isLoggable(Level.INFO)) {
                LOGGER.info(workerId + " PINNING PAGE: " + pageId);
            }

            try {
                ICachedPage page = bufferCache.pin(BufferedFileHandle.getDiskPageId(fileId, pageId), false);
                LatchType latch = null;

                switch (fta) {

                    case FTA_UNLATCHED: {
                        latch = null;
                    }
                        break;

                    case FTA_READONLY: {
                        if (LOGGER.isLoggable(Level.INFO)) {
                            LOGGER.info(workerId + " S LATCHING: " + pageId);
                        }
                        page.acquireReadLatch();
                        latch = LatchType.LATCH_S;
                    }
                        break;

                    case FTA_WRITEONLY: {
                        if (LOGGER.isLoggable(Level.INFO)) {
                            LOGGER.info(workerId + " X LATCHING: " + pageId);
                        }
                        page.acquireWriteLatch();
                        latch = LatchType.LATCH_X;
                    }
                        break;

                    case FTA_MIXED: {
                        if (rnd.nextInt() % 2 == 0) {
                            if (LOGGER.isLoggable(Level.INFO)) {
                                LOGGER.info(workerId + " S LATCHING: " + pageId);
                            }
                            page.acquireReadLatch();
                            latch = LatchType.LATCH_S;
                        } else {
                            if (LOGGER.isLoggable(Level.INFO)) {
                                LOGGER.info(workerId + " X LATCHING: " + pageId);
                            }
                            page.acquireWriteLatch();
                            latch = LatchType.LATCH_X;
                        }
                    }
                        break;

                }

                PinnedLatchedPage plPage = new PinnedLatchedPage(page, pageId, latch);
                pinnedPages.add(plPage);
            } catch (HyracksDataException e) {
                e.printStackTrace();
            }
        }

        private void unpinRandomPage() {
            int index = Math.abs(rnd.nextInt() % pinnedPages.size());
            try {
                PinnedLatchedPage plPage = pinnedPages.get(index);

                if (plPage.latch != null) {
                    if (plPage.latch == LatchType.LATCH_S) {
                        if (LOGGER.isLoggable(Level.INFO)) {
                            LOGGER.info(workerId + " S UNLATCHING: " + plPage.pageId);
                        }
                        plPage.page.releaseReadLatch();
                    } else {
                        if (LOGGER.isLoggable(Level.INFO)) {
                            LOGGER.info(workerId + " X UNLATCHING: " + plPage.pageId);
                        }
                        plPage.page.releaseWriteLatch();
                    }
                }
                if (LOGGER.isLoggable(Level.INFO)) {
                    LOGGER.info(workerId + " UNPINNING PAGE: " + plPage.pageId);
                }

                bufferCache.unpin(plPage.page);
                pinnedPages.remove(index);
            } catch (HyracksDataException e) {
                e.printStackTrace();
            }
        }

        private void openFile() {
            if (LOGGER.isLoggable(Level.INFO)) {
                LOGGER.info(workerId + " OPENING FILE: " + fileId);
            }
            try {
                bufferCache.openFile(fileId);
                fileIsOpen = true;
            } catch (HyracksDataException e) {
                e.printStackTrace();
            }
        }

        private void closeFile() {
            if (LOGGER.isLoggable(Level.INFO)) {
                LOGGER.info(workerId + " CLOSING FILE: " + fileId);
            }
            try {
                bufferCache.closeFile(fileId);
                fileIsOpen = false;
            } catch (HyracksDataException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void run() {

            openFile();

            while (loopCount < maxLoopCount) {
                loopCount++;

                if (LOGGER.isLoggable(Level.INFO)) {
                    LOGGER.info(workerId + " LOOP: " + loopCount + "/" + maxLoopCount);
                }

                if (fileIsOpen) {

                    // pin some pages
                    int pagesToPin = Math.abs(rnd.nextInt()) % (maxPinnedPages - pinnedPages.size());
                    for (int i = 0; i < pagesToPin; i++) {
                        pinRandomPage();
                    }

                    // do some thinking
                    try {
                        Thread.sleep(thinkTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    // unpin some pages
                    if (!pinnedPages.isEmpty()) {
                        int pagesToUnpin = Math.abs(rnd.nextInt()) % pinnedPages.size();
                        for (int i = 0; i < pagesToUnpin; i++) {
                            unpinRandomPage();
                        }
                    }

                    // possibly close file
                    int closeFileCheck = Math.abs(rnd.nextInt()) % closeFileChance;
                    if (pinnedPages.isEmpty() || closeFileCheck == 0) {
                        int numPinnedPages = pinnedPages.size();
                        for (int i = 0; i < numPinnedPages; i++) {
                            unpinRandomPage();
                        }
                        closeFile();
                    }
                } else {
                    openFile();
                }
            }

            if (fileIsOpen) {
                int numPinnedPages = pinnedPages.size();
                for (int i = 0; i < numPinnedPages; i++) {
                    unpinRandomPage();
                }
                closeFile();
            }
        }
    }

    @Test
    public void oneThreadOneFileTest() throws Exception {
        IBufferCache bufferCache = harness.getBufferCache();
        bufferCache.createFile(harness.getFileReference());
        int btreeFileId = harness.getFileMapProvider().lookupFileId(harness.getFileReference());
        bufferCache.openFile(btreeFileId);
        Thread worker = new Thread(new FileAccessWorker(0, harness.getBufferCache(), FileAccessType.FTA_UNLATCHED,
                btreeFileId, 10, 10, 100, 10, 0));
        worker.start();
        worker.join();
        bufferCache.closeFile(btreeFileId);
        bufferCache.close();
    }
}
