/** * Returns the name of a specific backup, or all backups found for a specific database, in a * descending order. * * @param db database * @return names of specified backups */ public StringList backups(final String db) { final StringList backups = new StringList(); final IOFile file = soptions.dbpath(db + IO.ZIPSUFFIX); if (file.exists()) { backups.add(db); } else { final String regex = db.replaceAll("([" + REGEXCHARS + "])", "\\\\$1") + DateTime.PATTERN + IO.ZIPSUFFIX; for (final IOFile f : soptions.dbpath().children()) { final String n = f.name(); if (n.matches(regex)) backups.add(n.substring(0, n.lastIndexOf('.'))); } } return backups.sort(Prop.CASE, false); }
/** * Returns the sorted names of all available databases and, optionally, backups. Filters for * {@code name} if not {@code null} with glob support. * * @param db return databases? * @param backup return backups? * @param name name filter (may be {@code null}) * @return database and backups list */ private StringList list(final boolean db, final boolean backup, final String name) { final Pattern pt; if (name != null) { final String nm = REGEX.matcher(name).matches() ? IOFile.regex(name) : name.replaceAll("([" + REGEXCHARS + "])", "\\\\$1"); pt = Pattern.compile(nm, Prop.CASE ? 0 : Pattern.CASE_INSENSITIVE); } else { pt = null; } final IOFile[] children = soptions.dbpath().children(); final StringList list = new StringList(children.length); final HashSet<String> map = new HashSet<>(children.length); for (final IOFile f : children) { final String fn = f.name(); String add = null; if (backup && fn.endsWith(IO.ZIPSUFFIX)) { final String nn = ZIPPATTERN.split(fn)[0]; if (!nn.equals(fn)) add = nn; } else if (db && f.isDir() && fn.indexOf('.') == -1) { add = fn; } // add entry if it matches the pattern, and has not already been added if (add != null && (pt == null || pt.matcher(add).matches()) && map.add(add)) { list.add(add); } } return list.sort(false); }
/** * Returns the names of all backups. * * @return backups */ public StringList backups() { final StringList backups = new StringList(); for (final IOFile f : soptions.dbpath().children()) { final String n = f.name(); if (n.endsWith(IO.ZIPSUFFIX)) backups.add(n.substring(0, n.lastIndexOf('.'))); } return backups; }
@Override public DiskData build() throws IOException { meta.assign(parser); meta.dirty = true; // calculate optimized output buffer sizes to reduce disk fragmentation final Runtime rt = Runtime.getRuntime(); final long max = Math.min(1 << 22, rt.maxMemory() - rt.freeMemory() >> 2); int bs = (int) Math.min(meta.filesize, max); bs = Math.max(IO.BLOCKSIZE, bs - bs % IO.BLOCKSIZE); // drop old database (if available) and create new one DropDB.drop(dbname, sopts); sopts.dbpath(dbname).md(); elemNames = new Names(meta); attrNames = new Names(meta); try { tout = new DataOutput(new TableOutput(meta, DATATBL)); xout = new DataOutput(meta.dbfile(DATATXT), bs); vout = new DataOutput(meta.dbfile(DATAATV), bs); sout = new DataOutput(meta.dbfile(DATATMP), bs); final Performance perf = Prop.debug ? new Performance() : null; Util.debug(tit() + DOTS); parse(); if (Prop.debug) Util.errln(" " + perf + " (" + Performance.getMemory() + ')'); } catch (final IOException ex) { try { close(); } catch (final IOException ignored) { } throw ex; } close(); // copy temporary values into database table try (final DataInput in = new DataInput(meta.dbfile(DATATMP))) { final TableAccess ta = new TableDiskAccess(meta, true); for (; spos < ssize; ++spos) ta.write4(in.readNum(), 8, in.readNum()); ta.close(); } meta.dbfile(DATATMP).delete(); // return database instance return new DiskData(meta, elemNames, attrNames, path, ns); }