root/platform/mysql/mycached/trunk/mycached.hh @ 35004

Revision 35004, 4.9 kB (checked in by kazuho, 4 years ago)

add license

Line 
1/*
2 * mycached - memcached protocol handler for mysqld
3 *
4 * Copyright (C) 2009 Cybozu Labs, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the FreeSoftware
8 * Foundation; either version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#ifndef mycached_hh
21#define mycached_hh
22
23#include <cassert>
24#include <stdexcept>
25#include <string>
26#include <vector>
27extern "C" {
28#include "picoev.h"
29}
30
31#define MYSQL_SERVER 1
32
33#include "mysql_priv.h"
34#include "sql_select.h"
35
36#define NUM_THREADS 4
37#define MAX_FDS 1024
38#define TIMEOUT_SECS 3600
39#define REQBUF_SZ 1048576
40
41namespace mycached {
42 
43  struct error_t : public std::domain_error {
44    error_t(const std::string& what) : std::domain_error(what) {}
45  };
46 
47  struct range_string {
48    const char* first_, * last_;
49    range_string() : first_(NULL), last_(NULL) {}
50    range_string(const char* first, const char* last)
51      : first_(first), last_(last) {}
52    size_t size() const { return last_ - first_; }
53    void clear() { first_ = last_ = NULL; }
54    bool to_int(long long& v) const {
55      v = 0;
56      bool is_negative = false;
57      const char* p = first_;
58      if (p != last_ && *p == '-') {
59        is_negative = true;
60        ++p;
61      }
62      if (p == last_) {
63        return false;
64      }
65      do {
66        if (! ('0' <= *p && *p <= '9')) {
67          return false;
68        }
69        v = v * 10 + *p - '0';
70      } while (++p != last_);
71      if (is_negative) {
72        v *= -1;
73      }
74      return v;
75    }
76  };
77
78  inline
79  bool
80  operator==(const range_string& x, const range_string& y)
81  {
82    if (x.size() != y.size()) {
83      return false;
84    }
85    if (x.first_ == y.first_) {
86      return true;
87    }
88    if (x.first_ == NULL || y.first_ == NULL) {
89      return true;
90    }
91    for (const char* xp = x.first_, * yp = y.first_;
92         xp != x.last_;
93         ++xp, ++yp) {
94      if (*xp != *yp) {
95        return false;
96      }
97    }
98    return true;
99  }
100 
101  inline
102  bool
103  operator!=(const range_string& x, const range_string& y)
104  {
105    return ! (x == y);
106  }
107
108  struct key_t {
109    range_string db_;
110    range_string table_;
111    range_string key_str_;
112    uchar key_value_[8];
113    range_string entire_key() const {
114      return range_string(db_.first_, key_str_.last_);
115    }
116  };
117
118  struct fetcher_t {
119    THD* thd_;
120    Query_tables_list tables_;
121    size_t num_tables_;
122    const std::vector<key_t>& keys_;
123    enum {
124      state_not_locked,
125      state_locked,
126      state_index_is_open
127    } state_;
128    fetcher_t(THD* thd, const std::vector<key_t>& keys);
129    ~fetcher_t();
130    void fetch(std::string& response);
131    void register_table(const range_string& db, const range_string& table);
132    TABLE_LIST* get_table(const range_string& db, const range_string& table,
133                          size_t& idx) {
134      idx = 0;
135      for (TABLE_LIST* tl = tables_.query_tables;
136           tl != NULL;
137           tl = tl->next_global, ++idx) {
138        if (table.size() == tl->table_name_length
139            && strncmp(table.first_, tl->table_name, table.size()) == 0
140            && db.size() == tl->db_length
141            && strncmp(db.first_, tl->db, db.size()) == 0) {
142          return tl;
143        }
144      }
145      return NULL;
146    }
147    static void build_response(const key_t& key, TABLE* table,
148                               std::string& response);
149  };
150 
151  struct conn_t {
152    enum {
153      rr_invalid_request = 0,
154      rr_too_long,
155      rr_closed
156    };
157    THD* thd_;
158    int sock_;
159    size_t res_off_;
160    std::string res_buf_;
161    size_t req_off_;
162    char req_buf_[REQBUF_SZ]; // TODO shrinkable
163    static int listen_sock_;
164    conn_t(THD* thd, picoev_loop* loop, int sock)
165      : thd_(thd), sock_(sock), res_off_(0), res_buf_(), req_off_(0) {
166      picoev_add(loop, sock_, PICOEV_READ, TIMEOUT_SECS, handle_conn, this);
167    }
168    size_t parse_request(std::vector<key_t>& keys, bool& is_partial) const;
169    bool build_send_response(const std::vector<key_t>& keys);
170    bool handle_request();
171    void handle_conn(picoev_loop* loop);
172    static const char* get_token(const char* s, const char* s_end,
173                                 range_string& token) {
174      const char* first = s;
175      for (; s != s_end; ++s) {
176        switch (*s) {
177        case '\r': case '\n': case ' ': case '.':
178          token = range_string(first, s);
179          return s;
180        default:
181          break;
182        }
183      }
184      token.clear();
185      return NULL;
186    }
187    static void handle_conn(picoev_loop* loop, int, int, void* cb_arg);
188    static void accept_conn(picoev_loop* loop, int fd, int, void* cb_arg);
189    static void* event_loop(void* _thd);
190    static bool start_server(unsigned host, unsigned short port);
191  };
192
193}
194
195#endif
Note: See TracBrowser for help on using the browser.