EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.command.dml]

COVERAGE SUMMARY FOR SOURCE FILE [BackupCommand.java]

nameclass, %method, %block, %line, %
BackupCommand.java100% (1/1)75%  (9/12)62%  (184/295)68%  (56.1/83)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BackupCommand100% (1/1)75%  (9/12)62%  (184/295)68%  (56.1/83)
backupFile (ZipOutputStream, String, String): void 0%   (0/1)0%   (0/9)0%   (0/3)
backupPageStore (ZipOutputStream, String, PageStore): void 0%   (0/1)0%   (0/49)0%   (0/15)
queryMeta (): ResultInterface 0%   (0/1)0%   (0/2)0%   (0/1)
backupFile (ZipOutputStream, String, String, InputStream): void 100% (1/1)72%  (31/43)90%  (9/10)
backupTo (String): void 100% (1/1)73%  (108/147)82%  (32.1/39)
BackupCommand (Session): void 100% (1/1)100% (4/4)100% (2/2)
correctFileName (String): String 100% (1/1)100% (15/15)100% (4/4)
getType (): int 100% (1/1)100% (2/2)100% (1/1)
isTransactional (): boolean 100% (1/1)100% (2/2)100% (1/1)
needRecompile (): boolean 100% (1/1)100% (2/2)100% (1/1)
setFileName (Expression): void 100% (1/1)100% (4/4)100% (2/2)
update (): int 100% (1/1)100% (16/16)100% (4/4)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.command.dml;
7 
8import java.io.IOException;
9import java.io.InputStream;
10import java.io.OutputStream;
11import java.util.ArrayList;
12import java.util.zip.ZipEntry;
13import java.util.zip.ZipOutputStream;
14import org.h2.api.DatabaseEventListener;
15import org.h2.api.ErrorCode;
16import org.h2.command.CommandInterface;
17import org.h2.command.Prepared;
18import org.h2.engine.Constants;
19import org.h2.engine.Database;
20import org.h2.engine.Session;
21import org.h2.expression.Expression;
22import org.h2.message.DbException;
23import org.h2.mvstore.MVStore;
24import org.h2.mvstore.db.MVTableEngine.Store;
25import org.h2.result.ResultInterface;
26import org.h2.store.FileLister;
27import org.h2.store.PageStore;
28import org.h2.store.fs.FileUtils;
29import org.h2.util.IOUtils;
30 
31/**
32 * This class represents the statement
33 * BACKUP
34 */
35public class BackupCommand extends Prepared {
36 
37    private Expression fileNameExpr;
38 
39    public BackupCommand(Session session) {
40        super(session);
41    }
42 
43    public void setFileName(Expression fileName) {
44        this.fileNameExpr = fileName;
45    }
46 
47    @Override
48    public int update() {
49        String name = fileNameExpr.getValue(session).getString();
50        session.getUser().checkAdmin();
51        backupTo(name);
52        return 0;
53    }
54 
55    private void backupTo(String fileName) {
56        Database db = session.getDatabase();
57        if (!db.isPersistent()) {
58            throw DbException.get(ErrorCode.DATABASE_IS_NOT_PERSISTENT);
59        }
60        try {
61            Store mvStore = db.getMvStore();
62            if (mvStore != null) {
63                mvStore.flush();
64            }
65            String name = db.getName();
66            name = FileUtils.getName(name);
67            OutputStream zip = FileUtils.newOutputStream(fileName, false);
68            ZipOutputStream out = new ZipOutputStream(zip);
69            db.flush();
70            if (db.getPageStore() != null) {
71                String fn = db.getName() + Constants.SUFFIX_PAGE_FILE;
72                backupPageStore(out, fn, db.getPageStore());
73            }
74            // synchronize on the database, to avoid concurrent temp file
75            // creation / deletion / backup
76            String base = FileUtils.getParent(db.getName());
77            synchronized (db.getLobSyncObject()) {
78                String prefix = db.getDatabasePath();
79                String dir = FileUtils.getParent(prefix);
80                dir = FileLister.getDir(dir);
81                ArrayList<String> fileList = FileLister.getDatabaseFiles(dir, name, true);
82                for (String n : fileList) {
83                    if (n.endsWith(Constants.SUFFIX_LOB_FILE)) {
84                        backupFile(out, base, n);
85                    }
86                    if (n.endsWith(Constants.SUFFIX_MV_FILE) && mvStore != null) {
87                        MVStore s = mvStore.getStore();
88                        boolean before = s.getReuseSpace();
89                        s.setReuseSpace(false);
90                        try {
91                            InputStream in = mvStore.getInputStream();
92                            backupFile(out, base, n, in);
93                        } finally {
94                            s.setReuseSpace(before);
95                        }
96                    }
97                }
98            }
99            out.close();
100            zip.close();
101        } catch (IOException e) {
102            throw DbException.convertIOException(e, fileName);
103        }
104    }
105 
106    private void backupPageStore(ZipOutputStream out, String fileName,
107            PageStore store) throws IOException {
108        Database db = session.getDatabase();
109        fileName = FileUtils.getName(fileName);
110        out.putNextEntry(new ZipEntry(fileName));
111        int pos = 0;
112        try {
113            store.setBackup(true);
114            while (true) {
115                pos = store.copyDirect(pos, out);
116                if (pos < 0) {
117                    break;
118                }
119                int max = store.getPageCount();
120                db.setProgress(DatabaseEventListener.STATE_BACKUP_FILE, fileName, pos, max);
121            }
122        } finally {
123            store.setBackup(false);
124        }
125        out.closeEntry();
126    }
127 
128    private static void backupFile(ZipOutputStream out, String base, String fn)
129            throws IOException {
130        InputStream in = FileUtils.newInputStream(fn);
131        backupFile(out, base, fn, in);
132    }
133 
134    private static void backupFile(ZipOutputStream out, String base, String fn,
135            InputStream in) throws IOException {
136        String f = FileUtils.toRealPath(fn);
137        base = FileUtils.toRealPath(base);
138        if (!f.startsWith(base)) {
139            DbException.throwInternalError(f + " does not start with " + base);
140        }
141        f = f.substring(base.length());
142        f = correctFileName(f);
143        out.putNextEntry(new ZipEntry(f));
144        IOUtils.copyAndCloseInput(in, out);
145        out.closeEntry();
146    }
147 
148    @Override
149    public boolean isTransactional() {
150        return true;
151    }
152 
153    /**
154     * Fix the file name, replacing backslash with slash.
155     *
156     * @param f the file name
157     * @return the corrected file name
158     */
159    public static String correctFileName(String f) {
160        f = f.replace('\\', '/');
161        if (f.startsWith("/")) {
162            f = f.substring(1);
163        }
164        return f;
165    }
166 
167    @Override
168    public boolean needRecompile() {
169        return false;
170    }
171 
172    @Override
173    public ResultInterface queryMeta() {
174        return null;
175    }
176 
177    @Override
178    public int getType() {
179        return CommandInterface.BACKUP;
180    }
181 
182}

[all classes][org.h2.command.dml]
EMMA 2.0.5312 (C) Vladimir Roubtsov