Exemple #1
0
static int
smrCbClose (void *arg, long long seq, short nid, int sid)
{
  redisClient *c;
  callbackInfo *cb;
  dlisth *node;

  if (nid != smr_get_nid (server.smr_conn)
      || !(server.smr_init_flags & SMR_INIT_DONE))
    return REDIS_OK;

  /* query from this server. get client from global callback list */
  assert (!dlisth_is_empty (&server.global_callbacks));	/* global callback list shouldn't be empty */
  node = server.global_callbacks.next;
  cb = (callbackInfo *) node;
  dlisth_delete (&cb->global_head);
  dlisth_delete (&cb->client_head);
  c = cb->client;
  zfree (cb);

  if (c->fd == -1)
    return REDIS_OK;		/* ignore if the client is already freed */

  assert (c->fd == sid);

  addReplyError (c, c->smr.protocol_error_reply);
  c->flags |= REDIS_CLOSE_AFTER_REPLY;

  return REDIS_OK;
}
Exemple #2
0
/*
 * hash_destroy - destroy static hash table
 *    return: void
 *    ht(in): hash table
 *    dtor(in): element destructor function
 */
void
hash_destroy (hash_table * ht, ht_destroyf dtor)
{
  int i;

  assert (ht != NULL);
  if (ht == NULL)
    return;

  for (i = 0; i < ht->bucket_sz; i++)
    {
      dlisth *h, *header;
      h = header = &ht->buckets[i].head;
      h = h->next;
      while (h != header)
	{
	  ht_elem *hte = (ht_elem *) h;
	  h = h->next;

	  dlisth_delete ((dlisth *) hte);
	  if (dtor)
	    dtor (hte->elem);
	  API_FREE (hte);
	}
    }
  API_FREE (ht);
}
Exemple #3
0
/*
 * li_api_delete - delete existing element at the given position
 *    return: NO_ERROR if successful, error code otherwise
 *    indexer(in): VALUE_INDEXER
 *    index(in): index of the element
 *    rva(out): pointer to VALUE_AREA
 *    dbval(out): pointer to API_VALUE
 */
static int
li_api_delete (VALUE_INDEXER * indexer, int index, VALUE_AREA ** rva,
	       API_VALUE ** dbval)
{
  LIST_INDEXER *li = (LIST_INDEXER *) indexer;
  LIST_INDEXER_ELEM *e;

  assert (li != NULL);
  assert (li->nelems > 0);
  assert (index >= 0 && index < li->nelems);
  assert (rva != NULL);
  assert (dbval != NULL);

  assert (li->cache_idx >= 0 && li->cache_elem != NULL);
  e = li_getf (li, index);
  assert (e != NULL);

  *rva = e->va;
  *dbval = e->value;
  li->nelems--;
  /* ajust cache */
  if (li->nelems > 0)
    {
      if (index < li->cache_idx)
	{
	  li->cache_idx--;
	}
      else if (index == li->cache_idx)
	{
	  if (index > 0)
	    {
	      li->cache_idx = index - 1;
	      li->cache_elem = (LIST_INDEXER_ELEM *) (((dlisth *) e)->prev);
	    }
	  else
	    {
	      li->cache_elem = (LIST_INDEXER_ELEM *) (((dlisth *) e)->next);
	    }
	}
    }
  else
    {
      li->cache_idx = -1;
      li->cache_elem = NULL;
    }
  dlisth_delete ((dlisth *) e);
  API_FREE (e);
  return NO_ERROR;
}
/*
 * li_api_destroy - destroy value indexer
 *    return: void
 *    indexer(in): VALUE_INDEXER
 *    df(in): element destroy function
 */
static void
li_api_destroy (VALUE_INDEXER * indexer, void (*df) (VALUE_AREA * va, API_VALUE * db))
{
  LIST_INDEXER *li = (LIST_INDEXER *) indexer;

  assert (li != NULL);
  while (!dlisth_is_empty (&li->elems))
    {
      LIST_INDEXER_ELEM *e = (LIST_INDEXER_ELEM *) li->elems.next;
      if (df)
	df (e->va, e->value);
      dlisth_delete ((dlisth *) e);
      API_FREE (e);
    }
  API_FREE (li);
}
Exemple #5
0
/*
 * api_free - free() debug version
 *    return: void
 *    ptr(in): pointer to allcated memory via api_malloc(), api_calloc()
 *    file(in): file name
 *    line(in): line number
 */
void
api_free (void *ptr, const char *file, int line)
{
  char *p = NULL;

  if (api_malloc_dhook_flag_set == 0)
    return free (ptr);

  API_ONCE_FUNC (&once, once_function);
  if (ptr)
    {
      p = (char *) ptr - MALLOC_HEADER_SZ;
      API_LOCK (&mutex);
      dlisth_delete ((dlisth *) p);
      free_count++;
      API_UNLOCK (&mutex);
    }
  free (p);
}
Exemple #6
0
/*
 * hash_delete - delete hash entry from hash table and return element found
 *    return: NO_ERROR if successful, error_code otherwise
 *    ht(in): hash table
 *    key(in): pointer to the key
 *    relem(out): element found, or set to NULL
 * 
 * NOTE
 *   When element is not found then NO_ERROR returned with NULL relem value
 */
int
hash_delete (hash_table * ht, void *key, void **relem)
{
  int rc;
  unsigned int hcode;
  dlisth *h, *header;

  assert (ht != NULL);
  assert (relem != NULL);
  *relem = NULL;

  rc = ht->hashf (key, &hcode);
  if (rc != NO_ERROR)
    return rc;

  hcode = hcode % ht->bucket_sz;
  header = &ht->buckets[(size_t) hcode].head;
  for (h = header->next; h != header; h = h->next)
    {
      int r;
      ht_elem *hte = (ht_elem *) h;
      void *ekey;

      if ((rc = ht->keyf (hte->elem, &ekey)) != NO_ERROR)
	return rc;

      if ((rc = ht->comparef (key, ekey, &r)) == NO_ERROR && r == 0)
	{
	  *relem = hte->elem;
	  dlisth_delete (h);
	  API_FREE (hte);
	  return NO_ERROR;
	}
      else if (rc != NO_ERROR)
	return rc;
    }
  return NO_ERROR;
}
Exemple #7
0
/* sid = |flags(4byte)|client fd(4byte)| */
static int
smrCbData (void *arg, long long seq, long long timestamp,
	   short nid, int sid, int hash, smrData * smr_data, int size)
{
  char *data = smr_data_get_data (smr_data);
  redisClient *c;
  short cmdflags;
  dlisth *node;

  /* Special commands */
  if (size == 1 && data[0] == REDIS_SMR_CMD_CATCHUP_CHECK)
    {
      if (nid == smr_get_nid (server.smr_conn)
	  && (server.smr_init_flags & SMR_INIT_CATCHUP_PHASE2))
	checkSmrCatchup ();
      goto release_seq;
    }
  else if (size == 1 && data[0] == REDIS_SMR_CMD_DELIVER_OOM)
    {
      server.smr_oom_until = timestamp + REDIS_OOM_DURATION_MS;
      goto release_seq;
    }

  /* Normal command */
  server.smr_mstime = timestamp;
  cmdflags = (0xFFFF0000 & sid) >> 16;

  /* Because we fixed the bug that causes timestamp be 0, 
   * this warning log is not necessary and just an assert statement is enough after all.
   * But currently, there are nbase-arc clusters which have the bug.
   * So, we don't assert for now. */
  if (timestamp == 0)
    {
      redisLog (REDIS_WARNING, "Timestamp of SMR callback is 0,"
		"seq:%lld, nid:%d, sid:%d, hash:%d, size:%d",
		seq, nid, sid, hash, size);
    }

  if ((server.smr_init_flags & SMR_INIT_DONE)
      && nid == smr_get_nid (server.smr_conn))
    {
      callbackInfo *cb;
      /* query from this server. get client from global callback list */
      assert (!dlisth_is_empty (&server.global_callbacks));	/* global callback list shouldn't be empty */
      node = server.global_callbacks.next;
      cb = (callbackInfo *) node;
      dlisth_delete (&cb->global_head);
      dlisth_delete (&cb->client_head);
      c = cb->client;
      assert (cb->hash == hash);
      assert (c->fd == -1 || c->fd == (0X0000FFFF & sid));

      /* We already parsed querybuf because the query is requested from this 
       * server before smr callback*/
      c->argc = cb->argc;
      c->argv = cb->argv;
      cb->argc = 0;
      cb->argv = NULL;
      zfree (cb);

      server.current_client = c;

      /* fake client doesn't need to execute non-write query(read-only or admin) */
      if (c->fd != -1 || cmdflags & REDIS_CMD_WRITE)
	{
	  assert (!(c->flags & REDIS_CLOSE_AFTER_REPLY));
	  processCommand (c);
	}
    }
  else
    {
      /* replicated query from other servers, or catchup query during initialize */
      c = server.smrlog_client;
      server.current_client = c;

      /* fake client doesn't need to execute non-write query(read-only or admin) */
      if (cmdflags & REDIS_CMD_WRITE)
	{
	  /* We need to parse querybuf because the query is from different server 
	   * or we are recovering without client */
	  sdsclear (c->querybuf);
	  c->querybuf = sdsMakeRoomFor (c->querybuf, size);
	  memcpy (c->querybuf, data, size);
	  sdsIncrLen (c->querybuf, size);
	  if (c->querybuf_peak < size)
	    c->querybuf_peak = size;
	  processInputBuffer (c);
	}
    }

  resetClient (c);
  zfree (c->argv);
  c->argv = NULL;
  server.current_client = NULL;

release_seq:
  if (smr_release_seq_upto (server.smr_conn, seq + size) == -1)
    {
      redisLog (REDIS_WARNING, "smr_release_seq_upto error");
      redisAssert (0);
      return REDIS_ERR;
    }
  server.smr_seqnum = seq + size;

  return REDIS_OK;
}