glusterfs

Форк
0
698 строк · 15.5 Кб
1
/*
2
   Copyright (c) 2013 Red Hat, Inc. <http://www.redhat.com>
3
   This file is part of GlusterFS.
4

5
   This file is licensed to you under your choice of the GNU Lesser
6
   General Public License, version 3 or any later version (LGPLv3 or
7
   later), or the GNU General Public License, version 2 (GPLv2), in all
8
   cases as published by the Free Software Foundation.
9
*/
10

11
#include <inttypes.h>
12
#include <libgen.h>
13

14
#include <glusterfs/logging.h>
15
#include "glusterfs/store.h"
16
#include "glusterfs/xlator.h"
17
#include "glusterfs/syscall.h"
18
#include "glusterfs/libglusterfs-messages.h"
19

20
int32_t
21
gf_store_mkdir(char *path)
22
{
23
    int32_t ret = -1;
24

25
    ret = mkdir_p(path, 0755, _gf_true);
26

27
    if ((-1 == ret) && (EEXIST != errno)) {
28
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_DIR_OP_FAILED,
29
               "mkdir()"
30
               " failed on path %s.",
31
               path);
32
    } else {
33
        ret = 0;
34
    }
35

36
    return ret;
37
}
38

39
int32_t
40
gf_store_handle_create_on_absence(gf_store_handle_t **shandle, char *path)
41
{
42
    GF_ASSERT(shandle);
43
    int32_t ret = 0;
44

45
    if (*shandle == NULL) {
46
        ret = gf_store_handle_new(path, shandle);
47

48
        if (ret) {
49
            gf_msg("", GF_LOG_ERROR, 0, LG_MSG_STORE_HANDLE_CREATE_FAILED,
50
                   "Unable to"
51
                   " create store handle for path: %s",
52
                   path);
53
        }
54
    }
55
    return ret;
56
}
57

58
int32_t
59
gf_store_mkstemp(gf_store_handle_t *shandle)
60
{
61
    char tmppath[PATH_MAX] = {
62
        0,
63
    };
64

65
    GF_VALIDATE_OR_GOTO("store", shandle, out);
66
    GF_VALIDATE_OR_GOTO("store", shandle->path, out);
67

68
    snprintf(tmppath, sizeof(tmppath), "%s.tmp", shandle->path);
69
    shandle->tmp_fd = open(tmppath, O_RDWR | O_CREAT | O_TRUNC, 0600);
70
    if (shandle->tmp_fd < 0) {
71
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
72
               "Failed to open %s.", tmppath);
73
    }
74
out:
75
    return shandle->tmp_fd;
76
}
77

78
int
79
gf_store_sync_direntry(char *path)
80
{
81
    int ret = -1;
82
    int dirfd = -1;
83
    char *dir = NULL;
84
    char *pdir = NULL;
85
    xlator_t *this = NULL;
86

87
    this = THIS;
88

89
    dir = gf_strdup(path);
90
    if (!dir)
91
        goto out;
92

93
    pdir = dirname(dir);
94
    dirfd = open(pdir, O_RDONLY);
95
    if (dirfd == -1) {
96
        gf_msg(this->name, GF_LOG_ERROR, errno, LG_MSG_DIR_OP_FAILED,
97
               "Failed to open directory %s.", pdir);
98
        goto out;
99
    }
100

101
    ret = sys_fsync(dirfd);
102
    if (ret) {
103
        gf_msg(this->name, GF_LOG_ERROR, errno, LG_MSG_DIR_OP_FAILED,
104
               "Failed to fsync %s.", pdir);
105
        goto out;
106
    }
107

108
    ret = 0;
109
out:
110
    if (dirfd >= 0) {
111
        ret = sys_close(dirfd);
112
        if (ret) {
113
            gf_msg(this->name, GF_LOG_ERROR, errno, LG_MSG_DIR_OP_FAILED,
114
                   "Failed to close %s", pdir);
115
        }
116
    }
117

118
    if (dir)
119
        GF_FREE(dir);
120

121
    return ret;
122
}
123

124
int32_t
125
gf_store_rename_tmppath(gf_store_handle_t *shandle)
126
{
127
    int32_t ret = -1;
128
    char tmppath[PATH_MAX] = {
129
        0,
130
    };
131

132
    GF_VALIDATE_OR_GOTO("store", shandle, out);
133
    GF_VALIDATE_OR_GOTO("store", shandle->path, out);
134

135
    ret = sys_fsync(shandle->tmp_fd);
136
    if (ret) {
137
        gf_msg(THIS->name, GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
138
               "Failed to fsync %s", shandle->path);
139
        goto out;
140
    }
141
    snprintf(tmppath, sizeof(tmppath), "%s.tmp", shandle->path);
142
    ret = sys_rename(tmppath, shandle->path);
143
    if (ret) {
144
        gf_msg(THIS->name, GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
145
               "Failed to rename %s to %s", tmppath, shandle->path);
146
        goto out;
147
    }
148

149
    ret = gf_store_sync_direntry(tmppath);
150
out:
151
    if (shandle && shandle->tmp_fd >= 0) {
152
        sys_close(shandle->tmp_fd);
153
        shandle->tmp_fd = -1;
154
    }
155
    return ret;
156
}
157

158
int32_t
159
gf_store_unlink_tmppath(gf_store_handle_t *shandle)
160
{
161
    int32_t ret = -1;
162
    char tmppath[PATH_MAX] = {
163
        0,
164
    };
165

166
    GF_VALIDATE_OR_GOTO("store", shandle, out);
167
    GF_VALIDATE_OR_GOTO("store", shandle->path, out);
168

169
    snprintf(tmppath, sizeof(tmppath), "%s.tmp", shandle->path);
170
    ret = gf_unlink(tmppath) ? 0 : -1;
171
out:
172
    if (shandle && shandle->tmp_fd >= 0) {
173
        sys_close(shandle->tmp_fd);
174
        shandle->tmp_fd = -1;
175
    }
176
    return ret;
177
}
178

179
int
180
gf_store_read_and_tokenize(FILE *file, char **iter_key, char **iter_val,
181
                           gf_store_op_errno_t *store_errno, char *str,
182
                           size_t buf_size)
183
{
184
    int32_t ret = -1;
185
    char *savetok = NULL;
186
    char *key = NULL;
187
    char *value = NULL;
188
    char *temp = NULL;
189
    size_t str_len = 0;
190

191
    GF_ASSERT(file);
192
    GF_ASSERT(iter_key);
193
    GF_ASSERT(iter_val);
194
    GF_ASSERT(store_errno);
195

196
    str[0] = '\0';
197

198
retry:
199
    temp = fgets(str, buf_size, file);
200
    if (temp == NULL || feof(file)) {
201
        ret = -1;
202
        *store_errno = GD_STORE_EOF;
203
        goto out;
204
    }
205

206
    if (strcmp(str, "\n") == 0)
207
        goto retry;
208

209
    str_len = strlen(str);
210
    str[str_len - 1] = '\0';
211
    /* Truncate the "\n", as fgets stores "\n" in str */
212

213
    key = strtok_r(str, "=", &savetok);
214
    if (!key) {
215
        ret = -1;
216
        *store_errno = GD_STORE_KEY_NULL;
217
        goto out;
218
    }
219

220
    value = strtok_r(NULL, "", &savetok);
221
    if (!value) {
222
        ret = -1;
223
        *store_errno = GD_STORE_VALUE_NULL;
224
        goto out;
225
    }
226

227
    *iter_key = key;
228
    *iter_val = value;
229
    *store_errno = GD_STORE_SUCCESS;
230
    ret = 0;
231
out:
232
    return ret;
233
}
234

235
int32_t
236
gf_store_retrieve_value(gf_store_handle_t *handle, char *key, char **value)
237
{
238
    int32_t ret = -1;
239
    char *iter_key = NULL;
240
    char *iter_val = NULL;
241
    gf_store_op_errno_t store_errno = GD_STORE_SUCCESS;
242

243
    GF_ASSERT(handle);
244

245
    if (handle->locked == F_ULOCK)
246
        /* no locking is used handle->fd gets closed() after usage */
247
        handle->fd = open(handle->path, O_RDWR);
248
    else
249
        /* handle->fd is valid already, kept open for lockf() */
250
        sys_lseek(handle->fd, 0, SEEK_SET);
251

252
    if (handle->fd == -1) {
253
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
254
               "Unable to open file %s", handle->path);
255
        goto out;
256
    }
257
    if (!handle->read) {
258
        int duped_fd = dup(handle->fd);
259

260
        if (duped_fd >= 0)
261
            handle->read = fdopen(duped_fd, "r");
262
        if (!handle->read) {
263
            if (duped_fd != -1)
264
                sys_close(duped_fd);
265
            gf_msg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
266
                   "Unable to open file %s", handle->path);
267
            goto out;
268
        }
269
    } else {
270
        fseek(handle->read, 0, SEEK_SET);
271
    }
272

273
    char buf[8192];
274
    do {
275
        ret = gf_store_read_and_tokenize(handle->read, &iter_key, &iter_val,
276
                                         &store_errno, buf, 8192);
277
        if (ret < 0) {
278
            gf_msg_trace("", 0,
279
                         "error while reading key '%s': "
280
                         "%s",
281
                         key, gf_store_strerror(store_errno));
282
            goto out;
283
        }
284

285
        gf_msg_trace("", 0, "key %s read", iter_key);
286

287
        if (!strcmp(key, iter_key)) {
288
            gf_msg_debug("", 0, "key %s found", key);
289
            ret = 0;
290
            if (iter_val)
291
                *value = gf_strdup(iter_val);
292
            goto out;
293
        }
294
    } while (1);
295
out:
296
    if (handle->read) {
297
        fclose(handle->read);
298
        handle->read = NULL;
299
    }
300

301
    if (handle->fd > 0 && handle->locked == F_ULOCK) {
302
        /* only invalidate handle->fd if not locked */
303
        sys_close(handle->fd);
304
    }
305

306
    return ret;
307
}
308

309
int32_t
310
gf_store_save_value(int fd, char *key, char *value)
311
{
312
    int32_t ret = -1;
313
    int dup_fd = -1;
314
    FILE *fp = NULL;
315

316
    GF_ASSERT(fd > 0);
317
    GF_ASSERT(key);
318
    GF_ASSERT(value);
319

320
    dup_fd = dup(fd);
321
    if (dup_fd == -1)
322
        goto out;
323

324
    fp = fdopen(dup_fd, "a+");
325
    if (fp == NULL) {
326
        gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
327
               "fdopen failed.");
328
        ret = -1;
329
        goto out;
330
    }
331

332
    ret = fprintf(fp, "%s=%s\n", key, value);
333
    if (ret < 0) {
334
        gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
335
               "Unable to store key: %s, value: %s.", key, value);
336
        ret = -1;
337
        goto out;
338
    }
339

340
    ret = fflush(fp);
341
    if (ret) {
342
        gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
343
               "fflush failed.");
344
        ret = -1;
345
        goto out;
346
    }
347

348
    ret = 0;
349
out:
350
    if (fp)
351
        fclose(fp);
352

353
    gf_msg_debug(THIS->name, 0, "returning: %d", ret);
354
    return ret;
355
}
356

357
int32_t
358
gf_store_save_items(int fd, char *items)
359
{
360
    int32_t ret = -1;
361
    int dup_fd = -1;
362
    FILE *fp = NULL;
363

364
    GF_ASSERT(fd > 0);
365
    GF_ASSERT(items);
366

367
    dup_fd = dup(fd);
368
    if (dup_fd == -1)
369
        goto out;
370

371
    fp = fdopen(dup_fd, "a+");
372
    if (fp == NULL) {
373
        gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
374
               "fdopen failed.");
375
        ret = -1;
376
        goto out;
377
    }
378

379
    ret = fputs(items, fp);
380
    if (ret < 0) {
381
        gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
382
               "Unable to store items: %s", items);
383
        ret = -1;
384
        goto out;
385
    }
386

387
    ret = fflush(fp);
388
    if (ret) {
389
        gf_msg(THIS->name, GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
390
               "fflush failed.");
391
        ret = -1;
392
        goto out;
393
    }
394

395
    ret = 0;
396
out:
397
    if (fp)
398
        fclose(fp);
399

400
    gf_msg_debug(THIS->name, 0, "returning: %d", ret);
401
    return ret;
402
}
403

404
int32_t
405
gf_store_handle_new(const char *path, gf_store_handle_t **handle)
406
{
407
    int32_t ret = -1;
408
    gf_store_handle_t *shandle = NULL;
409
    int fd = -1;
410
    char *spath = NULL;
411

412
    shandle = GF_CALLOC(1, sizeof(*shandle), gf_common_mt_store_handle_t);
413
    if (!shandle)
414
        goto out;
415

416
    spath = gf_strdup(path);
417
    if (!spath)
418
        goto out;
419

420
    fd = open(path, O_RDWR | O_CREAT | O_APPEND, 0600);
421
    if (fd < 0) {
422
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
423
               "Failed to open file: %s.", path);
424
        goto out;
425
    }
426

427
    ret = gf_store_sync_direntry(spath);
428
    if (ret)
429
        goto out;
430

431
    shandle->path = spath;
432
    shandle->locked = F_ULOCK;
433
    *handle = shandle;
434
    shandle->tmp_fd = -1;
435

436
    ret = 0;
437
out:
438
    if (fd >= 0)
439
        sys_close(fd);
440

441
    if (ret) {
442
        GF_FREE(spath);
443
        GF_FREE(shandle);
444
    }
445

446
    gf_msg_debug("", 0, "Returning %d", ret);
447
    return ret;
448
}
449

450
int
451
gf_store_handle_retrieve(char *path, gf_store_handle_t **handle)
452
{
453
    int32_t ret = -1;
454
    struct stat statbuf = {0};
455

456
    ret = sys_stat(path, &statbuf);
457
    if (ret) {
458
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_PATH_NOT_FOUND,
459
               "Path "
460
               "corresponding to %s.",
461
               path);
462
        goto out;
463
    }
464
    ret = gf_store_handle_new(path, handle);
465
out:
466
    gf_msg_debug("", 0, "Returning %d", ret);
467
    return ret;
468
}
469

470
int32_t
471
gf_store_handle_destroy(gf_store_handle_t *handle)
472
{
473
    int32_t ret = -1;
474

475
    if (!handle) {
476
        ret = 0;
477
        goto out;
478
    }
479

480
    GF_FREE(handle->path);
481

482
    GF_FREE(handle);
483

484
    ret = 0;
485

486
out:
487
    gf_msg_debug("", 0, "Returning %d", ret);
488

489
    return ret;
490
}
491

492
int32_t
493
gf_store_iter_new(gf_store_handle_t *shandle, gf_store_iter_t **iter)
494
{
495
    int32_t ret = -1;
496
    FILE *fp = NULL;
497
    gf_store_iter_t *tmp_iter = NULL;
498

499
    GF_ASSERT(shandle);
500
    GF_ASSERT(iter);
501

502
    fp = fopen(shandle->path, "r");
503
    if (!fp) {
504
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
505
               "Unable to open file %s", shandle->path);
506
        goto out;
507
    }
508

509
    tmp_iter = GF_MALLOC(sizeof(*tmp_iter), gf_common_mt_store_iter_t);
510
    if (!tmp_iter)
511
        goto out;
512

513
    tmp_iter->file = fp;
514
    if (snprintf(tmp_iter->filepath, sizeof(tmp_iter->filepath), "%s",
515
                 shandle->path) >= sizeof(tmp_iter->filepath))
516
        goto out;
517
    tmp_iter->buf[0] = '\0';
518

519
    *iter = tmp_iter;
520
    tmp_iter = NULL;
521
    ret = 0;
522

523
out:
524
    if (ret && fp)
525
        fclose(fp);
526

527
    GF_FREE(tmp_iter);
528

529
    gf_msg_debug("", 0, "Returning with %d", ret);
530
    return ret;
531
}
532

533
int32_t
534
gf_store_iter_get_next(gf_store_iter_t *iter, char **key, char **value,
535
                       gf_store_op_errno_t *op_errno)
536
{
537
    int32_t ret = -1;
538
    char *iter_key = NULL;
539
    char *iter_val = NULL;
540

541
    gf_store_op_errno_t store_errno = GD_STORE_SUCCESS;
542

543
    GF_ASSERT(iter);
544
    GF_ASSERT(key);
545
    GF_ASSERT(value);
546

547
    ret = gf_store_read_and_tokenize(iter->file, &iter_key, &iter_val,
548
                                     &store_errno, iter->buf, sizeof(iter->buf));
549
    if (ret < 0) {
550
        goto out;
551
    }
552

553
    *key = gf_strdup(iter_key);
554
    if (!*key) {
555
        ret = -1;
556
        store_errno = GD_STORE_ENOMEM;
557
        goto out;
558
    }
559
    *value = gf_strdup(iter_val);
560
    if (!*value) {
561
        ret = -1;
562
        store_errno = GD_STORE_ENOMEM;
563
        goto out;
564
    }
565
    ret = 0;
566

567
out:
568
    if (ret) {
569
        GF_FREE(*key);
570
        GF_FREE(*value);
571
        *key = NULL;
572
        *value = NULL;
573
    }
574
    if (op_errno)
575
        *op_errno = store_errno;
576

577
    gf_msg_debug("", 0, "Returning with %d", ret);
578
    return ret;
579
}
580

581
int32_t
582
gf_store_iter_get_matching(gf_store_iter_t *iter, char *key, char **value)
583
{
584
    int32_t ret = -1;
585
    char *tmp_key = NULL;
586
    char *tmp_value = NULL;
587

588
    ret = gf_store_iter_get_next(iter, &tmp_key, &tmp_value, NULL);
589
    while (!ret) {
590
        if (!strncmp(key, tmp_key, strlen(key))) {
591
            *value = tmp_value;
592
            GF_FREE(tmp_key);
593
            goto out;
594
        }
595
        GF_FREE(tmp_key);
596
        tmp_key = NULL;
597
        GF_FREE(tmp_value);
598
        tmp_value = NULL;
599
        ret = gf_store_iter_get_next(iter, &tmp_key, &tmp_value, NULL);
600
    }
601
out:
602
    return ret;
603
}
604

605
int32_t
606
gf_store_iter_destroy(gf_store_iter_t **iter)
607
{
608
    int32_t ret = -1;
609

610
    if (!(*iter))
611
        return 0;
612

613
    /* gf_store_iter_new will not return a valid iter object with iter->file
614
     * being NULL*/
615
    ret = fclose((*iter)->file);
616
    if (ret)
617
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
618
               "Unable"
619
               " to close file: %s, ret: %d",
620
               (*iter)->filepath, ret);
621

622
    GF_FREE(*iter);
623
    *iter = NULL;
624

625
    return ret;
626
}
627

628
char *
629
gf_store_strerror(gf_store_op_errno_t op_errno)
630
{
631
    switch (op_errno) {
632
        case GD_STORE_SUCCESS:
633
            return "Success";
634
        case GD_STORE_KEY_NULL:
635
            return "Invalid Key";
636
        case GD_STORE_VALUE_NULL:
637
            return "Invalid Value";
638
        case GD_STORE_KEY_VALUE_NULL:
639
            return "Invalid Key and Value";
640
        case GD_STORE_EOF:
641
            return "No data";
642
        case GD_STORE_ENOMEM:
643
            return "No memory";
644
        default:
645
            return "Invalid errno";
646
    }
647
}
648

649
int
650
gf_store_lock(gf_store_handle_t *sh)
651
{
652
    int ret;
653

654
    GF_ASSERT(sh);
655
    GF_ASSERT(sh->path);
656
    GF_ASSERT(sh->locked == F_ULOCK);
657

658
    sh->fd = open(sh->path, O_RDWR);
659
    if (sh->fd == -1) {
660
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED,
661
               "Failed to open '%s'", sh->path);
662
        return -1;
663
    }
664

665
    ret = lockf(sh->fd, F_LOCK, 0);
666
    if (ret)
667
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_LOCK_FAILED,
668
               "Failed to gain lock on '%s'", sh->path);
669
    else
670
        /* sh->locked is protected by the lockf(sh->fd) above */
671
        sh->locked = F_LOCK;
672

673
    return ret;
674
}
675

676
void
677
gf_store_unlock(gf_store_handle_t *sh)
678
{
679
    GF_ASSERT(sh);
680
    GF_ASSERT(sh->locked == F_LOCK);
681

682
    sh->locked = F_ULOCK;
683

684
    /* does not matter if this fails, locks are released on close anyway */
685
    if (lockf(sh->fd, F_ULOCK, 0) == -1)
686
        gf_msg("", GF_LOG_ERROR, errno, LG_MSG_UNLOCK_FAILED,
687
               "Failed to release lock on '%s'", sh->path);
688

689
    sys_close(sh->fd);
690
}
691

692
int
693
gf_store_locked_local(gf_store_handle_t *sh)
694
{
695
    GF_ASSERT(sh);
696

697
    return (sh->locked == F_LOCK);
698
}
699

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.