My Project
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
dbops.c
Go to the documentation of this file.
1 /*
2 START OF LICENSE STUB
3  DeDOS: Declarative Dispersion-Oriented Software
4  Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 END OF LICENSE STUB
19 */
20 #include <stdlib.h>
21 #include "logging.h"
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <strings.h>
25 #include <arpa/inet.h>
26 #include <unistd.h>
28 
29 #ifndef MAX_FILE_SIZE
30 #define MAX_FILE_SIZE (long)(1 * (1 << 29))
31 #endif
32 #define JUMP_SIZE (1 << 14)
33 
34 int db_num_files = -1;
35 struct sockaddr_in db_addr;
36 
37 struct mock_file {
38  int n_chunks;
39  int *chunk_size;
40  char **data;
41 };
42 
43 long allocate_file(struct mock_file *file, long file_size) {
44  int n_chunks = file_size / INT_MAX + 1;
45  file->n_chunks = n_chunks;
46  file->chunk_size = malloc(sizeof(int) * n_chunks);
47  long amount_allocated = 0;
48  int chunk_size = INT_MAX;
49  file->data = malloc(sizeof(char*) * n_chunks);
50  for (int i=0; amount_allocated < file_size; i++) {
51  if (amount_allocated + chunk_size > file_size) {
52  long chunk_tmp = (file_size - amount_allocated);
53  if (chunk_tmp > (long)(INT_MAX)) {
54  printf("Warning: Chunk size too big!\n");
55  }
56  chunk_size = (int)chunk_tmp;
57  }
58  file->chunk_size[i] = chunk_size;
59  file->data[i] = malloc(chunk_size);
60  amount_allocated += chunk_size;
61  memset(file->data[i], 0, chunk_size);
62  }
63  return amount_allocated;
64 }
65 
66 long access_file(struct mock_file *file, long total_size) {
67  long accessed = 0;
68  for (int chunk = 0; accessed < total_size; chunk++) {
69  int chunk_size = file->chunk_size[chunk];
70  char *data = file->data[chunk];
71  for (int i = 0; i < chunk_size; i += JUMP_SIZE) {
72  data[i]++;
73  }
74  accessed += (long)chunk_size;
75  }
76  return accessed;
77 }
78 
79 void init_db(char *ip, int port, int n_files) {
80  db_num_files = n_files;
81  bzero((char*)&db_addr, sizeof(db_addr));
82  db_addr.sin_family = AF_INET;
83  inet_pton(AF_INET, ip, &(db_addr.sin_addr));
84  db_addr.sin_port = htons(port);
85 }
86 
88  struct mock_file *file = malloc(sizeof(*file));
90  return (void*)file;
91 }
92 
93 void free_db_memory(void *memory) {
94  struct mock_file *file = memory;
95  for (int i=0; i <file->n_chunks; i++) {
96  free(file->data[i]);
97  }
98  free(file->chunk_size);
99  free(file->data);
100  free(file);
101 }
102 
103 
105  int db_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
106  if (db_fd < 0) {
107  log_error("failure opening socket");
108  return -1;
109  }
110  int optval = 1;
111  if (setsockopt(db_fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) < 0) {
112  log_error("failed to set SO_REUSEPORT");
113  }
114  if (setsockopt(db_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
115  log_error("failed to set SO_REUSEADDR");
116  }
117  //add_to_epoll(0, db_fd, 0);
118  return db_fd;
119 }
120 
122  if (state->db_fd <= 0) {
123  state->db_fd = init_db_socket();
124  if (state->db_fd == -1) {
125  return -1;
126  }
127  }
128  int rtn = connect(state->db_fd, (struct sockaddr*)&db_addr, sizeof(db_addr)) < 0;
129  if (rtn < 0) {
130  if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
131  log(LOG_DB_OPS, "Connection in progress..");
132  return 1;
133  } else {
134  log_perror("Connect to socket failed");
135  close(state->db_fd);
136  return -1;
137  }
138  }
139  int db_param = rand() % db_num_files;
140  sprintf(state->db_req, "%d", db_param);
141  return 0;
142 }
143 
144 int send_to_db(struct db_state *state) {
145  if (send(state->db_fd, state->db_req, strlen(state->db_req), 0) == -1) {
146  if (errno == EAGAIN || errno == EWOULDBLOCK) {
147  return 1;
148  } else {
149  log_perror("Error sending to database on fd %d", state->db_fd);
150  return -1;
151  }
152  }
153  return 0;
154 }
155 
156 #define MAX_DB_RCV_LEN 64
157 
159  char rcv[MAX_DB_RCV_LEN];
160  socklen_t addrlen = sizeof(db_addr);
161  int rtn = recvfrom(state->db_fd, rcv, MAX_DB_RCV_LEN, 0,
162  (struct sockaddr*)&db_addr, &addrlen);
163 
164  if (rtn < 0) {
165  if (errno == EAGAIN || errno == EWOULDBLOCK) {
166  return 1;
167  } else {
168  log_perror("Error receiving from database");
169  return -1;
170  }
171  }
172 
173  //long file_size = atol(rcv);
174  struct mock_file *local_file = state->data;
175 
176  access_file(local_file, MAX_FILE_SIZE);
177  close(state->db_fd);
178  state->db_fd = 0;
179  return 0;
180 }
181 
182 int query_db(struct db_state *state) {
183  if (db_num_files == -1) {
184  log_error("Database is not initialized");
185  return WS_ERROR;
186 
187  }
188 
189  int rtn;
190  switch (state->status) {
191  case DB_NO_CONNECTION:
192  case DB_CONNECTING:
193  rtn = connect_to_db(state);
194  if (rtn == -1) {
195  state->status = DB_ERR;
196  return WS_ERROR;
197  } else if (rtn == 1) {
198  state->status = DB_CONNECTING;
199  return WS_INCOMPLETE_WRITE;
200  } else if (rtn == 0) {
201  state->status = DB_SEND;
202  // Continue on...
203  } else {
204  log_error("Unknown status %d", rtn);
205  state->status = DB_ERR;
206  return WS_ERROR;
207  }
208  case DB_SEND:
209  rtn = send_to_db(state);
210  if (rtn == -1) {
211  state->status = DB_ERR;
212  return WS_ERROR;
213  } else if (rtn == 1) {
214  return WS_INCOMPLETE_WRITE;
215  } else if (rtn == 0) {
216  state->status = DB_RECV;
217  // Continue on...
218  } else {
219  log_error("Unknown status %d", rtn);
220  state->status = DB_ERR;
221  return WS_ERROR;
222  }
223  case DB_RECV:
224  rtn = recv_from_db(state);
225  if (rtn == -1) {
226  state->status = DB_ERR;
227  return WS_ERROR;
228  } else if (rtn == 1) {
229  return WS_INCOMPLETE_READ;
230  } else if (rtn == 0) {
231  state->status = DB_DONE;
232  return WS_COMPLETE;
233  } else {
234  state->status = DB_ERR;
235  log_error("Unknown status %d", rtn);
236  return WS_ERROR;
237  }
238  default:
239  log_error("Unhandled state: %d", state->status);
240  return WS_ERROR;
241  }
242 
243 }
int connect_to_db(struct db_state *state)
Definition: dbops.c:121
int * chunk_size
Definition: dbops.c:39
int recv_from_db(struct db_state *state)
Definition: dbops.c:158
long allocate_file(struct mock_file *file, long file_size)
Definition: dbops.c:43
struct sockaddr_in db_addr
Definition: dbops.c:35
void * allocate_db_memory()
Definition: dbops.c:87
#define JUMP_SIZE
Definition: dbops.c:32
#define MAX_DB_RCV_LEN
Definition: dbops.c:156
Definition: dbops.h:26
long access_file(struct mock_file *file, long total_size)
Definition: dbops.c:66
enum db_status status
Definition: dbops.h:36
#define WS_INCOMPLETE_READ
Definition: webserver.h:25
#define log_perror(fmt,...)
Definition: logging.h:102
int db_fd
Definition: dbops.h:33
Logging of status messages to the terminal.
int send_to_db(struct db_state *state)
Definition: dbops.c:144
Definition: dbops.h:27
#define WS_INCOMPLETE_WRITE
Definition: webserver.h:26
int init_db_socket()
Definition: dbops.c:104
void free_db_memory(void *memory)
Definition: dbops.c:93
#define log_error(fmt,...)
Definition: logging.h:101
char ** data
Definition: dbops.c:40
int n_chunks
Definition: dbops.c:38
Definition: dbops.h:29
Definition: dbops.h:32
int query_db(struct db_state *state)
Definition: dbops.c:182
void init_db(char *ip, int port, int n_files)
Definition: dbops.c:79
Definition: dbops.h:28
void * data
Definition: dbops.h:35
#define WS_COMPLETE
Definition: webserver.h:24
#define WS_ERROR
Definition: webserver.h:27
char db_req[16]
Definition: dbops.h:34
#define MAX_FILE_SIZE
Definition: dbops.c:30
#define log(level, fmt,...)
Log at a custom level.
Definition: logging.h:147
int db_num_files
Definition: dbops.c:34
state
Definition: http_parser.c:298