📄 persistentstorage.java
字号:
* * @param a The first string * @param b The second string * @param max The maximum value to return * @return The PrefixLength value */ private int getPrefixLength(String a, String b, int max) { int i = 0; for (; (i < a.length() - 1) && (i < b.length() - 1) && (i < max); i++) { if (a.charAt(i) != b.charAt(i)) { return i; } } return i; } /** * Returns whether or not the given file is a temporary file. * * @param name The name of the file * @return Whether or not it is temporary */ private boolean isTemporaryFile(String name) { return (name.indexOf(".") >= 0); } /** * Returns whether or not the provided file is an acestor of the other file. * * @param file The file to check * @param ancestor The potential ancestor * @return Whether or not the file is an ancestor */ private boolean isAncestor(File file, File ancestor) { while ((file != null) && (!file.equals(ancestor))) { file = file.getParentFile(); } return (file != null); } /** * Gets the file for a certain id from the disk * * @param id the id to get a file for * @return File the file for the id * @exception IOException DESCRIBE THE EXCEPTION */ private File getFile(Id id) throws IOException { File dir = getDirectoryForId(id); String name = id.toStringFull().substring(getPrefix(dir).length()); if (name.equals("")) { name = ZERO_LENGTH_NAME; } // check for ! directory File file = new File(dir, name); if (file.exists() && file.isDirectory()) { file = new File(file, ZERO_LENGTH_NAME); } return file; } /** * Gets the directory an id should be stored in * * @param id the string representation of the id * @return File the directory that should contain an id * @exception IOException DESCRIBE THE EXCEPTION */ private File getDirectoryForId(Id id) throws IOException { return getDirectoryForName(id.toStringFull()); } /** * Gets the directory a given file should be stored in * * @param name The name of the file * @return File the directory that should contain an id * @exception IOException DESCRIBE THE EXCEPTION */ private File getDirectoryForName(String name) throws IOException { return getDirectoryForName(name, appDirectory); } /** * Gets the best directory for the given name * * @param name The name to serach for * @param dir The directory to start at * @return The directory the name should be stored in * @exception IOException DESCRIBE THE EXCEPTION */ private File getDirectoryForName(String name, File dir) throws IOException { File[] subDirs = (File[]) directories.get(dir); if (subDirs.length == 0) { return dir; } else { for (int i = 0; i < subDirs.length; i++) { if (name.startsWith(subDirs[i].getName())) { return getDirectoryForName(name.substring(subDirs[i].getName().length()), subDirs[i]); } else if ((name.length() == 0) && subDirs[i].getName().equals(ZERO_LENGTH_NAME)) { return getDirectoryForName(name, subDirs[i]); } } /* * here, we must create the appropriate directory */ if ((name.length() >= subDirs[0].getName().length()) || ((name.length() == 0) && (subDirs[0].getName().length() == 1))) { File newDir = new File(dir, (name.length() == 0 ? ZERO_LENGTH_NAME : name.substring(0, subDirs[0].getName().length()))); if (logger.level <= Logger.FINE) { logger.log("Necessarily creating dir " + newDir.getName()); } createDirectory(newDir); this.directories.put(dir, append(subDirs, newDir)); this.directories.put(newDir, new File[0]); /* * finally, we must check if this caused too many dirs in one dir. If so, we * simply rerun the algorithm which will reflect the new dir */ if (checkDirectory(dir)) { return getDirectoryForName(name, dir); } else { return newDir; } } else { /* * here, we have to handle a wierd case where the filename is less than that of * an existing directory. To handle this, we pretend like we're doing a directory * split, and create new subdirs so we can accomidate everything. */ String[] dirs = new String[subDirs.length + 1]; for (int i = 0; i < subDirs.length; i++) { dirs[i] = subDirs[i].getName(); } dirs[subDirs.length] = (name.length() == 0 ? ZERO_LENGTH_NAME : name); /* * now reformat the directory, creating an entry for this name */ reformatDirectory(dir, getDirectories(dirs)); /* * and finally, recurse, which should find a directory for this name */ return getDirectoryForName(name, dir); } } } /** * Internal method which returns the postfix for a given id * * @param id The id to return the postfix for * @param file The directory the id will be stored in * @return The postfix */ private String getPostfix(Id id, File file) { return id.toStringFull().substring(getPrefix(file).length()); } /** * Internal method which returns the prefix of a given directory * * @param file The directory to return the prefix for * @return The prefix */ private String getPrefix(File file) { if (prefixes.get(file) != null) { return (String) prefixes.get(file); } StringBuffer buffer = new StringBuffer(); while (!file.equals(appDirectory)) { buffer.insert(0, file.getName().replaceAll(ZERO_LENGTH_NAME, "")); file = file.getParentFile(); } prefixes.put(file, buffer.toString()); return getPrefix(file); } /** * Returns whether or not the given filename represents a stored file * * @param name The name of the file * @param parent DESCRIBE THE PARAMETER * @return int the number of files */ private boolean isFile(File parent, String name) {// return (((getPrefix(parent).length() + name.length()) >= factory.getIdToStringLength()) && (! name.equals(METADATA_FILENAME))); return ((!new File(parent, name).isDirectory()) && (!name.equals(METADATA_FILENAME))); } /** * Returns whether or not the given filename represents a directory * * @param name The name of the file * @param parent DESCRIBE THE PARAMETER * @return int the number of files */ private boolean isDirectory(File parent, String name) {// return (((getPrefix(parent).length() + name.length()) < factory.getIdToStringLength()) && (new File(parent, name)).isDirectory()); return (new File(parent, name)).isDirectory(); } /** * Utility function which returns the range of keys which a directory * corresponds to. * * @param dir The directory * @return The RangeForDirectory value */ protected IdRange getRangeForDirectory(File dir) { String result = ""; while (!dir.equals(appDirectory)) { result = dir.getName() + result; dir = dir.getParentFile(); } return factory.buildIdRangeFromPrefix(result); } /** * gets the root directory that the persistence Manager uses * * @return String the directory for the root */ public String getRoot() { return rootDir; } /** * gets the amount of storage that the persistence Manager uses * * @return int the amount of storage in bytes allocated for use */ public long getStorageSize() { if (storageSize > 0) { return storageSize; } else { return Long.MAX_VALUE; } } /** * Gets the amound of space currently being used on disk * * @return long the amount of space being used */ private long getUsedSpace() { return usedSize; } /** * Gets the name of this instance * * @return String the name of the instance */ public String getName() { return name; } /** * Method which allows the persistence root to schedle an event which will * tell it to sync the metadata cached. Should be called exactly once after * the persistence root is created. * * @param timer The timer to use to schedule the events */ public void setTimer(rice.selector.Timer timer) { if (index) { timer.scheduleAtFixedRate( new rice.selector.TimerTask() { public String toString() { return "persistence dirty purge enqueue"; } public void run() { environment.getProcessor().processBlockingIO( new WorkRequest(new ListenerContinuation("Enqueue of writeMetadataFile", environment), environment.getSelectorManager()) { public String toString() { return "persistence dirty purge"; } public Object doWork() throws Exception { writeDirty(); return Boolean.TRUE; } }); } }, environment.getRandomSource().nextInt(METADATA_SYNC_TIME), METADATA_SYNC_TIME); } } /** * Updates the metadata stored under the given key to be the provided value. * As this may require a disk access, the requestor must also provide a * continuation to return the result to. * * @param id The id for the metadata * @param metadata The metadata to store * @param c The command to run once the operation is complete */ public void setMetadata(final Id id, final Serializable metadata, Continuation c) { printStats(); if (!exists(id)) { c.receiveResult(new Boolean(false)); } else { environment.getProcessor().processBlockingIO( new WorkRequest(c, environment.getSelectorManager()) { public String toString() { return "setMetadata " + id; } public Object doWork() throws Exception { synchronized (statLock) { numMetadataWrites++; } if (logger.level <= Logger.FINER) { logger.log("COUNT: Updating metadata for " + id.toStringFull() + " in " + name); } /* * write the metadata to the file */ File objFile = getFile(id); writeMetadata(objFile, metadata); /* * then update our cache */ if (index) { synchronized (PersistentStorage.this.metadata) { PersistentStorage.this.metadata.put(id, metadata); dirty.add(objFile.getParentFile()); } } return Boolean.TRUE; } }); } } /** * @param dir The new Root value * @return DESCRIBE THE RETURN VALUE */ /* * Functions for Configuration Management */ /** * @param dir The new Root value * @return DESCRIBE THE RETURN VALUE */ /** * Sets the root directory that the persistence Manager uses * * @param dir the String representing the directory to use * @return boolean, true if the operation suceeds false if it doesn't */ public boolean setRoot(String dir) { /* * We should do something logical here to the existing files */ rootDir = dir; return true; } /** * Sets the amount of storage that the persistence Manager uses * * @param size the amount of storage available to use in bytes * @return boolean, true if the operation suceeds false if it doesn't */ public boolean setStorageSize(long size) { if (storageSize <= size) { storageSize = size; return true; } else if (size > usedSize) { storageSize = size; return true; } else { return false; } } /** * DESCRIBE THE METHOD */ private void printStats() { synchronized (statLock) { long now = environment.getTimeSource().currentTimeMillis(); if ((statsLastWritten / statsWriteInterval) != (now / statsWriteInterval)) { if (logger.level <= Logger.INFO) { logger.log("@L.PE name=" + name + " interval=" + statsLastWritten + "-" + now); } statsLastWritten = now; if (logger.level <= Logger.INFO) { logger.log("@L.PE objsTotal=" + (index ? "" + metadata.keySet().size() : "?") + " objsBytesTotal=" + getTotalSize()); } if (logger.level <= Logger.INFO) { logger.log("@L.PE numWrites=" + numWrites + " numReads=" + numReads + " numDeletes=" + numDeletes); } if (logger.level <= Logger.INFO) { logger.log("@L.PE numMetadataWrites=" + numMetadataWrites + " numRenames=" + numRenames); } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -