001/*
002 * Syncany, www.syncany.org
003 * Copyright (C) 2011-2016 Philipp C. Heckel <philipp.heckel@gmail.com> 
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package org.syncany.chunk;
019
020import java.io.File;
021
022import org.syncany.database.MultiChunkEntry.MultiChunkId;
023
024/**
025 * Listener interface used by the {@link Deduper} to notify the caller of file
026 * events, and to retrieve information about chunks and output files. 
027 * 
028 * @author Philipp C. Heckel (philipp.heckel@gmail.com)
029 */
030public interface DeduperListener {
031        /**
032         * Called by {@link Deduper} before a file is processed. This method can be 
033         * used to ignore certain files. The method must return <code>true</code> if the deduper
034         * shall continue processing, or <code>false</code> if a file should be skipped.
035         * 
036         * <p>For files excluded by this method, neither {@link #onFileStart(File) onFileStart()} nor
037         * {@link #onFileEnd(File, byte[]) onFileEnd()} are called.
038         * 
039         * @param file File that is evaluated by the filter
040         * @return Returns <code>true</code> if the given file shall be processed, <code>false</code> otherwise
041         */
042        public boolean onFileFilter(File file);
043        
044        /**
045         * Called by {@link Deduper} before the deduplication process is started, and before the
046         * file is opened. The method must return <code>true</code> if the deduplication process should
047         * continue (e.g. for regular files), and <code>false</code> otherwise (e.g. for directories or
048         * symlink).
049         * 
050         * <p>The method is called for every file that was not excluded by {@link #onFileFilter(File) onFileFilter()}.
051         * 
052         * @param file File for which the deduplication process is about to be started
053         * @return Returns <code>true</code> if the given file shall be deduplicated, <code>false</code> otherwise
054         */
055        public boolean onFileStart(File file);
056        
057        /**
058         * Called by {@link Deduper} during the deduplication process for each chunk that was
059         * found in the given file.
060         * 
061         * <p>The method is called for every file that was not excluded by {@link #onFileFilter(File) onFileFilter()}.
062         * 
063         * @param file File that is being deduplicated, and for which the chunk was emitted
064         * @param chunk The new chunk that the chunker emitted
065         */
066        public void onFileAddChunk(File file, Chunk chunk);
067        
068        /**
069         * Called by {@link Deduper} after the deduplication process of the given file, i.e. when the end of
070         * the file was reached and no more chunks can be emitted. This method also returns the checksum for the
071         * entire file content which was created during the process. 
072         * 
073         * <p>The method is called for every file that was not excluded by {@link #onFileFilter(File) onFileFilter()}.
074         * 
075         * @param file File for which the deduplication process is finished
076         * @param checksum File checksum for the entire file content (using the checksum algorithm of the chunker)
077         */
078        public void onFileEnd(File file, byte[] checksum);
079        
080        /**
081         * Called by {@link Deduper} during the deduplication process whenever then break condition 
082         * of the {@link Chunker} was reached and a new {@link Chunk} was emitted. This method returns
083         * <code>true</code> if the chunk is a new (and should be further processed), and <code>false</code>
084         * otherwise.
085         * 
086         * <p>This method represents a query to the chunk index, i.e. it determines whether a chunk already exists
087         * in the persistence layer. If it does, the chunk should not be added to a multichunk and processing should 
088         * be stopped. Returning <code>false</code> has this effect. Returning <code>true</code> lets the deduper add the
089         * chunk to a multichunk.  
090         * 
091         * <p>The method is called zero to many times for every file, assuming that the file was not excluded
092         * by {@link #onFileFilter(File) onFileFilter()}, or by {@link #onFileStart(File) onFileStart()}.
093         * 
094         * @param chunk The new chunk that the chunker emitted
095         * @return Returns <code>true</code> if the chunk is new, and <code>false</code> otherwise
096         */
097        public boolean onChunk(Chunk chunk); 
098        
099        /**
100         * Called by {@link Deduper} during the deduplication process whenever a new {@link MultiChunk} is 
101         * created/opened. A new multichunk is opened when the previous multichunk is full.
102         * 
103         * @param multiChunk The new multichunk 
104         */
105        public void onMultiChunkOpen(MultiChunk multiChunk);
106        
107        /**
108         * Called by {@link Deduper} during the deduplication process before a new {@link MultiChunk} is
109         * created/opened. This method must determine and return a new unique multichunk identifier.
110         *  
111         * @param firstChunk The first chunk can/might be used to determine a new multichunk identifier
112         * @return Returns a new unique multichunk identifier
113         */
114        public MultiChunkId createNewMultiChunkId(Chunk firstChunk);
115
116        /**
117         * Called by {@link Deduper} during the deduplication process before a new {@link MultiChunk} is
118         * created/opened. In order to determine the destination to which the multichunk should be written,
119         * this method returns a multichunk file to a given multichunk ID.
120         * 
121         * @param multiChunkId Identifier for the new multichunk
122         * @return Returns the (temporary or final) file to which the multichunk should be written
123         */
124        public File getMultiChunkFile(MultiChunkId multiChunkId);
125
126        /**
127         * Called by {@link Deduper} during the deduplication process whenever a new {@link Chunk} is written 
128         * to the given multichunk.  
129         * 
130         * @param multiChunk The multichunk the given chunk is being written to
131         * @param chunk The chunk that's written to the multichunk
132         */
133        public void onMultiChunkWrite(MultiChunk multiChunk, Chunk chunk);
134        
135        /**
136         * Called by {@link Deduper} during the deduplication process whenever a multichunk is closed. This can 
137         * happen either because the multichunk is full (max. size reached/exceeded), or because there are no 
138         * more files to chunk/index.
139         *  
140         * @param multiChunk The multichunk that's being closed 
141         */
142        public void onMultiChunkClose(MultiChunk multiChunk);
143
144        /**
145         * Called by {@link Deduper} before starting the deduplication process.
146         *  
147         * @param fileCount the number of files to be processed
148         */
149        public void onStart(int fileCount);
150        
151        /**
152         * Called by {@link Deduper} after finishing the deduplication process.
153         */
154        public void onFinish();
155}