File: sqlite3_csv_vtab-mem.c

package info (click to toggle)
zsv 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 49,160 kB
  • sloc: ansic: 175,811; cpp: 56,301; sh: 3,623; makefile: 3,048; javascript: 577; cs: 90; awk: 70; python: 41; sql: 15
file content (142 lines) | stat: -rw-r--r-- 3,763 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <pthread.h>

/**
 * see sqlite3_csv_vtab-mem.h for background info
 */
#if defined(_WIN32) || defined(_WIN64)
#include <process.h>
#else
#include <unistd.h>
#endif

struct sqlite3_zsv_data {
  struct sqlite3_zsv_data *next;
  pid_t pid;
  char *filename;
  struct zsv_opts opts;
  struct zsv_prop_handler custom_prop_handler;
};

pthread_mutex_t sqlite3_zsv_data_mutex;
struct sqlite3_zsv_data *sqlite3_zsv_data_g = NULL;

/**
 * Our shared memory structure should be locked for read/write
 */
static int sqlite3_zsv_data_lock(void) {
#ifndef NO_THREADING
  pthread_mutex_lock(&sqlite3_zsv_data_mutex);
#endif
  return 0;
}

static int sqlite3_zsv_data_unlock(void) {
#ifndef NO_THREADING
  pthread_mutex_unlock(&sqlite3_zsv_data_mutex);
#endif
  return 0;
}

static void sqlite3_zsv_data_delete(struct sqlite3_zsv_data *e) {
  if (e) {
    free(e->filename);
  }
  free(e);
}

void sqlite3_zsv_list_delete(void **list) {
  for (struct sqlite3_zsv_data *next, *e = *list; e; e = next) {
    next = e->next;
    sqlite3_zsv_data_delete(e);
  }
#ifndef NO_THREADING
  pthread_mutex_destroy(&sqlite3_zsv_data_mutex);
#endif
  *list = NULL;
}

static struct sqlite3_zsv_data *sqlite3_zsv_data_new(const char *filename, struct zsv_opts *opts,
                                                     struct zsv_prop_handler *custom_prop_handler) {
  if (!filename)
    return NULL;
  struct sqlite3_zsv_data *e = calloc(1, sizeof(*e));
  if (e) {
    e->pid = getpid();
    e->filename = strdup(filename);
    if (opts)
      e->opts = *opts;
    if (custom_prop_handler)
      e->custom_prop_handler = *custom_prop_handler;
    if (e->filename)
      return e;
  }
  sqlite3_zsv_data_delete(e);
  return NULL;
}

int sqlite3_zsv_list_add(const char *filename, struct zsv_opts *opts, struct zsv_prop_handler *custom_prop_handler) {
  struct sqlite3_zsv_data **list = &sqlite3_zsv_data_g;
  struct sqlite3_zsv_data *e = sqlite3_zsv_data_new(filename, opts, custom_prop_handler);
  if (e) {
    struct sqlite3_zsv_data **next;
    if (sqlite3_zsv_data_lock()) {
      sqlite3_zsv_data_delete(e);
      return -1;
    } else {
      for (next = list; *next; next = &(*next)->next)
        ;
      *next = e;
      sqlite3_zsv_data_unlock();
      return 0;
    }
  }
  return ENOMEM;
}

static int sqlite3_zsv_data_cmp(struct sqlite3_zsv_data *x, const char *filename, pid_t pid) {
  return strcmp(x->filename, filename) && x->pid == pid;
}

struct sqlite3_zsv_data *sqlite3_zsv_data_find(const char *filename) {
  struct sqlite3_zsv_data *list = sqlite3_zsv_data_g;
  struct sqlite3_zsv_data *found = NULL;
  pid_t pid = getpid();
  if (!sqlite3_zsv_data_lock()) {
    for (struct sqlite3_zsv_data *e = list; e && !found; e = e->next) {
      if (!sqlite3_zsv_data_cmp(e, filename, pid))
        found = e;
    }
    if (sqlite3_zsv_data_unlock())
      fprintf(stderr, "Error unlocking sqlite3-csv-zsv shared mem lock\n");
  }
  return found;
}

int sqlite3_zsv_list_remove(const char *filename) {
  if (!filename)
    return 0;
  struct sqlite3_zsv_data **list = &sqlite3_zsv_data_g;
  struct sqlite3_zsv_data *found = NULL;
  pid_t pid = getpid();
  if (*list) {
    if (!sqlite3_zsv_data_cmp(*list, filename, pid)) {
      // found a match at the head of list
      found = *list;
      *list = found->next;
    } else {
      // look for a match somewhere after the first element
      for (struct sqlite3_zsv_data *prior = *list; prior->next != NULL; prior = prior->next) {
        if (!sqlite3_zsv_data_cmp(prior->next, filename, pid)) {
          found = prior->next;
          prior->next = prior->next->next;
          break;
        }
      }
    }
  }
  if (found) {
    sqlite3_zsv_data_delete(found);
    return 0;
  }
  return ENOENT; // not found
}