/*
 * Yet another daemon library especially designed to be used
 * with libsxmp based daemons.
 *
 * (c) Alexander Vdolainen 2016 <avdolainen@zoho.com>
 *
 * libsxmp is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libsxmp is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 *
 */

#ifndef __YDATA_CACHE_H__
#define __YDATA_CACHE_H__

#include <pthread.h>

#define YD_CACHE_SPACER_MAGIC  0xbeafbeef

/* item flags */
#define YDC_INVALIDATE  (1 << 1)
#define YDC_UNUSED      (1 << 2)
#define YDC_DIRTY       (1 << 3)

typedef struct __ydata_cache_item_type {
  oid_t oid;
  uint32_t idx;
  uint8_t attr;
  usrtc_node_t idxnode;
  list_node_t listnode;
} ydata_cache_item_t;

#define yd_item_idx(item)  (item)->idx
#define yd_item_setoid(it, id)  (it)->oid = id

typedef struct __ydata_qitem_type {
  ydata_cache_item_t *item;
  list_node_t node;
} ydata_qitem_t;

#define YDC_SYNCTHRESHOLD  64
#define YDC_SYNCDELTASEC   30

typedef struct  __ydata_cache_t {
  usrtc_t idx_tree;
  list_head_t free_poll;
  list_head_t dirty_poll;
  list_head_t pending_poll;
  void *cache;
  size_t object_size;
  size_t objects_amount;
  size_t cache_size;
  size_t dirties;
  pthread_t syncthread;
  pthread_rwlock_t rwlock;
  pthread_mutex_t dirtlock;
} ydata_cache_t;

#define yd_cache_rdlock(c)  pthread_rwlock_rdlock(&(c)->rwlock)
#define yd_cache_wrlock(c)  pthread_rwlock_wrlock(&(c)->rwlock)
#define yd_cache_unlock(c)  pthread_rwlock_unlock(&(c)->rwlock)

#define yd_cache_ptrbyidx(c, n)  (char *)(c)->cache + n*((c)->object_size + sizeof(uint32_t))

/* API, mostly internally used, but might be useful */
ydata_cache_t *yd_cache_init(dataobject_t *, size_t);

void *yd_cache_alloc_item(ydata_cache_t *, ydata_cache_item_t **);

void yd_cache_discard_alloc_item(ydata_cache_t *, ydata_cache_item_t *);

void yd_cache_confirm_alloc_item(ydata_cache_t *, ydata_cache_item_t *, oid_t);

void *yd_cache_lookup(ydata_cache_t *, oid_t);

list_head_t *yd_cache_getrslist(ydata_cache_t *, uint8_t);

void yd_cache_qitems_pullback(ydata_cache_t *, list_head_t *);

void yd_cache_item_dirtyoid(ydata_cache_t *, oid_t);

void yd_cache_item_invalidateoid(ydata_cache_t *, oid_t);

int yd_cache_start_thread(domx_t *);

#endif /* __YDATA_CACHE_H__ */