/* * Digital Audio Access Protocol (DAAP) Library * Copyright (C) 2004-2010 Roger Kapsi * * 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 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. */ package org.ardverk.daap; import java.util.Timer; import java.util.TimerTask; /** * An auto commiting Transaction. * * @author Roger Kapsi */ public class AutoCommitTransaction extends Transaction { public static final long TIMEOUT = 10000; // 10 Seconds public static final int ENFORCE_COMMIT = 100; protected Timer timer; protected TimerTask commitTask; protected Transaction transaction; protected long touched = 0; protected int txnCounter = 0; protected long timeout; protected int enforceCommit; public AutoCommitTransaction(Library library) { this(library, TIMEOUT, ENFORCE_COMMIT); } /** * Transaction will either auto commit after <code>timeout</code> or after * <code>enforceCommit</code> modifications of the Library. * * @param library * @param timeout * @param enforceTimeout */ public AutoCommitTransaction(Library library, long timeout, int enforceCommit) { super(library); this.timeout = timeout; this.enforceCommit = enforceCommit; } public int getEnforceCommit() { return enforceCommit; } public synchronized void setEnforceCommit(int enforceCommit) { this.enforceCommit = enforceCommit; } public long getTimeout() { return timeout; } public synchronized void setTimeout(long timeout) { this.timeout = timeout; } private synchronized void createTransactionIfNecessary() { touch(); if (transaction == null) { transaction = library.beginTransaction(); if (timer == null) { timer = new Timer(); } if (commitTask == null) { commitTask = new CommitTask(); timer.scheduleAtFixedRate(commitTask, 1000, 500); } } } protected synchronized void addTxn(Object obj, Txn txn) { createTransactionIfNecessary(); transaction.addTxn(obj, txn); if (enforceCommit > 0) { txnCounter++; if (txnCounter >= enforceCommit) { commit(); } } } protected synchronized void attach(Object obj) { createTransactionIfNecessary(); transaction.attach(obj); } protected synchronized boolean modified(Database database) { createTransactionIfNecessary(); return transaction.modified(database); } protected synchronized boolean modified(Library library) { createTransactionIfNecessary(); return transaction.modified(library); } protected synchronized boolean modified(Playlist playlist) { createTransactionIfNecessary(); return transaction.modified(playlist); } protected synchronized boolean modified(Song song) { createTransactionIfNecessary(); return transaction.modified(song); } public synchronized void commit() { if (transaction != null) { transaction.commit(); commitTask.cancel(); timer.cancel(); transaction = null; commitTask = null; timer = null; txnCounter = 0; touched = 0; } } public synchronized void rollback() { if (transaction != null) { transaction.rollback(); commitTask.cancel(); timer.cancel(); transaction = null; commitTask = null; timer = null; txnCounter = 0; touched = 0; } } protected synchronized void touch() { touched = System.currentTimeMillis(); } private class CommitTask extends TimerTask { public void run() { synchronized (AutoCommitTransaction.this) { if (System.currentTimeMillis() - touched >= timeout) { commit(); } } } } }