summaryrefslogtreecommitdiff
path: root/src/analysis/db
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-10-16 22:04:29 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-10-16 22:04:29 (GMT)
commit6d34dbbb00da0c276261d0e1ce4bf862f22fd8e0 (patch)
treea5d3c8644691934ba84a91919f7db177f70743f1 /src/analysis/db
parente75f44a99c8f984af4c47fa9a2c8e7e9841700d8 (diff)
Stored a bookmark into the data base and saved the archive.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@414 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/analysis/db')
-rw-r--r--src/analysis/db/cdb.c47
-rw-r--r--src/analysis/db/cdb.h2
-rw-r--r--src/analysis/db/client.c43
-rw-r--r--src/analysis/db/client.h3
-rw-r--r--src/analysis/db/collection.c162
-rw-r--r--src/analysis/db/collection.h6
-rw-r--r--src/analysis/db/item-int.h10
-rw-r--r--src/analysis/db/item.c93
-rw-r--r--src/analysis/db/item.h18
-rw-r--r--src/analysis/db/items/bookmark.c61
-rw-r--r--src/analysis/db/items/bookmark.h2
-rw-r--r--src/analysis/db/protocol.h27
12 files changed, 442 insertions, 32 deletions
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 563aa40..55d1b2d 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -34,7 +34,6 @@
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
-#include <sqlite3.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
@@ -283,6 +282,8 @@ GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const
result->filename = get_xdg_config_dir(suffix);
+ printf("dealing with '%s'...\n", result->filename);
+
free(suffix);
if (!mkpath(result->filename))
@@ -318,7 +319,7 @@ GCdbArchive *g_cdb_archive_new(const char *owner, const rle_string *hash, const
g_cdb_archive_create_xml_desc(result, user);
g_cdb_archive_create_db(result, NULL);
- if (!g_cdb_archive_write(result))
+ if (g_cdb_archive_write(result) != DBE_NONE)
goto gcan_error;
}
@@ -473,13 +474,13 @@ static bool g_cdb_archive_read(GCdbArchive *archive)
* *
******************************************************************************/
-bool g_cdb_archive_write(const GCdbArchive *archive)
+DBError g_cdb_archive_write(const GCdbArchive *archive)
{
- bool result; /* Conclusion à retourner */
+ DBError result; /* Conclusion à retourner */
struct archive *out; /* Archive à constituer */
int ret; /* Bilan d'un appel */
- result = false;
+ result = DBE_ARCHIVE_ERROR;
out = archive_write_new();
archive_write_add_filter_xz(out);
@@ -488,16 +489,19 @@ bool g_cdb_archive_write(const GCdbArchive *archive)
ret = archive_write_open_filename(out, archive->filename);
if (ret != ARCHIVE_OK) goto gcaw_exit;
- bool add_file_to_archive(struct archive *out, const char *src, const char *path)
+ DBError add_file_to_archive(struct archive *out, const char *src, const char *path)
{
+ DBError status; /* Bilan à renvoyer */
struct stat info; /* Informations d'origine */
struct archive_entry *entry; /* Elément de l'archive */
int fd; /* Flux ouvert en lecture */
char buffer[ARCHIVE_RBUF_SIZE]; /* Tampon pour les transferts */
ssize_t len; /* Quantité de données lues */
+ status = DBE_ARCHIVE_ERROR;
+
ret = stat(src, &info);
- if (ret != 0) return false;
+ if (ret != 0) return DBE_SYS_ERROR;
entry = archive_entry_new();
@@ -508,7 +512,11 @@ bool g_cdb_archive_write(const GCdbArchive *archive)
if (ret != 0) goto afta_error;
fd = open(src, O_RDONLY);
- if (fd == -1) goto afta_error;
+ if (fd == -1)
+ {
+ status = DBE_SYS_ERROR;
+ goto afta_error;
+ }
for (len = safe_read(fd, buffer, ARCHIVE_RBUF_SIZE);
len > 0;
@@ -522,18 +530,20 @@ bool g_cdb_archive_write(const GCdbArchive *archive)
archive_entry_free(entry);
- return true;
+ return DBE_NONE;
afta_error:
archive_entry_free(entry);
- return false;
+ return status;
}
result = add_file_to_archive(out, archive->xml_desc, "desc.xml");
- result &= add_file_to_archive(out, archive->sql_db, "sql.db");
+
+ if (result == DBE_NONE)
+ result = add_file_to_archive(out, archive->sql_db, "sql.db");
gcaw_exit:
@@ -781,6 +791,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
uint32_t val32; /* Valeur sur 32 bits */
bool status; /* Bilan de lecture initiale */
uint32_t command; /* Commande de la requête */
+ DBError error; /* Bilan d'une opération */
GDbCollection *collec; /* Collection visée au final */
void interrupt_poll_with_sigusr1(int sig) { };
@@ -843,6 +854,18 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
switch (command)
{
+ case DBC_SAVE:
+
+ error = g_cdb_archive_write(archive);
+
+ if (!safe_send(fds[i].fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t), 0))
+ goto gcap_bad_exchange;
+
+ if (!safe_send(fds[i].fd, (uint32_t []) { htobe32(error) }, sizeof(uint32_t), 0))
+ goto gcap_bad_exchange;
+
+ break;
+
case DBC_COLLECTION:
status = safe_recv(fds[i].fd, &val32, sizeof(uint32_t), 0);
@@ -851,7 +874,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
collec = find_collection_in_list(archive->collections, be32toh(val32));
if (collec == NULL) goto gcap_bad_exchange;
- status = g_db_collection_recv(collec, fds[i].fd);
+ status = g_db_collection_recv(collec, fds[i].fd, archive->db);
if (!status) goto gcap_bad_exchange;
printf("## CDB ## Got something for collection %p...\n", collec);
diff --git a/src/analysis/db/cdb.h b/src/analysis/db/cdb.h
index 17327f5..e9abb02 100644
--- a/src/analysis/db/cdb.h
+++ b/src/analysis/db/cdb.h
@@ -60,7 +60,7 @@ GType g_cdb_archive_get_type(void);
GCdbArchive *g_cdb_archive_new(const char *, const rle_string *, const rle_string *, DBError *);
/* Enregistre une archive avec tous les éléments à conserver. */
-bool g_cdb_archive_write(const GCdbArchive *);
+DBError g_cdb_archive_write(const GCdbArchive *);
/* Détermine si une empreinte correspond à celle d'une archive. */
int g_cdb_archive_compare_hash(const GCdbArchive *, const rle_string *);
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c
index 4b807ae..71df99c 100644
--- a/src/analysis/db/client.c
+++ b/src/analysis/db/client.c
@@ -328,6 +328,7 @@ static void *g_db_client_update(GDbClient *client)
uint32_t val32; /* Valeur sur 32 bits */
bool status; /* Bilan d'une opération */
uint32_t command; /* Commande de la requête */
+ DBError error; /* Bilan d'une commande passée */
GDbCollection *collec; /* Collection visée au final */
fds.fd = client->fd;
@@ -353,6 +354,19 @@ static void *g_db_client_update(GDbClient *client)
switch (command)
{
+ case DBC_SAVE:
+
+ status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0);
+ if (!status) goto gdcu_bad_exchange;
+
+ error = be32toh(val32);
+
+ printf("## CLIENT ## Saved ? %d\n", error);
+
+
+
+ break;
+
case DBC_COLLECTION:
status = safe_recv(fds.fd, &val32, sizeof(uint32_t), 0);
@@ -361,7 +375,7 @@ static void *g_db_client_update(GDbClient *client)
collec = find_collection_in_list(client->collections, be32toh(val32));
if (collec == NULL) goto gdcu_bad_exchange;
- status = g_db_collection_recv(collec, fds.fd);
+ status = g_db_collection_recv(collec, fds.fd, NULL);
if (!status) goto gdcu_bad_exchange;
@@ -459,3 +473,30 @@ void g_db_client_put_fd(GDbClient *client)
g_mutex_unlock(&client->sending_lock);
}
+
+
+/******************************************************************************
+* *
+* Paramètres : client = client pour les accès distants à manipuler. *
+* *
+* Description : Effectue une demande de sauvegarde de l'état courant. *
+* *
+* Retour : true si la commande a bien été envoyée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_client_save(GDbClient *client)
+{
+ bool result; /* Bilan partiel à remonter */
+
+ g_db_client_get_fd(client);
+
+ result = safe_send(client->fd, (uint32_t []) { htobe32(DBC_SAVE) }, sizeof(uint32_t), 0);
+
+ g_db_client_put_fd(client);
+
+ return result;
+
+}
diff --git a/src/analysis/db/client.h b/src/analysis/db/client.h
index a1a9f8e..963744b 100644
--- a/src/analysis/db/client.h
+++ b/src/analysis/db/client.h
@@ -65,6 +65,9 @@ int g_db_client_get_fd(GDbClient *);
/* Marque le canal de communication comme disponible. */
void g_db_client_put_fd(GDbClient *);
+/* Effectue une demande de sauvegarde de l'état courant. */
+bool g_db_client_save(GDbClient *);
+
#endif /* _ANALYSIS_DB_CLIENT_H */
diff --git a/src/analysis/db/collection.c b/src/analysis/db/collection.c
index 20b1ff3..5c25720 100644
--- a/src/analysis/db/collection.c
+++ b/src/analysis/db/collection.c
@@ -24,6 +24,11 @@
#include "collection.h"
+#include <stdio.h>
+#include <string.h>
+
+
+#include "../../common/extstr.h"
#include "../../common/io.h"
#include "../../glibext/chrysamarshal.h"
@@ -36,6 +41,7 @@ struct _GDbCollection
uint32_t featuring; /* Fonctionnalité représentée */
GType type; /* Identifiant GLib équivalent */
+ const char *name; /* Nom en base de données */
GList *items; /* Eléments rassemblés */
GList *sorted; /* Eléments triés */
@@ -71,6 +77,15 @@ static void g_db_collection_finalize(GDbCollection *);
+/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */
+
+
+/* Enregistre un élément de collection dans une base de données. */
+static bool g_db_collection_store_item(const GDbCollection *, const GDbItem *, sqlite3 *);
+
+
+
+
/* Indique le type défini pour une collection générique d'éléments. */
G_DEFINE_TYPE(GDbCollection, g_db_collection, G_TYPE_OBJECT);
@@ -170,7 +185,8 @@ static void g_db_collection_finalize(GDbCollection *collec)
/******************************************************************************
* *
* Paramètres : id = identifiant réseau des éléments à traiter. *
-* type = type GLib des éléments à intégrer dans la collection. *
+* type = type GLib des éléments à placer dans la collection. *
+* name = indique le nom désignant la table associée. *
* *
* Description : Prépare la mise en place d'une nouvelle collection. *
* *
@@ -180,7 +196,7 @@ static void g_db_collection_finalize(GDbCollection *collec)
* *
******************************************************************************/
-GDbCollection *g_db_collection_new(uint32_t id, GType type)
+GDbCollection *g_db_collection_new(uint32_t id, GType type, const char *name)
{
GDbCollection *result; /* Adresse à retourner */
@@ -188,6 +204,7 @@ GDbCollection *g_db_collection_new(uint32_t id, GType type)
result->featuring = id;
result->type = type;
+ result->name = name;
return result;
@@ -233,6 +250,7 @@ uint32_t g_db_collection_get_feature(const GDbCollection *collec)
* *
* Paramètres : collec = ensemble d'éléments à considérer. *
* fd = flux ouvert en lecture pour la réception de données.*
+* db = base de données à mettre à jour. *
* *
* Description : Réceptionne et traite une requête réseau pour collection. *
* *
@@ -244,7 +262,7 @@ uint32_t g_db_collection_get_feature(const GDbCollection *collec)
* *
******************************************************************************/
-bool g_db_collection_recv(GDbCollection *collec, int fd)
+bool g_db_collection_recv(GDbCollection *collec, int fd, sqlite3 *db)
{
bool result; /* Bilan à faire remonter */
uint32_t val32; /* Valeur sur 32 bits */
@@ -269,6 +287,8 @@ bool g_db_collection_recv(GDbCollection *collec, int fd)
{
case DBA_ADD_ITEM:
result = g_db_collection_add_item(collec, item);
+ if (result && db != NULL)
+ result = g_db_collection_store_item(collec, item, db);
break;
case DBA_REM_ITEM:
@@ -430,6 +450,10 @@ bool g_db_collection_add_item(GDbCollection *collec, GDbItem *item)
g_signal_emit_by_name(collec, "content-changed", DBA_ADD_ITEM, item);
+
+ printf(" ==== CONTENT CHANGED !!!\n");
+
+
result = true;
}
@@ -478,6 +502,138 @@ bool g_db_collection_modify_item(GDbCollection *collec, GDbItem *item)
/* ---------------------------------------------------------------------------------- */
/* CREATION DE L'ABSTRACTION POUR COLLECTIONS */
+/* MANIPULATIONS AVEC UNE BASE DE DONNEES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : collec = ensemble d'éléments à considérer. *
+* item = élément de collection à enregistrer. *
+* db = base de données à mettre à jour. *
+* *
+* Description : Enregistre un élément de collection dans une base de données.*
+* *
+* Retour : Bilan de l'exécution de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_collection_store_item(const GDbCollection *collec, const GDbItem *item, sqlite3 *db)
+{
+ bool result; /* Conclusion à faire remonter */
+ bound_value *values; /* Champs de table à inclure */
+ size_t count; /* Nombre de ces champs */
+ char *sql; /* Requête SQL à construire */
+ size_t i; /* Boucle de parcours */
+ sqlite3_stmt *stmt; /* Déclaration mise en place */
+ int ret; /* Bilan d'un appel à SQLite */
+ int index; /* Indice de valeur attachée */
+
+ if (!g_db_item_prepare_db_statement(item, true, &values, &count))
+ return false;
+
+ result = false;
+
+ /* Préparation de la requête */
+
+ sql = strdup("INSERT INTO ");
+ sql = stradd(sql, collec->name);
+ sql = stradd(sql, " (");
+
+ for (i = 0; i < count; i++)
+ {
+ if (i > 0) sql = stradd(sql, ", ");
+
+ sql = stradd(sql, values[i].name);
+
+ }
+
+ sql = stradd(sql, ") VALUES (");
+
+ for (i = 0; i < count; i++)
+ {
+ if (i > 0) sql = stradd(sql, ", ");
+
+ if (values[i].type == SQLITE_RAW)
+ sql = stradd(sql, values[i].cstring);
+ else
+ sql = stradd(sql, "?");
+
+ }
+
+ sql = stradd(sql, ");");
+
+ ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
+ if (ret != SQLITE_OK)
+ {
+ fprintf(stderr, "Can't prepare INSERT statment '%s' (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
+ goto gdcsi_exit;
+ }
+
+ /* Attribution des valeurs */
+
+ index = 1;
+
+ for (i = 0; i < count; i++)
+ {
+ switch (values[i].type)
+ {
+ case SQLITE_INT64:
+ ret = sqlite3_bind_int64(stmt, index, values[i].integer64);
+ index++;
+ break;
+
+ case SQLITE_TEXT:
+ ret = sqlite3_bind_text(stmt, index, values[i].string, -1, values[i].delete);
+ index++;
+ break;
+
+ default:
+ ret = SQLITE_OK;
+ break;
+
+ }
+
+ if (ret != SQLITE_OK)
+ {
+ fprintf(stderr, "Can't bind value for parameter nb %d in '%s' (ret=%d): %s\n",
+ index - 1, sql, ret, sqlite3_errmsg(db));
+ goto gdcsi_exit;
+ }
+
+ }
+
+ /* Exécution finale */
+
+ ret = sqlite3_step(stmt);
+
+ if (ret != SQLITE_DONE)
+ {
+ fprintf(stderr, "INSERT statement '%s' didn't return DONE (ret=%d): %s\n", sql, ret, sqlite3_errmsg(db));
+ goto gdcsi_exit;
+ }
+
+ sqlite3_finalize(stmt);
+
+ result = true;
+
+ gdcsi_exit:
+
+ free(sql);
+
+ printf("INSERT ? %d\n", result);
+
+ return result;
+
+}
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CREATION DE L'ABSTRACTION POUR COLLECTIONS */
/* ---------------------------------------------------------------------------------- */
diff --git a/src/analysis/db/collection.h b/src/analysis/db/collection.h
index 75ee7df..b400820 100644
--- a/src/analysis/db/collection.h
+++ b/src/analysis/db/collection.h
@@ -26,6 +26,8 @@
#include <glib-object.h>
+#include <sqlite3.h>
+#include <stdbool.h>
#include <stdint.h>
@@ -52,7 +54,7 @@ typedef struct _GDbCollectionClass GDbCollectionClass;
GType g_db_collection_get_type(void);
/* Prépare la mise en place d'une nouvelle collection. */
-GDbCollection *g_db_collection_new(uint32_t, GType);
+GDbCollection *g_db_collection_new(uint32_t, GType, const char *);
@@ -63,7 +65,7 @@ uint32_t g_db_collection_get_feature(const GDbCollection *);
/* Réceptionne et traite une requête réseau pour collection. */
-bool g_db_collection_recv(GDbCollection *, int);
+bool g_db_collection_recv(GDbCollection *, int, sqlite3 *);
/* Envoie pour traitement une requête réseau pour collection. */
bool g_db_collection_send(GDbCollection *, int, DBAction, GDbItem *);
diff --git a/src/analysis/db/item-int.h b/src/analysis/db/item-int.h
index b6d8f9c..0f75ed4 100644
--- a/src/analysis/db/item-int.h
+++ b/src/analysis/db/item-int.h
@@ -32,12 +32,20 @@
+
+
+
+
+
/* Importe la définition d'une base d'éléments pour collection. */
typedef bool (* recv_db_item_fc) (GDbItem *, int, int);
/* Exporte la définition d'une base d'éléments pour collection. */
typedef bool (* send_db_item_fc) (const GDbItem *, int, int);
+/* Constitue les champs destinés à une insertion / modification. */
+typedef bool (* prepare_db_statement) (const GDbItem *, bool, bound_value **, size_t *);
+
/* Base d'un élément pour collection générique (instance) */
struct _GDbItem
@@ -61,6 +69,8 @@ struct _GDbItemClass
recv_db_item_fc recv; /* Réception depuis le réseau */
send_db_item_fc send; /* Emission depuis le réseau */
+ prepare_db_statement prepare_stmt; /* Préparation d'une requête */
+
};
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
index e2fd7f3..7fa1a52 100644
--- a/src/analysis/db/item.c
+++ b/src/analysis/db/item.c
@@ -24,8 +24,13 @@
#include "item.h"
+#include <malloc.h>
+#include <sqlite3.h>
+
+
#include "item-int.h"
#include "../../common/io.h"
+#include "../../core/params.h"
@@ -52,6 +57,13 @@ static bool g_db_item_send_to_fd(const GDbItem *, int, int);
+/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */
+
+
+/* Constitue les champs destinés à une insertion / modification. */
+static bool _g_db_item_prepare_db_statement(const GDbItem *, bool, bound_value **, size_t *);
+
+
/* Indique le type défini pour une base d'élément de collection générique. */
G_DEFINE_TYPE(GDbItem, g_db_item, G_TYPE_OBJECT);
@@ -83,6 +95,8 @@ static void g_db_item_class_init(GDbItemClass *klass)
klass->recv = (recv_db_item_fc)g_db_item_recv_from_fd;
klass->send = (send_db_item_fc)g_db_item_send_to_fd;
+ klass->prepare_stmt = (prepare_db_statement)_g_db_item_prepare_db_statement;
+
}
@@ -354,3 +368,82 @@ bool g_db_item_is_volatile(const GDbItem *item)
return item->is_volatile;
}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATIONS AVEC UNE BASE DE DONNEES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = base d'éléments sur laquelle s'appuyer. *
+* create = indique si la préparation vise une création ou non. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
+* *
+* Description : Constitue les champs destinés à une insertion / modification.*
+* *
+* Retour : Bilan de l'opération : succès ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool _g_db_item_prepare_db_statement(const GDbItem *item, bool create, bound_value **values, size_t *count)
+{
+ char *author; /* Identification à diffuser */
+ bound_value *value; /* Valeur à éditer / définir */
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &author))
+ return false;
+
+ *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
+ value = &(*values)[*count - 1];
+
+ value->name = "user";
+ value->type = SQLITE_TEXT;
+ value->string = author;
+ value->delete = free;
+
+ if (!create)
+ {
+ *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
+ value = &(*values)[*count - 1];
+
+ value->name = "modified";
+ value->type = SQLITE_RAW;
+ value->string = "CURRENT_TIMESTAMP";
+ value->delete = SQLITE_STATIC;
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = base d'éléments sur laquelle s'appuyer. *
+* create = indique si la préparation vise une création ou non. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
+* *
+* Description : Constitue les champs destinés à une insertion / modification.*
+* *
+* Retour : Bilan de l'opération : succès ou non. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_db_item_prepare_db_statement(const GDbItem *item, bool create, bound_value **values, size_t *count)
+{
+ *values = NULL;
+ *count = 0;
+
+ return G_DB_ITEM_GET_CLASS(item)->prepare_stmt(item, create, values, count);
+
+}
diff --git a/src/analysis/db/item.h b/src/analysis/db/item.h
index 3938610..2f8ee60 100644
--- a/src/analysis/db/item.h
+++ b/src/analysis/db/item.h
@@ -29,6 +29,9 @@
#include <stdbool.h>
+#include "../../common/sqlite.h"
+
+
#define G_TYPE_DB_ITEM g_db_item_get_type()
#define G_DB_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_db_item_get_type(), GDbItem))
@@ -65,4 +68,19 @@ bool g_db_item_is_volatile(const GDbItem *);
+/* --------------------- MANIPULATIONS AVEC UNE BASE DE DONNEES --------------------- */
+
+
+/* Définition du tronc commun pour les créations SQLite */
+#define SQLITE_DB_ITEM_CREATE \
+ "user TEXT, " \
+ "created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " \
+ "modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
+
+
+/* Constitue les champs destinés à une insertion / modification. */
+bool g_db_item_prepare_db_statement(const GDbItem *, bool, bound_value **, size_t *);
+
+
+
#endif /* _ANALYSIS_DB_ITEM_H */
diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c
index c28a837..6ff386c 100644
--- a/src/analysis/db/items/bookmark.c
+++ b/src/analysis/db/items/bookmark.c
@@ -75,6 +75,9 @@ static bool g_db_bookmark_recv_from_fd(GDbBookmark *, int, int);
/* Exporte la définition d'un signet dans un flux réseau. */
static bool g_db_bookmark_send_to_fd(const GDbBookmark *, int, int);
+/* Constitue les champs destinés à une insertion / modification. */
+static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *, bool, bound_value **, size_t *);
+
@@ -97,10 +100,8 @@ bool create_bookmark_db_table(sqlite3 *db)
char *msg; /* Message d'erreur */
sql = "CREATE TABLE Bookmarks (" \
- "id INT PRIMARY KEY NOT NULL, " \
- "user TEXT NOT NULL, " \
- "created INT NOT NULL, " \
- "address INT NOT NULL, " \
+ SQLITE_DB_ITEM_CREATE \
+ SQLITE_VMPA_CREATE \
"comment TEXT" \
");";
@@ -157,6 +158,8 @@ static void g_db_bookmark_class_init(GDbBookmarkClass *klass)
item->recv = (recv_db_item_fc)g_db_bookmark_recv_from_fd;
item->send = (send_db_item_fc)g_db_bookmark_send_to_fd;
+ item->prepare_stmt = (prepare_db_statement)g_db_bookmark_prepare_db_statement;
+
}
@@ -235,13 +238,7 @@ GDbBookmark *g_db_bookmark_new(const vmpa2t *addr, const char *comment)
result = g_object_new(G_TYPE_DB_BOOKMARK, NULL);
-
-
-
- /* TODO */
-
- //dup addr;
-
+ copy_vmpa(&result->addr, addr);
g_db_bookmark_set_comment(result, comment);
@@ -351,6 +348,46 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl
}
+/******************************************************************************
+* *
+* Paramètres : item = base d'éléments sur laquelle s'appuyer. *
+* create = indique si la préparation vise une création ou non. *
+* values = couples de champs et de valeurs à lier. [OUT] *
+* count = nombre de ces couples. [OUT] *
+* *
+* Description : Constitue les champs destinés à une insertion / modification.*
+* *
+* Retour : Etat du besoin en sauvegarde. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_db_bookmark_prepare_db_statement(const GDbBookmark *bookmark, bool create, bound_value **values, size_t *count)
+{
+ bool status; /* Bilan d'opération initiale */
+ bound_value *value; /* Valeur à éditer / définir */
+
+ status = G_DB_ITEM_CLASS(g_db_bookmark_parent_class)->prepare_stmt(G_DB_ITEM(bookmark), create, values, count);
+ if (!status) return false;
+
+ status = prepare_vmpa_db_statement(&bookmark->addr, create, values, count);
+ if (!status) return false;
+
+ *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
+ value = &(*values)[*count - 1];
+
+ value->name = "comment";
+ value->type = SQLITE_TEXT;
+ value->cstring = g_db_bookmark_get_comment(bookmark);
+ value->delete = SQLITE_STATIC;
+
+ return true;
+
+}
+
+
+
@@ -370,7 +407,7 @@ static bool g_db_bookmark_send_to_fd(const GDbBookmark *bookmark, int fd, int fl
* *
******************************************************************************/
-vmpa2t *g_db_bookmark_get_address(GDbBookmark *bookmark)
+const vmpa2t *g_db_bookmark_get_address(GDbBookmark *bookmark)
{
return &bookmark->addr;
diff --git a/src/analysis/db/items/bookmark.h b/src/analysis/db/items/bookmark.h
index d1b073c..cd5e202 100644
--- a/src/analysis/db/items/bookmark.h
+++ b/src/analysis/db/items/bookmark.h
@@ -66,7 +66,7 @@ GType g_db_bookmark_get_type(void);
GDbBookmark *g_db_bookmark_new(const vmpa2t *, const char *);
/* Fournit l'adresse associée à un signet. */
-vmpa2t *g_db_bookmark_get_address(GDbBookmark *);
+const vmpa2t *g_db_bookmark_get_address(GDbBookmark *);
/* Fournit le commentaire associé à un signet. */
const char *g_db_bookmark_get_comment(const GDbBookmark *);
diff --git a/src/analysis/db/protocol.h b/src/analysis/db/protocol.h
index 05b559e..85d44cb 100644
--- a/src/analysis/db/protocol.h
+++ b/src/analysis/db/protocol.h
@@ -113,6 +113,7 @@ typedef enum _DBCommand
{
DBC_HELO, /* Connexion initiale C -> S */
DBC_WELCOME, /* Réponse initiale S -> C */
+ DBC_SAVE, /* Enregistrement de l'archive */
DBC_COLLECTION, /* Implication d'une collection*/
DBC_COUNT
@@ -132,6 +133,8 @@ typedef enum _DBError
{
DBE_NONE, /* Succès d'une opération */
DBE_WRONG_VERSION, /* Proto Client != Serveur */
+ DBE_SYS_ERROR, /* Erreur suite à un appel sys.*/
+ DBE_ARCHIVE_ERROR, /* Soucis du côté libarchive */
DBE_COUNT
@@ -141,6 +144,30 @@ typedef enum _DBError
+/**
+ * Gestion de la commande 'DBC_SAVE'.
+ *
+ * Le client connecté envoie un paquet de la forme suivante :
+ *
+ * [ Ordre de sauvegarde : DBC_SAVE ]
+ *
+ * Le serveur s'exécute et renvoie un bilan :
+ *
+ * [ Ordre de sauvegarde : DBC_SAVE ]
+ * [ Statut d'exécution ; cf. DBError ]
+ *
+ * Les traitements se réalisent dans :
+ * - g_db_client_save() pour la partie client en émission.
+ * - g_cdb_archive_process() pour la partie serveur.
+ * - g_db_client_update() pour la partie client en réception.
+ *
+ */
+
+
+
+
+
+