001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.dataAccess.db.mysql;
019
020import io.stallion.dataAccess.Tickets;
021import io.stallion.dataAccess.db.DB;
022import io.stallion.services.Log;
023import org.apache.commons.dbutils.QueryRunner;
024import org.apache.commons.dbutils.handlers.ScalarHandler;
025
026import java.math.BigInteger;
027import java.sql.SQLException;
028import java.util.List;
029import java.util.Queue;
030import java.util.concurrent.ConcurrentLinkedQueue;
031
032
033public class MySqlTickets implements Tickets {
034    private Queue<Long> loadedIds;
035    private DB db;
036
037    public MySqlTickets(DB db) {
038        loadedIds = new ConcurrentLinkedQueue<Long>();
039        this.db = db;
040        createSequence();
041        refillQueue();
042    }
043
044    @Override
045    public Long nextId() {
046        for (int x=0; x<20; x++) {
047            Long id = loadedIds.poll();
048            if (id != null) {
049                return id;
050            } else {
051                try {
052                    refillQueue();
053                } catch (Exception e) {
054                    Log.exception(e, "Error refilling queue");
055                    try {
056                        Thread.sleep(500);
057                    } catch (Exception ex) {
058                        throw new RuntimeException(e);
059                    }
060                }
061            }
062        }
063        throw new RuntimeException("Could not load the next ticket");
064    }
065
066    public void createSequence() {
067        List items = db.findRecords("SHOW TABLES LIKE 'stallion_tickets'");
068        if (items.size() > 0) {
069            return;
070        }
071        QueryRunner q = db.newQuery();
072        try {
073            q.update("CREATE TABLE `stallion_tickets` (\n" +
074                    "  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,\n" +
075                    "  `ticket_name` varchar(10) DEFAULT NULL,\n" +
076                    "  PRIMARY KEY (`id`),\n" +
077                    "  UNIQUE KEY `ticket_name_unique` (`ticket_name`)\n" +
078                    ") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;");
079            db.execute("INSERT INTO stallion_tickets (`ticket_name`) VALUES('a')");
080        } catch(Exception e) {
081            Log.exception(e, "Error creating tickets table");
082        }
083    }
084
085    public void refillQueue() {
086        QueryRunner q = db.newQuery();
087        //String sql = "insert into users (username) values (?)";
088        String sql = "REPLACE INTO stallion_tickets (ticket_name) VALUES('a')";
089        long nextId = 0;
090        try {
091            nextId = q.insert(sql, new ScalarHandler<Long>());
092        } catch (SQLException e) {
093            throw new RuntimeException(e);
094        }
095        Log.fine("Next ticket id {0}", nextId);
096        nextId = nextId * 1000;
097
098        //ScalarHandler<Long> scalar = new ScalarHandler<Long>();
099        //Long nextId = q.query("SELECT nextval('stallion_tickets_seq')", scalar);
100        for (int x= 0; x < 1000; x++ ) {
101            loadedIds.add(nextId + x);
102        }
103    }
104}