1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#ifndef _DbeSyncMap_h 22#define _DbeSyncMap_h 23 24#include "DbeLock.h" 25#include "DbeLinkList.h" 26#include "vec.h" 27 28typedef unsigned long hash_ty; 29 30template <class ITEM> class DbeSyncMap : public DbeLock 31{ 32public: 33 DbeSyncMap (int _chunkSize = DefaultChunkSize); 34 virtual ~DbeSyncMap (); 35 void reset (); 36 ITEM *get (const char *nm, int64_t chksum); 37 ITEM *sync_create_item (const char *nm, int64_t chksum); 38 ITEM *get (const char *nm, const char *path, DbeFile *df); 39 ITEM *sync_create_item (const char *nm, const char *path, DbeFile *df); 40 virtual void dump (); 41 42 Vector<ITEM *> * 43 values () 44 { 45 return items; 46 }; 47 48private: 49 hash_ty hash (const char *key); 50 51 DbeLinkList<ITEM *> **chunk; 52 Vector<ITEM *> *items; 53 long chunkSize; 54 55 enum 56 { 57 DefaultChunkSize = 1024 58 }; 59}; 60 61template <class ITEM> 62DbeSyncMap<ITEM>::DbeSyncMap (int _chunkSize) 63{ 64 chunkSize = _chunkSize; 65 chunk = new DbeLinkList<ITEM *> * [chunkSize]; 66 for (long i = 0; i < chunkSize; i++) 67 chunk[i] = NULL; 68 items = new Vector<ITEM *>(512); 69} 70 71template <class ITEM> 72DbeSyncMap<ITEM>::~DbeSyncMap () 73{ 74 for (long i = 0; i < chunkSize; i++) 75 Destroy (chunk[i]); 76 delete[] chunk; 77 delete items; 78} 79 80template <class ITEM> 81void 82DbeSyncMap<ITEM>::reset () 83{ 84 for (long i = 0; i < chunkSize; i++) 85 { 86 Destroy (chunk[i]); 87 chunk[i] = NULL; 88 } 89 items->reset (); 90} 91 92template <class ITEM> 93ITEM * 94DbeSyncMap<ITEM>::get (const char *nm, int64_t chksum) 95{ 96 hash_ty h = hash (nm); 97 for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) 98 { 99 ITEM *item = dl->get_item (); 100 if (item->compare (nm, chksum)) 101 return item; 102 } 103 return NULL; 104} 105 106template <class ITEM> 107hash_ty 108DbeSyncMap<ITEM>::hash (const char *key) 109{ 110 return (hash_ty) (crc64 (key, strlen (key)) % chunkSize); 111} 112 113template <class ITEM> 114ITEM * 115DbeSyncMap<ITEM>::sync_create_item (const char *nm, int64_t chksum) 116{ 117 hash_ty h = hash (nm); 118 for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) 119 { 120 ITEM *item = dl->get_item (); 121 if (item->compare (nm, chksum)) 122 return item; 123 } 124 aquireLock (); 125 for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) 126 { 127 ITEM *item = dl->get_item (); 128 if (item->compare (nm, chksum)) 129 { 130 releaseLock (); 131 return item; 132 } 133 } 134 ITEM *item = ITEM::create_item (nm, chksum); 135 DbeLinkList<ITEM *> *dl = new DbeLinkList<ITEM *>(item); 136 dl->set_next (chunk[h]); 137 chunk[h] = dl; 138 items->append (item); 139 releaseLock (); 140 return item; 141} 142 143template <class ITEM> 144ITEM * 145DbeSyncMap<ITEM>::get (const char *nm, const char *path, DbeFile *df) 146{ 147 int mask = 1 + (path != NULL ? 2 : 0) + (df != NULL ? 4 : 0); 148 hash_ty h = hash (nm); 149 for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) 150 { 151 ITEM *item = dl->get_item (); 152 if (mask == item->compare (nm, path, df)) 153 return item; 154 } 155 return NULL; 156} 157 158template <class ITEM> 159ITEM * 160DbeSyncMap<ITEM>::sync_create_item (const char *nm, const char *path, DbeFile *df) 161{ 162 int mask = CMP_PATH; 163 if (path != NULL) 164 mask += CMP_RUNTIMEPATH; 165 if (df != NULL) 166 mask += CMP_CHKSUM; 167 hash_ty h = hash (nm); 168 for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) 169 { 170 ITEM *item = dl->get_item (); 171 if (mask == item->compare (nm, path, df)) 172 return item; 173 } 174 aquireLock (); 175 for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) 176 { 177 ITEM *item = dl->get_item (); 178 if (mask == item->compare (nm, path, df)) 179 { 180 releaseLock (); 181 return item; 182 } 183 } 184 ITEM *item = ITEM::create_item (nm, path, df); 185 DbeLinkList<ITEM *> *dl = new DbeLinkList<ITEM *>(item); 186 dl->set_next (chunk[h]); 187 chunk[h] = dl; 188 items->append (item); 189 releaseLock (); 190 return item; 191} 192 193template <class ITEM> 194void 195DbeSyncMap<ITEM>::dump () 196{ 197 Dprintf (1, NTXT ("\nDbeSyncMap::dump: vals=%ld\n"), (long) VecSize (items)); 198 int tot = 0; 199 int max_cnt = 0; 200 for (long i = 0; i < chunkSize; i++) 201 { 202 DbeLinkList<ITEM *> *lp = chunk[i]; 203 if (lp) 204 { 205 int cnt = 0; 206 for (DbeLinkList<ITEM *> *lp1 = lp; lp1; lp1 = lp1->get_next ()) 207 cnt++; 208 tot += cnt; 209 if (max_cnt < cnt) 210 max_cnt = cnt; 211 cnt = 1; 212 for (DbeLinkList<ITEM *> *lp1 = lp; lp1; lp1 = lp1->get_next ()) 213 { 214 ITEM *p = lp1->get_item (); 215 Dprintf (1, NTXT (" %2d %s\n"), cnt, p->get_name ()); 216 cnt++; 217 } 218 } 219 } 220 Dprintf (1, NTXT ("\nDbeSyncMap::dump: vals=%ld max_cnt=%d tot=%d\n"), 221 (long) VecSize (items), max_cnt, tot); 222} 223 224#endif /* _DbeSyncMap_h */ 225