/**
 * A CCNx repository.
 *
 * Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
 *
 * This work is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the
 * Free Software Foundation.
 * This work 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 General Public License
 * for more details. You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

package org.ccnx.ccn.impl.repo;

import java.io.File;
import java.security.InvalidParameterException;
import java.util.logging.Level;

import org.ccnx.ccn.impl.support.Daemon;
import org.ccnx.ccn.impl.support.Log;
import org.ccnx.ccn.test.BitBucketRepository;

/**
 * Daemon for stand-alone repository on persistent storage in the filesystem.
 */
public class RepositoryDaemon extends Daemon {
	RepositoryServer _server;
	RepositoryStore _repo;
	
	protected class RepositoryWorkerThread extends Daemon.WorkerThread {

		private static final long serialVersionUID = -6093561895394961537L;
		
		protected RepositoryWorkerThread(String daemonName) {
			super(daemonName);
		}
		
		public void work() {
			synchronized(this) {
				boolean interrupted = false;
				do {
					try {
						interrupted = false;
						wait();
					} catch (InterruptedException e) {
						interrupted = true;
					}		
				} while (interrupted);
			}
		}
		
		public void initialize() {
			_server.start();
		}
		
		public void finish() {
			_server.shutDown();
			synchronized (this) {
				notifyAll(); // notifyAll ensures shutdown in interactive case when main thread is join()'ing
			}
		}
		
		public boolean signal(String name) {
			return _repo.diagnostic(name);
		}
		
		public Object status(String type) {
			return "running";
		}
	}
	
	public RepositoryDaemon() {
		super();
		// This is a daemon: it should not do anything in the
		// constructor but everything in the initialize() method
		// which will be run in the process that will finally 
		// execute as the daemon, rather than in the launching
		// and stopping processes also.
		_daemonName = "repository";
	}
	
	/**
	 * Parse arguments specific to the Repository
	 * 
	 * Current arguments are:<p>
	 * 
	 * -root <directory> sets the root of the repository (this argument is required).
	 * 
	 * The following arguments are optional:<p>
	 * <ul>
	 * <li>-log <level> enable logging and set the logging level to <level>
	 * <li>-policy <file> use the policy file to set initial policy for the repo
	 * <li>-local <path> set the local name for this repository
	 * <li>-global <path> set the global prefix for this repository
	 * </ul>
	 */
	public void initialize(String[] args, Daemon daemon) {
		Log.info("Starting " + _daemonName + "...");				
		Log.setLevel(Level.INFO);
		try {
			Log.setDefaultLevel(Level.SEVERE);	// turn off all but severe errors
			String repositoryRoot = null;
			File policyFile = null;
			String localName = null;
			String globalPrefix = null;
			String nameSpace = null;
			for (int i = 0; i < args.length; i++) {
				if (args[i].equals("-log")) {
					if (args.length < i + 2) {
						usage();
						return;
					}
					try {
						Level level = Level.parse(args[i + 1]);
						Log.setLevel(level);
					} catch (IllegalArgumentException iae) {
						usage();
						return;
					}
					i++;
				} else if (args[i].equals("-root")) {
					if (args.length < i + 2)
						throw new InvalidParameterException();
					repositoryRoot = args[i + 1];
					i++;
				} else if (args[i].equals("-policy")) {
					if (args.length < i + 2)
						throw new InvalidParameterException();
					policyFile = new File(args[i + 1]);
					i++;
				} else if (args[i].equals("-local")) {
					if (args.length < i + 2)
						throw new InvalidParameterException();
					localName = args[i + 1];
					i++;
				} else if (args[i].equals("-global")) {
					if (args.length < i + 2)
						throw new InvalidParameterException();
					globalPrefix = args[i + 1];
					if (!globalPrefix.startsWith("/"))
						globalPrefix = "/" + globalPrefix;
					i++;
				} else if (args[i].equals("-prefix")) {
					if (args.length < i + 2)
						throw new InvalidParameterException();
					nameSpace = args[i + 1];
					if (!nameSpace.startsWith("/"))
						nameSpace = "/" + nameSpace;
					i++;
				} else if (args[i].equals("-bb")) {
					// Following is for upper half performance testing for writes
					_repo = new BitBucketRepository();
				} else if(args[i].equals("-singlefile")) {
					// This is a reference to an old repo type that no longer exists
					System.out.println("-singlefile no longer supported");
					throw new InvalidParameterException();
				}
			}

			if (_repo == null)	// default lower half
				_repo = new LogStructRepoStore();
			
			_repo.initialize(repositoryRoot, policyFile, localName, globalPrefix, nameSpace, null);
			_server = new RepositoryServer(_repo);
			
			Log.info("started repo with response name: "+_server.getResponseName());

			
		} catch (InvalidParameterException ipe) {
			usage();
		} catch (Exception e) {
			e.printStackTrace();
			Log.logStackTrace(Level.SEVERE, e);
			System.exit(1);
		}
	}
	
	protected void usage() {
		try {
			// Without parsing args, we don't know which repo impl we will get, so show the default 
			// impl usage and allow for differences 
			String msg = "usage: " + this.getClass().getName() + " -start -root <repository_root> | -stop <pid> | -interactive | -signal <signal> <pid>" +
			" [-log <level>] [-policy <policy_file>] [-local <local_name>] [-global <global_prefix>] [-bb]";
			System.out.println(msg);
			Log.severe(msg);
		} catch (Exception e) {
			e.printStackTrace();
			Log.logStackTrace(Level.SEVERE, e);
		}
		System.exit(1);
	}

	protected WorkerThread createWorkerThread() {
		return new RepositoryWorkerThread(daemonName());
	}
	
	/**
	 * Start a new repository daemon
	 * @param args
	 */
	public static void main(String[] args) {
		Daemon daemon = null;
		try {
			daemon = new RepositoryDaemon();
			runDaemon(daemon, args);
			
		} catch (Exception e) {
			System.err.println("Error attempting to start daemon.");
			Log.warning("Error attempting to start daemon.");
			Log.warningStackTrace(e);
		}
	}
}

@@ -3502,16 +3502,105 @@
 (level);
+%09// XXX should level mean this or just FAC_REPO?%0A%09%09%09%09%09%09Log.setLevel(Log.FAC_REPO, level);
 %0A%09%09%09%09%09%7D 

Fix logging for repo