index_db.c

Go to the documentation of this file.
00001 /*
00002  * File Name: index_db.c
00003  */
00004 
00005 /*
00006  * This file is part of ctb.
00007  *
00008  * ctb is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * ctb is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2009 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #include "config.h"
00028 #include <unistd.h>
00029 #include <stdlib.h>
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 
00033 #include "log.h"
00034 #include "index_db.h"
00035 
00036 // maximum time to wait for a database transaction (seconds)
00037 #define MAX_WAIT_DATABASE (30)
00038 
00039 
00040 int db_open_global (db_state_t *db_state, const gchar *directory)
00041 {
00042     LOGPRINTF("entry: dir [%s]", directory);
00043     
00044     db_state->mdb = NULL;
00045     db_state->transaction_started = FALSE;
00046     db_state->values = NULL;
00047     db_state->db = NULL;
00048     db_state->num_rows = 0;
00049     db_state->num_cols = 0;
00050     db_state->row = 0;
00051 
00052     erMetadb db = ermetadb_global_open(directory, FALSE);
00053     if (db == NULL) {
00054         ERRORPRINTF("failed to open database in %s.", directory);
00055         return ER_FAIL;
00056     }
00057     
00058     db_state->mdb = db;
00059     return ER_OK;
00060 }
00061 
00062 
00063 void db_close (db_state_t *db_state)
00064 {
00065     LOGPRINTF("entry");
00066 
00067     if (db_state->mdb)
00068     {
00069         ermetadb_close(db_state->mdb);
00070         db_state->mdb = NULL;
00071     }
00072 }
00073 
00074 
00075 int db_start_transaction (db_state_t *db_state)
00076 {
00077     int           ret = ER_OK;    // return code
00078     const time_t  start = time(NULL);
00079 
00080     LOGPRINTF("entry");
00081 
00082     if (db_state->mdb)
00083     {
00084         if (db_state->transaction_started)
00085             WARNPRINTF("transaction already started");
00086         ret = ermetadb_begin_transaction(db_state->mdb);
00087         if (ret == ERMETADB_DATABASE_BUSY)
00088         {
00089             // database locked, wait till database becomes available
00090             while ((ret == ERMETADB_DATABASE_BUSY) &&
00091                    (time(NULL) - start) <= MAX_WAIT_DATABASE )
00092             {
00093                 WARNPRINTF("database locked");
00094                 ret = ermetadb_begin_transaction(db_state->mdb);
00095             }
00096         }
00097     }
00098 
00099     db_state->transaction_started = TRUE;
00100 
00101     return ret;
00102 }
00103 
00104 // end a database transaction
00105 int db_end_transaction (db_state_t *db_state)
00106 {
00107     int  ret = ER_OK;    // return code
00108 
00109     LOGPRINTF("entry");
00110 
00111     if (db_state->transaction_started && db_state->mdb)
00112     {
00113         ret = ermetadb_end_transaction(db_state->mdb);
00114         db_state->transaction_started = FALSE;
00115     }
00116 
00117     return ret;
00118 }
00119 
00120 
00121 void db_update_entry(db_state_t *db_state, const db_entry_t* entry)
00122 {
00123     ermetadb_global_update_size(db_state->mdb, entry->file_id, entry->last_modified, entry->filesize);
00124 }
00125 
00126 
00127 void db_update_shortcut_entry(db_state_t *db_state, const db_entry_t* entry, const char* display_name, const char* author)
00128 {
00129     ermetadb_global_update_title(db_state->mdb, entry->file_id, display_name, author);
00130 }
00131 
00132 
00133 void db_add_entry(db_state_t *db_state, const db_entry_t* entry, const char* tag, const char* display_name, const char* author)
00134 {
00135     if (entry->is_dir) {
00136         ermetadb_global_add_folder(db_state->mdb,
00137                                    entry->filepath,
00138                                    entry->filename,
00139                                    entry->last_modified);
00140     } else {
00141         if (display_name == NULL) display_name = entry->filename;
00142         ermetadb_global_add_file(db_state->mdb,
00143                                  entry->filepath,
00144                                  entry->filename,
00145                                  entry->filesize,
00146                                  entry->last_modified,
00147                                  display_name,
00148                                  author,
00149                                  tag);
00150     }
00151 }
00152 
00153 
00154 int db_delete_entry(db_state_t *db_state, const db_entry_t *entry)
00155 {
00156     // NOTE: only need to delete entry itself, not subdirs/files
00157     return ermetadb_global_remove_entry(db_state->mdb,
00158                                         entry->file_id,
00159                                         entry->filepath,
00160                                         entry->filename,
00161                                         entry->is_dir);
00162 }
00163 
00164 
00165 static db_entry_t* row2entry(const metadata_cell *row)
00166 {
00167     // SQL result: file_id, filename, dirpath, isdir, size, date
00168     db_entry_t* entry = g_malloc(sizeof(db_entry_t));
00169     memset(entry, 0, sizeof(db_entry_t));
00170 
00171     const metadata_cell *cell = row;
00172     gint64 file_id = cell->value.v_int64;
00173     entry->file_id = file_id;
00174 
00175     cell++;
00176     char* filename = cell->value.v_text->str;
00177     entry->filename = filename;
00178 
00179     cell++;
00180     char* filepath = cell->value.v_text->str;
00181     entry->filepath = filepath;
00182 
00183     cell++;
00184     gboolean is_dir = cell->value.v_int64;
00185     entry->is_dir = is_dir;
00186 
00187     cell++;
00188     gint64 size = cell->value.v_int64;
00189     entry->filesize = size;
00190 
00191     cell++;
00192     gint64 filedate = cell->value.v_int64;
00193     entry->last_modified = filedate;
00194 
00195     return entry;
00196 }
00197 
00198 
00199 GSList* db_get_model(const gchar* dir)
00200 {
00201     db_state_t db_state;
00202     GSList* model = 0;
00203 
00204     if (db_open_global(&db_state, dir) != ER_OK) {
00205         ERRORPRINTF("error opening db");
00206         return NULL;
00207     }
00208 
00209     metadata_table *values = NULL;
00210 
00211     int ret = ermetadb_global_select_all(db_state.mdb, &values);
00212     if (ret != ER_OK) {
00213         ERRORPRINTF("error [%d]", ret);
00214         goto out;
00215     }
00216 
00217     int n_rows = metadata_table_n_rows(values);
00218     int n_cols = metadata_table_n_columns(values);
00219 
00220     const metadata_cell *row = (const metadata_cell*) (values->cell_data->data);
00221     for (int i=0; i<n_rows; i++) {
00222         db_entry_t* entry = row2entry(row);
00223         model = g_slist_prepend(model, entry);
00224         row += n_cols; 
00225     }
00226 
00227     model = g_slist_reverse(model);
00228     
00229     // DONT FREE, strings are used
00230     //metadata_table_free(values);
00231 out:
00232     db_close(&db_state);
00233     return model;
00234 }
00235 
Generated by  doxygen 1.6.2-20100208