]> git.proxmox.com Git - libgit2.git/blame - src/odb_mempack.c
Include stacktrace summary in memory leak output.
[libgit2.git] / src / odb_mempack.c
CommitLineData
6105d597
VM
1/*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
3 *
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
6 */
7
8#include "common.h"
9#include "git2/object.h"
10#include "git2/sys/odb_backend.h"
11#include "fileops.h"
12#include "hash.h"
13#include "odb.h"
14#include "array.h"
15#include "oidmap.h"
16
17#include "git2/odb_backend.h"
18#include "git2/types.h"
19#include "git2/pack.h"
20
c8e02b87 21GIT__USE_OIDMAP
6105d597
VM
22
23struct memobject {
24 git_oid oid;
25 size_t len;
26 git_otype type;
27 char data[];
28};
29
30struct memory_packer_db {
31 git_odb_backend parent;
32 git_oidmap *objects;
33 git_array_t(struct memobject *) commits;
34};
35
36static int impl__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type)
37{
38 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
39 struct memobject *obj = NULL;
40 khiter_t pos;
f1453c59 41 size_t alloc_len;
6105d597
VM
42 int rval;
43
44 pos = kh_put(oid, db->objects, oid, &rval);
45 if (rval < 0)
46 return -1;
47
48 if (rval == 0)
49 return 0;
50
f1453c59
ET
51 GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(struct memobject), len);
52 obj = git__malloc(alloc_len);
6105d597
VM
53 GITERR_CHECK_ALLOC(obj);
54
55 memcpy(obj->data, data, len);
56 git_oid_cpy(&obj->oid, oid);
57 obj->len = len;
58 obj->type = type;
59
60 kh_key(db->objects, pos) = &obj->oid;
61 kh_val(db->objects, pos) = obj;
62
63 if (type == GIT_OBJ_COMMIT) {
64 struct memobject **store = git_array_alloc(db->commits);
65 GITERR_CHECK_ALLOC(store);
66 *store = obj;
67 }
68
69 return 0;
70}
71
72static int impl__exists(git_odb_backend *backend, const git_oid *oid)
73{
74 struct memory_packer_db *db = (struct memory_packer_db *)backend;
75 khiter_t pos;
76
77 pos = kh_get(oid, db->objects, oid);
78 if (pos != kh_end(db->objects))
79 return 1;
80
81 return 0;
82}
83
84static int impl__read(void **buffer_p, size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
85{
86 struct memory_packer_db *db = (struct memory_packer_db *)backend;
87 struct memobject *obj = NULL;
88 khiter_t pos;
89
90 pos = kh_get(oid, db->objects, oid);
91 if (pos == kh_end(db->objects))
92 return GIT_ENOTFOUND;
93
94 obj = kh_val(db->objects, pos);
95
96 *len_p = obj->len;
97 *type_p = obj->type;
98 *buffer_p = git__malloc(obj->len);
99 GITERR_CHECK_ALLOC(*buffer_p);
100
101 memcpy(*buffer_p, obj->data, obj->len);
102 return 0;
103}
104
105static int impl__read_header(size_t *len_p, git_otype *type_p, git_odb_backend *backend, const git_oid *oid)
106{
107 struct memory_packer_db *db = (struct memory_packer_db *)backend;
108 struct memobject *obj = NULL;
109 khiter_t pos;
110
111 pos = kh_get(oid, db->objects, oid);
112 if (pos == kh_end(db->objects))
113 return GIT_ENOTFOUND;
114
115 obj = kh_val(db->objects, pos);
116
117 *len_p = obj->len;
118 *type_p = obj->type;
119 return 0;
120}
121
122int git_mempack_dump(git_buf *pack, git_repository *repo, git_odb_backend *_backend)
123{
124 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
125 git_packbuilder *packbuilder;
126 uint32_t i;
127 int err = -1;
128
129 if (git_packbuilder_new(&packbuilder, repo) < 0)
130 return -1;
131
132 for (i = 0; i < db->commits.size; ++i) {
133 struct memobject *commit = db->commits.ptr[i];
134
135 err = git_packbuilder_insert_commit(packbuilder, &commit->oid);
136 if (err < 0)
137 goto cleanup;
138 }
139
140 err = git_packbuilder_write_buf(pack, packbuilder);
141
142cleanup:
143 git_packbuilder_free(packbuilder);
144 return err;
145}
146
147void git_mempack_reset(git_odb_backend *_backend)
148{
149 struct memory_packer_db *db = (struct memory_packer_db *)_backend;
150 struct memobject *object = NULL;
151
152 kh_foreach_value(db->objects, object, {
153 git__free(object);
154 });
155
156 git_array_clear(db->commits);
157}
158
159static void impl__free(git_odb_backend *_backend)
160{
161 git_mempack_reset(_backend);
162 git__free(_backend);
163}
164
165int git_mempack_new(git_odb_backend **out)
166{
167 struct memory_packer_db *db;
168
169 assert(out);
170
171 db = git__calloc(1, sizeof(struct memory_packer_db));
172 GITERR_CHECK_ALLOC(db);
173
174 db->objects = git_oidmap_alloc();
175
176 db->parent.read = &impl__read;
177 db->parent.write = &impl__write;
178 db->parent.read_header = &impl__read_header;
179 db->parent.exists = &impl__exists;
180 db->parent.free = &impl__free;
181
182 *out = (git_odb_backend *)db;
183 return 0;
184}