// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.netapp;

import java.io.IOException;
import java.rmi.ServerException;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;

import netapp.manage.NaException;

public class NetappDefaultAllocatorImpl implements NetappAllocator
{
	private static HashMap<String, Integer> _poolNameToLastVolumeIdAllocated = new HashMap<String, Integer>();
	private NetappManager _netappMgr;
    public static final Logger s_logger = Logger.getLogger(NetappDefaultAllocatorImpl.class.getName());
	
	public NetappDefaultAllocatorImpl(NetappManager netappMgr) {
		_netappMgr = netappMgr;
	}
	
	public synchronized NetappVolumeVO chooseLeastFullVolumeFromPool(String poolName, long lunSizeGb) 
	{
		List<NetappVolumeVO> volumesOnPoolAscending = _netappMgr.listVolumesAscending(poolName);
		
		if(volumesOnPoolAscending==null)
		{
			//no pools exist in db
			return null;
		}
		
		long maxAvailable = 0;
		NetappVolumeVO selectedVol = null;
		for(NetappVolumeVO vol : volumesOnPoolAscending)
		{
			try {
				long availableBytes = _netappMgr.returnAvailableVolumeSize(vol.getVolumeName(), vol.getUsername(), vol.getPassword(), vol.getIpAddress());

				if(lunSizeGb <= bytesToGb(availableBytes) && availableBytes>maxAvailable)
				{
					maxAvailable = availableBytes; //new max
					selectedVol = vol; //new least loaded vol
				}
			} catch (ServerException se) {
				s_logger.debug("Ignoring failure to obtain volume size for volume " + vol.getVolumeName());
				continue;	
			}
		}
		
		return selectedVol;
	}
	
	/**
	 * This method does the actual round robin allocation
	 * @param poolName 
	 * @param lunSizeGb
	 * @return -- the selected volume to create the lun on
	 * @throws IOException
	 * @throws NaException
	 */
	public synchronized NetappVolumeVO chooseVolumeFromPool(String poolName, long lunSizeGb)
	{
		int pos = 0; //0 by default
		List<NetappVolumeVO> volumesOnPoolAscending = _netappMgr.listVolumesAscending(poolName);
		
		if(volumesOnPoolAscending==null)
		{
			//no pools exist in db
			return null;
		}
		
		//get the index of the record from the map
		if(_poolNameToLastVolumeIdAllocated.get(poolName)==null)
		{
			pos=0;
		}
		else
		{
			pos=_poolNameToLastVolumeIdAllocated.get(poolName);
		}
		
		//update for RR effect
		_poolNameToLastVolumeIdAllocated.put(poolName, (pos+1)%volumesOnPoolAscending.size());
		
		//now iterate over the records
		Object[] volumesOnPoolAscendingArray = volumesOnPoolAscending.toArray();
		int counter=0;
		while (counter < volumesOnPoolAscendingArray.length)
		{
			NetappVolumeVO vol = (NetappVolumeVO)volumesOnPoolAscendingArray[pos];
			
			//check if the volume fits the bill
			long availableBytes;
			try {
				availableBytes = _netappMgr.returnAvailableVolumeSize(vol.getVolumeName(), vol.getUsername(), vol.getPassword(), vol.getIpAddress());
									
				if(lunSizeGb <= bytesToGb(availableBytes))
				{
					//found one
					return vol;
				}
				pos = (pos + 1) % volumesOnPoolAscendingArray.length;
				counter++;
			} catch (ServerException e) {
				s_logger.debug("Ignoring failure to obtain volume size for volume " + vol.getVolumeName());
				continue;
			}
		}
		
		return null;
	}
	
	
	/**
	 * This method does the byte to gb conversion
	 * @param bytes 
	 * @return -- converted gb
	 */
	private long bytesToGb(long bytes){
		long returnVal = (bytes/(1024*1024*1024));
		return returnVal;
	}

}

	 