Blame src/srvc_store.c.fix-glib-headers

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