<repo_name>Leaf27/CS542<file_sep>/HW3/Relation.java
package DB3;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Relation {
	// this result is used to store all information of this relation.
	private HashMap<String, ArrayList<String>> result=new HashMap<String, ArrayList<String>>();
	// store all keys of this relation.
	private HashSet<String> keys=new HashSet<String>();
	// this Iterator is used to iterate the relation
	private Iterator<String> it;
	private String fileName;
	// tell result which string is used to be the key for each record in result.
	int key_location;
	// number of records
	int recordSize=0;
	
	// constructor
	public Relation(String fileName,int key_location) throws IOException
	{
		this.fileName=fileName;
		this.key_location=key_location;
	}
	
	// call methods to read file into result and initialize iterator.
	public void open() throws IOException 
	{
		fileToHashMap(fileName,key_location);	
		it =keys.iterator(); 
	}
	
	public ArrayList<String> getNext()
	{
		if(it.hasNext()){
			String key=it.next();
			return result.get(key);	
		}
		else return null;
	}
	
	public void close()
	{
		result.clear();
		keys.clear();
	}
    
	// get record information for a given key.
	public ArrayList<String> get(String key)
	{
		return result.get(key);
	}
	
	// check whether this relation has next or not
	public boolean hasNext()
	{
		return it.hasNext();
	}
	
	// check whether this key is in the relation or not
	public boolean hasKey(String Key){
		return result.containsKey((String) Key);
	}
	
	 private void fileToHashMap(String fileName,int key_location) throws IOException
	 {
		 File file=new File(fileName);
    	 if(file.exists()){
    		 FileReader fis=new FileReader(fileName);
    		 BufferedReader br=new BufferedReader(fis);
    		 String line=null;
    		 int i=0;
    		 while((line=br.readLine())!=null){
    			 ArrayList<String> content=getContent(line.substring(0, line.length()-1));
    			 if(i==0)
    			 {
    			     recordSize=content.size();
    			     i++;
    			 }
    			 result.put(content.get(key_location), content); 
    			 keys.add(content.get(key_location));
    		 }
    		 br.close();
    	 }
    	 
     }
	 
	 // slice strings
	 private static ArrayList<String> getContent(String record)
	 {
		 ArrayList<String> result =new ArrayList<String>(); 
		 record=','+record;
		 int point=0;
		 while(point<record.length()){
			 if(record.charAt(point)==',') {
					// the following is a string
					 if(point+1<record.length()&&record.charAt(point+1)=='\'')
					 {	
						 if(point+2<record.length())
						 {
							int  nextQuote=record.indexOf("\'",point+2);
							if(nextQuote!=-1)
							{
								result.add(record.substring(point+2,nextQuote));
								point=nextQuote+1;
							}
							else 
							{
								result.add(record.substring(point+1,record.length()-1));
								break;
							}
							
						 }
						 else break;
					 }
                     // the following is a number
					 else if(point+1<record.length())
					 { 
						int nextQuote=record.indexOf(",",point+1); 
						if(nextQuote!=-1)
						{
							result.add(record.substring(point+1,nextQuote));
							point=nextQuote;
						}
						else 
						{
							result.add(record.substring(point+1));
							break;
						}
						
					 }
				     else break;
			 }			 
			 else point++;
			 }
		 return result;
		 }
}
<file_sep>/HW2/Util.java
package DB2;
import java.io.*;
import java.util.*;

/**
 */
public class Util
{
    private static Util m_instance;

    private Util()
    {
    }

    public static Util getInstance()
    {
        if (m_instance == null)
        {
            m_instance = new Util();
        }
        return m_instance;
    }
    // read data from cs542.db and return map of films of which key is its title and year.
    public Map<String, Film> readDataFile(String filePath) throws Exception
    {
        Map<String, Film> result = new HashMap<>();
        try(BufferedReader reader = new BufferedReader(new FileReader(filePath)))
        {
            String line;
            while ((line = reader.readLine()) != null)
            {
                Film film = new Film(line.split(","));
                result.put(film.getKey(), film);
            }

            return result;
        }
    }

    public void writeDateFile(File file, Collection<Film> filmList)
    {
        try(BufferedWriter out = new BufferedWriter(new FileWriter(file, false)))
        {
            for (Film film: filmList)
            {
                out.write(film.toString());
                out.write("\n");
            }
        }
        catch (Exception e)
        {
            System.out.println("Failed to write to data file, " + e);
            System.exit(1);
        }
    }
   
    public Map<String, Set<String>> readIndexFile(File file) throws Exception
    {
        try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)))
        {
            return (Map<String, Set<String>>) ois.readObject();
        }
    }

    public void writeIndexFile(File file, Map<String, Set<String>> indexes)
    {
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file, false)))
        {
            oos.writeObject(indexes);
        }
        catch (Exception e)
        {
            System.out.println("Failed to write to index file, " + e);
            System.exit(1);
        }
    }
}
<file_sep>/HW1/testDB/src/testDB.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class testDB {
	static HW1 test=HW1.getInstance();
	static int length=1024*1024;
		public static void main(String[] args) throws InterruptedException, IOException{
			    byte[] halfData=new byte[length/2];	 
				for(int i=0;i<halfData.length;i++){
					halfData[i]=1;
				}
				test.put(1,halfData);
				display(test.getFile());
				// starts concurrency 
			    System.out.println("Now starts test of concurrency:");
			    concurrency();
			    // starts fragmentation test
			    System.out.println("Now starts test of fragmentation: ");	
			    fragmentation();
	    }
		
		/* The main thread does a Remove() and the new thread t does a Get() with the same key a millisecond later.
		 * 
		 */
		private static void concurrency() throws InterruptedException, IOException{
			 byte[] halfData=new byte[length/2];	 
			for(int i=0;i<length/2;i++){
				halfData[i]=1;
			}
			// create a new thread to get value of which key is 1.
			Thread t=new Thread(){
				public void run(){
					System.out.println("Another thread is running!");	
					byte[] result=test.get(1);
					if(result!=null) {
						System.out.println("This is length of the '1' element:"+result.length);
					}			
			}
			};
			// start the new thread
			t.start();			
			// remove key-value pair of which key is 1.
			test.remove(1);	
			t.join(1);
			display(test.getFile());		
			// let the main thread wait 1000 milliseconds so that the new thread t can be finished before starting fragmentation method.
			t.join(1000);
		}
		
		
		/* Put() 4 values, byte arrays of 1 MB each, with keys A, B, C and D. Remove key B. Put() ½ MB in size for key E. 
		 * Validate that a Put() 1 MB in size for key F fails. Remove C and now validate that a Put() 1 MB in size for key G succeeds. 
		 * Remove E and try Put() 1 MB in size for key H. With a naive implementation, it will fail even though there is room in store.db. 
		 * An extra bonus point if you can modify your code such that Put("H", …) succeeds. 
		 */
		private static void fragmentation() throws IOException{
			   byte[] testData=new byte[length];					 
				for(int i=0;i<length;i++){
					testData[i]=1;
				}
				byte[] halfData=new byte[length/2];					 
				for(int i=0;i<length/2;i++){
					halfData[i]=1;
				}
			// put key A and it's associated value, byte array of 1 MB, into file!
			  test.put(1,testData);
			  display(test.getFile());
			// put key B and it's associated value, byte array of 1 MB, into file!
			  test.put(2,testData);
			  display(test.getFile());
			// put key C and it's associated value, byte array of 1 MB, into file!
			  test.put(3,testData);
			  display(test.getFile());
			// put key D and it's associated value, byte array of 1 MB, into file!
			  test.put(4,testData);
			  display(test.getFile());
			//Remove key B
			  test.remove(2);
			  display(test.getFile());
			 //Put() ½ MB in size for key E
			  test.put(5, halfData);
			  display(test.getFile());
			  // Put() 1 MB in size for key F and check the result!
			  test.put(6, testData);
			  display(test.getFile());
			  //Remove C
			  test.remove(3);
			  display(test.getFile());
			  //Put() 1 MB in size for key G  and check the result!
			  test.put(7, testData);
			  display(test.getFile());
			  //Remove E
			  test.remove(5);
			  display(test.getFile());
			  //Put() 1 MB in size for key H and check the result!
			  test.put(8, testData);	
			  display(test.getFile());
		}
		
		private synchronized static void display(File file) throws IOException{
       	 System.out.println("This is the layout of CS542: ");
       	 if(file.exists()){
       		 FileReader fis=new FileReader(file);
       		 BufferedReader br=new BufferedReader(fis);
       		 String line=null;
       		 int count=0;
       		 while((line=br.readLine())!=null){ 			 
       			 if(count==0) System.out.println(line+"  // Number of key-value paris");
       			 else if((count%2)==1) {
       				 System.out.println(line+"  // the "+(count+1)/2 +"th key");
       			 }
       			 else { 
       				 System.out.println(line.length()+"  // length of the "+(count+1)/2 +"th value");
       			 }
       			 count++;
       		 }
       		 if(count==0) System.out.println("CS542 is empty!");
       		 System.out.println("");
       		 br.close();
       	 }
       	 else{
       		 System.out.println("I cannot find the file");
       	 }
       }
	}
<file_sep>/HW4/Log.java
package DB4;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Log {
	 private String relationName;
     private String LogName;
     private String result;	
     private String transaction;
     
     /**
      * 
      * @param relationName
      * @param transaction
      * 
      * pass in the log name and which relation the log log.
      */
     public Log(String relationName,String transaction)
     {
    	 this.relationName=relationName;   
    	 this.transaction=transaction;
    	 LogName=relationName+"Log";
    	 result="start transaction " +transaction+"\n";
    	 
     }
     
     /**
      * 
      * @param recordPointer
      * @param oldValue
      * @param newValue
      * create a new log of which format is <transaction name, key of the updated record, old value, new value>
      */
     public void addLog(String recordPointer, String oldValue, String newValue)
     {
    	 result=result.concat(transaction+","+recordPointer+","+oldValue+","+newValue+"\n");
     }
     
     /**
      * push the log into disk
      */
     public void pushLog()
     {
    	 File LogFile=new File(LogName);
    	 if(!LogFile.exists())
    	 {    		 
    		 try{
    			 LogFile.createNewFile();
    		 }
    		 catch(IOException e){
    			 System.out.println("create log file fails!");
    			 e.getMessage();
    		 }
    	 }

    	 try(BufferedWriter out = new BufferedWriter(new FileWriter(LogFile, false)))
	    	 {
	    		 out.write(result);
	    		 out.write("commit "+ transaction);
	    	 }
	    	 catch (Exception e)
	         {
	             System.out.println("Failed to write log file into disk, " + e);
	             System.exit(1);
	         }
	 }
     
     /**
      * 
      * @return  logs information
      * @throws FileNotFoundException
      * @throws IOException
      * 
      * read logs from disk 
      */
     public ArrayList<String[]> readLog() throws FileNotFoundException, IOException{
    	 ArrayList<String[]> logs=new ArrayList<>();
    	 File logFile=new File(LogName);
    	 String line;
    	 String[] oneLog=new String[4];
    	 try(BufferedReader br=new BufferedReader(new FileReader(LogName)))
    	 {
    		 while((line=br.readLine())!=null)
    		 {
    			if(line.contains("start")||line.contains("commit")) continue;
    			logs.add(line.split(","));
    		 }
    	 } 
    	 return logs;
     }
     
     /**
      * display log
      */
     public void showLog(){
    	 System.out.println(result);
     }

}
<file_sep>/HW1/README.md
# CS542


Teammember:<br>
        <NAME> <br>
        <NAME>  <br>
        <NAME> <br>

The main function is in repository testDB/src/testDB.java
<file_sep>/HW4/Test.java
package DB4;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;

public class Test {
	
	private static String path=System.getProperty("user.dir");
	private static String CityPath=path+"/cs542.db/city.txt";
	private static String CountryPath=path+"/cs542.db/country.txt";
	private static String CityAPath=path+"/cs542A.db/city.txt";
	private static String CountryAPath=path+"/cs542A.db/country.txt";
	
	// index of population in city relation.
	private static int CityPopulation=4;
	
	// index of population in country relation.
	private static int CountryPopulation=6;
	
	private static ArrayList<String> record=null;
	
	// names of transactions
	private static String UpdateCity="UpdateCity";
	private static String UpdateCountry="UpdateCountry";
	
    public static void main(String[] args) throws IOException{
    	// update cs542.db and write logs
    	  Relation City=new Relation(CityPath,0);
    	  Relation Country=new Relation(CountryPath,0);
    	  
    	  Log CityLog=new Log("City",UpdateCity);
    	  Log CountryLog=new Log("Country",UpdateCountry);
  
    	  update(City,CityLog,CityPopulation);
    	  CityLog.pushLog();
    	  City.HashMaptofile();
    	  
    	  update(Country,CountryLog,CountryPopulation);
    	  CountryLog.pushLog();
    	  Country.HashMaptofile();
    	  
    	// use the log to update cs542A.db
    	  Relation CityA=new Relation(CityAPath,0);
    	  Relation CountryA=new Relation(CountryAPath,0);
    	  
    	  updateBackup(CityA,CityLog,CityPopulation);
    	  CityA.HashMaptofile();
    	  System.out.println("city in cs542 and city in cs542A are identical or not?");
    	  System.out.println("the result is: "+check(CityPath,CityAPath,CityPopulation));
    
    	  updateBackup(CountryA,CountryLog,CountryPopulation);
    	  CountryA.HashMaptofile();
    	  System.out.println("country in cs542 and country in cs542A are identical or not?");
    	  System.out.println("the result is: "+check(CountryPath,CountryAPath,CountryPopulation));
    	  
      }
      
      /**
       * 
       * @param relation, passed in to specify which relation need to be updated
       * @param log, specify where logs to be written.
       * @param population, index of population in one record.
       *
       * For each record in relation, write the undo/redo log into its associated log file.
       * The format of log is <transaction_name, pointer of record, old population, updated population >
       * After generating log, increase population in this record by 2%.
       */
    
      public static void update(Relation relation, Log log,int population){
    	  while(relation.hasNext())
    	  {
    		  record=relation.getNext();
    		  log.addLog(record.get(0), record.get(population), increasePopulation(record.get(population)));
    		  record.set(population, increasePopulation(record.get(population)));
    	  }
    	  log.showLog();
      }
      
      /**
       * 
       * @param relation
       * @param log
       * @param population
       * @throws FileNotFoundException
       * @throws IOException
       * 
       * read log from disk, and we can replace old population by new value in log.
       */
      public static void updateBackup(Relation relation, Log log,int population) throws FileNotFoundException, IOException
      {
    	  ArrayList<String[]> logs = log.readLog();
    	  for(String[] oneLog : logs){
    		  String pointer=oneLog[1];
    		  relation.get(pointer).set(population, oneLog[3]);
    	  }
    	  
      }
     
      /**
       * 
       * @param population
       * @return  updated population which is product of population and 102%.
       */
      private static String increasePopulation(String population)
      {
    	  int newPopulation = (int)(Integer.parseInt(population)*1.02);
    	  return Integer.toString(newPopulation);
      }
      
      /**
       * 
       * @param relationPath
       * @param relationAPath
       * @param population
       * @return
       * @throws IOException
       * check whether two relations are identical or not
       */
      private static boolean check(String relationPath, String relationAPath,int population) throws IOException
      {
    	  Relation DB1=new Relation(relationPath,0);
    	  Relation DB2=new Relation(relationAPath,0);
    	  while(DB1.hasNext())
    	  {   
    		  ArrayList<String> record = DB1.getNext();
    		  if(record.get(population).equals(DB2.get(record.get(0)).get(population))) continue;
    		  else return false;
    	  }
    	  return true;
      }
}
<file_sep>/README.md
# CS542
used for homework of DataBase system.<br>

Team Member:<br>
<NAME>, <EMAIL> <br>
<NAME>, <EMAIL> <br>
<NAME>, <EMAIL>  <br>

<file_sep>/HW2/Test.java
package DB2;
import java.util.*;

public class Test
{
    private static Map<String, Film> FILMS = new HashMap<>();
    private static final String DATA_FILE_PATH = "cs542.db";

    public static void main(String[] args)
    {
        try
        {
            FILMS = Util.getInstance().readDataFile(DATA_FILE_PATH);
        }
        catch (Exception e)
        {
            System.out.println("Failed to read data file, " + e);
            System.exit(1);
        }

        testCase1();
        testCase2();
        testCase3();
    }

    private static void testCase1()
    {
        DB db = DB.getInstance();
        for (String key: FILMS.keySet())
        {
            Film film = FILMS.get(key);
            String[] attributes = film.getAttributes();
            String index = attributes[Film.Attributes.Year.ordinal()] + "|" + attributes[Film.Attributes.Format.ordinal()];
            db.put(film.getKey(), index);
        }

        System.out.println("\nStarting Test 1...");
        System.out.println("------------------------------------");

        System.out.println("\nAll DVD movies made in 1977:");
        db.get("1977|DVD");

        System.out.println("\nAll VHS movies made in 1990:");
        db.get("1990|VHS");

        System.out.println("\nAll DVD movies made in 2001:");
        db.get("2001|DVD");
    }

    private static void testCase2()
    {
        System.out.println();
        System.out.println("Starting Test 2...");
        System.out.println("------------------------------------");

        DB db = DB.getInstance();
        for (String key: FILMS.keySet())
        {
            Film film = FILMS.get(key);
            String[] attributes = film.getAttributes();
            String index = attributes[Film.Attributes.Year.ordinal()];
            db.put(film.getKey(), index);
        }

        System.out.println("\nFind all movies made in 2000:");
        db.get("2000");

        System.out.println("\nFind all movies made in 2005:");
        db.get("2005");

        System.out.println("\nFind all movies made in 2010:");
        db.get("2010");
    }

    private static void testCase3()
    {
        System.out.println();
        System.out.println("Starting Test 3...");
        System.out.println("------------------------------------");

        DB db = DB.getInstance();
        for (String key: FILMS.keySet())
        {
            Film film = FILMS.get(key);
            String[] attributes = film.getAttributes();
            String index = attributes[Film.Attributes.Year.ordinal()];
            db.put(film.getKey(), index);
        }

        String title = "<NAME>";
        String year = "1977";
        String key = title + "|" + year;

        System.out.println("All movies made in " + year);
        System.out.println("\nBefore removing:");
        db.get(year);

        System.out.println("\nRemoving entry: " + key);
        db.remove(key);
        System.out.println("\nAfter removing:");
        db.get(year);
    }
}
