author | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-04-16 19:06:15 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-04-18 00:34:23 UTC |
parent | f318eae1ae5152ebbf70e67e2dec5919a104ed81 |
.gitignore | +3 | -0 |
libjio/Doxyfile.base | +204 | -0 |
libjio/Doxyfile.internal | +8 | -0 |
libjio/Doxyfile.public | +8 | -0 |
libjio/Makefile | +5 | -1 |
libjio/ansi.c | +13 | -16 |
libjio/autosync.c | +18 | -5 |
libjio/check.c | +3 | -3 |
libjio/checksum.c | +4 | -3 |
libjio/common.c | +7 | -10 |
libjio/common.h | +39 | -14 |
libjio/compat.c | +5 | -2 |
libjio/compat.h | +1 | -1 |
libjio/journal.c | +8 | -6 |
libjio/libjio.h | +322 | -29 |
libjio/trans.c | +13 | -16 |
libjio/trans.h | +21 | -8 |
libjio/unix.c | +14 | -13 |
diff --git a/.gitignore b/.gitignore index 2a82b46..24091ee 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ tests/performance/performance tests/performance/random *.pyc *.pyo +libjio/doc.internal +libjio/doc.public + diff --git a/libjio/Doxyfile.base b/libjio/Doxyfile.base new file mode 100644 index 0000000..b776b32 --- /dev/null +++ b/libjio/Doxyfile.base @@ -0,0 +1,204 @@ +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = libjio +PROJECT_NUMBER = 0.50 +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +INPUT = +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = NO +USE_HTAGS = NO +VERBATIM_HEADERS = YES +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = YES +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = YES +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NONE +TREEVIEW_WIDTH = 250 +FORMULA_FONTSIZE = 10 +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +GENERATE_AUTOGEN_DEF = NO +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = YES +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +SEARCHENGINE = NO diff --git a/libjio/Doxyfile.internal b/libjio/Doxyfile.internal new file mode 100644 index 0000000..581bdb3 --- /dev/null +++ b/libjio/Doxyfile.internal @@ -0,0 +1,8 @@ +@INCLUDE = Doxyfile.base +PROJECT_NAME = "libjio (internal)" +OUTPUT_DIRECTORY = doc.internal +EXTRACT_ALL = YES +EXTRACT_STATIC = YES +INTERNAL_DOCS = YES +EXCLUDE = jiofsck.c + diff --git a/libjio/Doxyfile.public b/libjio/Doxyfile.public new file mode 100644 index 0000000..bbbd2f9 --- /dev/null +++ b/libjio/Doxyfile.public @@ -0,0 +1,8 @@ +@INCLUDE = Doxyfile.base +PROJECT_NAME = "libjio (public)" +OUTPUT_DIRECTORY = doc.public +EXTRACT_ALL = YES +EXTRACT_STATIC = NO +INTERNAL_DOCS = NO +FILE_PATTERNS = libjio.h + diff --git a/libjio/Makefile b/libjio/Makefile index 6ccb28f..4f25361 100644 --- a/libjio/Makefile +++ b/libjio/Makefile @@ -82,11 +82,15 @@ install: all .c.o: $(NICE_CC) $(ALL_CFLAGS) -c $< -o $@ +doxygen: + doxygen Doxyfile.internal + doxygen Doxyfile.public clean: rm -f $(OBJS) libjio.a libjio.so libjio.pc jiofsck.o jiofsck rm -f *.bb *.bbg *.da *.gcov *.gcno *.gcda gmon.out + rm -rf doc.internal/ doc.public/ -.PHONY: default all install clean +.PHONY: default all install clean doxygen diff --git a/libjio/ansi.c b/libjio/ansi.c index c23f3c4..41180b6 100644 --- a/libjio/ansi.c +++ b/libjio/ansi.c @@ -1,8 +1,5 @@ /* - * libjio - A library for Journaled I/O - * Alberto Bertogli (albertito@blitiri.com.ar) - * * ANSI C API wrappers */ @@ -31,7 +28,7 @@ */ -/* fopen wrapper */ +/* fopen() wrapper */ struct jfs *jfopen(const char *path, const char *mode) { int flags; @@ -72,7 +69,7 @@ struct jfs *jfopen(const char *path, const char *mode) return fs; } -/* fclose wrapper */ +/* fclose() wrapper */ int jfclose(struct jfs *stream) { int rv; @@ -85,7 +82,7 @@ int jfclose(struct jfs *stream) return EOF; } -/* freopen wrapper */ +/* freopen() wrapper */ struct jfs *jfreopen(const char *path, const char *mode, struct jfs *stream) { if (stream) @@ -95,7 +92,7 @@ struct jfs *jfreopen(const char *path, const char *mode, struct jfs *stream) return stream; } -/* fread wrapper */ +/* fread() wrapper */ size_t jfread(void *ptr, size_t size, size_t nmemb, struct jfs *stream) { int rv; @@ -107,7 +104,7 @@ size_t jfread(void *ptr, size_t size, size_t nmemb, struct jfs *stream) return rv / size; } -/* fwrite wrapper */ +/* fwrite() wrapper */ size_t jfwrite(const void *ptr, size_t size, size_t nmemb, struct jfs *stream) { int rv; @@ -119,13 +116,13 @@ size_t jfwrite(const void *ptr, size_t size, size_t nmemb, struct jfs *stream) return rv / size; } -/* fileno wrapper */ +/* fileno() wrapper */ int jfileno(struct jfs *stream) { return stream->fd; } -/* feof wrapper */ +/* feof() wrapper */ int jfeof(struct jfs *stream) { /* ANSI expects that when an EOF is reached in any operation (like @@ -151,14 +148,14 @@ int jfeof(struct jfs *stream) return 0; } -/* clearerr wrapper */ +/* clearerr() wrapper */ void jclearerr(struct jfs *stream) { /* As we do not carry any kind of error state (like explained in * jfeof()), this function has no effect. */ } -/* ferror wrapper */ +/* ferror() wrapper */ int jferror(struct jfs *stream) { /* The same as the above; however not returning this might have some @@ -166,7 +163,7 @@ int jferror(struct jfs *stream) return 0; } -/* fseek wrapper */ +/* fseek() wrapper */ int jfseek(struct jfs *stream, long offset, int whence) { off_t pos; @@ -182,14 +179,14 @@ int jfseek(struct jfs *stream, long offset, int whence) return 0; } -/* ftell wrapper */ +/* ftell() wrapper */ long jftell(struct jfs *stream) { /* forced conversion to long to meet the prototype */ return (long) lseek(stream->fd, 0, SEEK_CUR); } -/* rewind wrapper */ +/* rewind() wrapper */ void jrewind(struct jfs *stream) { lseek(stream->fd, 0, SEEK_SET); @@ -197,7 +194,7 @@ void jrewind(struct jfs *stream) /* convert a struct jfs to a FILE so you can use it with other functions that * require a FILE pointer; be aware that you're bypassing the journaling layer - * and it can cause severe corruption if you're not extremely careful */ + * and it can cause corruption if you're not extremely careful */ FILE *jfsopen(struct jfs *stream, const char *mode) { return fdopen(stream->fd, mode); diff --git a/libjio/autosync.c b/libjio/autosync.c index 750bec8..edc6ec3 100644 --- a/libjio/autosync.c +++ b/libjio/autosync.c @@ -1,4 +1,8 @@ +/* + * Autosync API + */ + #include <pthread.h> /* pthread_* */ #include <errno.h> /* ETIMEDOUT */ #include <signal.h> /* sig_atomic_t */ @@ -8,22 +12,31 @@ #include "common.h" #include "libjio.h" +/** Configuration of an autosync thread */ struct autosync_cfg { + /** File structure to jsync() */ struct jfs *fs; + + /** Thread id */ pthread_t tid; + /** Max number of seconds between each jsync() */ time_t max_sec; + + /** Max number of bytes written between each jsync() */ size_t max_bytes; - /* When the thread must die, we set this to 1 */ + /** When the thread must die, we set this to 1 */ sig_atomic_t must_die; - /* Condition variable to wake up the thread */ + /** Condition variable to wake up the thread */ pthread_cond_t cond; + + /** Mutex to use for the condition variable */ pthread_mutex_t mutex; }; -/* Thread that performes the automatic syncing */ +/** Thread that performs the automatic syncing */ static void *autosync_thread(void *arg) { int rv; @@ -114,8 +127,8 @@ int jfs_autosync_stop(struct jfs *fs) return rv; } -/* Used internally to notify the autosync thread that the number of bytes has - * been exceeded. Must be called with fs' ltlock held. */ +/** Notify the autosync thread that it should check the number of bytes + * written. Must be called with fs' ltlock held. */ void autosync_check(struct jfs *fs) { if (fs->as_cfg == NULL) diff --git a/libjio/check.c b/libjio/check.c index 61a601c..48d8605 100644 --- a/libjio/check.c +++ b/libjio/check.c @@ -20,7 +20,7 @@ #include "trans.h" -/* fill a transaction structure from a mmapped transaction file */ +/** Fill a transaction structure from a mmapped transaction file */ static off_t fill_trans(unsigned char *map, off_t len, struct jtrans *ts) { int i; @@ -95,7 +95,7 @@ error: return 0; } -/* check the journal and rollback incomplete transactions */ +/* Check the journal and fix the incomplete transactions */ int jfsck(const char *name, const char *jdir, struct jfsck_result *res) { int tfd, rv, i, ret; @@ -324,7 +324,7 @@ exit: } -/* remove all the files in the journal directory (if any) */ +/* Remove all the files in the journal directory (if any) */ int jfsck_cleanup(const char *name, const char *jdir) { char path[PATH_MAX], tfile[PATH_MAX*3]; diff --git a/libjio/checksum.c b/libjio/checksum.c index 92a9227..250a96d 100644 --- a/libjio/checksum.c +++ b/libjio/checksum.c @@ -1,8 +1,5 @@ /* - * libjio - A library for Journaled I/O - * Alberto Bertogli (albertito@blitiri.com.ar) - * * Checksum functions * Based on RFC 1071, "Computing the Internet Checksum" */ @@ -13,6 +10,8 @@ #include "common.h" +/** Reads the contents of the given fd, up to len bytes, and stores the + * checksum in csum. Returns 1 on success, 0 on error. */ int checksum(int fd, size_t len, uint32_t *csum) { uint8_t *map; @@ -27,6 +26,8 @@ int checksum(int fd, size_t len, uint32_t *csum) return 1; } +/** Calculates the checksum of the given buffer, up to count bytes. Returns + * the checksum. */ uint32_t checksum_map(uint8_t *map, size_t count) { uint32_t sum = 0; diff --git a/libjio/common.c b/libjio/common.c index c37f144..7a3cdf9 100644 --- a/libjio/common.c +++ b/libjio/common.c @@ -1,8 +1,5 @@ /* - * libjio - A library for Journaled I/O - * Alberto Bertogli (albertito@blitiri.com.ar) - * * Common functions */ @@ -19,7 +16,7 @@ #include "common.h" -/* like lockf, but lock always from the beginning of the file */ +/** Like lockf(), but lock always from the given offset */ off_t plockf(int fd, int cmd, off_t offset, off_t len) { struct flock fl; @@ -50,8 +47,8 @@ off_t plockf(int fd, int cmd, off_t offset, off_t len) return fcntl(fd, op, &fl); } -/* like pread but either fails, or return a complete read; if we return less - * than count is because EOF was reached */ +/** Like pread() but either fails, or return a complete read. If it returns + * less than count it's because EOF was reached */ ssize_t spread(int fd, void *buf, size_t count, off_t offset) { int rv, c; @@ -78,7 +75,7 @@ ssize_t spread(int fd, void *buf, size_t count, off_t offset) return count; } -/* like spread() but for pwrite() */ +/** Like spread() but for pwrite() */ ssize_t spwrite(int fd, const void *buf, size_t count, off_t offset) { int rv, c; @@ -102,7 +99,7 @@ ssize_t spwrite(int fd, const void *buf, size_t count, off_t offset) return count; } -/* build the journal directory name out of the filename */ +/** Store in jdir the default journal directory path of the given filename */ int get_jdir(const char *filename, char *jdir) { char *base, *baset; @@ -128,8 +125,8 @@ int get_jdir(const char *filename, char *jdir) return 1; } -/* build the filename of a given transaction; assumes jtfile can hold at least - * PATH_MAX bytes */ +/** Build the filename of a given transaction. Assumes jtfile can hold at + * least PATH_MAX bytes. */ void get_jtfile(struct jfs *fs, unsigned int tid, char *jtfile) { snprintf(jtfile, PATH_MAX, "%s/%u", fs->jdir, tid); diff --git a/libjio/common.h b/libjio/common.h index 56837d6..4879eb5 100644 --- a/libjio/common.h +++ b/libjio/common.h @@ -26,21 +26,46 @@ #define MAX_TSIZE (SSIZE_MAX) -/* the main file structure */ +/** The main file structure */ struct jfs { - int fd; /* main file descriptor */ - char *name; /* and its name */ - char *jdir; /* journal directory */ - int jdirfd; /* journal directory file descriptor */ - int jfd; /* journal's lock file descriptor */ - unsigned int *jmap; /* journal's lock file mmap area */ - uint32_t flags; /* journal flags */ - uint32_t open_flags; /* open() flags */ - struct jlinger *ltrans; /* lingered transactions */ - size_t ltrans_len; /* length of all the lingered transactions */ - pthread_mutex_t ltlock; /* lingered transactions' lock */ - pthread_mutex_t lock; /* a soft lock used in some operations */ - struct autosync_cfg *as_cfg; /* autosync config */ + /** Real file fd */ + int fd; + + /** Real file path */ + char *name; + + /** Journal directory path */ + char *jdir; + + /** Journal directory file descriptor */ + int jdirfd; + + /** Journal's lock file descriptor */ + int jfd; + + /** Journal's lock file mmap */ + unsigned int *jmap; + + /** Journal flags */ + uint32_t flags; + + /** Flags passed to the real open() */ + uint32_t open_flags; + + /** Lingering transactions (linked list) */ + struct jlinger *ltrans; + + /** Length of all the lingered transactions */ + size_t ltrans_len; + + /** Lingering transactions' lock */ + pthread_mutex_t ltlock; + + /** A soft lock used in some operations */ + pthread_mutex_t lock; + + /** Autosync config */ + struct autosync_cfg *as_cfg; }; diff --git a/libjio/compat.c b/libjio/compat.c index 80c2300..8c7645b 100644 --- a/libjio/compat.c +++ b/libjio/compat.c @@ -1,4 +1,7 @@ +/* + * Compatibility functions + */ /* To get sync_file_range() we need to temporarily define _GNU_SOURCE, which * is not the nicest thing, but is not worth defining globally */ @@ -18,7 +21,7 @@ #ifdef SYNC_FILE_RANGE_WRITE const int have_sync_range = 1; -/* Initiate write-out of the dirty pages in the range. */ +/** Initiate write-out of the dirty pages in the range */ int sync_range_submit(int fd, off_t offset, size_t nbytes) { /* We don't need SYNC_FILE_RANGE_WAIT_BEFORE because we have exclusive @@ -26,7 +29,7 @@ int sync_range_submit(int fd, off_t offset, size_t nbytes) return sync_file_range(fd, offset, nbytes, SYNC_FILE_RANGE_WRITE); } -/* Wait for completion of the previously-submitted I/O in the given ranges. +/** Wait for completion of the previously-submitted I/O in the given ranges. * Does NOT force the submission of any new I/O. */ int sync_range_wait(int fd, off_t offset, size_t nbytes) { diff --git a/libjio/compat.h b/libjio/compat.h index 4f9d98d..cf90798 100644 --- a/libjio/compat.h +++ b/libjio/compat.h @@ -1,5 +1,5 @@ -/* Header to provide fallbacks for compatibility purposes. */ +/* Header to provide fallbacks for compatibility purposes */ #ifndef _COMPAT_H #define _COMPAT_H diff --git a/libjio/journal.c b/libjio/journal.c index 3b63402..2055da9 100644 --- a/libjio/journal.c +++ b/libjio/journal.c @@ -27,7 +27,7 @@ * helper functions */ -/* gets a new transaction id */ +/** Get a new transaction id */ static unsigned int get_tid(struct jfs *fs) { unsigned int curid, rv; @@ -53,7 +53,7 @@ exit: return rv; } -/* frees a transaction id */ +/** Free a transaction id */ static void free_tid(struct jfs *fs, unsigned int tid) { unsigned int curid, i; @@ -89,8 +89,10 @@ static void free_tid(struct jfs *fs, unsigned int tid) return; } -/* fsync()s a directory */ + static int already_warned_about_sync = 0; + +/** fsync() a directory */ static int fsync_dir(int fd) { int rv; @@ -121,7 +123,7 @@ static int fsync_dir(int fd) * Journal functions */ -/* Creates a new transaction in the journal, returns a pointer to an opaque +/** Create a new transaction in the journal. Returns a pointer to an opaque * jop_t (that is freed using journal_free), or NULL if there was an error. */ struct journal_op *journal_new(struct jtrans *ts) { @@ -202,7 +204,7 @@ error: return NULL; } -/* Saves the transaction in the journal */ +/** Save the given transaction in the journal */ int journal_save(struct journal_op *jop) { ssize_t rv; @@ -296,7 +298,7 @@ error: return -1; } -/* Frees a journal operation. +/** Free a journal operation. * NOTE: It can't assume the save completed successfuly, so we can call it * when journal_save() fails. */ int journal_free(struct journal_op *jop) diff --git a/libjio/libjio.h b/libjio/libjio.h index 1c295b4..2e47f15 100644 --- a/libjio/libjio.h +++ b/libjio/libjio.h @@ -23,81 +23,374 @@ #error "You must compile your application with Large File Support" #endif -/* empty declarations, the API does not expose these */ +/* + * Opaque types, the API does not expose these + */ + +/** An open file, similar to a file descriptor */ typedef struct jfs jfs_t; + +/** A single transaction */ typedef struct jtrans jtrans_t; + +/* + * Public types + */ + +/** The result of a jfsck() run */ struct jfsck_result { - int total; /* total transactions files we looked at */ - int invalid; /* invalid files in the journal directory */ - int in_progress; /* transactions in progress */ - int broken; /* transactions broken */ - int corrupt; /* corrupt transactions */ - int apply_error; /* errors applying the transaction */ - int reapplied; /* transactions that were reapplied */ + /** Total transactions files processed */ + int total; + + /** Number of invalid transactions */ + int invalid; + + /** Number of transactions in progress */ + int in_progress; + + /** Number of broken transactions */ + int broken; + + /** Number of corrupt transactions */ + int corrupt; + + /** Number of errors applying transactions */ + int apply_error; + + /** Number of transactions successfully reapplied */ + int reapplied; }; -/* core functions */ +/* + * Core functions + */ + +/** Open a file. + * + * Takes the same parameters as the UNIX open(2), with an additional one for + * internal flags. + * + * The only supported internal flag is J_LINGER, which enables lingering + * transactions. + * + * @param name path to the file to open + * @param flags flags to pass to open(2) + * @param mode mode to pass to open(2) + * @param jflags journal flags + * @returns a new jfs_t that identifies the open file on success, or NULL on + * error + * @see jclose(), open() + * + * */ jfs_t *jopen(const char *name, int flags, int mode, int jflags); + +/** Close a file opened with jopen(). + * + * After a call to this function, the memory allocated for the open file will + * be freed. + * + * If there was an autosync thread started for this file, it will be stopped. + * + * @param fs open file + * @returns 0 on success, -1 on error + * @see jopen(), jfs_autosync_start() + */ +int jclose(jfs_t *fs); + +/** Sync a file. Makes sense only when using lingering transactions. + * + * @param fs open file + * @returns 0 on success, -1 on error + */ +int jsync(jfs_t *fs); + +/** Create a new transaction. + * + * @param fs open file the transaction will apply to + * @returns a new transaction (must be freed using jtrans_free()) + * @see jtrans_free() + */ jtrans_t *jtrans_init(jfs_t *fs); + +/** Add an operation to a transaction. + * + * An operation consists of a buffer, its length, and the offset to write it + * to. + * + * The file will not be touched (not even locked) until commit time, where the + * first count bytes of buf will be written at offset. + * + * Transactions will be applied in order, and overlapping operations are + * permitted, in which case the latest one will prevail. + * + * @param ts transaction + * @param buf buffer to write + * @param count how many bytes from the buffer to write + * @param offset offset to write at + * @returns 1 on success, 0 on error + */ int jtrans_add(jtrans_t *ts, const void *buf, size_t count, off_t offset); + +/** Commit a transaction. + * + * All the operations added to it using jtrans_add() will be written to disk, + * in the same order they were added. + * + * After this function returns successfully, all the data can be trusted to be + * on the disk. The commit is atomic with regards to other processes using + * libjio, but not accessing directly to the file. + * + * @param ts transaction + * @returns the amount of bytes written to disk, or -1 if there was an error + * but atomic warranties were preserved, or -2 if there was an error and + * there is a possible break of atomic warranties (which is an indication + * of a severe underlying condition). + */ ssize_t jtrans_commit(jtrans_t *ts); + +/** Rollback a transaction. + * + * This function atomically undoes a previous committed transaction. After its + * successful return, the data can be trusted to be on disk. + * + * Use with care. + * + * @param ts transaction + * @returns the same as jtrans_commit() + * @see jtrans_commit() + */ ssize_t jtrans_rollback(jtrans_t *ts); + +/** Free a transaction structure. + * + * @param ts transaction to free + * @see jtrans_init() + */ void jtrans_free(jtrans_t *ts); -int jsync(jfs_t *fs); + +/** Change the location of the journal directory. + * + * The file MUST NOT be in use by any other thread or process. The older + * journal directory will be removed. + * + * @param fs open file + * @param newpath path to the new journal directory, which will be created if + * it doesn't exist + * @returns 0 on success, -1 on error + */ int jmove_journal(jfs_t *fs, const char *newpath); -int jclose(jfs_t *fs); -/* autosync */ + +/* + * Autosync + */ + +/** Start an autosync thread. + * + * The thread will call jsync(fs) every max_sec seconds, or every max_bytes + * have been written. Only one autosync thread per open file is allowed. + * + * @param fs open file + * @param max_sec maximum number of seconds that should pass between each + * call to jsync() + * @param max_bytes maximum number of bytes that should be written between + * each call to jsync() + * @returns 0 on success, -1 on error + */ int jfs_autosync_start(jfs_t *fs, time_t max_sec, size_t max_bytes); + +/** Stop an autosync thread that was started using jfs_autosync_start(fs). + * + * @param fs open file + * @returns 0 on success, -1 on error + */ int jfs_autosync_stop(jfs_t *fs); +/* + * Journal checker + */ -/* journal checker */ +/** Check and repair the given path. + * + * @param name path to the file to check + * @param jdir journal directory of the given file, use NULL for the default + * @param res structure where to store the result + * @see struct jfsck_result, jfsck_cleanup() + * @return 0 on success, < 0 on error, with the following possible negative + * values: J_ENOENT if there was no such file with the given name, + * J_ENOJOURNAL if there was no journal at the given jdir, J_ENOMEM if + * memory could not be allocated. + */ int jfsck(const char *name, const char *jdir, struct jfsck_result *res); + +/** Remove all the files in the journal directory, and clean it up. + * TODO: this should be merged with jfsck() and removed */ int jfsck_cleanup(const char *name, const char *jdir); -/* UNIX API wrappers */ + +/* + * UNIX API wrappers + */ + +/** Read from the file. Works just like UNIX read(2). + * + * @param fs file to read from + * @param buf buffer used to store the data + * @param count maximum number of bytes to read + * @returns number of bytes read on success, or -1 on error + * @see read(2) + */ ssize_t jread(jfs_t *fs, void *buf, size_t count); + +/** Read from the file at the given offset. Works just like UNIX pread(2). + * + * @param fs file to read from + * @param buf buffer used to store the data + * @param count maximum number of bytes to read + * @param offset offset to read at + * @returns number of bytes read on success, or -1 on error + * @see pread(2) + */ ssize_t jpread(jfs_t *fs, void *buf, size_t count, off_t offset); + +/** Read from the file into multiple buffers. Works just like UNIX readv(2). + * + * @param fs file to read from + * @param vector buffers used to store the data + * @param count maximum number of bytes to read + * @returns number of bytes read on success, or -1 on error + * @see readv(2) + */ ssize_t jreadv(jfs_t *fs, const struct iovec *vector, int count); + +/** Write to the file. Works just like UNIX write(2). + * + * @param fs file to write to + * @param buf buffer used to read the data from + * @param count maximum number of bytes to write + * @returns number of bytes written on success, or -1 on error + * @see write(2) + */ ssize_t jwrite(jfs_t *fs, const void *buf, size_t count); + +/** Write to the file at the given offset. Works just like UNIX pwrite(2). + * + * @param fs file to write to + * @param buf buffer used to read the data from + * @param count maximum number of bytes to write + * @param offset offset to write at + * @returns number of bytes written on success, or -1 on error + * @see pwrite(2) + */ ssize_t jpwrite(jfs_t *fs, const void *buf, size_t count, off_t offset); + +/** Write to the file from multiple buffers. Works just like UNIX writev(2). + * + * @param fs file to write to + * @param vector buffers used to read the data from + * @param count maximum number of bytes to write + * @returns number of bytes written on success, or -1 on error + * @see writev(2) + */ ssize_t jwritev(jfs_t *fs, const struct iovec *vector, int count); + +/** Truncates the file to the given length. Works just like UNIX ftruncate(2). + * + * @param fs file to truncate + * @param length lenght to truncate to + * @returns 0 on success, -1 on error + * @see ftruncate(2) + */ int jtruncate(jfs_t *fs, off_t length); + +/** Reposition read/write file offset. Works just like UNIX lseek(2). + * + * @param fs file to change the offset to + * @param offset offset to set + * @param whence where to count offset from, can be SEEK_SET to count from the + * beginning of the file, SEEK_CUR to count from the current position, or + * SEEK_END to count from the end. + * @returns the new offset counted from the beginning of the file, or -1 on + * error. + */ off_t jlseek(jfs_t *fs, off_t offset, int whence); -/* ANSI C stdio wrappers */ + +/* + * ANSI C stdio wrappers + */ + jfs_t *jfopen(const char *path, const char *mode); + int jfclose(jfs_t *stream); + jfs_t *jfreopen(const char *path, const char *mode, jfs_t *stream); + size_t jfread(void *ptr, size_t size, size_t nmemb, jfs_t *stream); + size_t jfwrite(const void *ptr, size_t size, size_t nmemb, jfs_t *stream); + int jfileno(jfs_t *stream); + int jfeof(jfs_t *stream); + void jclearerr(jfs_t *stream); + int jferror(jfs_t *stream); + int jfseek(jfs_t *stream, long offset, int whence); + long jftell(jfs_t *stream); + void jrewind(jfs_t *stream); + FILE *jfsopen(jfs_t *stream, const char *mode); -/* jfs and jtrans constants */ -#define J_NOLOCK 1 /* don't lock the file before operating on it */ -#define J_NOROLLBACK 2 /* no need to read rollback information */ -#define J_LINGER 4 /* use lingering transactions */ -#define J_COMMITTED 8 /* mark a transaction as committed */ -#define J_ROLLBACKED 16 /* mark a transaction as rollbacked */ -#define J_ROLLBACKING 32 /* mark a transaction as rollbacking */ -#define J_RDONLY 64 /* mark a file as read-only */ - -/* jfsck constants (return values) */ -#define J_ESUCCESS 0 /* success - shouldn't be used */ -#define J_ENOENT -1 /* no such file */ -#define J_ENOJOURNAL -2 /* no journal associated */ -#define J_ENOMEM -3 /* no enough free memory */ + +/* + * jopen() and jtrans_create() flags + */ + +/** Don't lock the file before operating on it */ +#define J_NOLOCK 1 + +/** No need to read rollback information */ +#define J_NOROLLBACK 2 + +/** Use lingering transactions */ +#define J_LINGER 4 + +/** Marks a transaction as committed */ +#define J_COMMITTED 8 + +/** Marks a transaction as rollbacked */ +#define J_ROLLBACKED 16 + +/** Marks a transaction as rollbacking */ +#define J_ROLLBACKING 32 + +/** Marks a file as read-only */ +#define J_RDONLY 64 + + +/* + * jfsck() constants (return values) + */ + +/** Success, shouldn't be used */ +#define J_ESUCCESS 0 + +/** No such file or directory */ +#define J_ENOENT -1 + +/** No journal associated with the given file */ +#define J_ENOJOURNAL -2 + +/** Not enough free memory */ +#define J_ENOMEM -3 #endif diff --git a/libjio/trans.c b/libjio/trans.c index d7ac3a4..2bb1b66 100644 --- a/libjio/trans.c +++ b/libjio/trans.c @@ -1,9 +1,6 @@ /* - * libjio - A library for Journaled I/O - * Alberto Bertogli (albertito@blitiri.com.ar) - * - * Core transaction API and recovery functions + * Core transaction API */ #include <sys/types.h> @@ -27,10 +24,10 @@ /* - * transaction functions + * Transaction functions */ -/* initialize a transaction structure */ +/* Initialize a transaction structure */ struct jtrans *jtrans_init(struct jfs *fs) { pthread_mutexattr_t attr; @@ -54,8 +51,7 @@ struct jtrans *jtrans_init(struct jfs *fs) return ts; } - -/* free the contents of a transaction structure */ +/* Free the contents of a transaction structure */ void jtrans_free(struct jtrans *ts) { struct joper *tmpop; @@ -78,7 +74,7 @@ void jtrans_free(struct jtrans *ts) free(ts); } - +/* Add an operation to a transaction */ int jtrans_add(struct jtrans *ts, const void *buf, size_t count, off_t offset) { struct joper *jop, *tmpop; @@ -153,7 +149,7 @@ int jtrans_add(struct jtrans *ts, const void *buf, size_t count, off_t offset) return 1; } -/* commit a transaction */ +/* Commit a transaction */ ssize_t jtrans_commit(struct jtrans *ts) { ssize_t rv; @@ -308,7 +304,7 @@ exit: return -2; } -/* rollback a transaction */ +/* Rollback a transaction */ ssize_t jtrans_rollback(struct jtrans *ts) { ssize_t rv; @@ -384,11 +380,12 @@ exit: return rv; } + /* - * basic operations + * Basic operations */ -/* open a file */ +/* Open a file */ struct jfs *jopen(const char *name, int flags, int mode, int jflags) { int jfd, rv; @@ -511,7 +508,7 @@ error_exit: return NULL; } -/* sync a file (makes sense only if using lingering transactions) */ +/* Sync a file */ int jsync(struct jfs *fs) { int rv; @@ -539,7 +536,7 @@ int jsync(struct jfs *fs) return 0; } -/* change the location of the journal directory */ +/* Change the location of the journal directory */ int jmove_journal(struct jfs *fs, const char *newpath) { int ret; @@ -601,7 +598,7 @@ exit: return ret; } -/* close a file */ +/* Close a file opened with jopen() */ int jclose(struct jfs *fs) { int ret; diff --git a/libjio/trans.h b/libjio/trans.h index 05c22b4..366585e 100644 --- a/libjio/trans.h +++ b/libjio/trans.h @@ -5,15 +5,28 @@ struct joper; -/* a transaction */ +/** A transaction */ struct jtrans { - struct jfs *fs; /* journal file structure to operate on */ - int id; /* transaction id */ - uint32_t flags; /* transaction flags */ - unsigned int numops; /* quantity of operations in the list */ - size_t len; /* transaction's length */ - pthread_mutex_t lock; /* used to modify the operation list */ - struct joper *op; /* list of operations */ + /** Journal file structure to operate on */ + struct jfs *fs; + + /** Transaction id */ + int id; + + /** Transaction flags */ + uint32_t flags; + + /** Number of operations in the list */ + unsigned int numops; + + /** Transaction's length */ + size_t len; + + /** Lock that protects the list of operations */ + pthread_mutex_t lock; + + /** List of operations */ + struct joper *op; }; /* a single operation */ diff --git a/libjio/unix.c b/libjio/unix.c index 9d6b685..a702a5b 100644 --- a/libjio/unix.c +++ b/libjio/unix.c @@ -1,8 +1,5 @@ /* - * libjio - A library for Journaled I/O - * Alberto Bertogli (albertito@blitiri.com.ar) - * * UNIX API wrappers */ @@ -17,9 +14,11 @@ #include "trans.h" -/* read() family wrappers */ +/* + * read() family wrappers + */ -/* read wrapper */ +/* read() wrapper */ ssize_t jread(struct jfs *fs, void *buf, size_t count) { int rv; @@ -43,7 +42,7 @@ ssize_t jread(struct jfs *fs, void *buf, size_t count) return rv; } -/* pread wrapper */ +/* pread() wrapper */ ssize_t jpread(struct jfs *fs, void *buf, size_t count, off_t offset) { int rv; @@ -55,7 +54,7 @@ ssize_t jpread(struct jfs *fs, void *buf, size_t count, off_t offset) return rv; } -/* readv wrapper */ +/* readv() wrapper */ ssize_t jreadv(struct jfs *fs, const struct iovec *vector, int count) { int rv, i; @@ -77,9 +76,11 @@ ssize_t jreadv(struct jfs *fs, const struct iovec *vector, int count) } -/* write family wrappers */ +/* + * write() family wrappers + */ -/* write wrapper */ +/* write() wrapper */ ssize_t jwrite(struct jfs *fs, const void *buf, size_t count) { int rv; @@ -113,7 +114,7 @@ ssize_t jwrite(struct jfs *fs, const void *buf, size_t count) return rv; } -/* pwrite wrapper */ +/* pwrite() wrapper */ ssize_t jpwrite(struct jfs *fs, const void *buf, size_t count, off_t offset) { int rv; @@ -132,7 +133,7 @@ ssize_t jpwrite(struct jfs *fs, const void *buf, size_t count, off_t offset) return rv; } -/* writev wrapper */ +/* writev() wrapper */ ssize_t jwritev(struct jfs *fs, const struct iovec *vector, int count) { int rv, i; @@ -175,7 +176,7 @@ ssize_t jwritev(struct jfs *fs, const struct iovec *vector, int count) } -/* truncate a file - be careful with this */ +/* Truncate a file. Be careful with this */ int jtruncate(struct jfs *fs, off_t length) { int rv; @@ -188,7 +189,7 @@ int jtruncate(struct jfs *fs, off_t length) return rv; } -/* lseek wrapper */ +/* lseek() wrapper */ off_t jlseek(struct jfs *fs, off_t offset, int whence) { off_t rv;