Blame src/srvc_store.c

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