Esempio n. 1
0
/**
 * General function to allocate and initialize a ZSockAddr structure,
 * and convert a libc style sockaddr * pointer to our representation.
 *
 * @param[in] sa libc sockaddr * pointer to convert
 * @param[in] salen size of sa
 *
 * @returns new ZSockAddr instance
 **/
ZSockAddr *
z_sockaddr_new(struct sockaddr *sa, gsize salen)
{
  z_enter();
  switch (sa->sa_family)
    {
#ifndef G_OS_WIN32
    case AF_INET6:
      if (salen >= sizeof(struct sockaddr_in6))
        z_return(z_sockaddr_inet6_new2((struct sockaddr_in6 *) sa));
      break;
      
#endif
    case AF_INET:
      if (salen == sizeof(struct sockaddr_in))
        z_return(z_sockaddr_inet_new2((struct sockaddr_in *) sa));
      break;
      
#ifndef G_OS_WIN32
    case AF_UNIX:
      /* NOTE: the sockaddr_un structure might be less than struct sockaddr_un */
      z_return(z_sockaddr_unix_new2((struct sockaddr_un *) sa, salen));
#endif
    default:
      /*LOG
        This message indicates an internal error, the program tried to use an
        unsupported address family. Please report this error to the Zorp QA team.
       */
      z_log(NULL, CORE_ERROR, 3, "Unsupported socket family in z_sockaddr_new(); family='%d'", sa->sa_family);
      z_return(NULL);
    }
  z_return(NULL);
}
Esempio n. 2
0
/**
 * z_dispatch_connection:
 * @chain this
 * @conn The new connection to dispatch
 *
 * Iterates through the chain and dispatches the connection to the
 * chain items by passing it to their callbacks (for example to
 * z_py_zorp_dispatch_accept, which passes it to Dispatcher.accepted).
 */
static void 
z_dispatch_connection(ZDispatchChain *chain, ZConnection *conn)
{
  GList *p;
  ZDispatchEntry *entry;
  gchar buf[256];
  
  z_enter();
  z_dispatch_chain_lock(chain);
  /* the list is ordered by priority */
  for (p = chain->elements; p; p = g_list_next(p))
    {
      entry = (ZDispatchEntry *) p->data;
      /*LOG
        This message reports that a new connections is coming.
       */
      z_log(entry->session_id, CORE_DEBUG, 6, "Incoming connection; %s", conn ? z_connection_format(conn, buf, sizeof(buf)) : "conn=NULL");
      if ((entry->callback)(conn, entry->callback_data))
        {
          z_dispatch_chain_unlock(chain);
          z_return();
        }
    }
  z_dispatch_chain_unlock(chain);
  
  /* nobody needed this connection, destroy it */
  /*LOG
    This message indicates that a new connection was accepted, but no
    Listenet/Receiver/Proxy was interested in it.
   */
  z_log(NULL, CORE_ERROR, 3, "Nobody was interested in this connection; %s", z_connection_format(conn, buf, sizeof(buf)));
  z_connection_destroy(conn, TRUE);
  z_return();
}
Esempio n. 3
0
/**
 * Get the (absolute) filename assigned to the blob.
 *
 * @param[in] self this
 * @param[in] user Owner of the created file or NULL
 * @param[in] group Group of the created file or NULL
 * @param[in] mode Mode of the created file of -1
 * @param[in] timeout timeout
 *
 * @returns The filename
 **/
const gchar * 
z_blob_get_file(ZBlob *self, const gchar *user, const gchar *group, gint mode, gint timeout)
{
  const gchar   *res = NULL;

  z_enter();
  g_assert(self);
  if (!self->filename || !self->system)
    z_return(NULL);

  if (z_blob_lock(self, timeout))
    {
      if (!self->is_in_file)
        {
          if (self->storage_locked)
            goto exit;

          g_mutex_lock(self->system->mtx_blobsys); /* swap_out() accesses the blob systems data
                                                      directly, so it needs to be locked */
          z_blob_swap_out(self);
          g_mutex_unlock(self->system->mtx_blobsys);
        }
      if (group || user)
        {
          uid_t user_id = -1;
          gid_t group_id = -1;
          
          if (user && !z_resolve_user(user, &user_id))
            {
              z_log(NULL, CORE_ERROR, 3, "Cannot resolve user; user='******'", user);
              goto exit;
            }
          
          if (group && !z_resolve_group(group, &group_id))
            {
              z_log(NULL, CORE_ERROR, 3, "Cannot resolve group; group='%s'", group);
              goto exit;
            }
          
          if (chown(self->filename, user_id, group_id) == -1)
            goto exit;
        }

      if ((mode != -1) && (chmod(self->filename, mode) == -1))
        goto exit;

      res = self->filename;

exit:
      if (res == NULL)
        z_blob_unlock(self);
    }

  z_return(res); 
}
Esempio n. 4
0
gboolean
z_kzorp_get_lookup_result(gint fd, struct z_kzorp_lookup_result *result)
{
  socklen_t size = sizeof(*result);

  z_enter();

  if (getsockopt(fd, SOL_IP, SO_KZORP_RESULT, result, &size) < 0)
    {
      z_log(NULL, CORE_ERROR, 3, "Error querying KZorp lookup result; fd='%d', error='%s'", fd, g_strerror(errno));
      z_return(FALSE);
    }

  z_return(TRUE);
}
Esempio n. 5
0
/**
 * Create a new blob.
 *
 * @param[in] sys Blob system to create the blob into
 * @param[in] initial_size Initial size to allocate.
 *
 * This function creates a new blob. If sys is NULL, z_blob_system_default will be used.
 *
 * @returns The new blob instance
 **/
ZBlob*
z_blob_new(ZBlobSystem *sys, gsize initial_size)
{
  ZBlob   *self;

  z_enter();
  if (!sys)
    sys = z_blob_system_default;

  if (!sys || !sys->active) 
    z_return(NULL);

  self = g_new0(ZBlob, 1);
  self->system = sys;

  self->filename = g_strdup_printf("%s/blob_XXXXXX", self->system->dir);
  self->fd = mkstemp(self->filename);

  if (self->fd < 0)
    {
      z_log(NULL, CORE_ERROR, 2, "Error creating blob file: file='%s', error='%s'", self->filename, strerror(errno));
      g_free(self->filename);
      g_free(self);
      z_return(NULL);
    }
  
  z_refcount_set(&self->ref_cnt, 1);
  self->size = 0;
  self->alloc_size = 0;
  self->data = NULL;
  self->is_in_file = FALSE;
  self->mtx_reply = g_mutex_new();
  self->cond_reply = g_cond_new();
  self->mapped_ptr = NULL;
  self->mapped_length = 0;
  self->storage_locked = FALSE;

  z_blob_statistic_init(&self->stat);
  self->mtx_lock = g_mutex_new();

  g_mutex_lock(self->system->mtx_blobsys);
  self->system->blobs = g_list_append(self->system->blobs, self);
  g_mutex_unlock(self->system->mtx_blobsys);

  if (initial_size > 0)
    z_blob_alloc(self, initial_size);
  z_return(self);
}
Esempio n. 6
0
/**
 * Increase reference count of a blob system.
 *
 * @param[in] self the blob system object
 **/
void
z_blob_system_ref(ZBlobSystem *self)
{
  z_enter();
  z_refcount_inc(&self->ref_cnt);
  z_return();
}
Esempio n. 7
0
/**
 * Increase reference count of blob and return a reference to it.
 *
 * @param[in] self this
 *
 * @returns self
 **/
ZBlob *
z_blob_ref(ZBlob *self)
{
  z_enter();
  z_refcount_inc(&self->ref_cnt);
  z_return(self);
}
Esempio n. 8
0
/**
 * z_policy_call:
 * @handler: Python object whose method shall be called
 * @name: Method name
 * @args: Arguments to pass to the method
 * @called: Flag to store into whether the call succeeded or not (may be NULL)
 * @session_id: Session ID for logging
 *
 * If the requested method exists and is callable, calls it.
 * If @called is not NULL, it will be set if the call succeeded, cleared if not.
 *
 * Returns:
 * The return value of the call
 */
PyObject *
z_policy_call(PyObject *handler, char *name, PyObject *args, gboolean *called, gchar *session_id)
{
  PyObject *attr;
  PyObject *res;

  z_enter();
  g_assert(PyThreadState_GET());
  attr = PyObject_GetAttrString(handler, name);
  if (!attr || !PyCallable_Check(attr))
    {
      if (attr)
        {
          Py_XDECREF(attr);
          PyErr_Format(PyExc_TypeError, "Event must be callable: %s", name);
          PyErr_Print(); /* produce a backtrace, and handle it immediately */
        }
      PyErr_Clear();
      Py_XDECREF(args);
      res = NULL;
      z_trace(NULL, "Cannot find function; name='%s'", name);
      if (called)
        *called = FALSE;
    }
  else
    {
      if (called)
        *called = TRUE;
      res = z_policy_call_object(attr, args, session_id);
      z_trace(NULL, "Function called; name='%s'", name);
      Py_XDECREF(attr);
    }
  z_return(res);
}
Esempio n. 9
0
/**
 * Create a new blob system using the given parameters.
 *
 * @param[in] dir directory to put the swapped blobs into
 * @param[in] dmax max disk usage size
 * @param[in] mmax max mem usage size
 * @param[in] low low water mark
 * @param[in] hiw high water mark
 * @param[in] nosw maximal size that wont't be swapped
 *
 * @returns The new blob system instance
 **/
ZBlobSystem* 
z_blob_system_new(const char *dir, gint64 dmax, gsize mmax, gsize low, gsize hiw, gsize nosw)
{
  ZBlobSystem   *self;

  z_enter();
  self = g_new0(ZBlobSystem, 1);

  z_refcount_set(&self->ref_cnt, 1);
  self->dir = strdup(dir);
  self->disk_max = dmax;
  self->mem_max = mmax;
  self->disk_used = self->mem_used = 0;
  if (mmax <= low)
      low = mmax - 1;
  self->lowat = low;
  if (mmax <= hiw)
      hiw = mmax - 1;
  self->hiwat = hiw;
  self->noswap_max = nosw;
  self->blobs = NULL;
  self->mtx_blobsys = g_mutex_new();
  self->cond_thread_started = g_cond_new();
  self->req_queue = g_async_queue_new();
  self->waiting_list = NULL;

  g_mutex_lock(self->mtx_blobsys);
  self->thr_management = g_thread_create((GThreadFunc)z_blob_system_threadproc,
                              (gpointer)self, TRUE, &self->thread_error);
  g_cond_wait(self->cond_thread_started, self->mtx_blobsys);
  g_mutex_unlock(self->mtx_blobsys);
  self->active = TRUE;
  z_return(self);
}
Esempio n. 10
0
static guint
z_plug_read_input(ZPlugSession *self, ZStream *input, ZPlugIOBuffer *buf)
{
  GIOStatus rc;

  z_enter();
  rc = z_stream_read(input, buf->buf, self->session_data->buffer_size, &buf->end, NULL);
  if (rc == G_IO_STATUS_NORMAL)
    {
      buf->packet_bytes += buf->end;
      buf->packet_count++;
      self->global_packet_count++;
      if (self->session_data->packet_stats_interval_packet &&
         (self->global_packet_count % self->session_data->packet_stats_interval_packet) == 0)
        {
          if (!self->session_data->packet_stats(self,
                                                self->buffers[EP_CLIENT].packet_bytes,
                                                self->buffers[EP_CLIENT].packet_count,
                                                self->buffers[EP_SERVER].packet_bytes,
                                                self->buffers[EP_SERVER].packet_count,
                                                self->user_data))
            {
              z_plug_update_eof_mask(self, EOF_ALL);
              rc = G_IO_STATUS_EOF;
            }
        }
    }
  z_return(rc);
}
Esempio n. 11
0
/**
 * Unlock a blob.
 *
 * @param self[in] this
 **/
void
z_blob_unlock(ZBlob *self)
{
  z_enter();
  g_assert(self);
  g_mutex_unlock(self->mtx_lock);
  z_return();
}
Esempio n. 12
0
/**
 * Write some data into the given position of the blob, expanding it if necessary.
 *
 * @param[in] self this
 * @param[in] pos position to write to
 * @param[in] data data to write
 * @param[in] req_datalen length of data
 * @param[in] timeout timeout
 *
 * @returns The amount of data written.
 **/
gsize
z_blob_add_copy(ZBlob *self, gint64 pos, const gchar* data, gsize req_datalen, gint timeout)
{
  off_t         err;
  gssize        written = 0;

  z_enter();
  g_assert(self);
  g_assert(data);
  g_assert(pos >= 0);
  if (z_blob_lock(self, timeout))
    {
      if (self->alloc_size < (pos + (gssize) req_datalen))
        z_blob_alloc(self, pos + req_datalen);

      if (self->is_in_file)
        {
          gssize remain;
          err = lseek(self->fd, pos, SEEK_SET);
          
          if (err < 0)
            {
              z_log(NULL, CORE_ERROR, 0, "Blob error, lseek() failed; file='%s', error='%s'", self->filename, g_strerror(errno));
              g_assert(0);
            }
          remain = req_datalen;
          while (remain > 0)
            {
              written = write(self->fd, data, remain);
              if (written < 0)
                {
                  if (errno == EINTR)
                    {
                      continue;
                    }
                  else
                    {
                      z_log(NULL, CORE_ERROR, 0, "Blob error, write() failed; file='%s', error='%s'", self->filename, g_strerror(errno));
                      g_assert(0);
                    }
                }
              remain -= written;
            }
        }
      else
        {
          memmove(self->data + pos, data, req_datalen);
          written = req_datalen;
        }
      if (self->size < (pos + written))
        self->size = pos + written;
      self->stat.req_wr++;
      self->stat.total_wr += written;
      self->stat.last_accessed = time(NULL);
      z_blob_unlock(self);
    }
  z_return(written);
}
Esempio n. 13
0
/**
 * Decrease reference count of a blob system; destroy it if the count reaches zero.
 *
 * @param[in] self the blob system object
 *
 * This function decreases the reference count of the blob system
 * object given. If the reference count reaches zero, the blob system
 * will be destroyed. If there were pending requests in a to-be-destroyed
 * blob system, this fact will be logged.
 **/
void
z_blob_system_unref(ZBlobSystem *self)
{
  ZBlob *blob;
  GList *cur, *next;
  gint n;

  z_enter();
  g_assert(self); 
  if (z_refcount_dec(&self->ref_cnt))
    {
      self->active = FALSE;
      /** @todo FIXME: itt lockolni kell */
      g_async_queue_push(self->req_queue, Z_BLOB_THREAD_KILL);
      g_thread_join(self->thr_management);

      n = 0;
      for (cur = self->waiting_list; cur; cur = next)
        {
          next = cur->next;
          blob = (ZBlob*) cur->data;
          blob->approved = FALSE;
          z_blob_signal_ready(blob);
          self->waiting_list = g_list_delete_link(self->waiting_list, cur);
          n++;
        }
      if (n)
        z_log(NULL, CORE_INFO, 5, "Pending requests found for a to-be-destroyed blob system; num_requests='%d'", n);

      n = 0;
      for (cur = self->blobs; cur; cur = next)
        {
          next = cur->next;
          blob = (ZBlob*)cur->data;
          z_blob_unref(blob);
          n++;
        }
      if (n)
        z_log(NULL, CORE_INFO, 5, "Active blobs found in a to-be-destroyed blob system; num_blobs='%d'", n);

      if (self->dir)
        g_free(self->dir);
      if (g_mutex_trylock(self->mtx_blobsys))
        {
          g_mutex_unlock(self->mtx_blobsys);
          g_mutex_free(self->mtx_blobsys);
        }
      else
        {
          /* Some blob operations are in progress: z_blob_new, _unref, _alloc, _get_file */
        }
      g_cond_free(self->cond_thread_started);
      g_async_queue_unref(self->req_queue);
      g_list_free(self->waiting_list);
      g_free(self);
    }
  z_return();
}
Esempio n. 14
0
/**
 * anypy_proxy_new:
 * @params: parameters for the AnyPyProxy class constructor
 *
 * This function is called upon startup to create a new AnyPy proxy.
 **/
ZProxy *
anypy_proxy_new(ZProxyParams *params)
{
  AnyPyProxy *self;
  
  z_enter();
  self = Z_CAST(z_proxy_new(Z_CLASS(AnyPyProxy), params), AnyPyProxy);
  z_return(&self->super);
}
Esempio n. 15
0
static void
z_header_set_destroy_foreach(gpointer key G_GNUC_UNUSED,
                                         gpointer value,
                                         gpointer user_data G_GNUC_UNUSED)
{
  z_enter();
  z_header_set_destroy_chain((GList *)value);
  z_return();
}
Esempio n. 16
0
/**
 * Reads some data from the blob into a buffer.
 *
 * @param[in] self this
 * @param[in] pos position to read from
 * @param[in] data buffer to read into
 * @param[in] req_datalen bytes to read
 * @param[in] timeout timeout
 *
 * @returns The amount of data actually read.
 **/
gsize
z_blob_get_copy(ZBlob *self, gint64 pos, gchar* data, gsize req_datalen, gint timeout)
{
  off_t         err;
  gssize        rd = 0;

  z_enter();
  g_assert(self);
  g_assert(data);
  g_assert(pos >= 0);
  if (pos < self->size)
    {
      if (req_datalen > (guint64) (self->size - pos))
        req_datalen = self->size - pos;
      if (z_blob_lock(self, timeout))
        {
          if (self->is_in_file)
            {
              gssize remain;
              err = lseek(self->fd, pos, SEEK_SET);
              if (err < 0)
                {
                  z_log(NULL, CORE_ERROR, 0, "Blob error, lseek() failed; file='%s', error='%s'", self->filename, g_strerror(errno));
                  g_assert(0);
                }
              remain = req_datalen;
              while (remain > 0)
                {
                  rd = read(self->fd, data, remain);
                  if (rd < 0)
                    {
                      if (errno == EINTR)
                        {
                          continue;
                        }
                      else
                        {
                          z_log(NULL, CORE_ERROR, 0, "Blob error, read() failed; file='%s', error='%s'", self->filename, g_strerror(errno));
                          g_assert(0);
                        }
                    }
                  remain -= rd;
                }
            }
          else
            {
              memmove(data, self->data + pos, req_datalen);
              rd = req_datalen;
            }
          self->stat.req_rd++;
          self->stat.total_rd += rd;
          self->stat.last_accessed = time(NULL);
          z_blob_unlock(self);
        }
    }
  z_return(rd);          
}
Esempio n. 17
0
/**
 * finger_proxy_new:
 * @params: ZProxyParams structure
 *
 * Finger proxy constructor. Allocates and initializes a proxy instance,
 * starts proxy thread.
 **/
static ZProxy *
finger_proxy_new(ZProxyParams *params)
{
    FingerProxy  *self;

    z_enter();
    self = Z_CAST(z_proxy_new(Z_CLASS(FingerProxy), params), FingerProxy);
    z_return((ZProxy *) self);
}
Esempio n. 18
0
ZHeader *
z_header_set_iterate(ZHeaderSet *self, gchar *key, gpointer *opaque)
{
  ZHeader *res;
  GList *value = opaque ? (GList *) *opaque : NULL;

  z_enter();
  if (value == NULL)
    value = (GList *) g_hash_table_lookup(self->headers, key);
  else
    value = g_list_next(value);

  if (value == NULL)
    z_return(NULL);

  res = value->data;
  if (opaque)
    *opaque = value;
  z_return(res);
}
Esempio n. 19
0
/**
 * Destroy the default blob system.
 **/
void
z_blob_system_default_destroy(void)
{
  z_enter();
  if (z_blob_system_default)
    {
      z_blob_system_unref(z_blob_system_default);
      z_blob_system_default = NULL;
    }
  z_return();
}
Esempio n. 20
0
GList *
z_header_set_get_all_headers(ZHeaderSet *self)
{
  GList *ret = NULL;

  z_enter();
  g_hash_table_foreach(self->headers,
                       z_header_set_append_foreach,
                       &ret);
  ret = g_list_reverse(ret);
  z_return(ret);
}
Esempio n. 21
0
/**
 * Initialize the default blob system.
 **/
void
z_blob_system_default_init(void)
{
  z_enter();
  z_blob_system_default = z_blob_system_new(z_blob_system_default_tmpdir,
                                            z_blob_system_default_max_disk_usage,
                                            z_blob_system_default_max_mem_usage,
                                            z_blob_system_default_lowat,
                                            z_blob_system_default_hiwat,
                                            z_blob_system_default_noswap_max);
  z_return();
}
Esempio n. 22
0
/**
 * Release the lock on the blob after z_blob_get_file.
 *
 * @param[in] self this
 *
 * Besides releasing the lock itself, this function also updates the
 * blob size from the file size.
 **/
void
z_blob_release_file(ZBlob *self)
{
  struct stat st;
  
  z_enter();
  g_assert(self);
  if (!fstat(self->fd, &st))
    self->size = self->alloc_size = st.st_size;
  else
    z_log(NULL, CORE_ERROR, 3, "Cannot stat file on release, blob size may be incorrect from now;");
  z_blob_unlock(self);
  z_return();
}
Esempio n. 23
0
gboolean
z_header_set_add(ZHeaderSet *self,
                 GString *key,
                 GString *value,
                 gboolean multiple)
{
  ZHeader *header;
  GList *hlist;

  z_enter();
  header = g_new0(ZHeader, 1);
  header->key = key;
  header->value = value;
  hlist = g_hash_table_lookup(self->headers, header->key->str);
  if (!hlist || (header->key->str[0] == 'X') || multiple)
    {
      self->headers_count++;
      hlist = g_list_append(hlist, header);
      g_hash_table_insert(self->headers, header->key->str, hlist);
      z_return(TRUE);
    }
  z_return(FALSE);
}
Esempio n. 24
0
gboolean 
z_policy_tuple_get_verdict(ZPolicyObj *tuple, guint *verdict)
{
  ZPolicyObj *tmp;
                                                                                
  z_enter();
  if (!z_policy_seq_check(tuple))
    {
      if (z_policy_var_parse(tuple, "i", verdict))
        z_return(TRUE);
      /* not a sequence nor an int */
      z_return(FALSE);
    }
                                                                                
  tmp = z_policy_seq_getitem(tuple, 0);
  if (!tmp || !z_policy_var_parse(tmp, "i", verdict))
    {
      /* policy syntax error */
      z_policy_var_unref(tmp);
      z_return(FALSE);
    }
  z_policy_var_unref(tmp);
  z_return(TRUE);
}
Esempio n. 25
0
/**
 * Truncates/expands a blob.
 *
 * @param[in] self this
 * @param[in] pos position to truncate at
 * @param[in] timeout timeout
 *
 * @returns TRUE on success
 **/
gboolean
z_blob_truncate(ZBlob *self, gint64 pos, gint timeout)
{
  gboolean      res = FALSE;

  z_enter();
  g_assert(self);
  g_assert(pos >= 0);
  if (z_blob_lock(self, timeout))
    {
      z_blob_alloc(self, pos);
      z_blob_unlock(self);
      res = TRUE;
    }
  z_return(res);
}
Esempio n. 26
0
/**
 * telnet_copy_buf:
 * @to: 
 * @from: 
 * @bytes: 
 *
 * 
 *
 * Returns:
 * 
 */
static gint
telnet_copy_buf(ZIOBufferDyn *to, ZIOBuffer *from, guint bytes)
{
  guint         i;

  z_enter();
  if ((i = to->size - to->end) < bytes)
    {
      /* we must allocate more buffer space */
      to->size += (1 + bytes / TELNET_BUFFER_SIZE) * TELNET_BUFFER_SIZE;
      to->buf = g_realloc(to->buf, to->size);
    }
  for (i = 0; to->end < to->size && from->ofs < from->end && i < bytes; to->end++, from->ofs++, i++)
      to->buf[to->end] = from->buf[from->ofs];
  z_return(i == bytes);
}
Esempio n. 27
0
static void
z_header_set_destroy_chain(GList *list)
{
  ZHeader *header;

  z_enter();
  while (list)
    {
      header = (ZHeader *)list->data;
      g_string_free(header->key, TRUE);
      g_string_free(header->value, TRUE);
      g_free(header);
      list = g_list_delete_link(list, list);
    }
  z_return();
}
Esempio n. 28
0
/**
 * Writes a blob out to disk, called only from z_blob_system_threadproc()
 *
 * @param[in] self this
 *
 * @warning Caller must hold a lock BOTH on the blob AND the blob system!
 **/
static void
z_blob_swap_out(ZBlob *self)
{
  off_t err;
  gssize written, remain;

  z_enter();
  g_assert(self);
  if (!self->storage_locked && !self->is_in_file && self->system)
    {
      err = lseek(self->fd, 0, SEEK_SET);
      if (err < 0)
        {
          z_log(NULL, CORE_ERROR, 0, "Blob error, lseek() failed; file='%s', error='%s'", self->filename, g_strerror(errno));
          g_assert(0);
        }
      remain = self->size;
      while (remain > 0)
        {
          written = write(self->fd, self->data, remain);
          if (written < 0)
            {
              if (errno == EINTR)
                {
                  continue;
                }
              else
                {
                  z_log(NULL, CORE_ERROR, 0, "Blob error, write() failed; file='%s', error='%s'", self->filename, g_strerror(errno));
                  g_assert(0);
                }
            }
          remain -= written;
        }
      self->is_in_file = 1;
      g_free(self->data);
      self->data = NULL;
      self->stat.swap_count++;
      self->stat.last_accessed = time(NULL);
      self->system->mem_used -= self->alloc_size;
      self->system->disk_used += self->alloc_size;
    }
  z_return();
}
Esempio n. 29
0
/**
 * Lock a blob.
 *
 * @param[in] self this
 * @param[in] timeout Timeout for locking. A negative value means infinite and thus blocking mode. Zero means nonblocking mode.
 *
 * @returns TRUE if successfully locked.
 **/
gboolean
z_blob_lock(ZBlob *self, gint timeout)
{
  gboolean        res;
  struct timeval  tvnow, tvfinish;

  z_enter();
  g_assert(self);

  if (timeout < 0)        /* infinite timeout -> blocking mode */
    {
      g_mutex_lock(self->mtx_lock);
      res = TRUE;
    }
  else if (timeout == 0)  /* zero timeout -> nonblocking mode */
    {
      res = g_mutex_trylock(self->mtx_lock);
    }
  else                    /* positive timeout */
    {
      gettimeofday(&tvfinish, NULL);
      tvfinish.tv_sec += (timeout / 1000);
      tvfinish.tv_usec += 1000 * (timeout % 1000);
      tvfinish.tv_sec += (tvfinish.tv_usec / 1000000);
      tvfinish.tv_usec %= 1000000;
      /* FIXME: maybe g_cond_wait_timed_wait ? */
      do
        {
          res = FALSE;
          if (g_mutex_trylock(self->mtx_lock))
            {
              res = TRUE;
              break;
            }
          usleep(1000);
          gettimeofday(&tvnow, NULL);
        } 
      while ((tvnow.tv_sec < tvfinish.tv_sec) ||
             ((tvnow.tv_sec == tvfinish.tv_sec) && (tvnow.tv_usec < tvfinish.tv_usec)));
    }
  z_return(res);
}
Esempio n. 30
0
/**
 * Decrease reference count of blob; destroy it if the count reaches zero.
 *
 * @param[in] self this
 **/
void
z_blob_unref(ZBlob *self)
{
  z_enter();
  if (self && z_refcount_dec(&self->ref_cnt))
    {
      g_mutex_lock(self->system->mtx_blobsys);
      self->alloc_req = -self->alloc_size;
      self->system->blobs = g_list_remove(self->system->blobs, self);
      z_blob_check_alloc(self);
      g_mutex_unlock(self->system->mtx_blobsys);

      if (self->data)
        g_free(self->data);

      if (self->fd >= 0)
        close(self->fd);

      if (self->filename)
        {
          if (unlink(self->filename))
            z_log(NULL, CORE_ERROR, 3, "Error removing blob file, unlink() failed; file='%s', error='%s'", self->filename, strerror(errno));
          g_free(self->filename);
          self->filename = NULL;
        }

      g_mutex_free(self->mtx_reply);
      g_cond_free(self->cond_reply);
      if (g_mutex_trylock(self->mtx_lock))
        {
          g_mutex_unlock(self->mtx_lock);
          g_mutex_free(self->mtx_lock);
        }
      else
        {
          z_log(NULL, CORE_ERROR, 3, "Error while destroying blob, someone still has a lock on it;");
          /* someone has locked the blob by z_blob_get_file or _get_ptr, and forgot to release it */
        }
      g_free(self);
    }
  z_return();
}