~drizzle-trunk/libdrizzle/jenkins-Libdrizzle-6

« back to all changes in this revision

Viewing changes to cli/drizzle_binlogs.c

  • Committer: Andrew Hutchings
  • Date: 2012-12-18 20:14:26 UTC
  • mfrom: (43.2.8 libdrizzle-redux-5)
  • Revision ID: andrew@linuxjedi.co.uk-20121218201426-rj8t6m4sc91jdxks
Megre libdrizzle redux 5 changes into trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Drizzle Client & Protocol Library
 
3
 *
 
4
 * Copyright (C) 2012 Andrew Hutchings (andrew@linuxjedi.co.uk)
 
5
 * All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions are
 
9
 * met:
 
10
 *
 
11
 *     * Redistributions of source code must retain the above copyright
 
12
 * notice, this list of conditions and the following disclaimer.
 
13
 *
 
14
 *     * Redistributions in binary form must reproduce the above
 
15
 * copyright notice, this list of conditions and the following disclaimer
 
16
 * in the documentation and/or other materials provided with the
 
17
 * distribution.
 
18
 *
 
19
 *     * The names of its contributors may not be used to endorse or
 
20
 * promote products derived from this software without specific prior
 
21
 * written permission.
 
22
 *
 
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
26
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
27
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
28
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
29
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
30
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
31
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
32
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
33
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
34
 *
 
35
 */
 
36
 
 
37
#include "config.h"
 
38
#include <libdrizzle-5.0/libdrizzle.h>
 
39
#include <stdlib.h>
 
40
#include <glib.h>
 
41
#include <glib/gstdio.h>
 
42
#include <pwd.h>
 
43
#include <unistd.h>
 
44
 
 
45
#define STR_HELPER(x) #x
 
46
#define STR(x) STR_HELPER(x)
 
47
 
 
48
gchar *host= NULL;
 
49
gint port= DRIZZLE_DEFAULT_TCP_PORT;
 
50
gchar *user= NULL;
 
51
gboolean user_alloced= FALSE;
 
52
gchar *pass= NULL;
 
53
gchar *outdir= NULL;
 
54
gchar *start_file= NULL;
 
55
gint start_pos= 0;
 
56
gboolean continuous= FALSE;
 
57
 
 
58
static GOptionEntry main_options[]= {
 
59
  { "host", 0, 0, G_OPTION_ARG_STRING, &host, "Hostname of server, default "DRIZZLE_DEFAULT_TCP_HOST, NULL },
 
60
  { "port", 0, 0, G_OPTION_ARG_INT, &port, "Port number of server, default "STR(DRIZZLE_DEFAULT_TCP_PORT), NULL },
 
61
  { "user", 0, 0, G_OPTION_ARG_STRING, &user, "Username for the server, default is current system user", NULL },
 
62
  { "pass", 0, 0, G_OPTION_ARG_STRING, &pass, "Password for the server", NULL },
 
63
  { "outdir", 0, 0, G_OPTION_ARG_FILENAME, &outdir, "Output directory", NULL },
 
64
  { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
 
65
};
 
66
 
 
67
static GOptionEntry binlog_options[]= {
 
68
  { "start-file", 0, 0, G_OPTION_ARG_FILENAME, &start_file, "Binlog file to start with", NULL },
 
69
  { "start-pos", 0, 0, G_OPTION_ARG_INT, &start_pos, "Position to start with", NULL },
 
70
  { "continuous", 0, 0, G_OPTION_ARG_NONE, &continuous, "Continous download mode", NULL }
 
71
};
 
72
 
 
73
gboolean get_system_user(char *dest, uint8_t len);
 
74
drizzle_con_st *_connect(void);
 
75
FILE *create_binlog_file(char *binlog_file);
 
76
void get_binlogs(drizzle_con_st *con);
 
77
void write_binlog(FILE* file, const uint8_t* data, uint32_t len);
 
78
 
 
79
gboolean get_system_user(char *dest, uint8_t len)
 
80
{
 
81
  long pw_len= sysconf(_SC_GETPW_R_SIZE_MAX);
 
82
  struct passwd pw_struct;
 
83
  struct passwd *pw_tmp_struct;
 
84
  if (pw_len == -1)
 
85
  {
 
86
    pw_len= 1024;
 
87
  }
 
88
  char *pw_buffer= g_malloc(pw_len);
 
89
 
 
90
  if (getpwuid_r(geteuid(), &pw_struct, pw_buffer, pw_len, &pw_tmp_struct) == 0)
 
91
  {
 
92
    g_strlcpy(dest, pw_struct.pw_name, len);
 
93
    g_free(pw_buffer);
 
94
    return TRUE;
 
95
  }
 
96
  g_free(pw_buffer);
 
97
  return FALSE;
 
98
}
 
99
 
 
100
drizzle_con_st *_connect(void)
 
101
{
 
102
  drizzle_st *drizzle;
 
103
  drizzle_con_st *con;
 
104
  drizzle_return_t ret;
 
105
 
 
106
  drizzle= drizzle_create();
 
107
  if (!drizzle)
 
108
  {
 
109
    g_print("Drizzle object creation error\n");
 
110
    return NULL;
 
111
  }
 
112
  con= drizzle_con_add_tcp(drizzle, host, port, user, pass, "", 0);
 
113
  if (!con)
 
114
  {
 
115
    g_print("Drizzle connection object creation error\n");
 
116
    return NULL;
 
117
  }
 
118
  ret= drizzle_con_connect(con);
 
119
  if (ret != DRIZZLE_RETURN_OK)
 
120
  {
 
121
    g_print("Error connecting to server: %s\n", drizzle_con_error(con));
 
122
    return NULL;
 
123
  }
 
124
  return con;
 
125
}
 
126
 
 
127
FILE *create_binlog_file(char *binlog_file)
 
128
{
 
129
  FILE *outfile;
 
130
  char *filename;
 
131
  if (outdir)
 
132
  {
 
133
    filename= g_strdup_printf("%s/%s", outdir, binlog_file);
 
134
  }
 
135
  else
 
136
  {
 
137
    filename= binlog_file;
 
138
  }
 
139
  outfile= g_fopen(filename, "w");
 
140
  if (outdir)
 
141
  {
 
142
    g_free(filename);
 
143
  }
 
144
  return outfile;
 
145
}
 
146
 
 
147
void get_binlogs(drizzle_con_st *con)
 
148
{
 
149
  drizzle_result_st *result;
 
150
  drizzle_return_t ret;
 
151
  int server_id;
 
152
  FILE *outfile;
 
153
  gchar *binlog_file;
 
154
  uint32_t event_len;
 
155
  gboolean read_end= FALSE;
 
156
 
 
157
  if (continuous)
 
158
  {
 
159
    server_id= g_random_int_range(32768, 65535);
 
160
  }
 
161
  else
 
162
  {
 
163
    server_id= 0;
 
164
  }
 
165
 
 
166
  result= drizzle_start_binlog(con, server_id, start_file, start_pos, &ret);
 
167
  if (ret != DRIZZLE_RETURN_OK)
 
168
  {
 
169
    g_print("Drizzle binlog start failure: %s\n", drizzle_con_error(con));
 
170
    exit(EXIT_FAILURE);
 
171
  }
 
172
 
 
173
  binlog_file= g_strdup(start_file);
 
174
  outfile= create_binlog_file(binlog_file);
 
175
  if (!outfile)
 
176
  {
 
177
    g_print("Could not create binlog file '%s', errno %d\n", binlog_file, errno);
 
178
    exit(EXIT_FAILURE);
 
179
  }
 
180
 
 
181
  while(1)
 
182
  {
 
183
    write_binlog(outfile, (uint8_t *)DRIZZLE_BINLOG_MAGIC, 4);
 
184
    while(1)
 
185
    {
 
186
      ret= drizzle_binlog_get_next_event(result);
 
187
      event_len= drizzle_binlog_event_raw_length(result);
 
188
      if (ret != DRIZZLE_RETURN_OK)
 
189
      {
 
190
          // EOF
 
191
          if (ret != DRIZZLE_RETURN_EOF)
 
192
          {
 
193
            g_print("Read error: %d - %s\n", ret, drizzle_con_error(con));
 
194
          }
 
195
          read_end= TRUE;
 
196
          break;
 
197
      }
 
198
      if (drizzle_binlog_event_type(result) == DRIZZLE_EVENT_TYPE_ROTATE)
 
199
      {
 
200
        fclose(outfile);
 
201
        g_free(binlog_file);
 
202
        binlog_file= g_strndup((const gchar *)drizzle_binlog_event_data(result), drizzle_binlog_event_length(result));
 
203
        outfile= create_binlog_file(binlog_file);
 
204
        if (!outfile)
 
205
        {
 
206
          g_print("Could not create binlog file '%s', errno %d\n", binlog_file, errno);
 
207
          exit(EXIT_FAILURE);
 
208
        }
 
209
        break;
 
210
      }
 
211
      write_binlog(outfile, drizzle_binlog_event_raw_data(result), event_len);
 
212
    }
 
213
    if (read_end)
 
214
    {
 
215
      break;
 
216
    }
 
217
  }
 
218
 
 
219
  drizzle_result_free(result);
 
220
}
 
221
 
 
222
void write_binlog(FILE* file, const uint8_t* data, uint32_t len)
 
223
{
 
224
  if (len)
 
225
  {
 
226
    if (write(fileno(file), data, len) <= 0)
 
227
    {
 
228
      g_print("Error: binlog: Error writing binary log: %s", strerror(errno));
 
229
      exit(EXIT_FAILURE);
 
230
    }
 
231
  }
 
232
 
 
233
}
 
234
 
 
235
int main(int argc, char *argv[])
 
236
{
 
237
  GError *error= NULL;
 
238
  GOptionContext *context;
 
239
  drizzle_st *drizzle;
 
240
  drizzle_con_st *con;
 
241
  char sysuser[DRIZZLE_MAX_USER_SIZE];
 
242
 
 
243
  context= g_option_context_new(" - Drizzle binlog retriever");
 
244
  GOptionGroup *main_group= g_option_group_new("main", "Main Options", "Main Options", NULL, NULL);
 
245
  GOptionGroup *binlog_group= g_option_group_new("binlog", "Binlog Options", "Binlog Options", NULL, NULL);
 
246
  g_option_group_add_entries(main_group, main_options);
 
247
  g_option_group_add_entries(binlog_group, binlog_options);
 
248
  g_option_context_set_main_group(context, main_group);
 
249
  g_option_context_add_group(context, binlog_group);
 
250
  if (!g_option_context_parse(context, &argc, &argv, &error))
 
251
  {
 
252
    g_print("Error parsing options: %s, try --help\n", error->message);
 
253
    return EXIT_FAILURE;
 
254
  }
 
255
  if (!user)
 
256
  {
 
257
    user= sysuser;
 
258
    if (!get_system_user(user, DRIZZLE_MAX_USER_SIZE))
 
259
    {
 
260
      g_print("No user specified and could not determine current user\n");
 
261
      return EXIT_FAILURE;
 
262
    }
 
263
  }
 
264
  if (!host)
 
265
  {
 
266
    host= g_strdup(DRIZZLE_DEFAULT_TCP_HOST);
 
267
  }
 
268
  if (!port)
 
269
  {
 
270
    port= DRIZZLE_DEFAULT_TCP_PORT;
 
271
  }
 
272
  if (!start_file)
 
273
  {
 
274
    g_print("Binlog start file required\n");
 
275
    return EXIT_FAILURE;
 
276
  }
 
277
  con = _connect();
 
278
  if (!con)
 
279
  {
 
280
    return EXIT_FAILURE;
 
281
  }
 
282
  get_binlogs(con);
 
283
  drizzle= drizzle_con_drizzle(con);
 
284
  drizzle_con_quit(con);
 
285
  drizzle_free(drizzle);
 
286
  g_option_context_free(context);
 
287
  return EXIT_SUCCESS;
 
288
}