1717
1818package org .apache .hugegraph .pd .common ;
1919
20+ import java .util .List ;
2021import java .util .Map ;
22+ import java .util .Objects ;
2123import java .util .concurrent .ConcurrentHashMap ;
2224import java .util .concurrent .atomic .AtomicBoolean ;
2325import java .util .concurrent .locks .ReentrantReadWriteLock ;
26+ import java .util .concurrent .locks .ReentrantReadWriteLock .WriteLock ;
2427
25- import com .google .common .collect .Range ;
26-
28+ import org .apache .commons .collections4 .CollectionUtils ;
2729import org .apache .hugegraph .pd .grpc .Metapb .Graph ;
2830import org .apache .hugegraph .pd .grpc .Metapb .Partition ;
2931
32+ import com .google .common .collect .Range ;
3033import com .google .common .collect .RangeMap ;
3134import com .google .common .collect .TreeRangeMap ;
3235
3336import lombok .Data ;
37+ import lombok .extern .slf4j .Slf4j ;
3438
3539@ Data
40+ @ Slf4j
3641public class GraphCache {
3742
3843 private Graph graph ;
@@ -41,13 +46,30 @@ public class GraphCache {
4146 private ReentrantReadWriteLock lock = new ReentrantReadWriteLock ();
4247 private Map <Integer , AtomicBoolean > state = new ConcurrentHashMap <>();
4348 private Map <Integer , Partition > partitions = new ConcurrentHashMap <>();
44- private RangeMap <Long , Integer > range = new SynchronizedRangeMap < Long , Integer >(). rangeMap ;
49+ private volatile RangeMap <Long , Integer > range = TreeRangeMap . create () ;
4550
4651 public GraphCache (Graph graph ) {
4752 this .graph = graph ;
4853 }
4954
50- public GraphCache () {
55+ public void init (List <Partition > ps ) {
56+ Map <Integer , Partition > gps = new ConcurrentHashMap <>(ps .size (), 1 );
57+ if (!CollectionUtils .isEmpty (ps )) {
58+ WriteLock lock = getLock ().writeLock ();
59+ try {
60+ lock .lock ();
61+ for (Partition p : ps ) {
62+ gps .put (p .getId (), p );
63+ range .put (Range .closedOpen (p .getStartKey (), p .getEndKey ()), p .getId ());
64+ }
65+ } catch (Exception e ) {
66+ log .warn ("init graph with error:" , e );
67+ } finally {
68+ lock .unlock ();
69+ }
70+ }
71+ setPartitions (gps );
72+
5173 }
5274
5375 public Partition getPartition (Integer id ) {
@@ -59,58 +81,87 @@ public Partition addPartition(Integer id, Partition p) {
5981 }
6082
6183 public Partition removePartition (Integer id ) {
84+ Partition p = partitions .get (id );
85+ if (p != null ) {
86+ RangeMap <Long , Integer > range = getRange ();
87+ if (Objects .equals (p .getId (), range .get (p .getStartKey ())) &&
88+ Objects .equals (p .getId (), range .get (p .getEndKey () - 1 ))) {
89+ WriteLock lock = getLock ().writeLock ();
90+ lock .lock ();
91+ try {
92+ range .remove (range .getEntry (p .getStartKey ()).getKey ());
93+ } catch (Exception e ) {
94+ log .warn ("remove partition with error:" , e );
95+ } finally {
96+ lock .unlock ();
97+ }
98+ }
99+ }
62100 return partitions .remove (id );
63101 }
64102
65- public class SynchronizedRangeMap <K extends Comparable <K >, V > {
66-
67- private final RangeMap <K , V > rangeMap = TreeRangeMap .create ();
68- private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock ();
69-
70- public void put (Range <K > range , V value ) {
71- lock .writeLock ().lock ();
72- try {
73- rangeMap .put (range , value );
74- } finally {
75- lock .writeLock ().unlock ();
103+ public void removePartitions () {
104+ getState ().clear ();
105+ RangeMap <Long , Integer > range = getRange ();
106+ WriteLock lock = getLock ().writeLock ();
107+ try {
108+ lock .lock ();
109+ if (range != null ) {
110+ range .clear ();
76111 }
112+ } catch (Exception e ) {
113+ log .warn ("remove partition with error:" , e );
114+ } finally {
115+ lock .unlock ();
77116 }
117+ getPartitions ().clear ();
118+ getInitialized ().set (false );
119+ }
78120
79- public V get ( K key ) {
80- lock . readLock (). lock ();
81- try {
82- return rangeMap . get ( key );
83- } finally {
84- lock . readLock (). unlock ();
85- }
86- }
121+ /*
122+ * 需要外部加写锁
123+ * */
124+ public void reset () {
125+ partitions . clear ();
126+ try {
127+ range . clear ();
128+ } catch ( Exception e ) {
87129
88- public void remove (Range <K > range ) {
89- lock .writeLock ().lock ();
90- try {
91- rangeMap .remove (range );
92- } finally {
93- lock .writeLock ().unlock ();
94- }
95130 }
131+ }
96132
97- public Map .Entry <Range <K >, V > getEntry (K key ) {
98- lock .readLock ().lock ();
99- try {
100- return rangeMap .getEntry (key );
101- } finally {
102- lock .readLock ().unlock ();
103- }
133+ public boolean updatePartition (Partition partition ) {
134+ int partId = partition .getId ();
135+ Partition p = getPartition (partId );
136+ if (p != null && p .equals (partition )) {
137+ return false ;
104138 }
105-
106- public void clear () {
107- lock .writeLock ().lock ();
139+ WriteLock lock = getLock ().writeLock ();
140+ try {
141+ lock .lock ();
142+ RangeMap <Long , Integer > range = getRange ();
143+ addPartition (partId , partition );
108144 try {
109- rangeMap .clear ();
110- } finally {
111- lock .writeLock ().unlock ();
145+ if (p != null ) {
146+ // The old [1-3) is overwritten by [2-3). When [1-3) becomes [1-2), the
147+ // original [1-3) should not be deleted.
148+ // Only when it is confirmed that the old start and end are both your own can
149+ // the old be deleted (i.e., before it is overwritten).
150+ if (Objects .equals (partId , range .get (partition .getStartKey ())) &&
151+ Objects .equals (partId , range .get (partition .getEndKey () - 1 ))) {
152+ range .remove (range .getEntry (partition .getStartKey ()).getKey ());
153+ }
154+ }
155+ range .put (Range .closedOpen (partition .getStartKey (), partition .getEndKey ()), partId );
156+ } catch (Exception e ) {
157+ log .warn ("update partition with error:" , e );
112158 }
159+ } catch (Exception e ) {
160+ throw new RuntimeException (e );
161+ } finally {
162+ lock .unlock ();
113163 }
164+ return true ;
114165 }
115166
116167}
0 commit comments