From 9d030cad2cf26bdd52b30229615b90fd1a67bf69 Mon Sep 17 00:00:00 2001 From: nvt-se Date: Mon, 10 Aug 2009 12:51:52 +0000 Subject: [PATCH] added support for extracting micro logs --- .../se/sics/coffee/CoffeeConfiguration.java | 6 +- .../se/sics/coffee/CoffeeFS.java | 24 ++-- .../se/sics/coffee/CoffeeFile.java | 43 ++++++-- .../se/sics/coffee/CoffeeHeader.java | 32 +++--- .../se/sics/coffee/CoffeeImageFile.java | 4 +- .../se/sics/coffee/CoffeeManager.java | 24 ++-- .../se/sics/coffee/CoffeeMicroLog.java | 103 ++++++++++++++++++ 7 files changed, 179 insertions(+), 57 deletions(-) create mode 100644 tools/coffee-manager/se/sics/coffee/CoffeeMicroLog.java diff --git a/tools/coffee-manager/se/sics/coffee/CoffeeConfiguration.java b/tools/coffee-manager/se/sics/coffee/CoffeeConfiguration.java index 72dce6ab0..a312d744d 100644 --- a/tools/coffee-manager/se/sics/coffee/CoffeeConfiguration.java +++ b/tools/coffee-manager/se/sics/coffee/CoffeeConfiguration.java @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: CoffeeConfiguration.java,v 1.1 2009/08/04 10:36:53 nvt-se Exp $ + * $Id: CoffeeConfiguration.java,v 1.2 2009/08/10 12:51:52 nvt-se Exp $ * * @author Nicolas Tsiftes * @@ -63,8 +63,8 @@ public class CoffeeConfiguration { new FileInputStream(filename); prop.load(fstream); - for(int i = 0; i < validParameters.length; i++) { - if(prop.getProperty(validParameters[i]) == null) { + for (int i = 0; i < validParameters.length; i++) { + if (prop.getProperty(validParameters[i]) == null) { throw new CoffeeException("missing the parameter \"" + validParameters[i] + "\" in the configuration file " + filename); } } diff --git a/tools/coffee-manager/se/sics/coffee/CoffeeFS.java b/tools/coffee-manager/se/sics/coffee/CoffeeFS.java index cd5889298..2706f8539 100644 --- a/tools/coffee-manager/se/sics/coffee/CoffeeFS.java +++ b/tools/coffee-manager/se/sics/coffee/CoffeeFS.java @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: CoffeeFS.java,v 1.3 2009/08/04 15:19:08 nvt-se Exp $ + * $Id: CoffeeFS.java,v 1.4 2009/08/10 12:51:52 nvt-se Exp $ * * @author Nicolas Tsiftes * @@ -67,7 +67,7 @@ public class CoffeeFS { while(currentPage < (conf.fsSize / conf.pageSize)) { CoffeeHeader header = readHeader(currentPage); - if(header.isActive()) { + if (header.isActive() && !header.isLog()) { CoffeeFile file = new CoffeeFile(this, header); files.put(file.getName(), file); } @@ -87,12 +87,12 @@ public class CoffeeFS { while(currentPage < (conf.fsSize / conf.pageSize)) { header = readHeader(currentPage); - if(header.isFree()) { - if(start == INVALID_PAGE) { + if (header.isFree()) { + if (start == INVALID_PAGE) { start = currentPage; } currentPage = nextFile(header, currentPage); - if(start + pages <= currentPage) { + if (start + pages <= currentPage) { return start; } } else { @@ -111,7 +111,7 @@ public class CoffeeFS { return conf; } - private CoffeeHeader readHeader(int page) throws IOException { + public CoffeeHeader readHeader(int page) throws IOException { byte[] bytes = new byte[conf.NAME_LENGTH + conf.pageTypeSize * 2 + 6]; int index = 0; @@ -121,16 +121,16 @@ public class CoffeeFS { return header; } - private void writeHeader(CoffeeHeader header) throws IOException { + public void writeHeader(CoffeeHeader header) throws IOException { byte[] bytes = header.toRawHeader(); image.write(bytes, bytes.length, header.getPage() * conf.pageSize); } private int nextFile(CoffeeHeader header, int page) { - if(header.isFree()) { + if (header.isFree()) { return page + conf.pagesPerSector & ~(conf.pagesPerSector - 1); - } else if(header.isIsolated()) { + } else if (header.isIsolated()) { return page + 1; } @@ -149,7 +149,7 @@ public class CoffeeFS { int allocatePages = pageCount(file.length()); int start = findFreeExtent(allocatePages); - if(start == INVALID_PAGE) { + if (start == INVALID_PAGE) { return null; } CoffeeHeader header = new CoffeeHeader(this, start); @@ -169,7 +169,7 @@ public class CoffeeFS { public void removeFile(String filename) throws CoffeeFileException, IOException { CoffeeFile file = files.get(filename); - if(file == null) { + if (file == null) { throw new CoffeeFileException("Coffee: attempt to remove inexistent file"); } @@ -181,7 +181,7 @@ public class CoffeeFS { public boolean extractFile(String filename) throws IOException { CoffeeFile file = files.get(filename); - if(file == null) { + if (file == null) { return false; } diff --git a/tools/coffee-manager/se/sics/coffee/CoffeeFile.java b/tools/coffee-manager/se/sics/coffee/CoffeeFile.java index 33a8e25f0..0c7700714 100644 --- a/tools/coffee-manager/se/sics/coffee/CoffeeFile.java +++ b/tools/coffee-manager/se/sics/coffee/CoffeeFile.java @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: CoffeeFile.java,v 1.2 2009/08/04 10:39:13 nvt-se Exp $ + * $Id: CoffeeFile.java,v 1.3 2009/08/10 12:51:52 nvt-se Exp $ * * @author Nicolas Tsiftes * @@ -39,30 +39,36 @@ package se.sics.coffee; import java.io.*; public class CoffeeFile { - private CoffeeFS coffeeFS; - private CoffeeHeader header; + protected CoffeeFS coffeeFS; + protected CoffeeHeader header; private String name; private int length; private int startPage; private int reservedSize; - private CoffeeFile logFile; + private CoffeeMicroLog microLog; private boolean knownLength; - public CoffeeFile(CoffeeFS coffeeFS, CoffeeHeader header) { + public CoffeeFile(CoffeeFS coffeeFS, CoffeeHeader header) throws IOException { this.coffeeFS = coffeeFS; this.header = header; name = header.name; startPage = header.getPage(); reservedSize = header.maxPages * coffeeFS.getConfiguration().pageSize; + if (header.isModified() && + coffeeFS.getConfiguration().useMicroLogs == true) { + microLog = new CoffeeMicroLog(coffeeFS, coffeeFS.readHeader(header.logPage)); + } else { + microLog = null; + } } private int calculateLength() throws IOException { byte[] bytes = new byte[1]; int i; - for(i = reservedSize; i >= header.rawLength(); i--) { + for (i = reservedSize; i >= header.rawLength(); i--) { coffeeFS.getImage().read(bytes, 1, header.getPage() * coffeeFS.getConfiguration().pageSize + i); - if(bytes[0] != 0) { + if (bytes[0] != 0) { return i - header.rawLength() + 1; } } @@ -89,16 +95,29 @@ public class CoffeeFile { } public void saveContents(String filename) throws IOException { - byte[] bytes = new byte[1]; int startOffset = header.getPage() * coffeeFS.getConfiguration().pageSize + header.rawLength(); int i; + byte[] bytes; FileOutputStream fOut = new FileOutputStream(filename); - for(i = 0; i < getLength(); i++) { - coffeeFS.getImage().read(bytes, 1, startOffset + i); - fOut.write(bytes); + + if(microLog != null) { + for(i = 0; i < microLog.getLogRecords(); i++) { + bytes = microLog.getRegion(i); + if(bytes == null) { + bytes = new byte[1]; + coffeeFS.getImage().read(bytes, 1, i * microLog.getLogRecordSize()); + } + fOut.write(bytes); + } + } else { + bytes = new byte[1]; + for (i = 0; i < getLength(); i++) { + coffeeFS.getImage().read(bytes, 1, startOffset + i); + fOut.write(bytes); + } } fOut.close(); @@ -113,7 +132,7 @@ public class CoffeeFile { } public int getLength() throws IOException { - if(!knownLength) { + if (!knownLength) { length = calculateLength(); knownLength = true; } diff --git a/tools/coffee-manager/se/sics/coffee/CoffeeHeader.java b/tools/coffee-manager/se/sics/coffee/CoffeeHeader.java index 37cd5bebb..51099c001 100644 --- a/tools/coffee-manager/se/sics/coffee/CoffeeHeader.java +++ b/tools/coffee-manager/se/sics/coffee/CoffeeHeader.java @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: CoffeeHeader.java,v 1.1 2009/08/04 10:36:53 nvt-se Exp $ + * $Id: CoffeeHeader.java,v 1.2 2009/08/10 12:51:52 nvt-se Exp $ * * @author Nicolas Tsiftes * @@ -97,7 +97,7 @@ class CoffeeHeader { name = new String(bytes).substring(index, index + conf.NAME_LENGTH); int nullCharOffset = name.indexOf(0); - if(nullCharOffset >= 0) { + if (nullCharOffset >= 0) { name = name.substring(0, nullCharOffset); } } @@ -105,23 +105,23 @@ class CoffeeHeader { private byte composeFlags() { byte flags = 0; - if(valid) { + if (valid) { flags |= HDR_FLAG_VALID; } - if(allocated) { + if (allocated) { flags |= HDR_FLAG_ALLOCATED; } - if(obsolete) { + if (obsolete) { flags |= HDR_FLAG_OBSOLETE; } - if(modified) { + if (modified) { flags |= HDR_FLAG_MODIFIED; } - if(log) { + if (log) { flags |= HDR_FLAG_LOG; } - if(isolated) { + if (isolated) { flags |= HDR_FLAG_ISOLATED; } @@ -129,22 +129,22 @@ class CoffeeHeader { } private void processFlags(int flags) { - if((flags & HDR_FLAG_VALID) != 0) { + if ((flags & HDR_FLAG_VALID) != 0) { valid = true; } - if((flags & HDR_FLAG_ALLOCATED) != 0) { + if ((flags & HDR_FLAG_ALLOCATED) != 0) { allocated = true; } - if((flags & HDR_FLAG_OBSOLETE) != 0) { + if ((flags & HDR_FLAG_OBSOLETE) != 0) { obsolete = true; } - if((flags & HDR_FLAG_MODIFIED) != 0) { + if ((flags & HDR_FLAG_MODIFIED) != 0) { modified = true; } - if((flags & HDR_FLAG_LOG) != 0) { + if ((flags & HDR_FLAG_LOG) != 0) { log = true; } - if((flags & HDR_FLAG_ISOLATED) != 0) { + if ((flags & HDR_FLAG_ISOLATED) != 0) { isolated = true; } } @@ -152,7 +152,7 @@ class CoffeeHeader { private byte[] setPageValue(int page) { byte[] bytes = new byte[conf.pageTypeSize]; - for(int i = conf.pageTypeSize - 1; i >= 0; i--) { + for (int i = conf.pageTypeSize - 1; i >= 0; i--) { bytes[i] = (byte) (page >> (8 * i)); } return bytes; @@ -161,7 +161,7 @@ class CoffeeHeader { private int getPageValue(byte[] bytes, int offset) { int page = 0; - for(int i = 0; i < conf.pageTypeSize; i++) { + for (int i = 0; i < conf.pageTypeSize; i++) { page |= bytes[offset + i] << (8 * i); } return page; diff --git a/tools/coffee-manager/se/sics/coffee/CoffeeImageFile.java b/tools/coffee-manager/se/sics/coffee/CoffeeImageFile.java index 8d814464d..cb889da57 100644 --- a/tools/coffee-manager/se/sics/coffee/CoffeeImageFile.java +++ b/tools/coffee-manager/se/sics/coffee/CoffeeImageFile.java @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: CoffeeImageFile.java,v 1.1 2009/08/04 10:36:53 nvt-se Exp $ + * $Id: CoffeeImageFile.java,v 1.2 2009/08/10 12:51:52 nvt-se Exp $ * * @author Nicolas Tsiftes * @@ -50,7 +50,7 @@ public class CoffeeImageFile implements CoffeeImage { this.conf = conf; File file = new File(filename); imageFile = new RandomAccessFile(file, "rw"); - if(imageFile.length() == 0) { + if (imageFile.length() == 0) { // Allocate a full file system image. imageFile.setLength(conf.fsSize); } diff --git a/tools/coffee-manager/se/sics/coffee/CoffeeManager.java b/tools/coffee-manager/se/sics/coffee/CoffeeManager.java index c65a6f7ad..33bf8e34a 100644 --- a/tools/coffee-manager/se/sics/coffee/CoffeeManager.java +++ b/tools/coffee-manager/se/sics/coffee/CoffeeManager.java @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: CoffeeManager.java,v 1.2 2009/08/04 15:19:08 nvt-se Exp $ + * $Id: CoffeeManager.java,v 1.3 2009/08/10 12:51:52 nvt-se Exp $ * * @author Nicolas Tsiftes * @@ -57,25 +57,25 @@ public class CoffeeManager { usage += "[-l|s] "; usage += ""; - if(args.length < 1) { + if (args.length < 1) { System.err.println(usage); System.exit(1); } - if(args.length > 1) { + if (args.length > 1) { Pattern validArg = Pattern.compile("-(i|e|r|l|s)"); Matcher m = validArg.matcher(args[0]); - if(!m.matches()) { + if (!m.matches()) { System.err.println(usage); System.exit(1); } - if(args[0].equals("-i") || args[0].equals("-e") || args[0].equals("-r")) { - if(args.length != 3) { + if (args[0].equals("-i") || args[0].equals("-e") || args[0].equals("-r")) { + if (args.length != 3) { System.err.println(usage); System.exit(1); } - if(args[0].equals("-i")) { + if (args[0].equals("-i")) { command = Command.INSERT; } else if (args[0].equals("-r")) { command = Command.REMOVE; @@ -85,11 +85,11 @@ public class CoffeeManager { filename = args[1]; fsImage = args[2]; } else { - if(args.length != 2) { + if (args.length != 2) { System.err.println(usage); System.exit(1); } - if(args[0].equals("-l")) { + if (args[0].equals("-l")) { command = Command.LIST; } else { command = Command.STATS; @@ -103,19 +103,19 @@ public class CoffeeManager { coffeeFS = new CoffeeFS(new CoffeeImageFile(fsImage, conf)); switch (command) { case INSERT: - if(coffeeFS.getFiles().get(filename) != null) { + if (coffeeFS.getFiles().get(filename) != null) { System.err.println("error: file \"" + filename + "\" already exists"); break; } - if(coffeeFS.insertFile(filename) != null) { + if (coffeeFS.insertFile(filename) != null) { System.out.println("Inserted the local file \"" + filename + "\" into the file system image"); } break; case EXTRACT: - if(coffeeFS.extractFile(filename) == false) { + if (coffeeFS.extractFile(filename) == false) { System.err.println("Inexistent file: " + filename); System.exit(1); diff --git a/tools/coffee-manager/se/sics/coffee/CoffeeMicroLog.java b/tools/coffee-manager/se/sics/coffee/CoffeeMicroLog.java new file mode 100644 index 000000000..a76345187 --- /dev/null +++ b/tools/coffee-manager/se/sics/coffee/CoffeeMicroLog.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2009, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: CoffeeMicroLog.java,v 1.1 2009/08/10 12:51:52 nvt-se Exp $ + * + * @author Nicolas Tsiftes + * + */ + +package se.sics.coffee; + +import java.io.IOException; + +public class CoffeeMicroLog extends CoffeeFile { + private int logRecords; + private int logRecordSize; + private int indexStart; + private int indexSize; + private int recordStart; + private int[] index; + + public CoffeeMicroLog(CoffeeFS fs, CoffeeHeader header) + throws IOException { + super(fs, header); + + CoffeeConfiguration conf = fs.getConfiguration(); + if (header.logRecordSize == 0) { + logRecordSize = conf.pageSize; + } + int logAreaSize; + if (header.logRecords == 0) { + logRecords = conf.defaultLogSize / logRecordSize; + } else { + logRecords = header.logRecords; + } + + indexStart = header.getPage() * conf.pageSize + + header.rawLength(); + /* An index entry uses two bytes. */ + indexSize = logRecords * 2; + recordStart = indexStart + indexSize; + + index = new int[logRecords]; + byte[] bytes = new byte[2]; + + for (int i = 0; i < logRecords; i++) { + coffeeFS.getImage().read(bytes, bytes.length, + indexStart + i * 2); + index[i] = bytes[1] << 8 | bytes[0]; + } + } + + public byte[] getRegion(int region) throws IOException { + int headerSize = header.rawLength(); + int indexSize = logRecords * 2; + + for(int i = logRecords - 1; i >= 0; i--) { + if(index[i] - 1 == region) { + byte[] bytes = new byte[logRecordSize]; + coffeeFS.getImage().read(bytes, bytes.length, + recordStart + i * logRecordSize); + return bytes; + } + } + + return null; + } + + public int getLogRecords() { + return logRecords; + } + + public int getLogRecordSize() { + return logRecordSize; + } +}