diff options
author | Mathieu Blondel <mathieu@mblondel.org> | 2009-09-17 07:39:39 +0000 |
---|---|---|
committer | Mathieu Blondel <mathieu@mblondel.org> | 2009-09-17 07:39:39 +0000 |
commit | f9574d04652c557a0348cdfe537316a9c55b219c (patch) | |
tree | 04e9883101009a412db9ee3716cd0124da9b8441 /src | |
parent | 916e28a1c9e8d221f1c13ad66e5d62aab8a1488f (diff) | |
download | wikipediafs-f9574d04652c557a0348cdfe537316a9c55b219c.tar.gz |
I would like to break this up more, but it's a big mess. But this fixes a fair
bit.
config.py: Handle a new general configuration variable,
login-cache-time, which defaults to 7200 seconds (two hours).
metadir.py:
Report mtime for stat.
Refuse to create a file (With EACCES) if it is not a valid wiki filename.
(Potential data loss.)
Implement fsync and flush, which attempts to actually write the file, so we
can report write failures to an application. (Potential data loss)
Slightly improved debug logging for release and mkdir.
In rename, try to report failure to write to the wiki. (Potential data loss)
fs.py:
Cache the login time for class ArticleDir.
Add a force argument to set_cookie_string to force it to get a new one
regardless of if one already exists.
Add a 'get_art' function which handles all the logic for getting the article
object, including caching and login timeouts.
Make all the functions use the get_art function.
Add a function for getting the mtime, used by the above change to metadir.
Add some debug logging.
article.py:
Lots and lots and lots of debug logging, trying to get all the above sorted
out.
Add some code to Article set to return false on success and true on failure,
so that we can report back to the application when a write failed. (Potential
data loss.)
git-svn-id: http://svn.code.sf.net/p/wikipediafs/code/trunk@68 59acd704-e115-0410-a914-e735a229ed7c
Diffstat (limited to 'src')
-rw-r--r-- | src/wikipediafs/article.py | 17 | ||||
-rw-r--r-- | src/wikipediafs/config.py | 13 | ||||
-rw-r--r-- | src/wikipediafs/fs.py | 78 | ||||
-rw-r--r-- | src/wikipediafs/metadir.py | 54 |
4 files changed, 114 insertions, 48 deletions
diff --git a/src/wikipediafs/article.py b/src/wikipediafs/article.py index 4793bce..c323ae4 100644 --- a/src/wikipediafs/article.py +++ b/src/wikipediafs/article.py @@ -119,6 +119,7 @@ class Article(SGMLParser): # Do not get article if cache is still ok if int(time.time()) - self.last_get > self.cache_time: + self.logger.debug("pre-GET wpStarttime: '%s', wpEdittime: '%s', cookies: '%s', time diff: %d\n", self.wpEdittime, self.wpStarttime, self.cookie_str, int(time.time()) - self.last_get) headers = {"User-agent" : "WikipediaFS"} if self.cookie_str is not None: @@ -143,6 +144,7 @@ class Article(SGMLParser): conn.close() self.last_get = int(time.time()) + self.logger.debug("post-GET wpStarttime: '%s', wpEdittime: '%s', cookies: '%s', time diff: %d\n", self.wpEdittime, self.wpStarttime, self.cookie_str, int(time.time()) - self.last_get) else: if self.logger: self.logger.debug("Get %s from cache" % self.name) @@ -158,7 +160,9 @@ class Article(SGMLParser): def set(self, text): if text == self.content: - return # useless to continue further... + return True # useless to continue further... + + self.logger.debug("POST wpStarttime: '%s', wpEdittime: '%s', cookies: '%s', time diff: %d\n", self.wpEdittime, self.wpStarttime, self.cookie_str, int(time.time()) - self.last_get) # Looking for a [[Summary:*]] regexp = '((\[\[)((s|S)ummary:)(.*)(\]\])(( )*\n)?)' @@ -208,6 +212,8 @@ class Article(SGMLParser): self.logger.info("Succesful") elif response.status == 200: self.logger.error("Problems occured %s\n" % response.read()) + self.logger.debug("Headers: '%s'\n" % headers) + self.logger.debug("Text: '%s'\n" % text) else: self.logger.info("%d \n %s " % \ (response.status,response.read())) @@ -226,6 +232,13 @@ class Article(SGMLParser): else: self.is_empty = False + # Did the write actually succeed? + if response.status == 302: + return True + else: + self.logger.debug("article.set: Returning false.\n") + return False + if __name__ == "__main__": import random @@ -254,4 +267,4 @@ if __name__ == "__main__": print art.get() art.set("Test ! (%s)" % str(random.random())) -
\ No newline at end of file + diff --git a/src/wikipediafs/config.py b/src/wikipediafs/config.py index 6a906c7..2d42b29 100644 --- a/src/wikipediafs/config.py +++ b/src/wikipediafs/config.py @@ -32,6 +32,7 @@ class Config: <general> <!-- Cache time in seconds --> <article-cache-time>30</article-cache-time> + <login-cache-time>7200</login-cache-time> </general> <sites> <!-- @@ -85,7 +86,7 @@ class Config: else: self.__config = minidom.parseString(config_str).documentElement - self.__setCacheTime() + self.__setCacheTimes() self.__setDebug() @@ -123,12 +124,17 @@ class Config: self.sites[dic["dirname"]] = dic - def __setCacheTime(self): + def __setCacheTimes(self): element = self.__config.getElementsByTagName("article-cache-time") if element.length == 0: self.cache_time = 30 else: self.cache_time = int(str(element[0].firstChild.nodeValue)) + element = self.__config.getElementsByTagName("login-cache-time") + if element.length == 0: + self.login_cache_time = 7200 + else: + self.login_cache_time = int(str(element[0].firstChild.nodeValue)) def __setDebug(self): element = self.__config.getElementsByTagName("debug") @@ -147,6 +153,7 @@ else: <general> <!-- Cache time in seconds --> <article-cache-time>30</article-cache-time> + <login-cache-time>7200</login-cache-time> <debug /> </general> <sites> @@ -172,4 +179,4 @@ else: print "cache time:", config.cache_time print "debug:", config.debug_mode for k, v in config.sites.items(): - print k, v
\ No newline at end of file + print k, v diff --git a/src/wikipediafs/fs.py b/src/wikipediafs/fs.py index 78dcf5e..42c94e5 100644 --- a/src/wikipediafs/fs.py +++ b/src/wikipediafs/fs.py @@ -17,7 +17,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import os.path, re +import os.path, re, time from metadir import MetaDir from config import CONFIG from article import Article @@ -27,7 +27,8 @@ from logger import LOGGER class ArticleDir: def __init__(self, fs, config): self.fs = fs - self.config = config + self.config = config + self.login_time = 0 self.files = {} self.dirs = {} @@ -73,52 +74,68 @@ class ArticleDir: else: return False - def set_cookie_string(self): - if not self.config.has_key("cookie_str"): + def set_cookie_string(self, force): + if force or not self.config.has_key("cookie_str"): if self.config["username"] is not None and \ self.config["password"] is not None: user = User(logger=LOGGER, **self.config) cookie_str = user.getCookieString() self.config["cookie_str"] = cookie_str - def read_file(self, path): + self.login_time = time.time() + + def get_art(self, path): file_name = self.get_article_file_name(path) full_name = self.get_article_full_name(path) - if self.files.has_key(file_name): - art = self.files[file_name] + + if int(time.time()) - self.login_time > CONFIG.login_cache_time: + self.set_cookie_string(1) else: - self.set_cookie_string() - - art = Article(full_name[0:-3], # removes .mw from the name - cache_time=CONFIG.cache_time, - logger = LOGGER, - **self.config) - txt = art.get() - self.files[file_name] = art - return art.get() + if self.files.has_key(file_name): + return self.files[file_name] + else: + self.set_cookie_string(0) + + art = Article(full_name[0:-3], # removes .mw from the name + cache_time=CONFIG.cache_time, + logger = LOGGER, + **self.config) + self.files[file_name] = art + + return art + + def read_file(self, path): + art = self.get_art(path) + txt = art.get() + return txt def write_to(self, path, txt): - file_name = self.get_article_file_name(path) - full_name = self.get_article_full_name(path) - if self.files.has_key(file_name): - art = self.files[file_name] - else: - self.set_cookie_string() - - art = Article(full_name[0:-3], - cache_time=CONFIG.cache_time, - logger = LOGGER, - **self.config) - self.files[file_name] = art - art.set(txt) + art = self.get_art(path); + return art.set(txt) def size(self, path): + LOGGER.debug("FSdir size %s" % (path)) return len(self.read_file(path)) + + def mtime(self, path): + art = self.get_art(path) + # Do a get here just so we have a current Edittime. + art.get() + tmp = art.wpEdittime + t = time.mktime((int(tmp[0:4]), int(tmp[4:6]), int(tmp[6:8]), int(tmp[8:10]), int(tmp[10:12]), int(tmp[12:21]), 0, 0, -1)) + if time.daylight: + t -= time.altzone + else: + t -= time.timezone + + return t def mode(self, path): + LOGGER.debug("FSdir mode %s" % (path)) return 0755 def unlink(self, path): + LOGGER.debug("FSdir unlink %s" % (path)) file_name = self.get_article_file_name(path) if self.files.has_key(file_name): self.files.pop(file_name) @@ -127,6 +144,7 @@ class ArticleDir: return False def mkdir(self, path): + LOGGER.debug("FSdir mkdir %s" % (path)) name = self.get_article_file_name(path) self.dirs[name] = True self.fs.set_dir(path, ArticleDir(self.fs, self.config)) @@ -200,4 +218,4 @@ if __name__ == "__main__": server.parse(errex=1) server.multithreaded = 0 - server.main()
\ No newline at end of file + server.main() diff --git a/src/wikipediafs/metadir.py b/src/wikipediafs/metadir.py index c48b2f3..8a0481a 100644 --- a/src/wikipediafs/metadir.py +++ b/src/wikipediafs/metadir.py @@ -132,6 +132,7 @@ class MetaDir(Fuse): st.st_mode = stat.S_IFREG | d.mode(path) st.st_nlink = 1 st.st_size = d.size(path) + st.st_mtime = d.mtime(path) else: return -errno.ENOENT # No such file or directory return st @@ -169,6 +170,8 @@ class MetaDir(Fuse): # We also need to check if it is a valid file for the fs if dir(d).count("is_valid_file") == 1 and not d.is_valid_file(path): return -errno.EACCES # Permission denied + else: + return -errno.EACCES # Permission denied self.get_file_buf(path) @@ -218,27 +221,54 @@ class MetaDir(Fuse): buf.write(txt) return len(txt) + + def fsync(self, path, isfsyncfile = 0): + LOGGER.info("Fsync %s %s" % (path, isfsyncfile)) + return self.flush (path, 0) + + def flush(self, path, flags = 0): + # Did we succeed? + success = True + + # Called to close the file + LOGGER.debug("flush %s %x" % (path, flags)) + + if self.open_mode == self.WRITE and self.is_valid_file(path): + # for valid files + buf = self.get_file_buf(path) + d = self.get_dir(path) + success = d.write_to(path, buf.getvalue()) + LOGGER.debug("flush: success: %d\n" % (success)); + if success == False: + LOGGER.debug("flush: Returning\n" % (-errno.EIO)); + return -errno.EIO + + return None + def release(self, path, flags): # Called to close the file - LOGGER.debug("release %s %d" % (path, flags)) + LOGGER.debug("release %s %x" % (path, flags)) + # Release can not return errors, but try anyhow because we have no other choices. + # XXX: Is the flush called reliably enough to do this there? if self.open_mode == self.WRITE and self.is_valid_file(path): # for valid files buf = self.get_file_buf(path) d = self.get_dir(path) - d.write_to(path, buf.getvalue()) + success = d.write_to(path, buf.getvalue()) + LOGGER.debug("release: success: %d\n" % (success)); if self.is_valid_file(path): self.remove_file_buf(path) # Do not keep buffer in memory... - self.open_mode = None - + self.open_mode = None + return None def mkdir(self, path, mode): - LOGGER.debug("mkdir %s %d" % (path, mode)) + LOGGER.debug("mkdir %s %x" % (path, mode)) d = self.get_dir(path) - + if dir(d).count("mkdir") == 0: return -errno.EACCES # Permission denied else: @@ -291,10 +321,12 @@ class MetaDir(Fuse): elif not self.is_valid_file(path): if self.is_valid_file(path1) and d.is_file(path1): # from an editor file to a valid file - buf = self.get_file_buf(path) - d.write_to(path1, buf.getvalue()) + buf = self.get_file_buf(path) + ret = d.write_to(path1, buf.getvalue()) self.open_mode = None self.remove_file_buf(path) + if ret == False: + return -errno.EIO elif not self.is_valid_file(path): # from an editor file to an editor file # TODO @@ -317,10 +349,6 @@ class MetaDir(Fuse): def chown(self, path, user, group): LOGGER.debug("chown %s %s %s" % (path,user,group)) return None - - def fsync(self, path, isfsyncfile): - LOGGER.info("Fsync %s %s" % (path, isfsyncfile)) - return 0 if __name__ == "__main__": class Hello: @@ -387,4 +415,4 @@ if __name__ == "__main__": fs.release('/hello_file', 32768) print fs.mkdir('/new_dir', 32768) -
\ No newline at end of file + |