http: refactor finish_http_pack_request()
[git.git] / lockfile.c
blobcc9a4b84283be34cdcd72770d77e2ef1adb998a6
1 /*
2 * Copyright (c) 2005, Junio C Hamano
3 */
5 #include "cache.h"
6 #include "lockfile.h"
8 /*
9 * path = absolute or relative path name
11 * Remove the last path name element from path (leaving the preceding
12 * "/", if any). If path is empty or the root directory ("/"), set
13 * path to the empty string.
15 static void trim_last_path_component(struct strbuf *path)
17 int i = path->len;
19 /* back up past trailing slashes, if any */
20 while (i && path->buf[i - 1] == '/')
21 i--;
24 * then go backwards until a slash, or the beginning of the
25 * string
27 while (i && path->buf[i - 1] != '/')
28 i--;
30 strbuf_setlen(path, i);
34 /* We allow "recursive" symbolic links. Only within reason, though */
35 #define MAXDEPTH 5
38 * path contains a path that might be a symlink.
40 * If path is a symlink, attempt to overwrite it with a path to the
41 * real file or directory (which may or may not exist), following a
42 * chain of symlinks if necessary. Otherwise, leave path unmodified.
44 * This is a best-effort routine. If an error occurs, path will
45 * either be left unmodified or will name a different symlink in a
46 * symlink chain that started with the original path.
48 static void resolve_symlink(struct strbuf *path)
50 int depth = MAXDEPTH;
51 static struct strbuf link = STRBUF_INIT;
53 while (depth--) {
54 if (strbuf_readlink(&link, path->buf, path->len) < 0)
55 break;
57 if (is_absolute_path(link.buf))
58 /* absolute path simply replaces p */
59 strbuf_reset(path);
60 else
62 * link is a relative path, so replace the
63 * last element of p with it.
65 trim_last_path_component(path);
67 strbuf_addbuf(path, &link);
69 strbuf_reset(&link);
72 /* Make sure errno contains a meaningful value on error */
73 static int lock_file(struct lock_file *lk, const char *path, int flags,
74 int mode)
76 struct strbuf filename = STRBUF_INIT;
78 strbuf_addstr(&filename, path);
79 if (!(flags & LOCK_NO_DEREF))
80 resolve_symlink(&filename);
82 strbuf_addstr(&filename, LOCK_SUFFIX);
83 lk->tempfile = create_tempfile_mode(filename.buf, mode);
84 strbuf_release(&filename);
85 return lk->tempfile ? lk->tempfile->fd : -1;
89 * Constants defining the gaps between attempts to lock a file. The
90 * first backoff period is approximately INITIAL_BACKOFF_MS
91 * milliseconds. The longest backoff period is approximately
92 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
94 #define INITIAL_BACKOFF_MS 1L
95 #define BACKOFF_MAX_MULTIPLIER 1000
98 * Try locking path, retrying with quadratic backoff for at least
99 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
100 * exactly once. If timeout_ms is -1, try indefinitely.
102 static int lock_file_timeout(struct lock_file *lk, const char *path,
103 int flags, long timeout_ms, int mode)
105 int n = 1;
106 int multiplier = 1;
107 long remaining_ms = 0;
108 static int random_initialized = 0;
110 if (timeout_ms == 0)
111 return lock_file(lk, path, flags, mode);
113 if (!random_initialized) {
114 srand((unsigned int)getpid());
115 random_initialized = 1;
118 if (timeout_ms > 0)
119 remaining_ms = timeout_ms;
121 while (1) {
122 long backoff_ms, wait_ms;
123 int fd;
125 fd = lock_file(lk, path, flags, mode);
127 if (fd >= 0)
128 return fd; /* success */
129 else if (errno != EEXIST)
130 return -1; /* failure other than lock held */
131 else if (timeout_ms > 0 && remaining_ms <= 0)
132 return -1; /* failure due to timeout */
134 backoff_ms = multiplier * INITIAL_BACKOFF_MS;
135 /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
136 wait_ms = (750 + rand() % 500) * backoff_ms / 1000;
137 sleep_millisec(wait_ms);
138 remaining_ms -= wait_ms;
140 /* Recursion: (n+1)^2 = n^2 + 2n + 1 */
141 multiplier += 2*n + 1;
142 if (multiplier > BACKOFF_MAX_MULTIPLIER)
143 multiplier = BACKOFF_MAX_MULTIPLIER;
144 else
145 n++;
149 void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
151 if (err == EEXIST) {
152 strbuf_addf(buf, _("Unable to create '%s.lock': %s.\n\n"
153 "Another git process seems to be running in this repository, e.g.\n"
154 "an editor opened by 'git commit'. Please make sure all processes\n"
155 "are terminated then try again. If it still fails, a git process\n"
156 "may have crashed in this repository earlier:\n"
157 "remove the file manually to continue."),
158 absolute_path(path), strerror(err));
159 } else
160 strbuf_addf(buf, _("Unable to create '%s.lock': %s"),
161 absolute_path(path), strerror(err));
164 NORETURN void unable_to_lock_die(const char *path, int err)
166 struct strbuf buf = STRBUF_INIT;
168 unable_to_lock_message(path, err, &buf);
169 die("%s", buf.buf);
172 /* This should return a meaningful errno on failure */
173 int hold_lock_file_for_update_timeout_mode(struct lock_file *lk,
174 const char *path, int flags,
175 long timeout_ms, int mode)
177 int fd = lock_file_timeout(lk, path, flags, timeout_ms, mode);
178 if (fd < 0) {
179 if (flags & LOCK_DIE_ON_ERROR)
180 unable_to_lock_die(path, errno);
181 if (flags & LOCK_REPORT_ON_ERROR) {
182 struct strbuf buf = STRBUF_INIT;
183 unable_to_lock_message(path, errno, &buf);
184 error("%s", buf.buf);
185 strbuf_release(&buf);
188 return fd;
191 char *get_locked_file_path(struct lock_file *lk)
193 struct strbuf ret = STRBUF_INIT;
195 strbuf_addstr(&ret, get_tempfile_path(lk->tempfile));
196 if (ret.len <= LOCK_SUFFIX_LEN ||
197 strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
198 BUG("get_locked_file_path() called for malformed lock object");
199 /* remove ".lock": */
200 strbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN);
201 return strbuf_detach(&ret, NULL);
204 int commit_lock_file(struct lock_file *lk)
206 char *result_path = get_locked_file_path(lk);
208 if (commit_lock_file_to(lk, result_path)) {
209 int save_errno = errno;
210 free(result_path);
211 errno = save_errno;
212 return -1;
214 free(result_path);
215 return 0;