Пример #1
0
        public IDictionary <Number640, Enum> PutAll(SortedDictionary <Number640, Data> dataMap, IPublicKey publicKey, bool putIfAbsent, bool domainProtection,
                                                    bool sendSelf)
        {
            if (dataMap.Count == 0)
            {
                return(Convenient.EmptyDictionary <Number640, Enum>());
            }
            var min         = dataMap.First().Key; // TODO check if correct
            var max         = dataMap.Last().Key;
            var retVal      = new Dictionary <Number640, Enum>();
            var keysToCheck = new HashSet <Number480>();
            var rangeLock   = Lock(min, max);

            try
            {
                foreach (var kvp in dataMap)
                {
                    var key = kvp.Key;
                    keysToCheck.Add(key.LocationAndDomainAndContentKey);
                    var newData = kvp.Value;
                    if (!SecurityDomainCheck(key.LocationAndDomainKey, publicKey, publicKey, domainProtection))
                    {
                        retVal.Add(key, PutStatus.FailedSecurity);
                        continue;
                    }

                    // We need this check in case we did not use the encoder/deconder,
                    // which is the case if we send the message to ourself. In that
                    // case, the public key of the data is never set to the message
                    // publick key, if the publick key of the data was null.
                    IPublicKey dataKey;
                    if (sendSelf && newData.PublicKey == null)
                    {
                        dataKey = publicKey;
                    }
                    else
                    {
                        dataKey = newData.PublicKey;
                    }

                    if (!SecurityEntryCheck(key.LocationAndDomainAndContentKey, publicKey, dataKey, newData.IsProtectedEntry))
                    {
                        retVal.Add(key, PutStatus.FailedSecurity);
                        continue;
                    }

                    var contains = _backend.Contains(key);
                    if (contains)
                    {
                        if (putIfAbsent)
                        {
                            retVal.Add(key, PutStatus.FailedNotAbsent);
                            continue;
                        }
                        var oldData = _backend.Get(key);
                        if (oldData.IsDeleted)
                        {
                            retVal.Add(key, PutStatus.Deleted);
                            continue;
                        }
                        if (!oldData.BasedOnSet.Equals(newData.BasedOnSet))
                        {
                            retVal.Add(key, PutStatus.VersionFork);
                            continue;
                        }
                    }

                    var  oldData2   = _backend.Put(key, newData);
                    long expiration = newData.ExpirationMillis;
                    // handle timeout
                    _backend.AddTimeout(key, expiration);
                    if (newData.HasPrepareFlag)
                    {
                        retVal.Add(key, PutStatus.OkPrepared);
                    }
                    else
                    {
                        if (newData.Equals(oldData2))
                        {
                            retVal.Add(key, PutStatus.OkUnchanged);
                        }
                        else
                        {
                            retVal.Add(key, PutStatus.Ok);
                        }
                    }
                }

                //now check for forks
                foreach (var key in keysToCheck)
                {
                    var minVersion = new Number640(key, Number160.Zero);
                    var maxVersion = new Number640(key, Number160.MaxValue);
                    var tmp        = _backend.SubMap(minVersion, maxVersion, -1, true);
                    var heads      = GetLatestInternal(tmp);
                    if (heads.Count > 1)
                    {
                        foreach (var fork in heads.Keys)
                        {
                            if (retVal.ContainsKey(fork))
                            {
                                retVal.Add(fork, PutStatus.VersionFork);
                            }
                        }
                    }
                }
                return(retVal);
            }
            finally
            {
                rangeLock.Unlock();
            }
        }