Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
git2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
git2
Commits
5df18424
Commit
5df18424
authored
Apr 01, 2013
by
Vicent Marti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lol this worked first try wtf
parent
a92dd316
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
184 additions
and
139 deletions
+184
-139
src/cache.c
+108
-61
src/cache.h
+16
-17
src/object.c
+33
-21
src/odb.c
+21
-15
src/odb.h
+3
-1
src/oidmap.h
+2
-4
src/repository.c
+1
-1
src/util.c
+0
-8
tests-clar/core/opts.c
+0
-11
No files found.
src/cache.c
View file @
5df18424
...
...
@@ -11,100 +11,147 @@
#include "thread-utils.h"
#include "util.h"
#include "cache.h"
#include "odb.h"
#include "object.h"
#include "git2/oid.h"
int
git_cache_init
(
git_cache
*
cache
,
size_t
size
,
git_cached_obj_freeptr
free_ptr
)
{
if
(
size
<
8
)
size
=
8
;
size
=
git__size_t_powerof2
(
size
);
cache
->
size_mask
=
size
-
1
;
cache
->
lru_count
=
0
;
cache
->
free_obj
=
free_ptr
;
GIT__USE_OIDMAP
int
git_cache_init
(
git_cache
*
cache
)
{
cache
->
map
=
git_oidmap_alloc
();
git_mutex_init
(
&
cache
->
lock
);
cache
->
nodes
=
git__malloc
(
size
*
sizeof
(
git_cached_obj
*
));
GITERR_CHECK_ALLOC
(
cache
->
nodes
);
memset
(
cache
->
nodes
,
0x0
,
size
*
sizeof
(
git_cached_obj
*
));
return
0
;
}
void
git_cache_free
(
git_cache
*
cache
)
{
size_t
i
;
for
(
i
=
0
;
i
<
(
cache
->
size_mask
+
1
);
++
i
)
{
if
(
cache
->
nodes
[
i
]
!=
NULL
)
git_cached_obj_decref
(
cache
->
nodes
[
i
],
cache
->
free_obj
);
}
git_oidmap_free
(
cache
->
map
);
git_mutex_free
(
&
cache
->
lock
);
git__free
(
cache
->
nodes
);
}
void
*
git_cache_get
(
git_cache
*
cache
,
const
git_oid
*
oid
)
static
bool
cache_should_store
(
git_cached_obj
*
entry
)
{
uint32_t
hash
;
git_cached_obj
*
node
=
NULL
,
*
result
=
NULL
;
return
true
;
}
memcpy
(
&
hash
,
oid
->
id
,
sizeof
(
hash
));
static
void
*
cache_get
(
git_cache
*
cache
,
const
git_oid
*
oid
,
unsigned
int
flags
)
{
khiter_t
pos
;
git_cached_obj
*
entry
=
NULL
;
if
(
git_mutex_lock
(
&
cache
->
lock
))
{
giterr_set
(
GITERR_THREAD
,
"unable to lock cache mutex"
);
if
(
git_mutex_lock
(
&
cache
->
lock
)
<
0
)
return
NULL
;
}
{
node
=
cache
->
nodes
[
hash
&
cache
->
size_mask
];
pos
=
kh_get
(
oid
,
cache
->
map
,
oid
);
if
(
pos
!=
kh_end
(
cache
->
map
))
{
entry
=
kh_val
(
cache
->
map
,
pos
);
if
(
node
!=
NULL
&&
git_oid_cmp
(
&
node
->
oid
,
oid
)
==
0
)
{
git_cached_obj_incref
(
node
);
result
=
node
;
if
(
flags
&&
entry
->
flags
!=
flags
)
{
entry
=
NULL
;
}
else
{
git_cached_obj_incref
(
entry
);
}
}
git_mutex_unlock
(
&
cache
->
lock
);
return
result
;
return
entry
;
}
void
*
git_cache_try_store
(
git_cache
*
cache
,
void
*
_
entry
)
static
void
*
cache_store
(
git_cache
*
cache
,
git_cached_obj
*
entry
)
{
git_cached_obj
*
entry
=
_entry
;
uint32_t
hash
;
khiter_t
pos
;
memcpy
(
&
hash
,
&
entry
->
oid
,
sizeof
(
uint32_t
)
);
git_cached_obj_incref
(
entry
);
if
(
git_mutex_lock
(
&
cache
->
lock
))
{
giterr_set
(
GITERR_THREAD
,
"unable to lock cache mutex"
);
return
NULL
;
}
if
(
!
cache_should_store
(
entry
))
return
entry
;
if
(
git_mutex_lock
(
&
cache
->
lock
)
<
0
)
return
entry
;
{
git_cached_obj
*
node
=
cache
->
nodes
[
hash
&
cache
->
size_mask
];
pos
=
kh_get
(
oid
,
cache
->
map
,
&
entry
->
oid
);
/* increase the refcount on this object, because
* the cache now owns it */
git_cached_obj_incref
(
entry
)
;
/* not found */
if
(
pos
==
kh_end
(
cache
->
map
))
{
int
rval
;
if
(
node
==
NULL
)
{
cache
->
nodes
[
hash
&
cache
->
size_mask
]
=
entry
;
}
else
if
(
git_oid_cmp
(
&
node
->
oid
,
&
entry
->
oid
)
==
0
)
{
git_cached_obj_decref
(
entry
,
cache
->
free_obj
);
entry
=
node
;
pos
=
kh_put
(
oid
,
cache
->
map
,
&
entry
->
oid
,
&
rval
);
if
(
rval
>=
0
)
{
kh_key
(
cache
->
map
,
pos
)
=
&
entry
->
oid
;
kh_val
(
cache
->
map
,
pos
)
=
entry
;
git_cached_obj_incref
(
entry
);
}
}
/* found */
else
{
git_cached_obj
*
stored_entry
=
kh_val
(
cache
->
map
,
pos
);
if
(
stored_entry
->
flags
==
entry
->
flags
)
{
git_cached_obj_decref
(
entry
);
git_cached_obj_incref
(
stored_entry
);
entry
=
stored_entry
;
}
else
if
(
stored_entry
->
flags
==
GIT_CACHE_STORE_RAW
&&
entry
->
flags
==
GIT_CACHE_STORE_PARSED
)
{
git_cached_obj_decref
(
stored_entry
);
git_cached_obj_incref
(
entry
);
kh_key
(
cache
->
map
,
pos
)
=
&
entry
->
oid
;
kh_val
(
cache
->
map
,
pos
)
=
entry
;
}
else
{
git_cached_obj_decref
(
node
,
cache
->
free_obj
);
cache
->
nodes
[
hash
&
cache
->
size_mask
]
=
entry
;
/* NO OP */
}
/* increase the refcount again, because we are
* returning it to the user */
git_cached_obj_incref
(
entry
);
}
git_mutex_unlock
(
&
cache
->
lock
);
git_mutex_unlock
(
&
cache
->
lock
);
return
entry
;
}
void
*
git_cache_store_raw
(
git_cache
*
cache
,
git_odb_object
*
entry
)
{
entry
->
cached
.
flags
=
GIT_CACHE_STORE_RAW
;
return
cache_store
(
cache
,
(
git_cached_obj
*
)
entry
);
}
void
*
git_cache_store_parsed
(
git_cache
*
cache
,
git_object
*
entry
)
{
entry
->
cached
.
flags
=
GIT_CACHE_STORE_PARSED
;
return
cache_store
(
cache
,
(
git_cached_obj
*
)
entry
);
}
git_odb_object
*
git_cache_get_raw
(
git_cache
*
cache
,
const
git_oid
*
oid
)
{
return
cache_get
(
cache
,
oid
,
GIT_CACHE_STORE_RAW
);
}
git_object
*
git_cache_get_parsed
(
git_cache
*
cache
,
const
git_oid
*
oid
)
{
return
cache_get
(
cache
,
oid
,
GIT_CACHE_STORE_PARSED
);
}
void
*
git_cache_get_any
(
git_cache
*
cache
,
const
git_oid
*
oid
)
{
return
cache_get
(
cache
,
oid
,
GIT_CACHE_STORE_ANY
);
}
void
git_cached_obj_decref
(
void
*
_obj
)
{
git_cached_obj
*
obj
=
_obj
;
if
(
git_atomic_dec
(
&
obj
->
refcount
)
==
0
)
{
switch
(
obj
->
flags
)
{
case
GIT_CACHE_STORE_RAW
:
git_odb_object__free
(
_obj
);
break
;
case
GIT_CACHE_STORE_PARSED
:
git_object__free
(
_obj
);
break
;
default:
git__free
(
_obj
);
break
;
}
}
}
src/cache.h
View file @
5df18424
...
...
@@ -12,30 +12,35 @@
#include "git2/odb.h"
#include "thread-utils.h"
#include "oidmap.h"
#define GIT_DEFAULT_CACHE_SIZE 128
typedef
void
(
*
git_cached_obj_freeptr
)(
void
*
);
enum
{
GIT_CACHE_STORE_ANY
=
0
,
GIT_CACHE_STORE_RAW
=
1
,
GIT_CACHE_STORE_PARSED
=
2
};
typedef
struct
{
git_oid
oid
;
git_atomic
refcount
;
uint32_t
flags
;
}
git_cached_obj
;
typedef
struct
{
git_
cached_obj
**
nodes
;
git_
oidmap
*
map
;
git_mutex
lock
;
unsigned
int
lru_count
;
size_t
size_mask
;
git_cached_obj_freeptr
free_obj
;
}
git_cache
;
int
git_cache_init
(
git_cache
*
cache
,
size_t
size
,
git_cached_obj_freeptr
free_ptr
);
int
git_cache_init
(
git_cache
*
cache
);
void
git_cache_free
(
git_cache
*
cache
);
void
*
git_cache_try_store
(
git_cache
*
cache
,
void
*
entry
);
void
*
git_cache_get
(
git_cache
*
cache
,
const
git_oid
*
oid
);
void
*
git_cache_store_raw
(
git_cache
*
cache
,
git_odb_object
*
entry
);
void
*
git_cache_store_parsed
(
git_cache
*
cache
,
git_object
*
entry
);
git_odb_object
*
git_cache_get_raw
(
git_cache
*
cache
,
const
git_oid
*
oid
);
git_object
*
git_cache_get_parsed
(
git_cache
*
cache
,
const
git_oid
*
oid
);
void
*
git_cache_get_any
(
git_cache
*
cache
,
const
git_oid
*
oid
);
GIT_INLINE
(
void
)
git_cached_obj_incref
(
void
*
_obj
)
{
...
...
@@ -43,12 +48,6 @@ GIT_INLINE(void) git_cached_obj_incref(void *_obj)
git_atomic_inc
(
&
obj
->
refcount
);
}
GIT_INLINE
(
void
)
git_cached_obj_decref
(
void
*
_obj
,
git_cached_obj_freeptr
free_obj
)
{
git_cached_obj
*
obj
=
_obj
;
if
(
git_atomic_dec
(
&
obj
->
refcount
)
==
0
)
free_obj
(
obj
);
}
void
git_cached_obj_decref
(
void
*
_obj
);
#endif
src/object.c
View file @
5df18424
...
...
@@ -121,12 +121,13 @@ int git_object__from_odb_object(
break
;
}
if
(
error
<
0
)
if
(
error
<
0
)
{
git_object__free
(
object
);
else
*
object_out
=
git_cache_try_store
(
&
repo
->
objects
,
object
);
return
error
;
}
return
error
;
*
object_out
=
git_cache_store_parsed
(
&
repo
->
objects
,
object
);
return
0
;
}
int
git_object_lookup_prefix
(
...
...
@@ -154,27 +155,38 @@ int git_object_lookup_prefix(
len
=
GIT_OID_HEXSZ
;
if
(
len
==
GIT_OID_HEXSZ
)
{
git_cached_obj
*
cached
=
NULL
;
/* We want to match the full id : we can first look up in the cache,
* since there is no need to check for non ambiguousity
*/
object
=
git_cache_get
(
&
repo
->
objects
,
id
);
if
(
object
!=
NULL
)
{
if
(
type
!=
GIT_OBJ_ANY
&&
type
!=
object
->
type
)
{
git_object_free
(
object
);
giterr_set
(
GITERR_INVALID
,
"The requested type does not match the type in ODB"
);
return
GIT_ENOTFOUND
;
cached
=
git_cache_get_any
(
&
repo
->
objects
,
id
);
if
(
cached
!=
NULL
)
{
if
(
cached
->
flags
==
GIT_CACHE_STORE_PARSED
)
{
object
=
(
git_object
*
)
cached
;
if
(
type
!=
GIT_OBJ_ANY
&&
type
!=
object
->
type
)
{
git_object_free
(
object
);
giterr_set
(
GITERR_INVALID
,
"The requested type does not match the type in ODB"
);
return
GIT_ENOTFOUND
;
}
*
object_out
=
object
;
return
0
;
}
else
if
(
cached
->
flags
==
GIT_CACHE_STORE_RAW
)
{
odb_obj
=
(
git_odb_object
*
)
cached
;
}
else
{
assert
(
!
"Wrong caching type in the global object cache"
);
}
*
object_out
=
object
;
return
0
;
}
else
{
/* Object was not found in the cache, let's explore the backends.
* We could just use git_odb_read_unique_short_oid,
* it is the same cost for packed and loose object backends,
* but it may be much more costly for sqlite and hiredis.
*/
error
=
git_odb_read
(
&
odb_obj
,
odb
,
id
);
}
/* Object was not found in the cache, let's explore the backends.
* We could just use git_odb_read_unique_short_oid,
* it is the same cost for packed and loose object backends,
* but it may be much more costly for sqlite and hiredis.
*/
error
=
git_odb_read
(
&
odb_obj
,
odb
,
id
);
}
else
{
git_oid
short_oid
;
...
...
@@ -245,7 +257,7 @@ void git_object_free(git_object *object)
if
(
object
==
NULL
)
return
;
git_cached_obj_decref
(
(
git_cached_obj
*
)
object
,
git_object__free
);
git_cached_obj_decref
(
object
);
}
const
git_oid
*
git_object_id
(
const
git_object
*
obj
)
...
...
src/odb.c
View file @
5df18424
...
...
@@ -14,6 +14,7 @@
#include "odb.h"
#include "delta-apply.h"
#include "filter.h"
#include "repository.h"
#include "git2/odb_backend.h"
#include "git2/oid.h"
...
...
@@ -34,7 +35,15 @@ typedef struct
ino_t
disk_inode
;
}
backend_internal
;
size_t
git_odb__cache_size
=
GIT_DEFAULT_CACHE_SIZE
;
static
git_cache
*
odb_cache
(
git_odb
*
odb
)
{
if
(
odb
->
rc
.
owner
!=
NULL
)
{
git_repository
*
owner
=
odb
->
rc
.
owner
;
return
&
owner
->
objects
;
}
return
&
odb
->
own_cache
;
}
static
int
load_alternates
(
git_odb
*
odb
,
const
char
*
objects_dir
,
int
alternate_depth
);
...
...
@@ -83,10 +92,8 @@ static git_odb_object *new_odb_object(const git_oid *oid, git_rawobj *source)
return
object
;
}
static
void
free_odb_object
(
void
*
o
)
void
git_odb_object__free
(
git_odb_object
*
object
)
{
git_odb_object
*
object
=
(
git_odb_object
*
)
o
;
if
(
object
!=
NULL
)
{
git__free
(
object
->
raw
.
data
);
git__free
(
object
);
...
...
@@ -118,7 +125,7 @@ void git_odb_object_free(git_odb_object *object)
if
(
object
==
NULL
)
return
;
git_cached_obj_decref
(
(
git_cached_obj
*
)
object
,
&
free_odb_
object
);
git_cached_obj_decref
(
object
);
}
int
git_odb__hashfd
(
git_oid
*
out
,
git_file
fd
,
size_t
size
,
git_otype
type
)
...
...
@@ -355,9 +362,8 @@ int git_odb_new(git_odb **out)
git_odb
*
db
=
git__calloc
(
1
,
sizeof
(
*
db
));
GITERR_CHECK_ALLOC
(
db
);
if
(
git_cache_init
(
&
db
->
cache
,
git_odb__cache_size
,
&
free_odb_object
)
<
0
||
git_vector_init
(
&
db
->
backends
,
4
,
backend_sort_cmp
)
<
0
)
{
if
(
git_cache_init
(
&
db
->
own_cache
)
<
0
||
git_vector_init
(
&
db
->
backends
,
4
,
backend_sort_cmp
)
<
0
)
{
git__free
(
db
);
return
-
1
;
}
...
...
@@ -559,7 +565,7 @@ static void odb_free(git_odb *db)
}
git_vector_free
(
&
db
->
backends
);
git_cache_free
(
&
db
->
cache
);
git_cache_free
(
&
db
->
own_
cache
);
git__free
(
db
);
}
...
...
@@ -580,7 +586,7 @@ int git_odb_exists(git_odb *db, const git_oid *id)
assert
(
db
&&
id
);
if
((
object
=
git_cache_get
(
&
db
->
cache
,
id
))
!=
NULL
)
{
if
((
object
=
git_cache_get
_raw
(
odb_cache
(
db
)
,
id
))
!=
NULL
)
{
git_odb_object_free
(
object
);
return
(
int
)
true
;
}
...
...
@@ -630,7 +636,7 @@ int git_odb__read_header_or_object(
assert
(
db
&&
id
&&
out
&&
len_p
&&
type_p
);
if
((
object
=
git_cache_get
(
&
db
->
cache
,
id
))
!=
NULL
)
{
if
((
object
=
git_cache_get
_raw
(
odb_cache
(
db
)
,
id
))
!=
NULL
)
{
*
len_p
=
object
->
raw
.
len
;
*
type_p
=
object
->
raw
.
type
;
*
out
=
object
;
...
...
@@ -678,7 +684,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
return
GIT_ENOTFOUND
;
}
*
out
=
git_cache_get
(
&
db
->
cache
,
id
);
*
out
=
git_cache_get
_raw
(
odb_cache
(
db
)
,
id
);
if
(
*
out
!=
NULL
)
return
0
;
...
...
@@ -704,7 +710,7 @@ attempt_lookup:
if
(
error
&&
error
!=
GIT_PASSTHROUGH
)
return
error
;
*
out
=
git_cache_
try_store
(
&
db
->
cache
,
new_odb_object
(
id
,
&
raw
));
*
out
=
git_cache_
store_raw
(
odb_cache
(
db
)
,
new_odb_object
(
id
,
&
raw
));
return
0
;
}
...
...
@@ -727,7 +733,7 @@ int git_odb_read_prefix(
len
=
GIT_OID_HEXSZ
;
if
(
len
==
GIT_OID_HEXSZ
)
{
*
out
=
git_cache_get
(
&
db
->
cache
,
short_id
);
*
out
=
git_cache_get
_raw
(
odb_cache
(
db
)
,
short_id
);
if
(
*
out
!=
NULL
)
return
0
;
}
...
...
@@ -768,7 +774,7 @@ attempt_lookup:
if
(
!
found
)
return
git_odb__error_notfound
(
"no match for prefix"
,
short_id
);
*
out
=
git_cache_
try_store
(
&
db
->
cache
,
new_odb_object
(
&
found_full_oid
,
&
raw
));
*
out
=
git_cache_
store_raw
(
odb_cache
(
db
)
,
new_odb_object
(
&
found_full_oid
,
&
raw
));
return
0
;
}
...
...
src/odb.h
View file @
5df18424
...
...
@@ -36,9 +36,11 @@ struct git_odb_object {
struct
git_odb
{
git_refcount
rc
;
git_vector
backends
;
git_cache
cache
;
git_cache
own_
cache
;
};
void
git_odb_object__free
(
git_odb_object
*
object
);
/*
* Hash a git_rawobj internally.
* The `git_rawobj` is supposed to be previously initialized
...
...
src/oidmap.h
View file @
5df18424
...
...
@@ -21,10 +21,8 @@ typedef khash_t(oid) git_oidmap;
GIT_INLINE
(
khint_t
)
hash_git_oid
(
const
git_oid
*
oid
)
{
int
i
;
khint_t
h
=
0
;
for
(
i
=
0
;
i
<
20
;
++
i
)
h
=
(
h
<<
5
)
-
h
+
oid
->
id
[
i
];
khint_t
h
;
memcpy
(
&
h
,
oid
,
sizeof
(
khint_t
));
return
h
;
}
...
...
src/repository.c
View file @
5df18424
...
...
@@ -119,7 +119,7 @@ static git_repository *repository_alloc(void)
memset
(
repo
,
0x0
,
sizeof
(
git_repository
));
if
(
git_cache_init
(
&
repo
->
objects
,
GIT_DEFAULT_CACHE_SIZE
,
&
git_object__free
)
<
0
)
{
if
(
git_cache_init
(
&
repo
->
objects
)
<
0
)
{
git__free
(
repo
);
return
NULL
;
}
...
...
src/util.c
View file @
5df18424
...
...
@@ -93,14 +93,6 @@ int git_libgit2_opts(int key, ...)
if
((
error
=
config_level_to_futils_dir
(
va_arg
(
ap
,
int
)))
>=
0
)
error
=
git_futils_dirs_set
(
error
,
va_arg
(
ap
,
const
char
*
));
break
;
case
GIT_OPT_GET_ODB_CACHE_SIZE
:
*
(
va_arg
(
ap
,
size_t
*
))
=
git_odb__cache_size
;
break
;
case
GIT_OPT_SET_ODB_CACHE_SIZE
:
git_odb__cache_size
=
va_arg
(
ap
,
size_t
);
break
;
}
va_end
(
ap
);
...
...
tests-clar/core/opts.c
View file @
5df18424
...
...
@@ -16,15 +16,4 @@ void test_core_opts__readwrite(void)
git_libgit2_opts
(
GIT_OPT_GET_MWINDOW_SIZE
,
&
new_val
);
cl_assert
(
new_val
==
old_val
);
git_libgit2_opts
(
GIT_OPT_GET_ODB_CACHE_SIZE
,
&
old_val
);
cl_assert
(
old_val
==
GIT_DEFAULT_CACHE_SIZE
);
git_libgit2_opts
(
GIT_OPT_SET_ODB_CACHE_SIZE
,
(
size_t
)
GIT_DEFAULT_CACHE_SIZE
*
2
);
git_libgit2_opts
(
GIT_OPT_GET_ODB_CACHE_SIZE
,
&
new_val
);
cl_assert
(
new_val
==
(
GIT_DEFAULT_CACHE_SIZE
*
2
));
git_libgit2_opts
(
GIT_OPT_GET_ODB_CACHE_SIZE
,
&
old_val
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment