watch_database.h File Reference

Public interface for using the watch database persistent store. More...

Go to the source code of this file.

Classes

struct  lwatch_path_info_t
 struct which mirrors one row from the watch database. More...
struct  database_iter_context_t
 Iteration context used to iterate over a set of lwatch_path_info_t structs returned by a watch database query. More...

Defines

#define WATCH_DATABASE_ERROR_BASE   -3500
 Base error code (minimum value) for watch database errors.
#define WATCH_DATABASE_ERROR_LIMIT   (WATCH_DATABASE_ERROR_BASE + 50)
 Maximum error code for watch database errors.
#define IS_WATCH_DATABASE_ERROR(error)   (((error) >= WATCH_DATABASE_ERROR_BASE) && ((error) < WATCH_DATABASE_ERROR_LIMIT))
 Return true if error code is within the range for watch database errors.
#define WATCH_DATABASE_ERROR_CANNOT_OPEN   (WATCH_DATABASE_ERROR_BASE + 1)
 could not open database
#define WATCH_DATABASE_ERROR_CANNOT_CLOSE   (WATCH_DATABASE_ERROR_BASE + 2)
 could not close database
#define WATCH_DATABASE_ERROR_CANNOT_QUERY   (WATCH_DATABASE_ERROR_BASE + 3)
 database query failed
#define WATCH_DATABASE_ERROR_CANNOT_CREATE_TABLE   (WATCH_DATABASE_ERROR_BASE + 4)
 cannot create table
#define WATCH_DATABASE_ERROR_CANNOT_INSERT   (WATCH_DATABASE_ERROR_BASE + 5)
 cannot insert record into table
#define WATCH_DATABASE_ERROR_NOT_FOUND   (WATCH_DATABASE_ERROR_BASE + 6)
 entry not found
#define WATCH_DATABASE_ERROR_FOUND_MULTIPLE   (WATCH_DATABASE_ERROR_BASE + 7)
 found multiple entries, expecting single entry
#define WATCH_DATABASE_PATHNAME   DATABASEDIR "/" PACKAGE_NAME ".db"
 The path name of the SQLite database used for lwatch.
#define LWATCH_TABLE_NAME   "lwatch"
 The name of the table where we persistently store lwatch_path_info_t data.
#define PATH_INFO_FLAG_SET_TARGET(path_info)
 Update the flags to indicate this path is a watch target.
#define PATH_INFO_FLAG_SET_BACKUP(path_info)
 Update the flags to indicate this path is a backup of a watch target.
#define PATH_INFO_FLAG_SET_INC_VERSION(path_info)
 Update the flags to indicate this path needs to have it's version number incremented the next time.
#define PATH_INFO_FLAG_SET_NEW_FILE(path_info)
 Update the flags to indicate this file has been lost and from this point forward we need to consider any reference to this file will represent new contents for the file.

Typedefs

typedef struct
lwatch_path_info_t *(* 
database_iter_next_t )(struct database_iter_context_t *iter)
 Pointer to function returning pointer to lwatch_path_info_t.

Enumerations

enum  path_info_flags_t {
  TARGET_FLAG = 0x0001, BACKUP_FLAG = 0x0002, NEEDS_REAPING_FLAG = 0x0004, STAT_DATA_VALID_FLAG = 0x0008,
  INC_VERSION_FLAG = 0x0010
}
 Boolean flags used to indicate path_info state. More...

Functions

int init_path_info (struct lwatch_path_info_t *path_info, const char *path)
 Initialize a lwatch_path_info_t struct.
int new_path_info (const char *path, struct lwatch_path_info_t **path_info_arg)
 Allocate and initialize a new lwatch_path_info_t struct.
char * path_info_flags_string (unsigned long flag, const char *separator)
 Render the lwatch_path_info_t flag bitset as a string.
char * path_info_string (struct lwatch_path_info_t *path_info, const char *prefix)
 Render a lwatch_path_info_t struct as a string.
int watch_database_init (void)
 Initialize the watch database subsystem.
int watch_database_fini (void)
 Close the watch database subsystem, release all resources, close database.
const char * watch_database_error_string (int error)
 Render a database error code as a string.
int database_lookup_path_info (const char *path, struct lwatch_path_info_t *path_info)
 Given a path name lookup the matching lwatch_path_info_t in the database.
int database_write_path_info (struct lwatch_path_info_t *path_info)
 Write the supplied lwatch_path_info_t struct into the database.
int database_query_all_paths_iter (struct database_iter_context_t **iter_arg, const char *path_filter_arg)
 Get an iterator to every lwatch_path_info_t row in the database.
int database_query_backups_iter (struct database_iter_context_t **iter_arg)
 Get an iterator to every lwatch_path_info_t row in the database which is a backup to a primary file.
int database_query_backups_of_target_iter (struct database_iter_context_t **iter_arg, const char *path)
 Get an iterator to each lwatch_path_info_t row in the database which is a backup to the specified primary file.
int database_query_pending_reaps_iter (struct database_iter_context_t **iter_arg)
 Get an iterator to every lwatch_path_info_t row which has a reap pending.
int database_query_targets_iter (struct database_iter_context_t **iter_arg)
 Get an iterator to every lwatch_path_info_t row which is a primary watch file, i.e.


Detailed Description

Public interface for using the watch database persistent store.

Definition in file watch_database.h.


Define Documentation

#define IS_WATCH_DATABASE_ERROR ( error   )     (((error) >= WATCH_DATABASE_ERROR_BASE) && ((error) < WATCH_DATABASE_ERROR_LIMIT))

Return true if error code is within the range for watch database errors.

Parameters:
[in] error The error code to test if it's a watch database error code.
Returns:
True if error code is a watch database error.

Definition at line 35 of file watch_database.h.

Referenced by error_string().

#define PATH_INFO_FLAG_SET_BACKUP ( path_info   ) 

Value:

{                                                               \
    (path_info)->flags |=  BACKUP_FLAG;                         \
    (path_info)->flags &= ~(TARGET_FLAG | INC_VERSION_FLAG);    \
}
Update the flags to indicate this path is a backup of a watch target.

Definition at line 66 of file watch_database.h.

Referenced by process_file_rename().

#define PATH_INFO_FLAG_SET_INC_VERSION ( path_info   ) 

Value:

{                                                       \
    if (!((path_info)->flags & BACKUP_FLAG))            \
        (path_info)->flags |= INC_VERSION_FLAG;         \
}
Update the flags to indicate this path needs to have it's version number incremented the next time.

This occurs when we detect a file has had it's contents replaced and is now a new file, hence it will have a higher version number.

Definition at line 78 of file watch_database.h.

#define PATH_INFO_FLAG_SET_NEW_FILE ( path_info   ) 

Value:

Update the flags to indicate this file has been lost and from this point forward we need to consider any reference to this file will represent new contents for the file.

Definition at line 89 of file watch_database.h.

Referenced by process_file_delete(), and process_file_rename().

#define PATH_INFO_FLAG_SET_TARGET ( path_info   ) 

Value:

{                                               \
    (path_info)->flags |=  TARGET_FLAG;         \
    (path_info)->flags &= ~BACKUP_FLAG;         \
}
Update the flags to indicate this path is a watch target.

Definition at line 57 of file watch_database.h.

Referenced by start_monitoring().


Enumeration Type Documentation

Boolean flags used to indicate path_info state.

Enumerator:
TARGET_FLAG  true if this path is a primary watch target
BACKUP_FLAG  true if this path is backup of a primary watch target
NEEDS_REAPING_FLAG  true if contents of this file needs to be collected (e.g.

reaped)

STAT_DATA_VALID_FLAG  true if stat information is valid
INC_VERSION_FLAG  true if we need to increment the version number on the primary watch target because the file was replaced

Definition at line 102 of file watch_database.h.

00102              {
00103     TARGET_FLAG             = 0x0001, /**< true if this path is a primary watch target */
00104     BACKUP_FLAG             = 0x0002, /**< true if this path is backup of a primary watch target */
00105     NEEDS_REAPING_FLAG      = 0x0004, /**< true if contents of this file needs to be collected (e.g. reaped) */
00106     STAT_DATA_VALID_FLAG    = 0x0008, /**< true if stat information is valid */
00107     INC_VERSION_FLAG        = 0x0010, /**< true if we need to increment the version number on the primary watch
00108                                            target because the file was replaced */
00109 } path_info_flags_t;


Function Documentation

int database_lookup_path_info ( const char *  path,
struct lwatch_path_info_t path_info 
)

Given a path name lookup the matching lwatch_path_info_t in the database.

Parameters:
[in] path Path Name whose lwatch_path_info_t we seek
[out] path_info Pointer to lwatch_path_info_t which will be initialized from the database upon success.
Returns:
SUCCESS (0) or non-zero error code otherwise. WATCH_DATABASE_ERROR_NOT_FOUND indicates the path was not found as opposed to other more general run-time errors.

Definition at line 968 of file watch_database.c.

Referenced by get_create_path_info(), process_file_close(), process_file_create(), process_file_delete(), process_file_modification(), and process_file_rename().

00969 {
00970     int error, result, step_result;
00971     int n_rows;
00972 
00973     result = SUCCESS;
00974 
00975     if ((error = reset_statement(lookup_path_stmt)) != SUCCESS) {
00976         result = WATCH_DATABASE_ERROR_CANNOT_QUERY;
00977         goto exit;
00978     }
00979 
00980     if ((error = sqlite3_bind_text(lookup_path_stmt, 1, path, -1, SQLITE_TRANSIENT)) != SQLITE_OK) {
00981         const char *err_msg = sqlite3_errmsg(database_handle);
00982         log_msg(LOG_ERROR, _("sqlite3_bind_text \"%s\", (%s)\n"),  sqlite3_sql(lookup_path_stmt), err_msg);
00983         result = WATCH_DATABASE_ERROR_CANNOT_QUERY;
00984         goto exit;
00985     }
00986 
00987     n_rows = 0;
00988     while(true) {
00989         step_result = sqlite3_step(lookup_path_stmt);
00990         if (step_result == SQLITE_DONE) {
00991             break;
00992         } else if (step_result == SQLITE_ROW) {
00993             if (n_rows == 0) {
00994                 if ((error = populate_path_info(path_info, lookup_path_stmt)) != SUCCESS) {
00995                     log_msg(LOG_ERROR, _("populate_path_info() failed for path \"%s\" (%s)"),
00996                             path, error_string(error));
00997                     result = error;
00998                 }
00999             }
01000             n_rows++;
01001         } else {
01002             const char *err_msg = sqlite3_errmsg(database_handle);
01003             log_msg(LOG_ERROR, _("sqlite3_step \"%s\", unexpected result %s (%s)\n"),
01004                     sqlite3_sql(lookup_path_stmt), sqlite3_result_string(step_result), err_msg);
01005         }
01006     }
01007 
01008  exit:
01009     if (result == SUCCESS) {
01010         if (n_rows == 0)
01011             result = WATCH_DATABASE_ERROR_NOT_FOUND;
01012         else if (n_rows > 1)
01013             result = WATCH_DATABASE_ERROR_FOUND_MULTIPLE;
01014     }
01015     return result;
01016 }

int database_query_all_paths_iter ( struct database_iter_context_t **  iter_arg,
const char *  path_filter_arg 
)

Get an iterator to every lwatch_path_info_t row in the database.

Parameters:
[out] iter_arg Iterator context returned here, NULL if failure
[in] path_filter_arg SQL "like" wildcard pattern, path must match this pattern to be included in result set. If NULL then no filtering is performed, all paths will match.
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1028 of file watch_database.c.

Referenced by dump_database().

01029 {
01030     int error;
01031     struct path_info_iter_context_t *iter;
01032     const char *path_filter;
01033 
01034     *iter_arg = NULL;
01035     if ((error = new_path_info_iter_context(&iter)) != SUCCESS) {
01036         log_msg(LOG_ERROR, _("cannot allocate new iteration context (%s)\n"), error_string(error));
01037         return error;
01038     }
01039 
01040     iter->stmt = query_all_stmt;
01041 
01042     if ((iter->iter.error = reset_statement(iter->stmt)) != SQLITE_OK) {
01043         free(iter);
01044         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
01045     }
01046 
01047     if (path_filter_arg == NULL)
01048         path_filter = "%";
01049     else
01050         path_filter = path_filter_arg;
01051 
01052     if ((iter->iter.error = sqlite3_bind_text(iter->stmt, 1, path_filter, -1, SQLITE_TRANSIENT)) != SQLITE_OK) {
01053         const char *err_msg = sqlite3_errmsg(database_handle);
01054         log_msg(LOG_ERROR, _("sqlite3_bind_text \"%s\", (%s)\n"),  sqlite3_sql(iter->stmt), err_msg);
01055         free(iter);
01056         return  WATCH_DATABASE_ERROR_CANNOT_QUERY;
01057     }
01058 
01059     *iter_arg = (struct database_iter_context_t *)iter;
01060     return SUCCESS;
01061 }

int database_query_backups_iter ( struct database_iter_context_t **  iter_arg  ) 

Get an iterator to every lwatch_path_info_t row in the database which is a backup to a primary file.

Parameters:
[out] iter_arg Iterator context returned here, NULL if failure
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1070 of file watch_database.c.

Referenced by validate_backups_in_database().

01071 {
01072     int error;
01073     struct path_info_iter_context_t *iter;
01074 
01075     *iter_arg = NULL;
01076     if ((error = new_path_info_iter_context(&iter)) != SUCCESS) {
01077         log_msg(LOG_ERROR, _("cannot allocate new iteration context (%s)\n"), error_string(error));
01078         return error;
01079     }
01080 
01081     iter->stmt = query_backups_stmt;
01082 
01083     if ((iter->iter.error = reset_statement(iter->stmt)) != SQLITE_OK) {
01084         free(iter);
01085         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
01086     }
01087 
01088     *iter_arg = (struct database_iter_context_t *)iter;
01089     return SUCCESS;
01090 }

int database_query_backups_of_target_iter ( struct database_iter_context_t **  iter_arg,
const char *  path 
)

Get an iterator to each lwatch_path_info_t row in the database which is a backup to the specified primary file.

Parameters:
[out] iter_arg Iterator context returned here, NULL if failure
[in] path The path name of the primary file whose backup's are sought
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1100 of file watch_database.c.

Referenced by dump_database().

01101 {
01102     int error;
01103     struct path_info_iter_context_t *iter;
01104 
01105     *iter_arg = NULL;
01106     if ((error = new_path_info_iter_context(&iter)) != SUCCESS) {
01107         log_msg(LOG_ERROR, _("cannot allocate new iteration context (%s)\n"), error_string(error));
01108         return error;
01109     }
01110 
01111     iter->stmt = query_backups_of_target_stmt;
01112 
01113     if ((iter->iter.error = reset_statement(iter->stmt)) != SQLITE_OK) {
01114         free(iter);
01115         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
01116     }
01117 
01118     if ((iter->iter.error = sqlite3_bind_text(iter->stmt, 1, path, -1, SQLITE_TRANSIENT)) != SQLITE_OK) {
01119         const char *err_msg = sqlite3_errmsg(database_handle);
01120         log_msg(LOG_ERROR, _("sqlite3_bind_text \"%s\", (%s)\n"),  sqlite3_sql(iter->stmt), err_msg);
01121         free(iter);
01122         return  WATCH_DATABASE_ERROR_CANNOT_QUERY;
01123     }
01124 
01125     *iter_arg = (struct database_iter_context_t *)iter;
01126     return SUCCESS;
01127 }

int database_query_pending_reaps_iter ( struct database_iter_context_t **  iter_arg  ) 

Get an iterator to every lwatch_path_info_t row which has a reap pending.

Parameters:
[out] iter_arg Iterator context returned here, NULL if failure
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1135 of file watch_database.c.

Referenced by process_pending_reaps().

01136 {
01137     int error;
01138     struct path_info_iter_context_t *iter;
01139 
01140     *iter_arg = NULL;
01141     if ((error = new_path_info_iter_context(&iter)) != SUCCESS) {
01142         log_msg(LOG_ERROR, _("cannot allocate new iteration context (%s)\n"), error_string(error));
01143         return error;
01144     }
01145 
01146     iter->stmt = query_pending_reaps_stmt;
01147 
01148     if ((iter->iter.error = reset_statement(iter->stmt)) != SQLITE_OK) {
01149         free(iter);
01150         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
01151     }
01152 
01153     *iter_arg = (struct database_iter_context_t *)iter;
01154     return SUCCESS;
01155 }

int database_query_targets_iter ( struct database_iter_context_t **  iter_arg  ) 

Get an iterator to every lwatch_path_info_t row which is a primary watch file, i.e.

a "target".

Parameters:
[out] iter_arg Iterator context returned here, NULL if failure
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 1164 of file watch_database.c.

01165 {
01166     int error;
01167     struct path_info_iter_context_t *iter;
01168 
01169     *iter_arg = NULL;
01170     if ((error = new_path_info_iter_context(&iter)) != SUCCESS) {
01171         log_msg(LOG_ERROR, _("cannot allocate new iteration context (%s)\n"), error_string(error));
01172         return error;
01173     }
01174 
01175     iter->stmt = query_targets_stmt;
01176 
01177     if ((iter->iter.error = reset_statement(iter->stmt)) != SQLITE_OK) {
01178         free(iter);
01179         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
01180     }
01181 
01182     *iter_arg = (struct database_iter_context_t *)iter;
01183     return SUCCESS;
01184 }

int database_write_path_info ( struct lwatch_path_info_t path_info  ) 

Write the supplied lwatch_path_info_t struct into the database.

Parameters:
[in] path_info The lwatch_path_info_t to write into the database
Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 523 of file watch_database.c.

Referenced by get_create_path_info(), process_file_close(), process_file_delete(), process_file_modification(), process_file_rename(), reap_file_data(), start_monitoring(), update_stat_info_and_write(), and validate_backups_in_database().

00524 {
00525     int error, result, step_result;
00526 
00527     result = SUCCESS;
00528 
00529     if ((error = reset_statement(insert_path_stmt)) != SUCCESS) {
00530         result = WATCH_DATABASE_ERROR_CANNOT_QUERY;
00531         goto exit;
00532     }
00533 
00534 
00535     if ((error = sqlite3_bind_text(insert_path_stmt,  PATH_COLUMN + 1,              path_info->path,          -1, SQLITE_TRANSIENT))
00536         != SQLITE_OK) goto bind_error;
00537     if ((error = sqlite3_bind_text(insert_path_stmt,  ORIGINAL_PATH_COLUMN + 1,     path_info->original_path, -1, SQLITE_TRANSIENT))
00538         != SQLITE_OK) goto bind_error;
00539     if ((error = sqlite3_bind_int64(insert_path_stmt, FLAGS_COLUMN + 1,             path_info->flags))
00540         != SQLITE_OK) goto bind_error;
00541     if ((error = sqlite3_bind_int64(insert_path_stmt, VERSION_COLUMN + 1,           path_info->version))
00542         != SQLITE_OK) goto bind_error;
00543     if ((error = sqlite3_bind_int64(insert_path_stmt, REAP_TIME_COLUMN + 1,         path_info->reap_time))
00544         != SQLITE_OK) goto bind_error;
00545     if ((error = sqlite3_bind_int64(insert_path_stmt, REAP_POSITION_COLUMN + 1,     path_info->reap_position))
00546         != SQLITE_OK) goto bind_error;
00547     if ((error = sqlite3_bind_int64(insert_path_stmt, DEV_COLUMN + 1,               path_info->dev))
00548         != SQLITE_OK) goto bind_error;
00549     if ((error = sqlite3_bind_int64(insert_path_stmt, INODE_COLUMN + 1,             path_info->inode))
00550         != SQLITE_OK) goto bind_error;
00551     if ((error = sqlite3_bind_int64(insert_path_stmt, MODE_COLUMN + 1,              path_info->mode))
00552         != SQLITE_OK) goto bind_error;
00553     if ((error = sqlite3_bind_int64(insert_path_stmt, UID_COLUMN + 1,               path_info->uid))
00554         != SQLITE_OK) goto bind_error;
00555     if ((error = sqlite3_bind_int64(insert_path_stmt, GID_COLUMN + 1,               path_info->gid))
00556         != SQLITE_OK) goto bind_error;
00557     if ((error = sqlite3_bind_int64(insert_path_stmt, SIZE_COLUMN + 1,              path_info->size))
00558         != SQLITE_OK) goto bind_error;
00559     if ((error = sqlite3_bind_int64(insert_path_stmt, ACCESS_TIME_COLUMN + 1,       path_info->access_time))
00560         != SQLITE_OK) goto bind_error;
00561     if ((error = sqlite3_bind_int64(insert_path_stmt, MODIFICATION_TIME_COLUMN + 1, path_info->modification_time))
00562         != SQLITE_OK) goto bind_error;
00563     if ((error = sqlite3_bind_int64(insert_path_stmt, CHANGE_TIME_COLUMN + 1,       path_info->change_time))
00564         != SQLITE_OK) goto bind_error;
00565 
00566     if ((step_result = sqlite3_step(insert_path_stmt)) != SQLITE_DONE) {
00567         const char *err_msg = sqlite3_errmsg(database_handle);
00568         log_msg(LOG_ERROR, _("sqlite3_step \"%s\", unexpected result %s (%s)\n"),
00569                 sqlite3_sql(insert_path_stmt), sqlite3_result_string(step_result), err_msg);
00570         result =  WATCH_DATABASE_ERROR_CANNOT_INSERT;
00571         goto exit;
00572     }
00573 
00574  exit:
00575     return result;
00576 
00577  bind_error: {
00578         const char *err_msg = sqlite3_errmsg(database_handle);
00579         log_msg(LOG_ERROR, _("sqlite3_bind_text \"%s\", (%s)\n"),  sqlite3_sql(insert_path_stmt), err_msg);
00580         result = WATCH_DATABASE_ERROR_CANNOT_QUERY;
00581         return result;
00582     }
00583 }

int init_path_info ( struct lwatch_path_info_t path_info,
const char *  path 
)

Initialize a lwatch_path_info_t struct.

Parameters:
[in] path_info The lwatch_path_info_t to initialize
[in] path The path name bound to the lwatch_path_info_t
Returns:
SUCCESS (0) or non-zero error code otherwise
  • Zero the lwatch_path_info_t struct.
  • Copy the supplied path into the struct.
  • Set the flag indicating the version needs to be incremented.

Definition at line 596 of file watch_database.c.

Referenced by get_create_path_info(), and new_path_info().

00597 {
00598     int error;
00599 
00600     memset(path_info, 0, sizeof(struct lwatch_path_info_t));
00601 
00602     if (path) {
00603         if ((error = copy_path(path_info->path, path, sizeof(path_info->path))) != SUCCESS) {
00604             log_msg(LOG_ERROR, _("failed to copy path \"%s\" (%s)\n"), path, error_string(error));
00605             return error;
00606         }
00607     }
00608 
00609     path_info->flags = INC_VERSION_FLAG;
00610     return SUCCESS;
00611 }

int new_path_info ( const char *  path,
struct lwatch_path_info_t **  path_info_arg 
)

Allocate and initialize a new lwatch_path_info_t struct.

Parameters:
[in] path The path name which will be bound to the lwatch_path_info_t
[in] path_info_arg Pointer to variable to receive pointer to new path_info
Returns:
SUCCESS (0) or non-zero error code otherwise
See also:
init_path_info() for information about how the path_info is initialized.

Definition at line 622 of file watch_database.c.

00623 {
00624     int error;
00625     struct lwatch_path_info_t *path_info;
00626 
00627     if ((path_info = malloc(sizeof(struct lwatch_path_info_t))) == NULL) {
00628         return ENOMEM;
00629     }
00630 
00631     if ((error = init_path_info(path_info, path)) != SUCCESS) {
00632         log_msg(LOG_ERROR, _("could not initialize path_info for path \"%s\" (%s)\n"),
00633                 path, error_string(error));
00634         free(path_info);
00635         return error;
00636     }
00637 
00638     *path_info_arg = path_info;
00639     return SUCCESS;
00640 }

char* path_info_flags_string ( unsigned long  flag,
const char *  separator 
)

Render the lwatch_path_info_t flag bitset as a string.

Parameters:
[in] flag The bitset whose boolean flags will be converted to strings
[in] separator The string used to separate adjacent flags
Returns:
Pointer to thread local static string
For each boolean flag in the bitset which is enabled output it's name as a string. Join adjacent flag names with the separator parameter.

Definition at line 652 of file watch_database.c.

Referenced by path_info_string().

00653 {
00654     static __thread char buf[1024]; /* thread local static buffer */
00655     char *p, *buf_end;
00656     int separator_len;
00657     unsigned int unknown;
00658 
00659     p = buf;                     /* current position in buffer */
00660     buf_end = &buf[sizeof(buf)]; /* non-inclusive end of buffer */
00661     separator_len = strlen(separator);
00662     *p = 0;
00663 
00664     /* validate there is nothing in the event mask we don't know about */
00665     unknown = flag & ~(TARGET_FLAG | BACKUP_FLAG | NEEDS_REAPING_FLAG |
00666                        STAT_DATA_VALID_FLAG | INC_VERSION_FLAG);
00667 
00668     if (unknown) p += snprintf(p, buf_end - p, "unknown bits=0x%x%s", unknown, separator);
00669     if (p >= buf_end) goto fail;
00670 
00671     if (flag & TARGET_FLAG)          p += snprintf(p, buf_end - p, "TARGET%s",          separator);
00672     if (p >= buf_end) goto fail;
00673     if (flag & BACKUP_FLAG)          p += snprintf(p, buf_end - p, "BACKUP%s",          separator);
00674     if (p >= buf_end) goto fail;
00675     if (flag & NEEDS_REAPING_FLAG)   p += snprintf(p, buf_end - p, "NEEDS_REAPING%s",   separator);
00676     if (p >= buf_end) goto fail;
00677     if (flag & STAT_DATA_VALID_FLAG) p += snprintf(p, buf_end - p, "STAT_DATA_VALID%s", separator);
00678     if (p >= buf_end) goto fail;
00679     if (flag & INC_VERSION_FLAG)     p += snprintf(p, buf_end - p, "INC_VERSION%s",     separator);
00680     if (p >= buf_end) goto fail;
00681 
00682     if (p > buf) p[-separator_len] = 0; /* nuke trailing separator */
00683 
00684     return buf;
00685 
00686  fail:
00687     /* exhausted the buffer; NULL terminate then return truncated string */
00688     buf_end[-1] = 0;   /* should already be NULL terminated, but be safe */
00689     return buf;
00690 }

char* path_info_string ( struct lwatch_path_info_t path_info,
const char *  prefix 
)

Render a lwatch_path_info_t struct as a string.

Parameters:
[in] path_info The lwatch_path_info_t struct to convert to a string
[in] prefix String prepended to each line in the output
Returns:
Pointer to thread local static string
The output is muli-line due to the complexity of the struct. Each line in the result will have the prefix parameter prepended to the line.

Definition at line 702 of file watch_database.c.

Referenced by dump_database().

00703 {
00704     static __thread char buf[1024]; /* thread local static buffer */
00705     const char *indent = "    ";
00706     char prefix_indent[128];
00707     char *p, *buf_end;
00708     char *uid_name, *gid_name;
00709 
00710     strncpy(prefix_indent, prefix, sizeof(prefix_indent));
00711     prefix_indent[sizeof(prefix_indent) - 1] = 0;
00712     strncat(prefix_indent, indent, sizeof(prefix_indent) - 1);
00713 
00714     get_uid_name(path_info->uid, &uid_name);
00715     get_gid_name(path_info->gid, &gid_name);
00716 
00717 
00718     p = buf;                     /* current position in buffer */
00719     buf_end = &buf[sizeof(buf)]; /* non-inclusive end of buffer */
00720     *p = 0;
00721 
00722     p += snprintf(p, buf_end - p, "%spath: %s\n",
00723                   prefix, path_info->path);
00724     if (p >= buf_end) goto fail;
00725 
00726     if (path_info->original_path[0]) {
00727         p += snprintf(p, buf_end - p, "%soriginal path:     %s\n",
00728                       prefix_indent,
00729                       path_info->original_path);
00730         if (p >= buf_end) goto fail;
00731     }
00732 
00733     p += snprintf(p, buf_end - p, "%sflags:             [%s]\n",
00734                   prefix_indent,
00735                   path_info_flags_string(path_info->flags, ","));
00736     if (p >= buf_end) goto fail;
00737 
00738     p += snprintf(p, buf_end - p, "%sversion:           %lu\n",
00739                   prefix_indent,
00740                   path_info->version);
00741     if (p >= buf_end) goto fail;
00742 
00743     p += snprintf(p, buf_end - p, "%sreap_time:         %s (%ld)\n",
00744                   prefix_indent,
00745                   time_string(path_info->reap_time, true, NULL),
00746                   path_info->reap_time);
00747     if (p >= buf_end) goto fail;
00748 
00749     p += snprintf(p, buf_end - p, "%sreap_position:     %ld\n",
00750                   prefix_indent,
00751                   path_info->reap_position);
00752     if (p >= buf_end) goto fail;
00753 
00754     if (path_info->flags & STAT_DATA_VALID_FLAG) {
00755         p += snprintf(p, buf_end - p, "%sdev:               %llu\n",
00756                       prefix_indent,
00757                       path_info->dev);
00758         if (p >= buf_end) goto fail;
00759 
00760         p += snprintf(p, buf_end - p, "%sinode:             %lu\n",
00761                       prefix_indent,
00762                       path_info->inode);
00763         if (p >= buf_end) goto fail;
00764 
00765         p += snprintf(p, buf_end - p, "%smode:              %s (%#o)\n",
00766                       prefix_indent,
00767                       file_mode_string(path_info->mode),
00768                       path_info->mode);
00769         if (p >= buf_end) goto fail;
00770 
00771         p += snprintf(p, buf_end - p, "%suid:gid:           %s:%s (%u:%u)\n",
00772                       prefix_indent,
00773                       uid_name, gid_name,
00774                       path_info->uid, path_info->gid);
00775         if (p >= buf_end) goto fail;
00776 
00777         p += snprintf(p, buf_end - p, "%ssize:              %ld\n",
00778                       prefix_indent,
00779                       path_info->size);
00780         if (p >= buf_end) goto fail;
00781 
00782         p += snprintf(p, buf_end - p, "%saccess_time:       %s (%ld)\n",
00783                       prefix_indent,
00784                       time_string(path_info->access_time, true, NULL),
00785                       path_info->access_time);
00786         if (p >= buf_end) goto fail;
00787 
00788         p += snprintf(p, buf_end - p, "%smodification time: %s (%ld)\n",
00789                       prefix_indent,
00790                       time_string(path_info->modification_time, true, NULL),
00791                       path_info->modification_time);
00792         if (p >= buf_end) goto fail;
00793 
00794         p += snprintf(p, buf_end - p, "%schange_time:       %s (%ld)\n",
00795                       prefix_indent,
00796                       time_string(path_info->change_time, true, NULL),
00797                       path_info->change_time);
00798         if (p >= buf_end) goto fail;
00799     }
00800 
00801 
00802     free(uid_name);
00803     free(gid_name);
00804     return buf;
00805 
00806  fail:
00807     /* exhausted the buffer; NULL terminate then return truncated string */
00808     buf_end[-1] = 0;   /* should already be NULL terminated, but be safe */
00809     free(uid_name);
00810     free(gid_name);
00811     return buf;
00812 }

const char* watch_database_error_string ( int  error  ) 

Render a database error code as a string.

Parameters:
[in] error The database error code to convert to a string
Returns:
Pointer to thread local static string containing error description

Definition at line 820 of file watch_database.c.

Referenced by error_string().

00821 {
00822     static __thread char buf[80]; /* thread local static buffer */
00823 
00824     switch(error) {
00825     case SUCCESS:                                  return _("success");
00826     case WATCH_DATABASE_ERROR_CANNOT_OPEN:         return _("could not open database");
00827     case WATCH_DATABASE_ERROR_CANNOT_CLOSE:        return _("could not close database");
00828     case WATCH_DATABASE_ERROR_CANNOT_QUERY:        return _("database query failed");
00829     case WATCH_DATABASE_ERROR_CANNOT_CREATE_TABLE: return _("cannot create table");
00830     case WATCH_DATABASE_ERROR_CANNOT_INSERT:       return _("cannot insert record into table");
00831     case WATCH_DATABASE_ERROR_NOT_FOUND:           return _("entry not found");
00832     case WATCH_DATABASE_ERROR_FOUND_MULTIPLE:      return _("found multiple entries, expecting single entry");
00833     default:
00834         snprintf(buf, sizeof(buf), _("unknown(%d)"), error);
00835         return buf;
00836     }
00837 }

int watch_database_fini ( void   ) 

Close the watch database subsystem, release all resources, close database.

Returns:
SUCCESS (0) or non-zero error code otherwise

Definition at line 935 of file watch_database.c.

Referenced by main().

00936 {
00937     int error;
00938 
00939     destroy_statement(&table_exists_stmt);
00940     destroy_statement(&lookup_path_stmt);
00941     destroy_statement(&insert_path_stmt);
00942     destroy_statement(&query_all_stmt);
00943     destroy_statement(&query_backups_stmt);
00944     destroy_statement(&query_backups_of_target_stmt);
00945     destroy_statement(&query_pending_reaps_stmt);
00946     destroy_statement(&query_targets_stmt);
00947 
00948     if ((error = sqlite3_close(database_handle)) != SQLITE_OK) {
00949         const char *err_msg = sqlite3_errmsg(database_handle);
00950         log_msg(LOG_ERROR, _("could not close database file \"%s\", (%s)\n"),  watch_database_pathname, err_msg);
00951         database_handle = NULL;
00952         return WATCH_DATABASE_ERROR_CANNOT_CLOSE;
00953     }
00954     database_handle = NULL;
00955     return SUCCESS;
00956 }

int watch_database_init ( void   ) 

Initialize the watch database subsystem.

Returns:
SUCCESS (0) or non-zero error code otherwise
Initialization consists of:
  • Initializing the SQLite subsystem, opening the database
  • Validating our tables exist, if not create each table
  • Create & initialize all our prepared SQL statements (prepared statements are more efficient)

Definition at line 850 of file watch_database.c.

Referenced by main().

00851 {
00852     int error;
00853     bool exists;
00854 
00855     if ((error = sqlite3_open(watch_database_pathname, &database_handle)) != SQLITE_OK) {
00856         const char *err_msg = sqlite3_errmsg(database_handle);
00857         log_msg(LOG_ERROR, _("could not open database file \"%s\", (%s)\n"),watch_database_pathname, err_msg);
00858         sqlite3_close(database_handle);
00859         database_handle = NULL;
00860         return WATCH_DATABASE_ERROR_CANNOT_OPEN;
00861     }
00862 
00863     /* Create prepared SQL statements for master table */
00864     if ((error = init_statement(&table_exists_stmt,
00865                                 "SELECT name FROM sqlite_master WHERE type='table' AND name=?1;")) != SUCCESS) {
00866         return error;
00867     }
00868 
00869     /* Assure our table exists, if not create it */
00870     if ((error = table_exists(LWATCH_TABLE_NAME, &exists)) != SUCCESS) {
00871         log_msg(LOG_ERROR, _("table_exists failed \"%s\" (%s)\n"),  LWATCH_TABLE_NAME, error_string(error));
00872         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00873     }
00874 
00875     if (!exists) {
00876         if ((error = create_table(LWATCH_TABLE_NAME, lwatch_table_schema)) != SUCCESS) {
00877             log_msg(LOG_ERROR, _("\"%s\" table does not exist, but failed to create (%s)\n"),
00878                     LWATCH_TABLE_NAME, error_string(error));
00879             return error;
00880         }
00881     }
00882 
00883     /* Create prepared SQL statements for our table */
00884     if ((error = init_statement(&lookup_path_stmt,
00885                                 "SELECT %s FROM \"%s\" WHERE path=?1;",
00886                                 COLUMNS_STRING, LWATCH_TABLE_NAME)) != SUCCESS) {
00887         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00888     }
00889 
00890     if ((error = init_statement(&insert_path_stmt,
00891                                 "INSERT OR REPLACE INTO \"%s\" (%s) VALUES "
00892                                 "(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15);",
00893                                 LWATCH_TABLE_NAME, COLUMNS_STRING)) != SUCCESS) {
00894         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00895     }
00896 
00897     if ((error = init_statement(&query_all_stmt,
00898                                 "SELECT %s FROM \"%s\" where path like ?1;",
00899                                 COLUMNS_STRING, LWATCH_TABLE_NAME)) != SUCCESS) {
00900         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00901     }
00902 
00903     if ((error = init_statement(&query_backups_stmt,
00904                                 "SELECT %s FROM \"%s\" where flags & %d;",
00905                                 COLUMNS_STRING, LWATCH_TABLE_NAME, BACKUP_FLAG)) != SUCCESS) {
00906         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00907     }
00908 
00909     if ((error = init_statement(&query_backups_of_target_stmt,
00910                                 "SELECT %s FROM \"%s\" where flags & %d AND original_path == ?1;",
00911                                 COLUMNS_STRING, LWATCH_TABLE_NAME, BACKUP_FLAG)) != SUCCESS) {
00912         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00913     }
00914 
00915     if ((error = init_statement(&query_pending_reaps_stmt,
00916                                 "SELECT %s FROM \"%s\" where flags & %d;",
00917                                 COLUMNS_STRING, LWATCH_TABLE_NAME, NEEDS_REAPING_FLAG)) != SUCCESS) {
00918         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00919     }
00920 
00921     if ((error = init_statement(&query_targets_stmt,
00922                                 "SELECT %s FROM \"%s\" where flags & %d;",
00923                                 COLUMNS_STRING, LWATCH_TABLE_NAME, TARGET_FLAG)) != SUCCESS) {
00924         return WATCH_DATABASE_ERROR_CANNOT_QUERY;
00925     }
00926 
00927     return SUCCESS;
00928 }


Generated on Mon Aug 31 10:06:21 2009 by  doxygen 1.5.8