cmogstored.git  about / heads / tags
alternative mogstored implementation for MogileFS
blob 855ed69395f15c596b88ffb99063262880d031ba 2137 bytes (raw)
$ git show HEAD:file.c	# shows this blob on the CLI

 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
 
/*
 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
 */
#include "cmogstored.h"
#include "digest.h"

bool mog_open_expire_retry(struct mog_svc *svc)
{
	switch (errno) {
	case ENFILE:
	case EMFILE:
	case ENOMEM:
		if (mog_fdmap_expire(svc->idle_timeout) > 0)
			return true;
	}
	return false;
}

static struct mog_fd *mog_file_init_common(int fd, struct mog_svc *svc)
{
	struct mog_fd *mfd = mog_fd_init(fd, MOG_FD_TYPE_FILE);
	struct mog_file *file;

	file = &mfd->as.file;
	memset(file, 0, sizeof(struct mog_file));
	file->svc = svc;
	file->ioq = mog_ioq_current;

	return mfd;
}

/* path must be a free()-able pointer */
struct mog_fd *
mog_file_open_read(struct mog_svc *svc, char *path)
{
	struct mog_fd *mfd;
	int fd = mog_open_read(svc, path);

	if (fd < 0 && mog_open_expire_retry(svc))
		fd = mog_open_read(svc, path);

	if (fd < 0) return NULL;

	mfd = mog_file_init_common(fd, svc);
	mfd->as.file.fsize = -1;

	return mfd;
}

static int mkpath_open_put(struct mog_svc *svc, char *path, int flags)
{
	int fd = mog_open_put(svc, path, flags);

	if (fd < 0 && errno == ENOENT) {
		/* directory does not exist, create it and retry open */
		if (mog_mkpath_for(svc, path) == 0)
			return mog_open_put(svc, path, flags);

		syslog(LOG_ERR, "failed to create directory for path=%s (%m)",
		       path);
		errno = ENOENT; /* restore open() errno */
	}

	return fd;
}

/* path must be a free()-able pointer */
struct mog_fd *
mog_file_open_put(struct mog_svc *svc, char *path, int flags)
{
	int fd = mkpath_open_put(svc, path, flags);

	if (fd < 0 && mog_open_expire_retry(svc))
		fd = mkpath_open_put(svc, path, flags);

	if (fd < 0) return NULL;

	return mog_file_init_common(fd, svc);
}

void mog_file_close(struct mog_fd *mfd)
{
	struct mog_file *mfile = &mfd->as.file;
	struct mog_ioq *ioq;

	assert(mfd->fd_type == MOG_FD_TYPE_FILE && "mog_fd is not a file");

	/* all of these may already be NULL */
	free(mfile->path);
	free(mfile->tmppath);
	mog_digest_destroy(&mfile->digest);

	ioq = mfile->ioq;
	mog_fd_put(mfd);
	mog_ioq_next(ioq);
}

git clone https://yhbt.net/cmogstored.git