/*
 * 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.asterix.metadata;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import edu.uci.ics.asterix.common.functions.FunctionSignature;
import edu.uci.ics.asterix.external.dataset.adapter.AdapterIdentifier;
import edu.uci.ics.asterix.metadata.api.IMetadataEntity;
import edu.uci.ics.asterix.metadata.entities.Dataset;
import edu.uci.ics.asterix.metadata.entities.DatasourceAdapter;
import edu.uci.ics.asterix.metadata.entities.Datatype;
import edu.uci.ics.asterix.metadata.entities.Dataverse;
import edu.uci.ics.asterix.metadata.entities.Function;
import edu.uci.ics.asterix.metadata.entities.Index;
import edu.uci.ics.asterix.metadata.entities.Library;
import edu.uci.ics.asterix.metadata.entities.NodeGroup;

/**
 * Caches metadata entities such that the MetadataManager does not have to
 * contact the MetadataNode. The cache is updated transactionally via logical
 * logging in the MetadataTransactionContext. Note that transaction abort is
 * simply ignored, i.e., updates are not not applied to the cache.
 */
public class MetadataCache {
	// Key is dataverse name.
	protected final Map<String, Dataverse> dataverses = new HashMap<String, Dataverse>();
	// Key is dataverse name. Key of value map is dataset name.
	protected final Map<String, Map<String, Dataset>> datasets = new HashMap<String, Map<String, Dataset>>();
	// Key is dataverse name. Key of value map is dataset name. Key of value map
	// of value map is index name.
	protected final Map<String, Map<String, Map<String, Index>>> indexes = new HashMap<String, Map<String, Map<String, Index>>>();
	// Key is dataverse name. Key of value map is datatype name.
	protected final Map<String, Map<String, Datatype>> datatypes = new HashMap<String, Map<String, Datatype>>();
	// Key is dataverse name.
	protected final Map<String, NodeGroup> nodeGroups = new HashMap<String, NodeGroup>();
	// Key is function Identifier . Key of value map is function name.
	protected final Map<FunctionSignature, Function> functions = new HashMap<FunctionSignature, Function>();
	// Key is adapter dataverse. Key of value map is the adapter name
	protected final Map<AdapterIdentifier, DatasourceAdapter> adapters = new HashMap<AdapterIdentifier, DatasourceAdapter>();
	// Key is library dataverse. Key of value map is the library name
	protected final Map<String, Map<String, Library>> libraries = new HashMap<String, Map<String, Library>>();

	// Atomically executes all metadata operations in ctx's log.
	public void commit(MetadataTransactionContext ctx) {
		// Forward roll the operations written in ctx's log.
		int logIx = 0;
		ArrayList<MetadataLogicalOperation> opLog = ctx.getOpLog();
		try {
			for (logIx = 0; logIx < opLog.size(); logIx++) {
				doOperation(opLog.get(logIx));
			}
		} catch (Exception e) {
			// Undo operations.
			try {
				for (int i = logIx - 1; i >= 0; i--) {
					undoOperation(opLog.get(i));
				}
			} catch (Exception e2) {
				// We encountered an error in undo. This case should never
				// happen. Our only remedy to ensure cache consistency
				// is to clear everything.
				clear();
			}
		} finally {
			ctx.clear();
		}
	}

	public void clear() {
		synchronized (dataverses) {
			synchronized (nodeGroups) {
				synchronized (datasets) {
					synchronized (datatypes) {
						synchronized (functions) {
							synchronized (adapters) {
								synchronized (libraries) {
									dataverses.clear();
									nodeGroups.clear();
									datasets.clear();
									datatypes.clear();
									functions.clear();
									adapters.clear();
									libraries.clear();
								}
							}
						}
					}
				}
			}
		}
	}

	public Object addDataverseIfNotExists(Dataverse dataverse) {
		synchronized (dataverses) {
			synchronized (datasets) {
				synchronized (datatypes) {
					if (!dataverses.containsKey(dataverse)) {
						datasets.put(dataverse.getDataverseName(),
								new HashMap<String, Dataset>());
						datatypes.put(dataverse.getDataverseName(),
								new HashMap<String, Datatype>());
						return dataverses.put(dataverse.getDataverseName(),
								dataverse);
					}
					return null;
				}
			}
		}
	}

	public Object addDatasetIfNotExists(Dataset dataset) {
		synchronized (datasets) {
			Map<String, Dataset> m = datasets.get(dataset.getDataverseName());
			if (m == null) {
				m = new HashMap<String, Dataset>();
				datasets.put(dataset.getDataverseName(), m);
			}
			if (!m.containsKey(dataset.getDatasetName())) {
				return m.put(dataset.getDatasetName(), dataset);
			}
			return null;
		}
	}

	public Object addIndexIfNotExists(Index index) {
		synchronized (indexes) {
			Map<String, Map<String, Index>> datasetMap = indexes.get(index
					.getDataverseName());
			if (datasetMap == null) {
				datasetMap = new HashMap<String, Map<String, Index>>();
				indexes.put(index.getDataverseName(), datasetMap);
			}
			Map<String, Index> indexMap = datasetMap
					.get(index.getDatasetName());
			if (indexMap == null) {
				indexMap = new HashMap<String, Index>();
				datasetMap.put(index.getDatasetName(), indexMap);
			}
			if (!indexMap.containsKey(index.getIndexName())) {
				return indexMap.put(index.getIndexName(), index);
			}
			return null;
		}
	}

	public Object addDatatypeIfNotExists(Datatype datatype) {
		synchronized (datatypes) {
			Map<String, Datatype> m = datatypes
					.get(datatype.getDataverseName());
			if (m == null) {
				m = new HashMap<String, Datatype>();
				datatypes.put(datatype.getDataverseName(), m);
			}
			if (!m.containsKey(datatype.getDatatypeName())) {
				return m.put(datatype.getDatatypeName(), datatype);
			}
			return null;
		}
	}

	public Object addNodeGroupIfNotExists(NodeGroup nodeGroup) {
		synchronized (nodeGroups) {
			if (!nodeGroups.containsKey(nodeGroup.getNodeGroupName())) {
				return nodeGroups.put(nodeGroup.getNodeGroupName(), nodeGroup);
			}
			return null;
		}
	}

	public Object dropDataverse(Dataverse dataverse) {
		synchronized (dataverses) {
			synchronized (datasets) {
				synchronized (indexes) {
					synchronized (datatypes) {
						synchronized (functions) {
							datasets.remove(dataverse.getDataverseName());
							indexes.remove(dataverse.getDataverseName());
							datatypes.remove(dataverse.getDataverseName());
							adapters.remove(dataverse.getDataverseName());
							List<FunctionSignature> markedFunctionsForRemoval = new ArrayList<FunctionSignature>();
							for (FunctionSignature signature : functions
									.keySet()) {
								if (signature.getNamespace().equals(
										dataverse.getDataverseName())) {
									markedFunctionsForRemoval.add(signature);
								}
							}
							for (FunctionSignature signature : markedFunctionsForRemoval) {
								functions.remove(signature);
							}
							return dataverses.remove(dataverse
									.getDataverseName());
						}
					}
				}
			}
		}
	}

	public Object dropDataset(Dataset dataset) {
		synchronized (datasets) {
			synchronized (indexes) {

				// remove the indexes of the dataset from indexes' cache
				Map<String, Map<String, Index>> datasetMap = indexes
						.get(dataset.getDataverseName());
				if (datasetMap != null) {
					datasetMap.remove(dataset.getDatasetName());
				}

				// remove the dataset from datasets' cache
				Map<String, Dataset> m = datasets.get(dataset
						.getDataverseName());
				if (m == null) {
					return null;
				}
				return m.remove(dataset.getDatasetName());
			}
		}
	}

	public Object dropIndex(Index index) {
		synchronized (indexes) {
			Map<String, Map<String, Index>> datasetMap = indexes.get(index
					.getDataverseName());
			if (datasetMap == null) {
				return null;
			}

			Map<String, Index> indexMap = datasetMap
					.get(index.getDatasetName());
			if (indexMap == null) {
				return null;
			}

			return indexMap.remove(index.getIndexName());
		}
	}

	public Object dropDatatype(Datatype datatype) {
		synchronized (datatypes) {
			Map<String, Datatype> m = datatypes
					.get(datatype.getDataverseName());
			if (m == null) {
				return null;
			}
			return m.remove(datatype.getDatatypeName());
		}
	}

	public Object dropNodeGroup(NodeGroup nodeGroup) {
		synchronized (nodeGroups) {
			return nodeGroups.remove(nodeGroup.getNodeGroupName());
		}
	}

	public Dataverse getDataverse(String dataverseName) {
		synchronized (dataverses) {
			return dataverses.get(dataverseName);
		}
	}

	public Dataset getDataset(String dataverseName, String datasetName) {
		synchronized (datasets) {
			Map<String, Dataset> m = datasets.get(dataverseName);
			if (m == null) {
				return null;
			}
			return m.get(datasetName);
		}
	}

	public Index getIndex(String dataverseName, String datasetName,
			String indexName) {
		synchronized (indexes) {
			Map<String, Map<String, Index>> datasetMap = indexes
					.get(dataverseName);
			if (datasetMap == null) {
				return null;
			}
			Map<String, Index> indexMap = datasetMap.get(datasetName);
			if (indexMap == null) {
				return null;
			}
			return indexMap.get(indexName);
		}
	}

	public Datatype getDatatype(String dataverseName, String datatypeName) {
		synchronized (datatypes) {
			Map<String, Datatype> m = datatypes.get(dataverseName);
			if (m == null) {
				return null;
			}
			return m.get(datatypeName);
		}
	}

	public NodeGroup getNodeGroup(String nodeGroupName) {
		synchronized (nodeGroups) {
			return nodeGroups.get(nodeGroupName);
		}
	}

	public Function getFunction(FunctionSignature functionSignature) {
		synchronized (functions) {
			return functions.get(functionSignature);
		}
	}

	public List<Dataset> getDataverseDatasets(String dataverseName) {
		List<Dataset> retDatasets = new ArrayList<Dataset>();
		synchronized (datasets) {
			Map<String, Dataset> m = datasets.get(dataverseName);
			if (m == null) {
				return retDatasets;
			}
			for (Map.Entry<String, Dataset> entry : m.entrySet()) {
				retDatasets.add(entry.getValue());
			}
			return retDatasets;
		}
	}

	/**
	 * Represents a logical operation against the metadata.
	 */
	protected class MetadataLogicalOperation {
		// Entity to be added/dropped.
		public final IMetadataEntity entity;
		// True for add, false for drop.
		public final boolean isAdd;

		public MetadataLogicalOperation(IMetadataEntity entity, boolean isAdd) {
			this.entity = entity;
			this.isAdd = isAdd;
		}
	};

	protected void doOperation(MetadataLogicalOperation op) {
		if (op.isAdd) {
			op.entity.addToCache(this);
		} else {
			op.entity.dropFromCache(this);
		}
	}

	protected void undoOperation(MetadataLogicalOperation op) {
		if (!op.isAdd) {
			op.entity.addToCache(this);
		} else {
			op.entity.dropFromCache(this);
		}
	}

	public Object addFunctionIfNotExists(Function function) {
		synchronized (functions) {
			FunctionSignature signature = new FunctionSignature(
					function.getDataverseName(), function.getName(),
					function.getArity());
			Function fun = functions.get(signature);
			if (fun == null) {
				return functions.put(signature, function);
			}
			return null;
		}
	}

	public Object dropFunction(Function function) {
		synchronized (functions) {
			FunctionSignature signature = new FunctionSignature(
					function.getDataverseName(), function.getName(),
					function.getArity());
			Function fun = functions.get(signature);
			if (fun == null) {
				return null;
			}
			return functions.remove(signature);
		}
	}

	public Object addAdapterIfNotExists(DatasourceAdapter adapter) {
		synchronized (adapters) {
			boolean needToAddd = adapters.get(adapter.getAdapterIdentifier()) == null;
			if (needToAddd) {
				return adapters.put(adapter.getAdapterIdentifier(), adapter);
			}
			return null;
		}
	}

	public Object dropAdapter(DatasourceAdapter adapter) {
		synchronized (adapters) {
			if (adapters.get(adapter.getAdapterIdentifier()) != null) {
				return adapters.remove(adapter.getAdapterIdentifier());
			}
			return null;
		}
	}

	public Object addLibraryIfNotExists(Library library) {
		synchronized (libraries) {
			Map<String, Library> libsInDataverse = libraries.get(library
					.getDataverseName());
			boolean needToAddd = (libsInDataverse == null || libsInDataverse
					.get(library.getName()) != null);
			if (needToAddd) {
				if (libsInDataverse == null) {
					libsInDataverse = new HashMap<String, Library>();
					libraries.put(library.getDataverseName(), libsInDataverse);
				}
				return libsInDataverse.put(library.getDataverseName(), library);
			}
			return null;
		}
	}

	public Object dropLibrary(Library library) {
		synchronized (libraries) {
			Map<String, Library> librariesInDataverse = libraries.get(library
					.getDataverseName());
			if (librariesInDataverse != null) {
				return librariesInDataverse.remove(library.getName());
			}
			return null;
		}
	}
}
