Package primarydatamanager

Source Code of primarydatamanager.PrimaryDataManager

/*
* TV-Browser
* Copyright (C) 04-2003 Martin Oberhauser (darras@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* CVS information:
*  $RCSfile$
*   $Source$
*     $Date: 2010-08-14 19:33:47 +0200 (Sat, 14 Aug 2010) $
*   $Author: jo_mormes $
* $Revision: 6700 $
*/
package primarydatamanager;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.lang.StringUtils;

import primarydatamanager.primarydataservice.PrimaryDataService;
import tvbrowserdataservice.file.ChannelList;
import tvbrowserdataservice.file.DayProgramFile;
import tvbrowserdataservice.file.SummaryFile;
import util.io.FileFormatException;
import util.io.IOUtilities;
import util.io.Mirror;
import util.io.VerySimpleFormatter;
import devplugin.ChannelGroup;
import devplugin.Date;

/**
*
*
* @author Til Schneider, www.murfman.de
*/
public class PrimaryDataManager {

  private static final Logger mLog = Logger.getLogger(PrimaryDataManager.class.getName());

  private File mRawDir;
  private File mPreparedDir;
  private File mWorkDir;
  private File mBackupDir;
  private File mConfigDir;

  private ChannelList[] mChannelListArr;
  private String[] mGroupNameArr;

  private RawDataProcessor mRawDataProcessor;
 
  private static RandomAccessFile mLockFile;

  private static FileLock mLock;



  public PrimaryDataManager(File baseDir) throws PreparationException {
    Logger.getLogger("sun.awt.X11.timeoutTask.XToolkit").setLevel(Level.INFO);
    mRawDir      = new File(baseDir, "raw");
    mPreparedDir = new File(baseDir, "prepared");
    mWorkDir     = new File(baseDir, "temp");
    mBackupDir   = new File(baseDir, "backup");
    mConfigDir   = new File(baseDir, "config");
    mRawDataProcessor = new RawDataProcessor();
  }

  public void setGroupNames(String[] groupNames) {
    mChannelListArr = new ChannelList[groupNames.length];
    mGroupNameArr = groupNames;
  }


  public void forceCompleteUpdateFor(String channel) {
    mRawDataProcessor.forceCompleteUpdateFor(channel);
  }


  public void createGroupFiles() throws PreparationException {

    /* A groupname file contains the name of the group in
     * an internationalized form */
    for (String group : mGroupNameArr) {
      File fromFile = new File(mConfigDir, group + ".txt");
      File toFile = new File(mWorkDir, group + "_info");
      try {
        IOUtilities.copy(fromFile, toFile);
      } catch (IOException exc) {
        throw new PreparationException("Could not copy file from " + fromFile.getAbsolutePath() + " to " + toFile.getAbsolutePath(), exc);
      }
    }

  }


  public void updateRawDataDir() throws PreparationException {
    // Delete the old work directory
    try {
      IOUtilities.deleteDirectory(mWorkDir);
    }
    catch (IOException exc) {
      throw new PreparationException("Deleting old work directory failed", exc);
    }

    // Create a new work directory
    if (! mWorkDir.mkdir()) {
      throw new PreparationException("Could not create work directory: "
        + mWorkDir.getAbsolutePath());
    }

    // Create a new raw directory if it does not exist
    if (! mRawDir.exists()) {
      if (! mRawDir.mkdir()) {
        throw new PreparationException("Could not create raw directory: "
          + mRawDir.getAbsolutePath());
      }
    }

    //Create the channel list file
    createChannelList();

    // Update the mirror lists
    updateMirrorList();

    // Process the new raw data
    for (int i=0; i<mGroupNameArr.length; i++) {
      mRawDataProcessor.processRawDataDir(mRawDir, mPreparedDir, mWorkDir, mChannelListArr[i]);
    }

    // Create a summary files
    createSummaryFile();
    createGroupFiles();

    // Delete the old backup
    try {
      IOUtilities.deleteDirectory(mBackupDir);
    }
    catch (IOException exc) {
      throw new PreparationException("Deleting old backup directory failed", exc);
    }

    // Let the prepared dir become the new backup
    if (mPreparedDir.exists()) {
      if (! mPreparedDir.renameTo(mBackupDir)) {
        throw new PreparationException("Renaming file '"
          + mPreparedDir.getAbsolutePath() + "' to '"
          + mBackupDir.getAbsolutePath() + "' failed");
      }
    }

    // Let the work dir become the new prepared dir
    if (! mWorkDir.renameTo(mPreparedDir)) {
      throw new PreparationException("Renaming file '"
        + mWorkDir.getAbsolutePath() + "' to '"
        + mPreparedDir.getAbsolutePath() + "' failed");
    }

    // Print out the statistics

    int quarantineCount = mRawDataProcessor.getQuarantineCount();
    if (quarantineCount > 0) {
      mLog.warning(quarantineCount + " day programs where put into quarantine");

      File txtDir = new File(mPreparedDir, "quarantine");
      if (!txtDir.exists()) {
        System.out.println("file "+txtDir.getAbsolutePath()+" does not exist");
      }
      if (!txtDir.isDirectory()) {
        System.out.println("file "+txtDir.getAbsolutePath()+" is not a directory");
      }

      if (txtDir.exists() && txtDir.isDirectory()) {
        File destDir=new File(txtDir,"txt");
        destDir.mkdirs();
        try {
          DayProgramFileTranslator.translateAllDayPrograms(txtDir);
        } catch (IOException e) {
          e.printStackTrace();
        } catch (FileFormatException e) {
          e.printStackTrace();
        }
      }

    }
  }


  public static PrimaryDataService createPrimaryDataService(String className)
    throws PreparationException
  {
    Class clazz;

    if (className.startsWith(".")) {
      className="primarydatamanager.primarydataservice.secret"+className;
    }

    try {
      clazz = Class.forName(className);
    }
    catch (ClassNotFoundException exc) {
      throw new PreparationException("Primary data service class does not exist: "
        + className, exc);
    }

    Object obj;
    try {
      obj = clazz.newInstance();
    }
    catch (Exception exc) {
      throw new PreparationException("Can't create instance of primary data "
        + "service class: " + className, exc);
    }

    if (obj instanceof PrimaryDataService) {
      return (PrimaryDataService) obj;
    } else {
      throw new PreparationException("Class " + className + " does not implement "
        + PrimaryDataService.class.getName());
    }
  }



  private void createChannelList() throws PreparationException {
    mLog.fine("Updating the channel list");

    for (int i=0; i<mGroupNameArr.length; i++) {
      // Load the channellist.txt
      mChannelListArr[i] = loadChannelListTxt(mGroupNameArr[i]+"_channellist.txt");

      // Save the mirrorlist.gz
      File toFile = new File(mWorkDir, mGroupNameArr[i]+"_"+ChannelList.FILE_NAME);
      try {
        mChannelListArr[i].writeToFile(toFile);
      }
      catch (Exception exc) {
        throw new PreparationException("Writing channel list for group "+mGroupNameArr[i]+" failed", exc);
      }
    }
  }




  private void createSummaryFile()
    throws PreparationException
  {


    for (int i=0; i<mGroupNameArr.length; i++) {

      // Create the file
      SummaryFile summary = new SummaryFile();
      File[] fileArr = mWorkDir.listFiles();
      for (File file : fileArr) {
        String fileName = file.getName();
        if (fileName.endsWith("_full.prog.gz")) {
          // This is a complete file -> Put its version to the summary
          try {
            Date date = DayProgramFile.getDateFromFileName(fileName);
            String country = DayProgramFile.getCountryFromFileName(fileName);
            String channelId = DayProgramFile.getChannelNameFromFileName(fileName);
            String levelName = DayProgramFile.getLevelFromFileName(fileName);

            //if (channelBelongsToGroup(channelId, country)) {
            if (RawDataProcessor.channelBelongsToGroup(mChannelListArr[i], channelId, country)) {
              int level = DayProgramFile.getLevelIndexForId(levelName);
              if (level == -1) {
                throw new PreparationException("Day program file has unknown level '"
                    + levelName + "': " + file.getAbsolutePath());
              }
              int version = DayProgramFile.readVersionFromFile(file);

              summary.setDayProgramVersion(date, country, channelId, level, version);
            }
          }
          catch (Exception exc) {
            throw new PreparationException("Adding day program file to summary " +
                "failed: " + file.getAbsolutePath(), exc);
          }
        }
      }

      System.out.println("writing summary to file...");

      // Save the file
      File file = new File(mWorkDir, mGroupNameArr[i]+"_"+SummaryFile.SUMMARY_FILE_NAME);
      try {
        summary.writeToFile(file);
      }
      catch (Exception exc) {
        throw new PreparationException("Writing summary file failed: "
          + file.getAbsolutePath(), exc);
      }
    }

    System.out.println("done.");
  }


  private void updateMirrorList() throws PreparationException {
    mLog.fine("Updating the mirror list");

    for (String groupNameArr : mGroupNameArr) {
      // Load the mirrorlist.txt
      Mirror[] mirrorArr = loadMirrorListTxt(groupNameArr + "_mirrorlist.txt");

      // Save the mirrorlist.gz
      File toFile = new File(mWorkDir, groupNameArr + "_" + Mirror.MIRROR_LIST_FILE_NAME);
      try {
        Mirror.writeMirrorListToFile(toFile, mirrorArr);
      }
      catch (IOException exc) {
        throw new PreparationException("Writing mirror list for group " + groupNameArr + " failed", exc);
      }
    }
  }


  private ChannelList loadChannelListTxt(String fileName) throws PreparationException {
    ChannelList result = new ChannelList((ChannelGroup)null);

    File fromFile = new File(mConfigDir, fileName);
    try {
      result.readFromStream(new FileInputStream(fromFile), null, false);
    } catch (IOException e) {
      throw new PreparationException("Loading "+fileName+" failed", e);
    } catch (FileFormatException e) {
      throw new PreparationException("Loading "+fileName+" failed", e);
    }

    return result;

  }

  private Mirror[] loadMirrorListTxt(String fileName) throws PreparationException {
    ArrayList<Mirror> mirrorList = new ArrayList<Mirror>();

    File fromFile = new File(mConfigDir, fileName);
    BufferedInputStream stream = null;
    try {
      stream = new BufferedInputStream(new FileInputStream(fromFile), 0x4000);
      BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

      String line;
      while ((line = reader.readLine()) != null) {
        line = line.trim();
        int weight = 100;
        if (StringUtils.isNotEmpty(line)) {
          String url = line;
          String[] s = url.split(";");
          if (s.length==2) {
            url = s[0];
            String weightStr = s[1];
            try {
              weight = Integer.parseInt(weightStr);
            }catch(NumberFormatException e) {
              weight = 100;
              mLog.warning("Invalid weight entry in "+fileName+": "+line+" - set to 100 instead");
            }
          }
          mirrorList.add(new Mirror(url, weight));
        }
      }
    }
    catch (Exception exc) {
      throw new PreparationException("Loading "+fileName+" failed", exc);
    }
    finally {
      if (stream != null) {
        try { stream.close(); } catch (IOException exc) {
          //Empty
        }
      }
    }

    // Convert the list into an array
    Mirror[] mirrorArr = new Mirror[mirrorList.size()];
    mirrorList.toArray(mirrorArr);

    return mirrorArr;
  }

  /**
   * @return <code>true</code>, if the prepared directory exists
   */
  private boolean doesPreparedExist() {
     return mPreparedDir.exists() && mPreparedDir.isDirectory();
  }
 
  /**
   * Create the .lock file in the config directory
   * @return false, if the .lock file exist and is locked or cannot be locked.
   */
  private boolean createLockFile() {


    File lockFile = new File(mConfigDir, ".lock");

    if(lockFile.exists()) {
      try {
        mLockFile = new RandomAccessFile(lockFile.toString(),"rw");
        mLock = mLockFile.getChannel().tryLock();

        if(mLock == null) {
          return false;
        }
      }catch(Exception e) {
        return false;
      }
    }
    else {
      try {
        lockFile.createNewFile();
        mLockFile = new RandomAccessFile(lockFile.toString(),"rw");
        mLock = mLockFile.getChannel().tryLock();
      }catch(Exception e){
        if(e instanceof IOException) {
          mLog.log(Level.WARNING, e.getLocalizedMessage(), e);
        }
      }
    }

    return true;
  }

  private void deleteLockFile() {
    File lockFile = new File(mConfigDir, ".lock");

    try {
      mLock.release();
    }catch(Exception e) {
      // ignore
    }

    try {
      mLockFile.close();
    }catch(Exception e) {
      // ignore
    }

    lockFile.delete();
  }

  public static void main(String[] args) {
    // setup logging
    try {
      // Get the default Logger
      Logger mainLogger = Logger.getLogger("");
      mainLogger.setLevel(Level.FINEST);

      Handler consoleHandler = mainLogger.getHandlers()[0];
      consoleHandler.setLevel(Level.FINEST);
      consoleHandler.setFormatter(new VerySimpleFormatter());

      // Add a file handler
      new File("log").mkdir();
      Handler fileHandler = new FileHandler("log/datamanager.log", 50000, 2, true);
      fileHandler.setLevel(Level.INFO);
      mainLogger.addHandler(fileHandler);
    }
    catch (IOException exc) {
      System.out.println("Can't create log file");
      exc.printStackTrace();
    }

    // Start the update
    if (args.length == 0) {
      System.out.println("USAGE: PrimaryDataManager [-forceCompleteUpdate [channel{;channel}]] groups...");
      System.exit(1);
    } else {
      try {
        PrimaryDataManager manager = new PrimaryDataManager(new File("."));
        ArrayList<String> groupNames = new ArrayList<String>();
        for (int i = 0; i < args.length; i++) {
          if (args[i].equalsIgnoreCase("-forceCompleteUpdate")) {
            if ((i + 1) >= args.length) {
              System.out.println("You have to specify a colon separated " +
                "list of channels after -forceCompleteUpdate");
              System.exit(1);
            } else {
              i++;
              StringTokenizer tokenizer = new StringTokenizer(args[i], ":");
              while (tokenizer.hasMoreTokens()) {
                manager.forceCompleteUpdateFor(tokenizer.nextToken());
              }
            }
          } else {
            final String[] groups = args[i].split(",");
            groupNames.addAll(Arrays.asList(groups));
          }
        }

        if (groupNames.size() == 0) {
          System.out.println("Please specify at least one channel group");
          System.exit(-1);
        }

        if (!manager.doesPreparedExist()) {
          System.out.println("The prepared directory is missing, this directory is very important and shouldn't " +
              "be deleted, because this leeds to massiv problems.");
          System.exit(-1);
        }
       
        if (!manager.createLockFile()) {
          System.out.println("The PrimaryDataManager is already running.");
          System.exit(-1);
        }

        String[] groupNamesArr = new String[groupNames.size()];
        groupNames.toArray(groupNamesArr);
        manager.setGroupNames(groupNamesArr);

        manager.updateRawDataDir();

        manager.deleteLockFile();

        // Exit with error code 2 if some day programs were put into quarantine
        if (manager.mRawDataProcessor.getQuarantineCount() != 0) {
          System.exit(2);
        }
      }
      catch (PreparationException exc) {
        exc.printStackTrace();
        System.exit(1);
      }
    }
  }


}
TOP

Related Classes of primarydatamanager.PrimaryDataManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.