| /* Copyright (C) 2021-2023 Free Software Foundation, Inc. | 
 |    Contributed by Oracle. | 
 |  | 
 |    This file is part of GNU Binutils. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3, or (at your option) | 
 |    any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program; if not, write to the Free Software | 
 |    Foundation, 51 Franklin Street - Fifth Floor, Boston, | 
 |    MA 02110-1301, USA.  */ | 
 |  | 
 | #ifndef _DbeSyncMap_h | 
 | #define _DbeSyncMap_h | 
 |  | 
 | #include "DbeLock.h" | 
 | #include "DbeLinkList.h" | 
 | #include "vec.h" | 
 |  | 
 | typedef unsigned long hash_ty; | 
 |  | 
 | template <class ITEM> class DbeSyncMap : public DbeLock | 
 | { | 
 | public: | 
 |   DbeSyncMap (int _chunkSize = DefaultChunkSize); | 
 |   virtual ~DbeSyncMap (); | 
 |   void reset (); | 
 |   ITEM *get (const char *nm, int64_t chksum); | 
 |   ITEM *sync_create_item (const char *nm, int64_t chksum); | 
 |   ITEM *get (const char *nm, const char *path, DbeFile *df); | 
 |   ITEM *sync_create_item (const char *nm, const char *path, DbeFile *df); | 
 |   virtual void dump (); | 
 |  | 
 |   Vector<ITEM *> * | 
 |   values () | 
 |   { | 
 |     return items; | 
 |   }; | 
 |  | 
 | private: | 
 |   hash_ty hash (const char *key); | 
 |  | 
 |   DbeLinkList<ITEM *> **chunk; | 
 |   Vector<ITEM *> *items; | 
 |   long chunkSize; | 
 |  | 
 |   enum | 
 |   { | 
 |     DefaultChunkSize = 1024 | 
 |   }; | 
 | }; | 
 |  | 
 | template <class ITEM> | 
 | DbeSyncMap<ITEM>::DbeSyncMap (int _chunkSize) | 
 | { | 
 |   chunkSize = _chunkSize; | 
 |   chunk = new DbeLinkList<ITEM *> * [chunkSize]; | 
 |   for (long i = 0; i < chunkSize; i++) | 
 |     chunk[i] = NULL; | 
 |   items = new Vector<ITEM *>(512); | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | DbeSyncMap<ITEM>::~DbeSyncMap () | 
 | { | 
 |   for (long i = 0; i < chunkSize; i++) | 
 |     Destroy (chunk[i]); | 
 |   delete[] chunk; | 
 |   delete items; | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | void | 
 | DbeSyncMap<ITEM>::reset () | 
 | { | 
 |   for (long i = 0; i < chunkSize; i++) | 
 |     { | 
 |       Destroy (chunk[i]); | 
 |       chunk[i] = NULL; | 
 |     } | 
 |   items->reset (); | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | ITEM * | 
 | DbeSyncMap<ITEM>::get (const char *nm, int64_t chksum) | 
 | { | 
 |   hash_ty h = hash (nm); | 
 |   for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) | 
 |     { | 
 |       ITEM *item = dl->get_item (); | 
 |       if (item->compare (nm, chksum)) | 
 | 	return item; | 
 |     } | 
 |   return NULL; | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | hash_ty | 
 | DbeSyncMap<ITEM>::hash (const char *key) | 
 | { | 
 |   return (hash_ty) (crc64 (key, strlen (key)) % chunkSize); | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | ITEM * | 
 | DbeSyncMap<ITEM>::sync_create_item (const char *nm, int64_t chksum) | 
 | { | 
 |   hash_ty h = hash (nm); | 
 |   for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) | 
 |     { | 
 |       ITEM *item = dl->get_item (); | 
 |       if (item->compare (nm, chksum)) | 
 | 	return item; | 
 |     } | 
 |   aquireLock (); | 
 |   for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) | 
 |     { | 
 |       ITEM *item = dl->get_item (); | 
 |       if (item->compare (nm, chksum)) | 
 | 	{ | 
 | 	  releaseLock (); | 
 | 	  return item; | 
 | 	} | 
 |     } | 
 |   ITEM *item = ITEM::create_item (nm, chksum); | 
 |   DbeLinkList<ITEM *> *dl = new DbeLinkList<ITEM *>(item); | 
 |   dl->set_next (chunk[h]); | 
 |   chunk[h] = dl; | 
 |   items->append (item); | 
 |   releaseLock (); | 
 |   return item; | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | ITEM * | 
 | DbeSyncMap<ITEM>::get (const char *nm, const char *path, DbeFile *df) | 
 | { | 
 |   int mask = 1 + (path != NULL ? 2 : 0) + (df != NULL ? 4 : 0); | 
 |   hash_ty h = hash (nm); | 
 |   for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) | 
 |     { | 
 |       ITEM *item = dl->get_item (); | 
 |       if (mask == item->compare (nm, path, df)) | 
 | 	return item; | 
 |     } | 
 |   return NULL; | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | ITEM * | 
 | DbeSyncMap<ITEM>::sync_create_item (const char *nm, const char *path, DbeFile *df) | 
 | { | 
 |   int mask = CMP_PATH; | 
 |   if (path != NULL) | 
 |     mask += CMP_RUNTIMEPATH; | 
 |   if (df != NULL) | 
 |     mask += CMP_CHKSUM; | 
 |   hash_ty h = hash (nm); | 
 |   for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) | 
 |     { | 
 |       ITEM *item = dl->get_item (); | 
 |       if (mask == item->compare (nm, path, df)) | 
 | 	return item; | 
 |     } | 
 |   aquireLock (); | 
 |   for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) | 
 |     { | 
 |       ITEM *item = dl->get_item (); | 
 |       if (mask == item->compare (nm, path, df)) | 
 | 	{ | 
 | 	  releaseLock (); | 
 | 	  return item; | 
 | 	} | 
 |     } | 
 |   ITEM *item = ITEM::create_item (nm, path, df); | 
 |   DbeLinkList<ITEM *> *dl = new DbeLinkList<ITEM *>(item); | 
 |   dl->set_next (chunk[h]); | 
 |   chunk[h] = dl; | 
 |   items->append (item); | 
 |   releaseLock (); | 
 |   return item; | 
 | } | 
 |  | 
 | template <class ITEM> | 
 | void | 
 | DbeSyncMap<ITEM>::dump () | 
 | { | 
 |   Dprintf (1, NTXT ("\nDbeSyncMap::dump:  vals=%ld\n"), (long) VecSize (items)); | 
 |   int tot = 0; | 
 |   int max_cnt = 0; | 
 |   for (long i = 0; i < chunkSize; i++) | 
 |     { | 
 |       DbeLinkList<ITEM *> *lp = chunk[i]; | 
 |       if (lp) | 
 | 	{ | 
 | 	  int cnt = 0; | 
 | 	  for (DbeLinkList<ITEM *> *lp1 = lp; lp1; lp1 = lp1->get_next ()) | 
 | 	    cnt++; | 
 | 	  tot += cnt; | 
 | 	  if (max_cnt < cnt) | 
 | 	    max_cnt = cnt; | 
 | 	  cnt = 1; | 
 | 	  for (DbeLinkList<ITEM *> *lp1 = lp; lp1; lp1 = lp1->get_next ()) | 
 | 	    { | 
 | 	      ITEM *p = lp1->get_item (); | 
 | 	      Dprintf (1, NTXT ("      %2d %s\n"), cnt, p->get_name ()); | 
 | 	      cnt++; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   Dprintf (1, NTXT ("\nDbeSyncMap::dump: vals=%ld max_cnt=%d tot=%d\n"), | 
 | 	   (long) VecSize (items), max_cnt, tot); | 
 | } | 
 |  | 
 | #endif /* _DbeSyncMap_h */ |