|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/*
|
|
Packit |
ee6627 |
Meanwhile - Unofficial Lotus Sametime Community Client Library
|
|
Packit |
ee6627 |
Copyright (C) 2004 Christopher (siege) O'Brien
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
This library is free software; you can redistribute it and/or
|
|
Packit |
ee6627 |
modify it under the terms of the GNU Library General Public
|
|
Packit |
ee6627 |
License as published by the Free Software Foundation; either
|
|
Packit |
ee6627 |
version 2 of the License, or (at your option) any later version.
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
This library is distributed in the hope that it will be useful,
|
|
Packit |
ee6627 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
ee6627 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
ee6627 |
Library General Public License for more details.
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
You should have received a copy of the GNU Library General Public
|
|
Packit |
ee6627 |
License along with this library; if not, write to the Free
|
|
Packit |
ee6627 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
ee6627 |
*/
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#include <glib/glist.h>
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#include "mw_channel.h"
|
|
Packit |
ee6627 |
#include "mw_debug.h"
|
|
Packit |
ee6627 |
#include "mw_error.h"
|
|
Packit |
ee6627 |
#include "mw_message.h"
|
|
Packit |
ee6627 |
#include "mw_service.h"
|
|
Packit |
ee6627 |
#include "mw_session.h"
|
|
Packit |
ee6627 |
#include "mw_srvc_store.h"
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#define PROTOCOL_TYPE 0x00000025
|
|
Packit |
ee6627 |
#define PROTOCOL_VER 0x00000001
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
enum storage_action {
|
|
Packit |
ee6627 |
action_load = 0x0004,
|
|
Packit |
ee6627 |
action_loaded = 0x0005,
|
|
Packit |
ee6627 |
action_save = 0x0006,
|
|
Packit |
ee6627 |
action_saved = 0x0007,
|
|
Packit |
ee6627 |
};
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageUnit {
|
|
Packit |
ee6627 |
/** key by which data is referenced in service
|
|
Packit |
ee6627 |
@see mwStorageKey */
|
|
Packit |
ee6627 |
guint32 key;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/** Data associated with key in service */
|
|
Packit |
ee6627 |
struct mwOpaque data;
|
|
Packit |
ee6627 |
};
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageReq {
|
|
Packit |
ee6627 |
guint32 id; /**< unique id for this request */
|
|
Packit |
ee6627 |
guint32 result_code; /**< result code for completed request */
|
|
Packit |
ee6627 |
enum storage_action action; /**< load or save */
|
|
Packit |
ee6627 |
struct mwStorageUnit *item; /**< the key/data pair */
|
|
Packit |
ee6627 |
mwStorageCallback cb; /**< callback to notify upon completion */
|
|
Packit |
ee6627 |
gpointer data; /**< user data to pass with callback */
|
|
Packit |
ee6627 |
GDestroyNotify data_free; /**< optionally frees user data */
|
|
Packit |
ee6627 |
};
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwServiceStorage {
|
|
Packit |
ee6627 |
struct mwService service;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/** collection of mwStorageReq */
|
|
Packit |
ee6627 |
GList *pending;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/** current service channel */
|
|
Packit |
ee6627 |
struct mwChannel *channel;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/** keep track of the counter */
|
|
Packit |
ee6627 |
guint32 id_counter;
|
|
Packit |
ee6627 |
};
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void request_get(struct mwGetBuffer *b, struct mwStorageReq *req) {
|
|
Packit |
ee6627 |
guint32 id, count, junk;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(mwGetBuffer_error(b)) return;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32_get(b, &id;;
|
|
Packit |
ee6627 |
guint32_get(b, &req->result_code);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(req->action == action_loaded) {
|
|
Packit |
ee6627 |
guint32_get(b, &count);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(count > 0) {
|
|
Packit |
ee6627 |
guint32_get(b, &junk);
|
|
Packit |
ee6627 |
guint32_get(b, &req->item->key);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwOpaque_clear(&req->item->data);
|
|
Packit |
ee6627 |
mwOpaque_get(b, &req->item->data);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void request_put(struct mwPutBuffer *b, struct mwStorageReq *req) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32_put(b, req->id);
|
|
Packit |
ee6627 |
guint32_put(b, 1);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(req->action == action_save) {
|
|
Packit |
ee6627 |
guint32_put(b, 20 + req->item->data.len); /* ugh, offset garbage */
|
|
Packit |
ee6627 |
guint32_put(b, req->item->key);
|
|
Packit |
ee6627 |
mwOpaque_put(b, &req->item->data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
} else {
|
|
Packit |
ee6627 |
guint32_put(b, req->item->key);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static int request_send(struct mwChannel *chan, struct mwStorageReq *req) {
|
|
Packit |
ee6627 |
struct mwPutBuffer *b;
|
|
Packit |
ee6627 |
struct mwOpaque o = { 0, 0 };
|
|
Packit |
ee6627 |
int ret;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwPutBuffer_new();
|
|
Packit |
ee6627 |
request_put(b, req);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwPutBuffer_finalize(&o, b);
|
|
Packit |
ee6627 |
ret = mwChannel_send(chan, req->action, &o);
|
|
Packit |
ee6627 |
mwOpaque_clear(&o);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(! ret) {
|
|
Packit |
ee6627 |
if(req->action == action_save) {
|
|
Packit |
ee6627 |
req->action = action_saved;
|
|
Packit |
ee6627 |
} else if(req->action == action_load) {
|
|
Packit |
ee6627 |
req->action = action_loaded;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return ret;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static struct mwStorageReq *request_find(struct mwServiceStorage *srvc,
|
|
Packit |
ee6627 |
guint32 id) {
|
|
Packit |
ee6627 |
GList *l;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
for(l = srvc->pending; l; l = l->next) {
|
|
Packit |
ee6627 |
struct mwStorageReq *r = l->data;
|
|
Packit |
ee6627 |
if(r->id == id) return r;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return NULL;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static const char *action_str(enum storage_action act) {
|
|
Packit |
ee6627 |
switch(act) {
|
|
Packit |
ee6627 |
case action_load: return "load";
|
|
Packit |
ee6627 |
case action_loaded: return "loaded";
|
|
Packit |
ee6627 |
case action_save: return "save";
|
|
Packit |
ee6627 |
case action_saved: return "saved";
|
|
Packit |
ee6627 |
default: return "UNKNOWN";
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void request_trigger(struct mwServiceStorage *srvc,
|
|
Packit |
ee6627 |
struct mwStorageReq *req) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageUnit *item = req->item;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_message("storage request %s: key = 0x%x, result = 0x%x, length = %u",
|
|
Packit |
ee6627 |
action_str(req->action),
|
|
Packit |
ee6627 |
item->key, req->result_code, (guint) item->data.len);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(req->cb)
|
|
Packit |
ee6627 |
req->cb(srvc, req->result_code, item, req->data);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void request_free(struct mwStorageReq *req) {
|
|
Packit |
ee6627 |
if(req->data_free) {
|
|
Packit |
ee6627 |
req->data_free(req->data);
|
|
Packit |
ee6627 |
req->data = NULL;
|
|
Packit |
ee6627 |
req->data_free = NULL;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwStorageUnit_free(req->item);
|
|
Packit |
ee6627 |
g_free(req);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void request_remove(struct mwServiceStorage *srvc,
|
|
Packit |
ee6627 |
struct mwStorageReq *req) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc->pending = g_list_remove_all(srvc->pending, req);
|
|
Packit |
ee6627 |
request_free(req);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static const char *get_name(struct mwService *srvc) {
|
|
Packit |
ee6627 |
return "User Storage";
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static const char *get_desc(struct mwService *srvc) {
|
|
Packit |
ee6627 |
return "Stores user data and settings on the server";
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static struct mwChannel *make_channel(struct mwServiceStorage *srvc) {
|
|
Packit |
ee6627 |
struct mwSession *session;
|
|
Packit |
ee6627 |
struct mwChannelSet *cs;
|
|
Packit |
ee6627 |
struct mwChannel *chan;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
session = mwService_getSession(MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
cs = mwSession_getChannels(session);
|
|
Packit |
ee6627 |
chan = mwChannel_newOutgoing(cs);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwChannel_setService(chan, MW_SERVICE(srvc));
|
|
Packit |
ee6627 |
mwChannel_setProtoType(chan, PROTOCOL_TYPE);
|
|
Packit |
ee6627 |
mwChannel_setProtoVer(chan, PROTOCOL_VER);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return mwChannel_create(chan)? NULL: chan;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void start(struct mwService *srvc) {
|
|
Packit |
ee6627 |
struct mwServiceStorage *srvc_store;
|
|
Packit |
ee6627 |
struct mwChannel *chan;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
srvc_store = (struct mwServiceStorage *) srvc;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
chan = make_channel(srvc_store);
|
|
Packit |
ee6627 |
if(chan) {
|
|
Packit |
ee6627 |
srvc_store->channel = chan;
|
|
Packit |
ee6627 |
} else {
|
|
Packit |
ee6627 |
mwService_stopped(srvc);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void stop(struct mwService *srvc) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwServiceStorage *srvc_store;
|
|
Packit |
ee6627 |
GList *l;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
srvc_store = (struct mwServiceStorage *) srvc;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(srvc_store->channel) {
|
|
Packit |
ee6627 |
mwChannel_destroy(srvc_store->channel, ERR_SUCCESS, NULL);
|
|
Packit |
ee6627 |
srvc_store->channel = NULL;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#if 1
|
|
Packit |
ee6627 |
/* the new way */
|
|
Packit |
ee6627 |
/* remove pending requests. Sometimes we can crash the storage
|
|
Packit |
ee6627 |
service, and when that happens, we end up resending the killer
|
|
Packit |
ee6627 |
request over and over again, and the service never stays up */
|
|
Packit |
ee6627 |
for(l = srvc_store->pending; l; l = l->next)
|
|
Packit |
ee6627 |
request_free(l->data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_list_free(srvc_store->pending);
|
|
Packit |
ee6627 |
srvc_store->pending = NULL;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc_store->id_counter = 0;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
#else
|
|
Packit |
ee6627 |
/* the old way */
|
|
Packit |
ee6627 |
/* reset all of the started requests to their unstarted states */
|
|
Packit |
ee6627 |
for(l = srvc_store->pending; l; l = l->next) {
|
|
Packit |
ee6627 |
struct mwStorageReq *req = l->data;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(req->action == action_loaded) {
|
|
Packit |
ee6627 |
req->action = action_load;
|
|
Packit |
ee6627 |
} else if(req->action == action_saved) {
|
|
Packit |
ee6627 |
req->action = action_save;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
#endif
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwService_stopped(srvc);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void recv_channelAccept(struct mwService *srvc,
|
|
Packit |
ee6627 |
struct mwChannel *chan,
|
|
Packit |
ee6627 |
struct mwMsgChannelAccept *msg) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwServiceStorage *srvc_stor;
|
|
Packit |
ee6627 |
GList *l;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
srvc_stor = (struct mwServiceStorage *) srvc;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(chan != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan == srvc_stor->channel);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* send all pending requests */
|
|
Packit |
ee6627 |
for(l = srvc_stor->pending; l; l = l->next) {
|
|
Packit |
ee6627 |
struct mwStorageReq *req = l->data;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(req->action == action_save || req->action == action_load) {
|
|
Packit |
ee6627 |
request_send(chan, req);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwService_started(srvc);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void recv_channelDestroy(struct mwService *srvc,
|
|
Packit |
ee6627 |
struct mwChannel *chan,
|
|
Packit |
ee6627 |
struct mwMsgChannelDestroy *msg) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwSession *session;
|
|
Packit |
ee6627 |
struct mwServiceStorage *srvc_stor;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
session = mwService_getSession(srvc);
|
|
Packit |
ee6627 |
g_return_if_fail(session != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc_stor = (struct mwServiceStorage *) srvc;
|
|
Packit |
ee6627 |
srvc_stor->channel = NULL;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwService_stop(srvc);
|
|
Packit |
ee6627 |
mwSession_senseService(session, mwService_getType(srvc));
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void recv(struct mwService *srvc, struct mwChannel *chan,
|
|
Packit |
ee6627 |
guint16 type, struct mwOpaque *data) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* process into results, trigger callbacks */
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwGetBuffer *b;
|
|
Packit |
ee6627 |
struct mwServiceStorage *srvc_stor;
|
|
Packit |
ee6627 |
struct mwStorageReq *req;
|
|
Packit |
ee6627 |
guint32 id;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(srvc != NULL);
|
|
Packit |
ee6627 |
srvc_stor = (struct mwServiceStorage *) srvc;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(chan != NULL);
|
|
Packit |
ee6627 |
g_return_if_fail(chan == srvc_stor->channel);
|
|
Packit |
ee6627 |
g_return_if_fail(data != NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwGetBuffer_wrap(data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
id = guint32_peek(b);
|
|
Packit |
ee6627 |
req = request_find(srvc_stor, id);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(! req) {
|
|
Packit |
ee6627 |
g_warning("couldn't find request 0x%x in storage service", id);
|
|
Packit |
ee6627 |
mwGetBuffer_free(b);
|
|
Packit |
ee6627 |
return;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_if_fail(req->action == type);
|
|
Packit |
ee6627 |
request_get(b, req);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(mwGetBuffer_error(b)) {
|
|
Packit |
ee6627 |
mw_mailme_opaque(data, "storage request 0x%x, type: 0x%x", id, type);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
} else {
|
|
Packit |
ee6627 |
request_trigger(srvc_stor, req);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwGetBuffer_free(b);
|
|
Packit |
ee6627 |
request_remove(srvc_stor, req);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static void clear(struct mwService *srvc) {
|
|
Packit |
ee6627 |
struct mwServiceStorage *srvc_stor;
|
|
Packit |
ee6627 |
GList *l;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc_stor = (struct mwServiceStorage *) srvc;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
for(l = srvc_stor->pending; l; l = l->next)
|
|
Packit |
ee6627 |
request_free(l->data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_list_free(srvc_stor->pending);
|
|
Packit |
ee6627 |
srvc_stor->pending = NULL;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc_stor->id_counter = 0;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwServiceStorage *mwServiceStorage_new(struct mwSession *session) {
|
|
Packit |
ee6627 |
struct mwServiceStorage *srvc_store;
|
|
Packit |
ee6627 |
struct mwService *srvc;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc_store = g_new0(struct mwServiceStorage, 1);
|
|
Packit |
ee6627 |
srvc = MW_SERVICE(srvc_store);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwService_init(srvc, session, mwService_STORAGE);
|
|
Packit |
ee6627 |
srvc->get_name = get_name;
|
|
Packit |
ee6627 |
srvc->get_desc = get_desc;
|
|
Packit |
ee6627 |
srvc->recv_accept = recv_channelAccept;
|
|
Packit |
ee6627 |
srvc->recv_destroy = recv_channelDestroy;
|
|
Packit |
ee6627 |
srvc->recv = recv;
|
|
Packit |
ee6627 |
srvc->start = start;
|
|
Packit |
ee6627 |
srvc->stop = stop;
|
|
Packit |
ee6627 |
srvc->clear = clear;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return srvc_store;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageUnit *mwStorageUnit_new(guint32 key) {
|
|
Packit |
ee6627 |
struct mwStorageUnit *u;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
u = g_new0(struct mwStorageUnit, 1);
|
|
Packit |
ee6627 |
u->key = key;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return u;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageUnit *mwStorageUnit_newOpaque(guint32 key,
|
|
Packit |
ee6627 |
struct mwOpaque *data) {
|
|
Packit |
ee6627 |
struct mwStorageUnit *u;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
u = g_new0(struct mwStorageUnit, 1);
|
|
Packit |
ee6627 |
u->key = key;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(data)
|
|
Packit |
ee6627 |
mwOpaque_clone(&u->data, data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return u;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageUnit *mwStorageUnit_newBoolean(guint32 key,
|
|
Packit |
ee6627 |
gboolean val) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return mwStorageUnit_newInteger(key, (guint32) val);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageUnit *mwStorageUnit_newInteger(guint32 key,
|
|
Packit |
ee6627 |
guint32 val) {
|
|
Packit |
ee6627 |
struct mwStorageUnit *u;
|
|
Packit |
ee6627 |
struct mwPutBuffer *b;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
u = g_new0(struct mwStorageUnit, 1);
|
|
Packit |
ee6627 |
u->key = key;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwPutBuffer_new();
|
|
Packit |
ee6627 |
guint32_put(b, val);
|
|
Packit |
ee6627 |
mwPutBuffer_finalize(&u->data, b);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return u;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageUnit *mwStorageUnit_newString(guint32 key,
|
|
Packit |
ee6627 |
const char *str) {
|
|
Packit |
ee6627 |
struct mwStorageUnit *u;
|
|
Packit |
ee6627 |
struct mwPutBuffer *b;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
u = g_new0(struct mwStorageUnit, 1);
|
|
Packit |
ee6627 |
u->key = key;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwPutBuffer_new();
|
|
Packit |
ee6627 |
mwString_put(b, str);
|
|
Packit |
ee6627 |
mwPutBuffer_finalize(&u->data, b);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return u;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32 mwStorageUnit_getKey(struct mwStorageUnit *item) {
|
|
Packit |
ee6627 |
g_return_val_if_fail(item != NULL, 0x00); /* feh, unsafe */
|
|
Packit |
ee6627 |
return item->key;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
gboolean mwStorageUnit_asBoolean(struct mwStorageUnit *item,
|
|
Packit |
ee6627 |
gboolean val) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return !! mwStorageUnit_asInteger(item, (guint32) val);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32 mwStorageUnit_asInteger(struct mwStorageUnit *item,
|
|
Packit |
ee6627 |
guint32 val) {
|
|
Packit |
ee6627 |
struct mwGetBuffer *b;
|
|
Packit |
ee6627 |
guint32 v;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_val_if_fail(item != NULL, val);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwGetBuffer_wrap(&item->data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
guint32_get(b, &v);
|
|
Packit |
ee6627 |
if(! mwGetBuffer_error(b)) val = v;
|
|
Packit |
ee6627 |
mwGetBuffer_free(b);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return val;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
char *mwStorageUnit_asString(struct mwStorageUnit *item) {
|
|
Packit |
ee6627 |
struct mwGetBuffer *b;
|
|
Packit |
ee6627 |
char *c = NULL;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
g_return_val_if_fail(item != NULL, NULL);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
b = mwGetBuffer_wrap(&item->data);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwString_get(b, &c);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(mwGetBuffer_error(b))
|
|
Packit |
ee6627 |
g_debug("error obtaining string value from opaque");
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwGetBuffer_free(b);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return c;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwOpaque *mwStorageUnit_asOpaque(struct mwStorageUnit *item) {
|
|
Packit |
ee6627 |
g_return_val_if_fail(item != NULL, NULL);
|
|
Packit |
ee6627 |
return &item->data;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
void mwStorageUnit_free(struct mwStorageUnit *item) {
|
|
Packit |
ee6627 |
if(! item) return;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
mwOpaque_clear(&item->data);
|
|
Packit |
ee6627 |
g_free(item);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
static struct mwStorageReq *request_new(struct mwServiceStorage *srvc,
|
|
Packit |
ee6627 |
struct mwStorageUnit *item,
|
|
Packit |
ee6627 |
mwStorageCallback cb,
|
|
Packit |
ee6627 |
gpointer data, GDestroyNotify df) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageReq *req = g_new0(struct mwStorageReq, 1);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
req->id = ++srvc->id_counter;
|
|
Packit |
ee6627 |
req->item = item;
|
|
Packit |
ee6627 |
req->cb = cb;
|
|
Packit |
ee6627 |
req->data = data;
|
|
Packit |
ee6627 |
req->data_free = df;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
return req;
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
void mwServiceStorage_load(struct mwServiceStorage *srvc,
|
|
Packit |
ee6627 |
struct mwStorageUnit *item,
|
|
Packit |
ee6627 |
mwStorageCallback cb,
|
|
Packit |
ee6627 |
gpointer data, GDestroyNotify d_free) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* - construct a request
|
|
Packit |
ee6627 |
- put request at end of pending
|
|
Packit |
ee6627 |
- if channel is open and connected
|
|
Packit |
ee6627 |
- compose the load message
|
|
Packit |
ee6627 |
- send message
|
|
Packit |
ee6627 |
- set request to sent
|
|
Packit |
ee6627 |
- else
|
|
Packit |
ee6627 |
- start service
|
|
Packit |
ee6627 |
*/
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageReq *req;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
req = request_new(srvc, item, cb, data, d_free);
|
|
Packit |
ee6627 |
req->action = action_load;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc->pending = g_list_append(srvc->pending, req);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(MW_SERVICE_IS_STARTED(MW_SERVICE(srvc)))
|
|
Packit |
ee6627 |
request_send(srvc->channel, req);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
void mwServiceStorage_save(struct mwServiceStorage *srvc,
|
|
Packit |
ee6627 |
struct mwStorageUnit *item,
|
|
Packit |
ee6627 |
mwStorageCallback cb,
|
|
Packit |
ee6627 |
gpointer data, GDestroyNotify d_free) {
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
/* - construct a request
|
|
Packit |
ee6627 |
- put request at end of pending
|
|
Packit |
ee6627 |
- if channel is open and connected
|
|
Packit |
ee6627 |
- compose the save message
|
|
Packit |
ee6627 |
- send message
|
|
Packit |
ee6627 |
- set request to sent
|
|
Packit |
ee6627 |
- else
|
|
Packit |
ee6627 |
- start service
|
|
Packit |
ee6627 |
*/
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
struct mwStorageReq *req;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
req = request_new(srvc, item, cb, data, d_free);
|
|
Packit |
ee6627 |
req->action = action_save;
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
srvc->pending = g_list_append(srvc->pending, req);
|
|
Packit |
ee6627 |
|
|
Packit |
ee6627 |
if(MW_SERVICE_IS_STARTED(MW_SERVICE(srvc)))
|
|
Packit |
ee6627 |
request_send(srvc->channel, req);
|
|
Packit |
ee6627 |
}
|
|
Packit |
ee6627 |
|